mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 01:22:25 +00:00
Compare commits
5 Commits
1a3955554a
...
staging-mt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26b61bbdd9 | ||
|
|
7f5f4ccad0 | ||
|
|
71e5c425e9 | ||
|
|
aadfd5ceff | ||
|
|
b2dacf060c |
2
.github/workflows/build-dev.yml
vendored
2
.github/workflows/build-dev.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: [ 'cig_wf189h', 'cig_wf189w', 'cig_wf660a', 'cig_wf672', 'cig_wf186h', 'cig_wf186w', 'cig_wf188n', 'cig_wf189', 'cig_wf196', 'cig_wf196', 'cybertan_eww631-a1', 'cybertan_eww631-b1', 'sonicfi_rap630w-312g', 'sonicfi_rap63xc-211g', 'sonicfi_rap630c-311g', 'sonicfi_rap630w-311g', 'sonicfi_rap630w-211g', 'sonicfi_rap650c', 'sonicfi_rap7110c-341x', 'sonicfi_rap750e-h', 'sonicfi_rap750e-s', 'sonicfi_rap750w-311a', 'edgecore_eap101', 'edgecore_eap102', 'edgecore_eap104', 'edgecore_eap105', 'edgecore_eap111', 'edgecore_eap112', 'edgecore_oap101', 'edgecore_oap101-6e', 'edgecore_oap101e', 'edgecore_oap101e-6e', 'edgecore_oap103', 'hfcl_ion4xe', 'hfcl_ion4xi', 'hfcl_ion4x', 'hfcl_ion4x_2', 'hfcl_ion4x_3', 'hfcl_ion4xi_w', 'hfcl_ion4x_w', 'indio_um-305ax', 'senao_iap4300m', 'senao_iap2300m', 'senao_jeap6500', 'udaya_a6-id2', 'udaya_a6-od2', 'yuncore_ax820', 'yuncore_ax840', 'yuncore_fap640', 'yuncore_fap650', 'yuncore_fap655', 'emplus_wap588m', 'zyxel_nwa130be', 'sercomm_ap72tip-v4' ]
|
||||
target: [ ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
--- a/hostapd/ctrl_iface.c 2025-09-24 14:15:25.135668867 +0800
|
||||
+++ b/hostapd/ctrl_iface.c 2025-09-24 15:32:46.082317382 +0800
|
||||
@@ -2657,6 +2657,11 @@ static int hostapd_ctrl_iface_chan_switc
|
||||
break;
|
||||
}
|
||||
|
||||
+ /* Initialize HT/VHT/HE parameters */
|
||||
+ settings.freq_params.ht_enabled = iface->conf->ieee80211n;
|
||||
+ settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
|
||||
+ settings.freq_params.he_enabled = iface->conf->ieee80211ax;
|
||||
+
|
||||
if (settings.freq_params.center_freq1)
|
||||
dfs_range += hostapd_is_dfs_overlap(
|
||||
iface, bandwidth, settings.freq_params.center_freq1);
|
||||
@@ -47,10 +47,6 @@ ALLWIFIBOARDS:= \
|
||||
indio-um-310ax-v1 \
|
||||
indio-um-510axp-v1 \
|
||||
indio-um-510axm-v1 \
|
||||
indio-um-325ax-v2 \
|
||||
indio-um-335ax \
|
||||
indio-um-525axp \
|
||||
indio-um-525axm \
|
||||
muxi-ap3220l \
|
||||
plasmacloud-pax1800 \
|
||||
wallys-dr5018 \
|
||||
@@ -445,10 +441,6 @@ $(eval $(call generate-ath11k-wifi-package,liteon-wpx8324,Liteon WPX8324))
|
||||
$(eval $(call generate-ath11k-wifi-package,indio-um-310ax-v1,Indio UM-310AX V1))
|
||||
$(eval $(call generate-ath11k-wifi-package,indio-um-510axp-v1,Indio UM-510AXP V1))
|
||||
$(eval $(call generate-ath11k-wifi-package,indio-um-510axm-v1,Indio UM-510AXM V1))
|
||||
$(eval $(call generate-ath11k-wifi-package,indio-um-325ax-v2,Indio UM-325AX V2))
|
||||
$(eval $(call generate-ath11k-wifi-package,indio-um-335ax,Indio UM-335AX))
|
||||
$(eval $(call generate-ath11k-wifi-package,indio-um-525axp,Indio UM-525AXP))
|
||||
$(eval $(call generate-ath11k-wifi-package,indio-um-525axm,Indio UM-525AXM))
|
||||
$(eval $(call generate-ath11k-wifi-package,sonicfi-rap630c-311g,Sonicfi RAP630C 311G))
|
||||
$(eval $(call generate-ath11k-wifi-package,sonicfi-rap630w-311g,Sonicfi RAP630W 311G))
|
||||
$(eval $(call generate-ath11k-wifi-package,sonicfi-rap630w-312g,Sonicfi RAP630W 312G))
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -4,19 +4,19 @@ let fs = require("fs");
|
||||
let ubus = require('ubus').connect();
|
||||
|
||||
let gps_info = ubus.call('gps', 'info');
|
||||
let latitude = gps_info.latitude || 0;
|
||||
let longitude = gps_info.longitude || 0;
|
||||
let latitude = gps_info.latitude ?? 0;
|
||||
let longitude = gps_info.longitude ?? 0;
|
||||
|
||||
// afc-location.json file content
|
||||
let afc_location = {};
|
||||
afc_location.location_type = "ellipse";
|
||||
afc_location.location = longitude + ":" + latitude ;
|
||||
afc_location.height = gps_info.elevation || 0;
|
||||
afc_location.height = gps_info.elevation ?? 0;
|
||||
afc_location.height_type = "AMSL";
|
||||
afc_location.major_axis = int(gps_info.major_axis) || 1;
|
||||
afc_location.minor_axis = int(gps_info.minor_axis) || 1;
|
||||
afc_location.orientation = gps_info.major_orientation || 0;
|
||||
afc_location.vertical_tolerance = int(gps_info.vdop) || 1;
|
||||
afc_location.major_axis = gps_info.major_axis ?? 0;
|
||||
afc_location.minor_axis = gps_info.minor_axis ?? 0;
|
||||
afc_location.orientation = gps_info.major_orientation ?? 0;
|
||||
afc_location.vertical_tolerance = gps_info.vdop ?? 0;
|
||||
|
||||
let afc_location_json = fs.open("/etc/ucentral/afc-location.json", "w");
|
||||
afc_location_json.write(afc_location);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
let libubus = require("ubus");
|
||||
import { open, readfile, writefile } from "fs";
|
||||
import { open, readfile } from "fs";
|
||||
import { wdev_create, wdev_remove, is_equal, vlist_new, phy_is_fullmac, phy_open } from "common";
|
||||
|
||||
let uci = require('uci').cursor();
|
||||
let ubus = libubus.connect(null, 60);
|
||||
|
||||
hostapd.data.config = {};
|
||||
@@ -894,24 +893,10 @@ return {
|
||||
hostapd.ubus.disconnect();
|
||||
},
|
||||
afc_request: function(iface, data) {
|
||||
let wireless_config = uci.get_all('wireless');
|
||||
for (let l, afc_server in wireless_config) {
|
||||
if (afc_server['.type'] == 'afc-server' && afc_server.url && data) {
|
||||
hostapd.printf(`Sending AFC request: ${data}`);
|
||||
writefile("/tmp/afc-request.json", data);
|
||||
|
||||
if (afc_server.access_token)
|
||||
system(`curl -s -X POST ${afc_server.url} -H \'accept: \*\/\*\' -H \'Authorization: Bearer ${afc_server.access_token}\' -H \'Content-Type: application/json\' -d \'${data}\' --output /tmp/afc-response.json`);
|
||||
else if (afc_server.cert)
|
||||
system(`curl -s -X POST ${afc_server.url} -H \'accept: \*\/\*\' --cert \'${afc_server.cert}\' -H \'Content-Type: application/json\' -d \'${data}\' --output /tmp/afc-response.json`);
|
||||
|
||||
let afc_response = (readfile("/tmp/afc-response.json"));
|
||||
if (afc_response)
|
||||
return afc_response;
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
let ret = ubus.call("afc", "request", { data });
|
||||
if (type(ret) != "object")
|
||||
return;
|
||||
return ret.data;
|
||||
},
|
||||
bss_add: function(name, obj) {
|
||||
bss_event("add", name);
|
||||
|
||||
@@ -16,14 +16,6 @@ edgecore,eap104)
|
||||
ucidef_set_led_netdev "wan" "wan" "yellow:uplink" "eth0"
|
||||
ucidef_set_led_default "power" "POWER" "green:power" "on"
|
||||
;;
|
||||
indio,um-325ax-v2|\
|
||||
indio,um-335ax|\
|
||||
indio,um-525axm|\
|
||||
indio,um-525axp)
|
||||
ucidef_set_led_wlan "wlan2g" "WLAN2G" "led_2g" "phy0tpt"
|
||||
ucidef_set_led_wlan "wlan5g" "WLAN5G" "led_5g" "phy1tpt"
|
||||
ucidef_set_led_default "power" "POWER" "led_sys" "on"
|
||||
;;
|
||||
cig,wf186h|\
|
||||
cig,wf186w)
|
||||
ucidef_set_led_default "power" "POWER" "green:status" "on"
|
||||
|
||||
@@ -48,15 +48,6 @@ qcom_setup_interfaces()
|
||||
ucidef_add_switch "switch1" \
|
||||
"6u@eth1" "1:lan" "2:lan" "3:lan" "4:lan"
|
||||
;;
|
||||
indio,um-325ax-v2|\
|
||||
indio,um-335ax|\
|
||||
indio,um-525axm|\
|
||||
indio,um-525axp)
|
||||
ucidef_set_interface_wan "eth1"
|
||||
ucidef_set_interface_lan "eth0"
|
||||
ucidef_add_switch "switch1" \
|
||||
"6@eth1" "1:lan" "2:lan" "3:lan" "4:lan"
|
||||
;;
|
||||
emplus,wap385c|\
|
||||
hfcl,ion4x_w|\
|
||||
hfcl,ion4xi_w)
|
||||
|
||||
@@ -142,10 +142,6 @@ ath11k/IPQ5018/hw1.0/caldata.bin)
|
||||
emplus,wap385c|\
|
||||
hfcl,ion4x_w|\
|
||||
hfcl,ion4xi_w|\
|
||||
indio,um-325ax-v2|\
|
||||
indio,um-335ax|\
|
||||
indio,um-525axm|\
|
||||
indio,um-525axp|\
|
||||
optimcloud,d60|\
|
||||
optimcloud,d60-5g|\
|
||||
optimcloud,d50|\
|
||||
@@ -187,9 +183,6 @@ ath11k/qcn6122/hw1.0/caldata_1.bin)
|
||||
;;
|
||||
ath11k/qcn6122/hw1.0/caldata_2.bin)
|
||||
case "$board" in
|
||||
indio,um-325ax-v2|\
|
||||
indio,um-525axm|\
|
||||
indio,um-525axp|\
|
||||
wallys,dr5018|\
|
||||
edgecore,eap104|\
|
||||
edgecore,oap101-6e|\
|
||||
@@ -208,7 +201,6 @@ ath11k/qcn6122/hw1.0/caldata_2.bin)
|
||||
;;
|
||||
ath11k/QCN9074/hw1.0/caldata_1.bin)
|
||||
case "$board" in
|
||||
indio,um-335ax|\
|
||||
optimcloud,d60|\
|
||||
optimcloud,d60-5g|\
|
||||
optimcloud,d50|\
|
||||
@@ -242,9 +234,6 @@ ath11k-macs)
|
||||
edgecore,oap101|\
|
||||
edgecore,oap101-6e|\
|
||||
edgecore,oap101e-6e|\
|
||||
indio,um-325ax-v2|\
|
||||
indio,um-525axp|\
|
||||
indio,um-525axm|\
|
||||
optimcloud,d60|\
|
||||
optimcloud,d60-5g|\
|
||||
optimcloud,d50|\
|
||||
|
||||
@@ -81,10 +81,6 @@ platform_check_image() {
|
||||
wallys,dr5018|\
|
||||
hfcl,ion4x_w|\
|
||||
hfcl,ion4xi_w|\
|
||||
indio,um-325ax-v2|\
|
||||
indio,um-335ax|\
|
||||
indio,um-525axp|\
|
||||
indio,um-525axm|\
|
||||
optimcloud,d60|\
|
||||
optimcloud,d60-5g|\
|
||||
optimcloud,d50|\
|
||||
@@ -111,46 +107,29 @@ platform_do_upgrade() {
|
||||
|
||||
board=$(board_name)
|
||||
case $board in
|
||||
indio,um-325ax-v2|\
|
||||
indio,um-335ax|\
|
||||
indio,um-525axp|\
|
||||
indio,um-525axm|\
|
||||
glinet,b3000|\
|
||||
edgecore,oap101|\
|
||||
edgecore,oap101-6e|\
|
||||
edgecore,oap101e|\
|
||||
edgecore,oap101e-6e|\
|
||||
edgecore,eap104)
|
||||
if [ "$(find_mtd_chardev rootfs)" ]; then
|
||||
CI_UBIPART="rootfs"
|
||||
else
|
||||
if grep -q rootfs1 /proc/cmdline; then
|
||||
CI_UBIPART="rootfs2"
|
||||
CI_FWSETENV="active 2"
|
||||
else
|
||||
CI_UBIPART="rootfs1"
|
||||
CI_FWSETENV="active 1"
|
||||
fi
|
||||
fi
|
||||
nand_upgrade_tar "$1"
|
||||
;;
|
||||
glinet,b3000)
|
||||
CI_UBIPART="rootfs1"
|
||||
[ "$(find_mtd_chardev rootfs)" ] && CI_UBIPART="rootfs"
|
||||
nand_upgrade_tar "$1"
|
||||
;;
|
||||
hfcl,ion4x_w|\
|
||||
hfcl,ion4x_w|\
|
||||
hfcl,ion4xi_w)
|
||||
wp_part=$(fw_printenv primary | cut -d = -f2)
|
||||
echo "Current Primary is $wp_part"
|
||||
if [[ $wp_part == 1 ]]; then
|
||||
CI_UBIPART="rootfs"
|
||||
CI_FWSETENV="primary 0"
|
||||
else
|
||||
CI_UBIPART="rootfs_1"
|
||||
CI_FWSETENV="primary 1"
|
||||
fi
|
||||
nand_upgrade_tar "$1"
|
||||
;;
|
||||
wp_part=$(fw_printenv primary | cut -d = -f2)
|
||||
echo "Current Primary is $wp_part"
|
||||
if [[ $wp_part == 1 ]]; then
|
||||
CI_UBIPART="rootfs"
|
||||
CI_FWSETENV="primary 0"
|
||||
else
|
||||
CI_UBIPART="rootfs_1"
|
||||
CI_FWSETENV="primary 1"
|
||||
fi
|
||||
nand_upgrade_tar "$1"
|
||||
;;
|
||||
cig,wf186w|\
|
||||
cig,wf186h|\
|
||||
emplus,wap385c|\
|
||||
|
||||
@@ -1,941 +0,0 @@
|
||||
/dts-v1/;
|
||||
/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ipq5018.dtsi"
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
/ {
|
||||
#address-cells = <0x2>;
|
||||
#size-cells = <0x2>;
|
||||
model = "Indio UM-325AX V2";
|
||||
compatible = "indio,um-325ax-v2", "qcom,ipq5018-mp03.5-c1", "qcom,ipq5018";
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
aliases {
|
||||
sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
|
||||
serial0 = &blsp1_uart1;
|
||||
serial1 = &blsp1_uart2;
|
||||
ethernet0 = "/soc/dp1";
|
||||
ethernet1 = "/soc/dp2";
|
||||
//led-failsafe = &led_red;
|
||||
//led-running = &led_green;
|
||||
//led-upgrade = &led_green;
|
||||
//led-gateway = &led_blue;
|
||||
//led-factory = &led_blue;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyMSM0,115200,n8 rw init=/init";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
bootargs-append = " swiotlb=1";
|
||||
#else
|
||||
bootargs-append = " swiotlb=1 coherent_pool=2M";
|
||||
#endif
|
||||
stdout-path = "serial0";
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
/* 256 MB Profile
|
||||
* +==========+==============+=========================+
|
||||
* | | | |
|
||||
* | Region | Start Offset | Size |
|
||||
* | | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | NSS | 0x40000000 | 8MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Linux | 0x40800000 | Depends on total memory |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | uboot | 0x4A600000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | SBL | 0x4AA00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | smem | 0x4AB00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | TZ | 0x4AC00000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Q6 | | |
|
||||
* | code/ | 0x4B000000 | 20MB |
|
||||
* | data | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | data | 0x4C400000 | 13MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | M3 Dump | 0x4D100000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | QDSS | 0x4D200000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | data | 0x4D300000 | 15MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | M3 Dump | 0x4E200000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | QDSS | 0x4E300000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | data | 0x4E400000 | 15MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | M3 Dump | 0x4F300000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | QDSS | 0x4F400000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | |
|
||||
* | Rest of the memory for Linux |
|
||||
* | |
|
||||
* +===================================================+
|
||||
*/
|
||||
q6_mem_regions: q6_mem_regions@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x4500000>;
|
||||
};
|
||||
|
||||
q6_code_data: q6_code_data@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x1400000>;
|
||||
};
|
||||
|
||||
q6_ipq5018_data: q6_ipq5018_data@4C400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4C400000 0x0 0xD00000>;
|
||||
};
|
||||
|
||||
m3_dump: m3_dump@4D100000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D100000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_etr_region: q6_etr_dump@4D200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data1: q6_qcn6122_data1@4D300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D300000 0x0 0xF00000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data2: q6_qcn6122_data2@4E400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E400000 0x0 0xF00000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_2: m3_dump_qcn6122_2@4F300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4F300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_2: q6_qcn6122_etr_2@4F400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4F400000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
#else
|
||||
/* 512MB/1GB Profiles
|
||||
* +==========+==============+=========================+
|
||||
* | | | |
|
||||
* | Region | Start Offset | Size |
|
||||
* | | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | NSS | 0x40000000 | 16MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Linux | 0x41000000 | Depends on total memory |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | uboot | 0x4A600000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | SBL | 0x4AA00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | smem | 0x4AB00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | TZ | 0x4AC00000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Q6 | | |
|
||||
* | code/ | 0x4B000000 | 20MB |
|
||||
* | data | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | data | 0x4C400000 | 14MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | M3 Dump | 0x4D200000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | QDSS | 0x4D300000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | Caldb | 0x4D400000 | 2MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | data | 0x4D600000 | 16MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | M3 Dump | 0x4E600000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | QDSS | 0x4E700000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | Caldb | 0x4E800000 | 5MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | data | 0x4ED00000 | 16MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | M3 Dump | 0x4FD00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | QDSS | 0x4FE00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | Caldb | 0x4FF00000 | 5MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | |
|
||||
* | Rest of the memory for Linux |
|
||||
* | |
|
||||
* +===================================================+
|
||||
*/
|
||||
q6_mem_regions: q6_mem_regions@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x5400000>;
|
||||
};
|
||||
|
||||
q6_code_data: q6_code_data@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 01400000>;
|
||||
};
|
||||
|
||||
q6_ipq5018_data: q6_ipq5018_data@4C400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4C400000 0x0 0xE00000>;
|
||||
};
|
||||
|
||||
m3_dump: m3_dump@4D200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_etr_region: q6_etr_dump@4D300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_caldb_region: q6_caldb_region@4D400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D400000 0x0 0x200000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data1: q6_qcn6122_data1@4D600000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D600000 0x0 0x1000000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E600000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E600000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E700000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E700000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_caldb_1: q6_qcn6122_caldb_1@4E800000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E800000 0x0 0x500000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data2: q6_qcn6122_data2@4E900000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4ED00000 0x0 0x1000000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_2: m3_dump_qcn6122_2@4FD00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4FD00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_2: q6_qcn6122_etr_2@4FE00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4FE00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_caldb_2: q6_qcn6122_caldb_2@4FF00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4FF00000 0x0 0x500000>;
|
||||
};
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
soc {
|
||||
gpio-watchdog {
|
||||
compatible = "linux,wdt-gpio";
|
||||
gpios = <&tlmm 27 GPIO_ACTIVE_LOW>;
|
||||
hw_algo = "toggle";
|
||||
hw_margin_ms = <5000>;
|
||||
always-running;
|
||||
};
|
||||
|
||||
serial@78af000 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
blsp1_uart2: serial@78b0000 {
|
||||
pinctrl-0 = <&blsp1_uart_pins>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
qpic_bam: dma@7984000{
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
nand: qpic-nand@79b0000 {
|
||||
pinctrl-0 = <&qspi_nand_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
spi_0: spi@78b5000 { /* BLSP1 QUP0 */
|
||||
pinctrl-0 = <&blsp0_spi_pins>;
|
||||
pinctrl-names = "default";
|
||||
cs-select = <0>;
|
||||
status = "ok";
|
||||
|
||||
m25p80@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0>;
|
||||
compatible = "n25q128a11";
|
||||
linux,modalias = "m25p80", "n25q128a11";
|
||||
spi-max-frequency = <50000000>;
|
||||
use-default-sizes;
|
||||
};
|
||||
};
|
||||
|
||||
mdio0: mdio@88000 {
|
||||
status = "ok";
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <7>;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1: mdio@90000 {
|
||||
status = "ok";
|
||||
pinctrl-0 = <&mdio1_pins>;
|
||||
pinctrl-names = "default";
|
||||
phy-reset-gpio = <&tlmm 39 0>;
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <28>;
|
||||
};
|
||||
};
|
||||
|
||||
ess-instance {
|
||||
num_devices = <0x1>;
|
||||
ess-switch@0x39c00000 {
|
||||
switch_mac_mode = <0xf>; /* mac mode for uniphy instance*/
|
||||
cmnblk_clk = "internal_96MHz"; /* cmnblk clk*/
|
||||
qcom,port_phyinfo {
|
||||
port@0 {
|
||||
port_id = <1>;
|
||||
phy_address = <7>;
|
||||
mdiobus = <&mdio0>;
|
||||
};
|
||||
port@1 {
|
||||
port_id = <2>;
|
||||
phy_address = <0x1c>;
|
||||
mdiobus = <&mdio1>;
|
||||
port_mac_sel = "QGMAC_PORT";
|
||||
};
|
||||
};
|
||||
led_source@0 {
|
||||
source = <0>;
|
||||
mode = "normal";
|
||||
speed = "all";
|
||||
blink_en = "enable";
|
||||
active = "high";
|
||||
};
|
||||
};
|
||||
ess-switch1@1 {
|
||||
compatible = "qcom,ess-switch-qca83xx";
|
||||
device_id = <1>;
|
||||
switch_access_mode = "mdio";
|
||||
mdio-bus = <&mdio1>;
|
||||
reset_gpio = <0x28>;
|
||||
switch_cpu_bmp = <0x40>; /* cpu port bitmap */
|
||||
switch_lan_bmp = <0x1e>; /* lan port bitmap */
|
||||
switch_wan_bmp = <0x0>; /* wan port bitmap */
|
||||
qca,ar8327-initvals = <
|
||||
0x00004 0x7600000 /* PAD0_MODE */
|
||||
0x00008 0x1000000 /* PAD5_MODE */
|
||||
0x0000c 0x80 /* PAD6_MODE */
|
||||
0x00010 0x2613a0 /* PORT6 FORCE MODE*/
|
||||
0x000e4 0xaa545 /* MAC_POWER_SEL */
|
||||
0x000e0 0xc74164de /* SGMII_CTRL */
|
||||
0x0007c 0x4e /* PORT0_STATUS */
|
||||
0x00094 0x4e /* PORT6_STATUS */
|
||||
>;
|
||||
qcom,port_phyinfo {
|
||||
port@0 {
|
||||
port_id = <1>;
|
||||
phy_address = <28>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dp1 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
qcom,id = <1>;
|
||||
reg = <0x39C00000 0x10000>;
|
||||
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
|
||||
qcom,mactype = <2>;
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <7>;
|
||||
mdio-bus = <&mdio0>;
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
dp2 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
qcom,id = <2>;
|
||||
reg = <0x39D00000 0x10000>;
|
||||
interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
|
||||
qcom,mactype = <2>;
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <28>;
|
||||
mdio-bus = <&mdio1>;
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
qcom,test@0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
nss-macsec1 {
|
||||
compatible = "qcom,nss-macsec";
|
||||
phy_addr = <0x1c>;
|
||||
mdiobus = <&mdio1>;
|
||||
};
|
||||
|
||||
lpass: lpass@0xA000000{
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcm: pcm@0xA3C0000{
|
||||
pinctrl-0 = <&audio_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcm_lb: pcm_lb@0 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
pinctrl-0 = <&blsp0_uart_pins &phy_led_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
blsp0_uart_pins: uart_pins {
|
||||
blsp0_uart_rx_tx {
|
||||
pins = "gpio20", "gpio21";
|
||||
function = "blsp0_uart0";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
blsp1_uart_pins: blsp1_uart_pins {
|
||||
blsp1_uart_rx_tx {
|
||||
pins = "gpio22", "gpio24", "gpio23", "gpio25";
|
||||
function = "blsp1_uart2";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
blsp0_spi_pins: blsp0_spi_pins {
|
||||
mux {
|
||||
pins = "gpio10", "gpio11", "gpio12", "gpio13";
|
||||
function = "blsp0_spi";
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
qspi_nand_pins: qspi_nand_pins {
|
||||
qspi_clock {
|
||||
pins = "gpio9";
|
||||
function = "qspi_clk";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_cs {
|
||||
pins = "gpio8";
|
||||
function = "qspi_cs";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_0 {
|
||||
pins = "gpio7";
|
||||
function = "qspi0";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_1 {
|
||||
pins = "gpio6";
|
||||
function = "qspi1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_2 {
|
||||
pins = "gpio5";
|
||||
function = "qspi2";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_3 {
|
||||
pins = "gpio4";
|
||||
function = "qspi3";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1_pins: mdio_pinmux {
|
||||
mux_0 {
|
||||
pins = "gpio36";
|
||||
function = "mdc";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
mux_1 {
|
||||
pins = "gpio37";
|
||||
function = "mdio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
phy_led_pins: phy_led_pins {
|
||||
gephy_led_pin {
|
||||
pins = "gpio46";
|
||||
function = "led0";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
i2c_pins: i2c_pins {
|
||||
i2c_scl {
|
||||
pins = "gpio25";
|
||||
function = "blsp2_i2c1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
i2c_sda {
|
||||
pins = "gpio26";
|
||||
function = "blsp2_i2c1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
button_pins: button_pins {
|
||||
reset_button {
|
||||
pins = "gpio38";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
audio_pins: audio_pinmux {
|
||||
};
|
||||
leds_pins: leds_pins {
|
||||
led_5g {
|
||||
pins = "gpio34";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
led_2g {
|
||||
pins = "gpio33";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
led_sys {
|
||||
pins = "gpio26";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
led_onekey {
|
||||
pins = "gpio28";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&soc {
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
pinctrl-0 = <&button_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
button@1 {
|
||||
label = "reset";
|
||||
linux,code = <KEY_RESTART>;
|
||||
gpios = <&tlmm 38 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
pinctrl-0 = <&leds_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
led_blue: led@34 {
|
||||
label = "led_5g";
|
||||
gpios = <&tlmm 34 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_5g";
|
||||
default-state = "off";
|
||||
};
|
||||
led_green: led@33 {
|
||||
label = "led_2g";
|
||||
gpios = <&tlmm 33 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_2g";
|
||||
default-state = "off";
|
||||
};
|
||||
led_red: led@26 {
|
||||
label = "led_sys";
|
||||
gpios = <&tlmm 26 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_sys";
|
||||
default-state = "off";
|
||||
};
|
||||
led@28 {
|
||||
label = "led_onekey";
|
||||
gpios = <&tlmm 28 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_onekey";
|
||||
default-state = "off";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&q6v5_wcss {
|
||||
compatible = "qcom,ipq5018-q6-mpd";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
reg = <0x0cd00000 0x4040>,
|
||||
<0x1938000 0x8>,
|
||||
<0x193d204 0x4>;
|
||||
reg-names = "qdsp6",
|
||||
"tcsr-msip",
|
||||
"tcsr-q6";
|
||||
resets = <&gcc GCC_WCSSAON_RESET>,
|
||||
<&gcc GCC_WCSS_Q6_BCR>;
|
||||
|
||||
reset-names = "wcss_aon_reset",
|
||||
"wcss_q6_reset";
|
||||
|
||||
clocks = <&gcc GCC_Q6_AXIS_CLK>,
|
||||
<&gcc GCC_WCSS_ECAHB_CLK>,
|
||||
<&gcc GCC_Q6_AXIM_CLK>,
|
||||
<&gcc GCC_Q6_AXIM2_CLK>,
|
||||
<&gcc GCC_Q6_AHB_CLK>,
|
||||
<&gcc GCC_Q6_AHB_S_CLK>,
|
||||
<&gcc GCC_WCSS_AXI_S_CLK>;
|
||||
clock-names = "gcc_q6_axis_clk",
|
||||
"gcc_wcss_ecahb_clk",
|
||||
"gcc_q6_axim_clk",
|
||||
"gcc_q6_axim2_clk",
|
||||
"gcc_q6_ahb_clk",
|
||||
"gcc_q6_ahb_s_clk",
|
||||
"gcc_wcss_axi_s_clk";
|
||||
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_mem_regions>, <&q6_etr_region>;
|
||||
#else
|
||||
memory-region = <&q6_mem_regions>, <&q6_etr_region>,
|
||||
<&q6_caldb_region>;
|
||||
#endif
|
||||
|
||||
qcom,rproc = <&q6v5_wcss>;
|
||||
qcom,bootargs_smem = <507>;
|
||||
boot-args = <0x1 0x4 0x3 0x0F 0x0 0x0>,
|
||||
<0x2 0x4 0x2 0x12 0x0 0x0>;
|
||||
status = "ok";
|
||||
q6_wcss_pd1: remoteproc_pd1@4ab000 {
|
||||
compatible = "qcom,ipq5018-wcss-ahb-mpd";
|
||||
reg = <0x4ab000 0x20>;
|
||||
reg-names = "rmb";
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
m3_firmware = "IPQ5018/m3_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 8 0>,
|
||||
<&wcss_smp2p_in 9 0>,
|
||||
<&wcss_smp2p_in 12 0>,
|
||||
<&wcss_smp2p_in 11 0>;
|
||||
interrupt-names = "fatal",
|
||||
"ready",
|
||||
"spawn-ack",
|
||||
"stop-ack";
|
||||
|
||||
resets = <&gcc GCC_WCSSAON_RESET>,
|
||||
<&gcc GCC_WCSS_BCR>,
|
||||
<&gcc GCC_CE_BCR>;
|
||||
reset-names = "wcss_aon_reset",
|
||||
"wcss_reset",
|
||||
"ce_reset";
|
||||
|
||||
clocks = <&gcc GCC_WCSS_AHB_S_CLK>,
|
||||
<&gcc GCC_WCSS_ACMT_CLK>,
|
||||
<&gcc GCC_WCSS_AXI_M_CLK>;
|
||||
clock-names = "gcc_wcss_ahb_s_clk",
|
||||
"gcc_wcss_acmt_clk",
|
||||
"gcc_wcss_axi_m_clk";
|
||||
|
||||
qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>;
|
||||
|
||||
qcom,smem-states = <&wcss_smp2p_out 8>,
|
||||
<&wcss_smp2p_out 9>,
|
||||
<&wcss_smp2p_out 10>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_ipq5018_data>, <&m3_dump>,
|
||||
<&q6_etr_region>;
|
||||
#else
|
||||
memory-region = <&q6_ipq5018_data>, <&m3_dump>,
|
||||
<&q6_etr_region>, <&q6_caldb_region>;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
q6_wcss_pd2: remoteproc_pd2 {
|
||||
compatible = "qcom,ipq5018-wcss-pcie-mpd";
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
m3_firmware = "qcn6122/m3_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 16 0>,
|
||||
<&wcss_smp2p_in 17 0>,
|
||||
<&wcss_smp2p_in 20 0>,
|
||||
<&wcss_smp2p_in 19 0>;
|
||||
interrupt-names = "fatal",
|
||||
"ready",
|
||||
"spawn-ack",
|
||||
"stop-ack";
|
||||
|
||||
qcom,smem-states = <&wcss_smp2p_out 16>,
|
||||
<&wcss_smp2p_out 17>,
|
||||
<&wcss_smp2p_out 18>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>,
|
||||
<&q6_qcn6122_etr_1>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>,
|
||||
<&q6_qcn6122_etr_1>, <&q6_qcn6122_caldb_1>;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
q6_wcss_pd3: remoteproc_pd3 {
|
||||
compatible = "qcom,ipq5018-wcss-pcie-mpd";
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 24 0>,
|
||||
<&wcss_smp2p_in 25 0>,
|
||||
<&wcss_smp2p_in 28 0>,
|
||||
<&wcss_smp2p_in 27 0>;
|
||||
interrupt-names = "fatal",
|
||||
"ready",
|
||||
"spawn-ack",
|
||||
"stop-ack";
|
||||
|
||||
qcom,smem-states = <&wcss_smp2p_out 24>,
|
||||
<&wcss_smp2p_out 25>,
|
||||
<&wcss_smp2p_out 26>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>,
|
||||
<&q6_qcn6122_etr_2>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>,
|
||||
<&q6_qcn6122_etr_2>, <&q6_qcn6122_caldb_2>;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_0 {
|
||||
pinctrl-0 = <&i2c_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&wifi0 {
|
||||
/* IPQ5018 */
|
||||
qcom,multipd_arch;
|
||||
qcom,rproc = <&q6_wcss_pd1>;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd1";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0x24>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,bdf-addr = <0x4C400000 0x4C400000 0x4C400000 0x0 0x0>;
|
||||
qcom,caldb-addr = <0x4D400000 0x4D400000 0 0 0>;
|
||||
qcom,caldb-size = <0x200000>;
|
||||
mem-region = <&q6_ipq5018_data>;
|
||||
#else
|
||||
memory-region = <&q6_ipq5018_data>;
|
||||
#endif
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&wifi1 {
|
||||
/* QCN6122 5G */
|
||||
qcom,multipd_arch;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd2";
|
||||
qcom,rproc = <&q6_wcss_pd2>;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0x50>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,bdf-addr = <0x4D600000 0x4D600000 0x4D300000 0x0 0x0>;
|
||||
qcom,caldb-addr = <0x4E800000 0x4E800000 0 0 0>;
|
||||
qcom,caldb-size = <0x500000>;
|
||||
mem-region = <&q6_qcn6122_data1>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data1>;
|
||||
#endif
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&wifi2 {
|
||||
/* QCN6122 6G */
|
||||
qcom,multipd_arch;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd3";
|
||||
qcom,rproc = <&q6_wcss_pd3>;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0xb0>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,bdf-addr = <0x4ED00000 0x4ED00000 0x4E400000 0x0 0x0>;
|
||||
qcom,caldb-addr = <0x4FF00000 0x4FF00000 0 0 0>;
|
||||
qcom,caldb-size = <0x500000>;
|
||||
mem-region = <&q6_qcn6122_data2>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data2>;
|
||||
#endif
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
|
||||
&usb3 {
|
||||
status = "ok";
|
||||
device-power-gpio = <&tlmm 24 1>;
|
||||
};
|
||||
|
||||
&dwc_0 {
|
||||
/delete-property/ #phy-cells;
|
||||
/delete-property/ phys;
|
||||
/delete-property/ phy-names;
|
||||
};
|
||||
&hs_m31phy_0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&eud {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&pcie_x1 {
|
||||
#status = "disabled";
|
||||
#perst-gpio = <&tlmm 18 1>;
|
||||
perst-gpio = <&tlmm 18 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
&pcie_x2 {
|
||||
#status = "disabled";
|
||||
#perst-gpio = <&tlmm 15 1>;
|
||||
perst-gpio = <&tlmm 15 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
&pcie_x1_rp {
|
||||
status = "disabled";
|
||||
|
||||
mhi_0: qcom,mhi@0 {
|
||||
reg = <0 0 0 0 0 >;
|
||||
};
|
||||
};
|
||||
|
||||
&pcie_x2_rp {
|
||||
status = "disabled";
|
||||
|
||||
mhi_1: qcom,mhi@1 {
|
||||
reg = <0 0 0 0 0 >;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,731 +0,0 @@
|
||||
/dts-v1/;
|
||||
/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2025, Shubham Vishwakarma <shubhamvis98@fossfrog.in>.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ipq5018.dtsi"
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
/ {
|
||||
#address-cells = <0x2>;
|
||||
#size-cells = <0x2>;
|
||||
model = "Indio UM-335AX";
|
||||
compatible = "indio,um-335ax", "qcom,ipq5018-ap-mp03.1", "qcom,ipq5018-mp03.1", "qcom,ipq5018";
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
aliases {
|
||||
sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
|
||||
serial0 = &blsp1_uart1;
|
||||
serial1 = &blsp1_uart2;
|
||||
ethernet0 = "/soc/dp1";
|
||||
ethernet1 = "/soc/dp2";
|
||||
led-boot = &led_red;
|
||||
led-failsafe = &led_red;
|
||||
led-running = &led_red;
|
||||
led-upgrade = &led_red;
|
||||
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyMSM0,115200,n8 rw init=/init";
|
||||
bootargs-append = " swiotlb=1 coherent_pool=2M";
|
||||
stdout-path = "serial0";
|
||||
};
|
||||
|
||||
gpio-watchdog {
|
||||
compatible = "linux,wdt-gpio";
|
||||
gpios = <&tlmm 27 GPIO_ACTIVE_LOW>;
|
||||
hw_algo = "toggle";
|
||||
hw_margin_ms = <5000>;
|
||||
always-running;
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
q6_mem_regions: q6_mem_regions@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x1800000>;
|
||||
};
|
||||
|
||||
q6_ipq5018_data: q6_ipq5018_data@4C400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4C400000 0x0 0xE00000>;
|
||||
};
|
||||
|
||||
m3_dump: m3_dump@4C800000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4C800000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_etr_region: q6_etr_dump@4C900000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4C900000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_caldb_region: q6_caldb_region@4CA00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4CA00000 0x0 0x200000>;
|
||||
};
|
||||
|
||||
qcn9000_pcie0: qcn9000_pcie0@4cc00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4CC00000 0x0 0x2600000>;
|
||||
};
|
||||
|
||||
#if defined(__CNSS2__)
|
||||
mhi_region1: dma_pool1@4F200000 {
|
||||
compatible = "shared-dma-pool";
|
||||
no-map;
|
||||
reg = <0x0 0x4F200000 0x0 0x900000>;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
soc {
|
||||
serial@78af000 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
blsp1_uart2: serial@78b0000 {
|
||||
pinctrl-0 = <&blsp1_uart_pins>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
qpic_bam: dma@7984000{
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
nand: qpic-nand@79b0000 {
|
||||
pinctrl-0 = <&qspi_nand_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
spi_0: spi@78b5000 { /* BLSP1 QUP0 */
|
||||
pinctrl-0 = <&blsp0_spi_pins>;
|
||||
pinctrl-names = "default";
|
||||
cs-select = <0>;
|
||||
status = "ok";
|
||||
|
||||
m25p80@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0>;
|
||||
compatible = "n25q128a11";
|
||||
linux,modalias = "m25p80", "n25q128a11";
|
||||
spi-max-frequency = <50000000>;
|
||||
use-default-sizes;
|
||||
};
|
||||
};
|
||||
|
||||
mdio0: mdio@88000 {
|
||||
status = "ok";
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <7>;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1: mdio@90000 {
|
||||
status = "ok";
|
||||
pinctrl-0 = <&mdio1_pins>;
|
||||
pinctrl-names = "default";
|
||||
phy-reset-gpio = <&tlmm 39 0>;
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <28>;
|
||||
};
|
||||
};
|
||||
|
||||
ess-instance {
|
||||
num_devices = <0x1>;
|
||||
ess-switch@0x39c00000 {
|
||||
switch_mac_mode = <0xf>; /* mac mode for uniphy instance*/
|
||||
cmnblk_clk = "internal_96MHz"; /* cmnblk clk*/
|
||||
qcom,port_phyinfo {
|
||||
port@0 {
|
||||
port_id = <1>;
|
||||
phy_address = <7>;
|
||||
mdiobus = <&mdio0>;
|
||||
};
|
||||
port@1 {
|
||||
port_id = <2>;
|
||||
phy_address = <0x1c>;
|
||||
mdiobus = <&mdio1>;
|
||||
port_mac_sel = "QGMAC_PORT";
|
||||
};
|
||||
};
|
||||
led_source@0 {
|
||||
source = <0>;
|
||||
mode = "normal";
|
||||
speed = "all";
|
||||
blink_en = "enable";
|
||||
active = "high";
|
||||
};
|
||||
};
|
||||
ess-switch1@1 {
|
||||
compatible = "qcom,ess-switch-qca83xx";
|
||||
device_id = <1>;
|
||||
switch_access_mode = "mdio";
|
||||
mdio-bus = <&mdio1>;
|
||||
reset_gpio = <0x28>;
|
||||
switch_cpu_bmp = <0x40>; /* cpu port bitmap */
|
||||
switch_lan_bmp = <0x1e>; /* lan port bitmap */
|
||||
switch_wan_bmp = <0x0>; /* wan port bitmap */
|
||||
qca,ar8327-initvals = <
|
||||
0x00004 0x7600000 /* PAD0_MODE */
|
||||
0x00008 0x1000000 /* PAD5_MODE */
|
||||
0x0000c 0x80 /* PAD6_MODE */
|
||||
0x00010 0x2613a0 /* PORT6 FORCE MODE*/
|
||||
0x000e4 0xaa545 /* MAC_POWER_SEL */
|
||||
0x000e0 0xc74164de /* SGMII_CTRL */
|
||||
0x0007c 0x4e /* PORT0_STATUS */
|
||||
0x00094 0x4e /* PORT6_STATUS */
|
||||
>;
|
||||
qcom,port_phyinfo {
|
||||
port@0 {
|
||||
port_id = <1>;
|
||||
phy_address = <28>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dp1 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
qcom,id = <1>;
|
||||
reg = <0x39C00000 0x10000>;
|
||||
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
|
||||
qcom,mactype = <2>;
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <7>;
|
||||
mdio-bus = <&mdio0>;
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
dp2 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
qcom,id = <2>;
|
||||
reg = <0x39D00000 0x10000>;
|
||||
interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
|
||||
qcom,mactype = <2>;
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <28>;
|
||||
mdio-bus = <&mdio1>;
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
qcom,test@0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
nss-macsec1 {
|
||||
compatible = "qcom,nss-macsec";
|
||||
phy_addr = <0x1c>;
|
||||
mdiobus = <&mdio1>;
|
||||
};
|
||||
|
||||
lpass: lpass@0xA000000{
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcm: pcm@0xA3C0000{
|
||||
pinctrl-0 = <&audio_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcm_lb: pcm_lb@0 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
pinctrl-0 = <&blsp0_uart_pins &phy_led_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
blsp0_uart_pins: uart_pins {
|
||||
blsp0_uart_rx_tx {
|
||||
pins = "gpio20", "gpio21";
|
||||
function = "blsp0_uart0";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
blsp1_uart_pins: blsp1_uart_pins {
|
||||
blsp1_uart_rx_tx {
|
||||
pins = "gpio22", "gpio24", "gpio23", "gpio25";
|
||||
function = "blsp1_uart2";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
blsp0_spi_pins: blsp0_spi_pins {
|
||||
mux {
|
||||
pins = "gpio10", "gpio11", "gpio12", "gpio13";
|
||||
function = "blsp0_spi";
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
qspi_nand_pins: qspi_nand_pins {
|
||||
qspi_clock {
|
||||
pins = "gpio9";
|
||||
function = "qspi_clk";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_cs {
|
||||
pins = "gpio8";
|
||||
function = "qspi_cs";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_0 {
|
||||
pins = "gpio7";
|
||||
function = "qspi0";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_1 {
|
||||
pins = "gpio6";
|
||||
function = "qspi1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_2 {
|
||||
pins = "gpio5";
|
||||
function = "qspi2";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_3 {
|
||||
pins = "gpio4";
|
||||
function = "qspi3";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1_pins: mdio_pinmux {
|
||||
mux_0 {
|
||||
pins = "gpio36";
|
||||
function = "mdc";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
mux_1 {
|
||||
pins = "gpio37";
|
||||
function = "mdio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
phy_led_pins: phy_led_pins {
|
||||
gephy_led_pin {
|
||||
pins = "gpio46";
|
||||
function = "led0";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
i2c_pins: i2c_pins {
|
||||
i2c_scl {
|
||||
pins = "gpio25";
|
||||
function = "blsp2_i2c1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
i2c_sda {
|
||||
pins = "gpio26";
|
||||
function = "blsp2_i2c1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
button_pins: button_pins {
|
||||
reset_button {
|
||||
pins = "gpio38";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
audio_pins: audio_pinmux {
|
||||
};
|
||||
|
||||
leds_pins: leds_pins {
|
||||
led_blue: led_5g {
|
||||
label = "led_5g";
|
||||
pins = "gpio34";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
led_green: led_2g {
|
||||
label = "led_2g";
|
||||
pins = "gpio33";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
led_red: led_sys {
|
||||
label = "led_sys";
|
||||
pins = "gpio26";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
led_onekey {
|
||||
pins = "gpio28";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&soc {
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
pinctrl-0 = <&button_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
button@1 {
|
||||
label = "reset";
|
||||
linux,code = <KEY_RESTART>;
|
||||
gpios = <&tlmm 38 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
pinctrl-0 = <&leds_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
led@33 {
|
||||
label = "led_5g";
|
||||
gpios = <&tlmm 34 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_5g";
|
||||
default-state = "off";
|
||||
};
|
||||
led@34 {
|
||||
label = "led_2g";
|
||||
gpios = <&tlmm 33 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_2g";
|
||||
default-state = "off";
|
||||
};
|
||||
led@26 {
|
||||
label = "led_sys";
|
||||
gpios = <&tlmm 26 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_sys";
|
||||
default-state = "on";
|
||||
};
|
||||
led@28 {
|
||||
label = "led_onekey";
|
||||
gpios = <&tlmm 28 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_onekey";
|
||||
default-state = "off";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&q6v5_wcss {
|
||||
compatible = "qcom,ipq5018-q6-mpd";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
reg = <0x0cd00000 0x4040>,
|
||||
<0x1938000 0x8>,
|
||||
<0x193d204 0x4>;
|
||||
reg-names = "qdsp6",
|
||||
"tcsr-msip",
|
||||
"tcsr-q6";
|
||||
resets = <&gcc GCC_WCSSAON_RESET>,
|
||||
<&gcc GCC_WCSS_Q6_BCR>;
|
||||
|
||||
reset-names = "wcss_aon_reset",
|
||||
"wcss_q6_reset";
|
||||
|
||||
clocks = <&gcc GCC_Q6_AXIS_CLK>,
|
||||
<&gcc GCC_WCSS_ECAHB_CLK>,
|
||||
<&gcc GCC_Q6_AXIM_CLK>,
|
||||
<&gcc GCC_Q6_AXIM2_CLK>,
|
||||
<&gcc GCC_Q6_AHB_CLK>,
|
||||
<&gcc GCC_Q6_AHB_S_CLK>,
|
||||
<&gcc GCC_WCSS_AXI_S_CLK>;
|
||||
clock-names = "gcc_q6_axis_clk",
|
||||
"gcc_wcss_ecahb_clk",
|
||||
"gcc_q6_axim_clk",
|
||||
"gcc_q6_axim2_clk",
|
||||
"gcc_q6_ahb_clk",
|
||||
"gcc_q6_ahb_s_clk",
|
||||
"gcc_wcss_axi_s_clk";
|
||||
|
||||
memory-region = <&q6_mem_regions>, <&q6_etr_region>,
|
||||
<&q6_caldb_region>;
|
||||
|
||||
qcom,rproc = <&q6v5_wcss>;
|
||||
qcom,bootargs_smem = <507>;
|
||||
boot-args = <0x1 0x4 0x3 0x0F 0x0 0x0>,
|
||||
<0x2 0x4 0x2 0x12 0x0 0x0>;
|
||||
status = "ok";
|
||||
q6_wcss_pd1: remoteproc_pd1@4ab000 {
|
||||
compatible = "qcom,ipq5018-wcss-ahb-mpd";
|
||||
reg = <0x4ab000 0x20>;
|
||||
reg-names = "rmb";
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
m3_firmware = "IPQ5018/m3_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 8 0>,
|
||||
<&wcss_smp2p_in 9 0>,
|
||||
<&wcss_smp2p_in 12 0>,
|
||||
<&wcss_smp2p_in 11 0>;
|
||||
interrupt-names = "fatal",
|
||||
"ready",
|
||||
"spawn-ack",
|
||||
"stop-ack";
|
||||
|
||||
resets = <&gcc GCC_WCSSAON_RESET>,
|
||||
<&gcc GCC_WCSS_BCR>,
|
||||
<&gcc GCC_CE_BCR>;
|
||||
reset-names = "wcss_aon_reset",
|
||||
"wcss_reset",
|
||||
"ce_reset";
|
||||
|
||||
clocks = <&gcc GCC_WCSS_AHB_S_CLK>,
|
||||
<&gcc GCC_WCSS_ACMT_CLK>,
|
||||
<&gcc GCC_WCSS_AXI_M_CLK>;
|
||||
clock-names = "gcc_wcss_ahb_s_clk",
|
||||
"gcc_wcss_acmt_clk",
|
||||
"gcc_wcss_axi_m_clk";
|
||||
|
||||
qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>;
|
||||
|
||||
qcom,smem-states = <&wcss_smp2p_out 8>,
|
||||
<&wcss_smp2p_out 9>,
|
||||
<&wcss_smp2p_out 10>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
memory-region = <&q6_ipq5018_data>, <&m3_dump>,
|
||||
<&q6_etr_region>, <&q6_caldb_region>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_0 {
|
||||
pinctrl-0 = <&i2c_pins>;
|
||||
pinctrl-names = "default";
|
||||
// status = "disabled";
|
||||
};
|
||||
|
||||
&usb3 {
|
||||
status = "ok";
|
||||
device-power-gpio = <&tlmm 24 1>;
|
||||
};
|
||||
|
||||
&dwc_0 {
|
||||
/delete-property/ #phy-cells;
|
||||
/delete-property/ phys;
|
||||
/delete-property/ phy-names;
|
||||
};
|
||||
|
||||
&blsp1_uart1 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&ssuniphy_0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&hs_m31phy_0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&eud {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&pcie_x1 {
|
||||
perst-gpio = <&tlmm 18 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
&pcie_x2 {
|
||||
status = "ok";
|
||||
perst-gpio = <&tlmm 15 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
&wcss {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&pcie_x2phy {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&pcie_x1_rp {
|
||||
status = "disabled";
|
||||
|
||||
mhi_0: qcom,mhi@0 {
|
||||
reg = <0 0 0 0 0 >;
|
||||
};
|
||||
};
|
||||
|
||||
&pcie_x2_rp {
|
||||
status = "ok";
|
||||
|
||||
mhi_1: qcom,mhi@1 {
|
||||
reg = <0 0 0 0 0 >;
|
||||
qrtr_instance_id = <0x20>;
|
||||
qti,disable-rddm-prealloc;
|
||||
qti,rddm-seg-len = <0x1000>;
|
||||
#address-cells = <0x2>;
|
||||
#size-cells = <0x2>;
|
||||
#if defined(__CNSS2__)
|
||||
memory-region = <0>,<&mhi_region1>;
|
||||
#else
|
||||
base-addr = <0x4CB00000>;
|
||||
m3-dump-addr = <0x4DF00000>;
|
||||
etr-addr = <0x4E000000>;
|
||||
qcom,caldb-addr = <0x4E100000>;
|
||||
pageable-addr = <0x4E900000>;
|
||||
qcom,tgt-mem-mode = <0x1>;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
&wifi0 {
|
||||
/* IPQ5018 */
|
||||
qcom,multipd_arch;
|
||||
qcom,rproc = <&q6_wcss_pd1>;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd1";
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
qcom,board_id = <0x24>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,bdf-addr = <0x4C400000 0x4C400000 0x4C400000 0x0 0x0>;
|
||||
qcom,caldb-addr = <0x4D400000 0x4D400000 0 0 0>;
|
||||
qcom,caldb-size = <0x200000>;
|
||||
mem-region = <&q6_ipq5018_data>;
|
||||
#else
|
||||
memory-region = <&q6_ipq5018_data>;
|
||||
#endif
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&wifi3 {
|
||||
/* QCN9000 5G */
|
||||
board_id = <0xa0>;
|
||||
hremote_node = <&qcn9000_pcie0>;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
/* QCN9000 tgt-mem-mode=2 layout - 17MB
|
||||
* +=========+==============+=========+
|
||||
* | Region | Start Offset | Size |
|
||||
* +---------+--------------+---------+
|
||||
* | HREMOTE | 0x4C900000 | 11MB |
|
||||
* +---------+--------------+---------+
|
||||
* | M3 Dump | 0x4D400000 | 1MB |
|
||||
* +---------+--------------+---------+
|
||||
* | ETR | 0x4D500000 | 1MB |
|
||||
* +---------+--------------+---------+
|
||||
* | Pageable| 0x4D600000 | 4MB |
|
||||
* +==================================+
|
||||
*/
|
||||
base-addr = <0x4C900000>;
|
||||
m3-dump-addr = <0x4D400000>;
|
||||
etr-addr = <0x4D500000>;
|
||||
caldb-addr = <0>;
|
||||
pageable-addr = <0x4D600000>;
|
||||
caldb-size = <0>;
|
||||
hremote-size = <0xB00000>;
|
||||
tgt-mem-mode = <0x2>;
|
||||
pageable-size = <0x400000>;
|
||||
#elif __IPQ_MEM_PROFILE_512_MB__
|
||||
/* QCN9000 tgt-mem-mode=1 layout - 26MB
|
||||
* +=========+==============+=========+
|
||||
* | Region | Start Offset | Size |
|
||||
* +---------+--------------+---------+
|
||||
* | HREMOTE | 0x4CB00000 | 12MB |
|
||||
* +---------+--------------+---------+
|
||||
* | M3 Dump | 0x4D700000 | 1MB |
|
||||
* +---------+--------------+---------+
|
||||
* | ETR | 0x4D800000 | 1MB |
|
||||
* +---------+--------------+---------+
|
||||
* | Caldb | 0x4D900000 | 8MB |
|
||||
* +---------+--------------+---------+
|
||||
* | Pageable| 0x4E100000 | 4MB |
|
||||
* +==================================+
|
||||
*/
|
||||
base-addr = <0x4CB00000>;
|
||||
m3-dump-addr = <0x4D700000>;
|
||||
etr-addr = <0x4D800000>;
|
||||
caldb-addr = <0x4D900000>;
|
||||
pageable-addr = <0x4E100000>;
|
||||
caldb-size = <0x800000>;
|
||||
hremote-size = <0xC00000>;
|
||||
tgt-mem-mode = <0x1>;
|
||||
pageable-size = <0x400000>;
|
||||
#else
|
||||
/* QCN9000 tgt-mem-mode=0 layout - 53MB
|
||||
* +=========+==============+=========+
|
||||
* | Region | Start Offset | Size |
|
||||
* +---------+--------------+---------+
|
||||
* | HREMOTE | 0x4CB00000 | 35MB |
|
||||
* +---------+--------------+---------+
|
||||
* | M3 Dump | 0x4EE00000 | 1MB |
|
||||
* +---------+--------------+---------+
|
||||
* | ETR | 0x4EF00000 | 1MB |
|
||||
* +---------+--------------+---------+
|
||||
* | Caldb | 0x4F000000 | 8MB |
|
||||
* +---------+--------------+---------+
|
||||
* | Pageable| 0x4F800000 | 8MB |
|
||||
* +==================================+
|
||||
*/
|
||||
base-addr = <0x4CB00000>;
|
||||
m3-dump-addr = <0x4EE00000>;
|
||||
etr-addr = <0x4EF00000>;
|
||||
caldb-addr = <0x4F000000>;
|
||||
pageable-addr = <0x4F800000>;
|
||||
hremote-size = <0x2300000>;
|
||||
caldb-size = <0x800000>;
|
||||
tgt-mem-mode = <0x0>;
|
||||
pageable-size = <0x800000>;
|
||||
#endif
|
||||
status = "ok";
|
||||
};
|
||||
@@ -1,941 +0,0 @@
|
||||
/dts-v1/;
|
||||
/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ipq5018.dtsi"
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
/ {
|
||||
#address-cells = <0x2>;
|
||||
#size-cells = <0x2>;
|
||||
model = "Indio UM-525AXM";
|
||||
compatible = "indio,um-525axm", "qcom,ipq5018-mp03.5-c1", "qcom,ipq5018";
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
aliases {
|
||||
sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
|
||||
serial0 = &blsp1_uart1;
|
||||
serial1 = &blsp1_uart2;
|
||||
ethernet0 = "/soc/dp1";
|
||||
ethernet1 = "/soc/dp2";
|
||||
//led-failsafe = &led_red;
|
||||
//led-running = &led_green;
|
||||
//led-upgrade = &led_green;
|
||||
//led-gateway = &led_blue;
|
||||
//led-factory = &led_blue;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyMSM0,115200,n8 rw init=/init";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
bootargs-append = " swiotlb=1";
|
||||
#else
|
||||
bootargs-append = " swiotlb=1 coherent_pool=2M";
|
||||
#endif
|
||||
stdout-path = "serial0";
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
/* 256 MB Profile
|
||||
* +==========+==============+=========================+
|
||||
* | | | |
|
||||
* | Region | Start Offset | Size |
|
||||
* | | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | NSS | 0x40000000 | 8MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Linux | 0x40800000 | Depends on total memory |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | uboot | 0x4A600000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | SBL | 0x4AA00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | smem | 0x4AB00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | TZ | 0x4AC00000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Q6 | | |
|
||||
* | code/ | 0x4B000000 | 20MB |
|
||||
* | data | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | data | 0x4C400000 | 13MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | M3 Dump | 0x4D100000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | QDSS | 0x4D200000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | data | 0x4D300000 | 15MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | M3 Dump | 0x4E200000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | QDSS | 0x4E300000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | data | 0x4E400000 | 15MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | M3 Dump | 0x4F300000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | QDSS | 0x4F400000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | |
|
||||
* | Rest of the memory for Linux |
|
||||
* | |
|
||||
* +===================================================+
|
||||
*/
|
||||
q6_mem_regions: q6_mem_regions@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x4500000>;
|
||||
};
|
||||
|
||||
q6_code_data: q6_code_data@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x1400000>;
|
||||
};
|
||||
|
||||
q6_ipq5018_data: q6_ipq5018_data@4C400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4C400000 0x0 0xD00000>;
|
||||
};
|
||||
|
||||
m3_dump: m3_dump@4D100000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D100000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_etr_region: q6_etr_dump@4D200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data1: q6_qcn6122_data1@4D300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D300000 0x0 0xF00000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data2: q6_qcn6122_data2@4E400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E400000 0x0 0xF00000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_2: m3_dump_qcn6122_2@4F300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4F300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_2: q6_qcn6122_etr_2@4F400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4F400000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
#else
|
||||
/* 512MB/1GB Profiles
|
||||
* +==========+==============+=========================+
|
||||
* | | | |
|
||||
* | Region | Start Offset | Size |
|
||||
* | | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | NSS | 0x40000000 | 16MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Linux | 0x41000000 | Depends on total memory |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | uboot | 0x4A600000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | SBL | 0x4AA00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | smem | 0x4AB00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | TZ | 0x4AC00000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Q6 | | |
|
||||
* | code/ | 0x4B000000 | 20MB |
|
||||
* | data | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | data | 0x4C400000 | 14MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | M3 Dump | 0x4D200000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | QDSS | 0x4D300000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | Caldb | 0x4D400000 | 2MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | data | 0x4D600000 | 16MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | M3 Dump | 0x4E600000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | QDSS | 0x4E700000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | Caldb | 0x4E800000 | 5MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | data | 0x4ED00000 | 16MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | M3 Dump | 0x4FD00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | QDSS | 0x4FE00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | Caldb | 0x4FF00000 | 5MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | |
|
||||
* | Rest of the memory for Linux |
|
||||
* | |
|
||||
* +===================================================+
|
||||
*/
|
||||
q6_mem_regions: q6_mem_regions@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x5400000>;
|
||||
};
|
||||
|
||||
q6_code_data: q6_code_data@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 01400000>;
|
||||
};
|
||||
|
||||
q6_ipq5018_data: q6_ipq5018_data@4C400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4C400000 0x0 0xE00000>;
|
||||
};
|
||||
|
||||
m3_dump: m3_dump@4D200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_etr_region: q6_etr_dump@4D300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_caldb_region: q6_caldb_region@4D400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D400000 0x0 0x200000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data1: q6_qcn6122_data1@4D600000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D600000 0x0 0x1000000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E600000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E600000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E700000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E700000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_caldb_1: q6_qcn6122_caldb_1@4E800000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E800000 0x0 0x500000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data2: q6_qcn6122_data2@4E900000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4ED00000 0x0 0x1000000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_2: m3_dump_qcn6122_2@4FD00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4FD00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_2: q6_qcn6122_etr_2@4FE00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4FE00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_caldb_2: q6_qcn6122_caldb_2@4FF00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4FF00000 0x0 0x500000>;
|
||||
};
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
soc {
|
||||
gpio-watchdog {
|
||||
compatible = "linux,wdt-gpio";
|
||||
gpios = <&tlmm 27 GPIO_ACTIVE_LOW>;
|
||||
hw_algo = "toggle";
|
||||
hw_margin_ms = <5000>;
|
||||
always-running;
|
||||
};
|
||||
|
||||
serial@78af000 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
blsp1_uart2: serial@78b0000 {
|
||||
pinctrl-0 = <&blsp1_uart_pins>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
qpic_bam: dma@7984000{
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
nand: qpic-nand@79b0000 {
|
||||
pinctrl-0 = <&qspi_nand_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
spi_0: spi@78b5000 { /* BLSP1 QUP0 */
|
||||
pinctrl-0 = <&blsp0_spi_pins>;
|
||||
pinctrl-names = "default";
|
||||
cs-select = <0>;
|
||||
status = "ok";
|
||||
|
||||
m25p80@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0>;
|
||||
compatible = "n25q128a11";
|
||||
linux,modalias = "m25p80", "n25q128a11";
|
||||
spi-max-frequency = <50000000>;
|
||||
use-default-sizes;
|
||||
};
|
||||
};
|
||||
|
||||
mdio0: mdio@88000 {
|
||||
status = "ok";
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <7>;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1: mdio@90000 {
|
||||
status = "ok";
|
||||
pinctrl-0 = <&mdio1_pins>;
|
||||
pinctrl-names = "default";
|
||||
phy-reset-gpio = <&tlmm 39 0>;
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <28>;
|
||||
};
|
||||
};
|
||||
|
||||
ess-instance {
|
||||
num_devices = <0x1>;
|
||||
ess-switch@0x39c00000 {
|
||||
switch_mac_mode = <0xf>; /* mac mode for uniphy instance*/
|
||||
cmnblk_clk = "internal_96MHz"; /* cmnblk clk*/
|
||||
qcom,port_phyinfo {
|
||||
port@0 {
|
||||
port_id = <1>;
|
||||
phy_address = <7>;
|
||||
mdiobus = <&mdio0>;
|
||||
};
|
||||
port@1 {
|
||||
port_id = <2>;
|
||||
phy_address = <0x1c>;
|
||||
mdiobus = <&mdio1>;
|
||||
port_mac_sel = "QGMAC_PORT";
|
||||
};
|
||||
};
|
||||
led_source@0 {
|
||||
source = <0>;
|
||||
mode = "normal";
|
||||
speed = "all";
|
||||
blink_en = "enable";
|
||||
active = "high";
|
||||
};
|
||||
};
|
||||
ess-switch1@1 {
|
||||
compatible = "qcom,ess-switch-qca83xx";
|
||||
device_id = <1>;
|
||||
switch_access_mode = "mdio";
|
||||
mdio-bus = <&mdio1>;
|
||||
reset_gpio = <0x28>;
|
||||
switch_cpu_bmp = <0x40>; /* cpu port bitmap */
|
||||
switch_lan_bmp = <0x1e>; /* lan port bitmap */
|
||||
switch_wan_bmp = <0x0>; /* wan port bitmap */
|
||||
qca,ar8327-initvals = <
|
||||
0x00004 0x7600000 /* PAD0_MODE */
|
||||
0x00008 0x1000000 /* PAD5_MODE */
|
||||
0x0000c 0x80 /* PAD6_MODE */
|
||||
0x00010 0x2613a0 /* PORT6 FORCE MODE*/
|
||||
0x000e4 0xaa545 /* MAC_POWER_SEL */
|
||||
0x000e0 0xc74164de /* SGMII_CTRL */
|
||||
0x0007c 0x4e /* PORT0_STATUS */
|
||||
0x00094 0x4e /* PORT6_STATUS */
|
||||
>;
|
||||
qcom,port_phyinfo {
|
||||
port@0 {
|
||||
port_id = <1>;
|
||||
phy_address = <28>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dp1 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
qcom,id = <1>;
|
||||
reg = <0x39C00000 0x10000>;
|
||||
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
|
||||
qcom,mactype = <2>;
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <7>;
|
||||
mdio-bus = <&mdio0>;
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
dp2 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
qcom,id = <2>;
|
||||
reg = <0x39D00000 0x10000>;
|
||||
interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
|
||||
qcom,mactype = <2>;
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <28>;
|
||||
mdio-bus = <&mdio1>;
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
qcom,test@0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
nss-macsec1 {
|
||||
compatible = "qcom,nss-macsec";
|
||||
phy_addr = <0x1c>;
|
||||
mdiobus = <&mdio1>;
|
||||
};
|
||||
|
||||
lpass: lpass@0xA000000{
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcm: pcm@0xA3C0000{
|
||||
pinctrl-0 = <&audio_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcm_lb: pcm_lb@0 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
pinctrl-0 = <&blsp0_uart_pins &phy_led_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
blsp0_uart_pins: uart_pins {
|
||||
blsp0_uart_rx_tx {
|
||||
pins = "gpio20", "gpio21";
|
||||
function = "blsp0_uart0";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
blsp1_uart_pins: blsp1_uart_pins {
|
||||
blsp1_uart_rx_tx {
|
||||
pins = "gpio22", "gpio24", "gpio23", "gpio25";
|
||||
function = "blsp1_uart2";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
blsp0_spi_pins: blsp0_spi_pins {
|
||||
mux {
|
||||
pins = "gpio10", "gpio11", "gpio12", "gpio13";
|
||||
function = "blsp0_spi";
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
qspi_nand_pins: qspi_nand_pins {
|
||||
qspi_clock {
|
||||
pins = "gpio9";
|
||||
function = "qspi_clk";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_cs {
|
||||
pins = "gpio8";
|
||||
function = "qspi_cs";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_0 {
|
||||
pins = "gpio7";
|
||||
function = "qspi0";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_1 {
|
||||
pins = "gpio6";
|
||||
function = "qspi1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_2 {
|
||||
pins = "gpio5";
|
||||
function = "qspi2";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_3 {
|
||||
pins = "gpio4";
|
||||
function = "qspi3";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1_pins: mdio_pinmux {
|
||||
mux_0 {
|
||||
pins = "gpio36";
|
||||
function = "mdc";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
mux_1 {
|
||||
pins = "gpio37";
|
||||
function = "mdio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
phy_led_pins: phy_led_pins {
|
||||
gephy_led_pin {
|
||||
pins = "gpio46";
|
||||
function = "led0";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
i2c_pins: i2c_pins {
|
||||
i2c_scl {
|
||||
pins = "gpio25";
|
||||
function = "blsp2_i2c1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
i2c_sda {
|
||||
pins = "gpio26";
|
||||
function = "blsp2_i2c1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
button_pins: button_pins {
|
||||
reset_button {
|
||||
pins = "gpio38";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
audio_pins: audio_pinmux {
|
||||
};
|
||||
leds_pins: leds_pins {
|
||||
led_5g {
|
||||
pins = "gpio34";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
led_2g {
|
||||
pins = "gpio33";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
led_sys {
|
||||
pins = "gpio26";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
led_onekey {
|
||||
pins = "gpio28";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&soc {
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
pinctrl-0 = <&button_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
button@1 {
|
||||
label = "reset";
|
||||
linux,code = <KEY_RESTART>;
|
||||
gpios = <&tlmm 38 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
pinctrl-0 = <&leds_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
led_blue: led@34 {
|
||||
label = "led_5g";
|
||||
gpios = <&tlmm 34 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_5g";
|
||||
default-state = "off";
|
||||
};
|
||||
led_green: led@33 {
|
||||
label = "led_2g";
|
||||
gpios = <&tlmm 33 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_2g";
|
||||
default-state = "off";
|
||||
};
|
||||
led_red: led@26 {
|
||||
label = "led_sys";
|
||||
gpios = <&tlmm 26 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_sys";
|
||||
default-state = "off";
|
||||
};
|
||||
led@28 {
|
||||
label = "led_onekey";
|
||||
gpios = <&tlmm 28 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_onekey";
|
||||
default-state = "off";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&q6v5_wcss {
|
||||
compatible = "qcom,ipq5018-q6-mpd";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
reg = <0x0cd00000 0x4040>,
|
||||
<0x1938000 0x8>,
|
||||
<0x193d204 0x4>;
|
||||
reg-names = "qdsp6",
|
||||
"tcsr-msip",
|
||||
"tcsr-q6";
|
||||
resets = <&gcc GCC_WCSSAON_RESET>,
|
||||
<&gcc GCC_WCSS_Q6_BCR>;
|
||||
|
||||
reset-names = "wcss_aon_reset",
|
||||
"wcss_q6_reset";
|
||||
|
||||
clocks = <&gcc GCC_Q6_AXIS_CLK>,
|
||||
<&gcc GCC_WCSS_ECAHB_CLK>,
|
||||
<&gcc GCC_Q6_AXIM_CLK>,
|
||||
<&gcc GCC_Q6_AXIM2_CLK>,
|
||||
<&gcc GCC_Q6_AHB_CLK>,
|
||||
<&gcc GCC_Q6_AHB_S_CLK>,
|
||||
<&gcc GCC_WCSS_AXI_S_CLK>;
|
||||
clock-names = "gcc_q6_axis_clk",
|
||||
"gcc_wcss_ecahb_clk",
|
||||
"gcc_q6_axim_clk",
|
||||
"gcc_q6_axim2_clk",
|
||||
"gcc_q6_ahb_clk",
|
||||
"gcc_q6_ahb_s_clk",
|
||||
"gcc_wcss_axi_s_clk";
|
||||
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_mem_regions>, <&q6_etr_region>;
|
||||
#else
|
||||
memory-region = <&q6_mem_regions>, <&q6_etr_region>,
|
||||
<&q6_caldb_region>;
|
||||
#endif
|
||||
|
||||
qcom,rproc = <&q6v5_wcss>;
|
||||
qcom,bootargs_smem = <507>;
|
||||
boot-args = <0x1 0x4 0x3 0x0F 0x0 0x0>,
|
||||
<0x2 0x4 0x2 0x12 0x0 0x0>;
|
||||
status = "ok";
|
||||
q6_wcss_pd1: remoteproc_pd1@4ab000 {
|
||||
compatible = "qcom,ipq5018-wcss-ahb-mpd";
|
||||
reg = <0x4ab000 0x20>;
|
||||
reg-names = "rmb";
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
m3_firmware = "IPQ5018/m3_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 8 0>,
|
||||
<&wcss_smp2p_in 9 0>,
|
||||
<&wcss_smp2p_in 12 0>,
|
||||
<&wcss_smp2p_in 11 0>;
|
||||
interrupt-names = "fatal",
|
||||
"ready",
|
||||
"spawn-ack",
|
||||
"stop-ack";
|
||||
|
||||
resets = <&gcc GCC_WCSSAON_RESET>,
|
||||
<&gcc GCC_WCSS_BCR>,
|
||||
<&gcc GCC_CE_BCR>;
|
||||
reset-names = "wcss_aon_reset",
|
||||
"wcss_reset",
|
||||
"ce_reset";
|
||||
|
||||
clocks = <&gcc GCC_WCSS_AHB_S_CLK>,
|
||||
<&gcc GCC_WCSS_ACMT_CLK>,
|
||||
<&gcc GCC_WCSS_AXI_M_CLK>;
|
||||
clock-names = "gcc_wcss_ahb_s_clk",
|
||||
"gcc_wcss_acmt_clk",
|
||||
"gcc_wcss_axi_m_clk";
|
||||
|
||||
qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>;
|
||||
|
||||
qcom,smem-states = <&wcss_smp2p_out 8>,
|
||||
<&wcss_smp2p_out 9>,
|
||||
<&wcss_smp2p_out 10>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_ipq5018_data>, <&m3_dump>,
|
||||
<&q6_etr_region>;
|
||||
#else
|
||||
memory-region = <&q6_ipq5018_data>, <&m3_dump>,
|
||||
<&q6_etr_region>, <&q6_caldb_region>;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
q6_wcss_pd2: remoteproc_pd2 {
|
||||
compatible = "qcom,ipq5018-wcss-pcie-mpd";
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
m3_firmware = "qcn6122/m3_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 16 0>,
|
||||
<&wcss_smp2p_in 17 0>,
|
||||
<&wcss_smp2p_in 20 0>,
|
||||
<&wcss_smp2p_in 19 0>;
|
||||
interrupt-names = "fatal",
|
||||
"ready",
|
||||
"spawn-ack",
|
||||
"stop-ack";
|
||||
|
||||
qcom,smem-states = <&wcss_smp2p_out 16>,
|
||||
<&wcss_smp2p_out 17>,
|
||||
<&wcss_smp2p_out 18>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>,
|
||||
<&q6_qcn6122_etr_1>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>,
|
||||
<&q6_qcn6122_etr_1>, <&q6_qcn6122_caldb_1>;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
q6_wcss_pd3: remoteproc_pd3 {
|
||||
compatible = "qcom,ipq5018-wcss-pcie-mpd";
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 24 0>,
|
||||
<&wcss_smp2p_in 25 0>,
|
||||
<&wcss_smp2p_in 28 0>,
|
||||
<&wcss_smp2p_in 27 0>;
|
||||
interrupt-names = "fatal",
|
||||
"ready",
|
||||
"spawn-ack",
|
||||
"stop-ack";
|
||||
|
||||
qcom,smem-states = <&wcss_smp2p_out 24>,
|
||||
<&wcss_smp2p_out 25>,
|
||||
<&wcss_smp2p_out 26>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>,
|
||||
<&q6_qcn6122_etr_2>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>,
|
||||
<&q6_qcn6122_etr_2>, <&q6_qcn6122_caldb_2>;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_0 {
|
||||
pinctrl-0 = <&i2c_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&wifi0 {
|
||||
/* IPQ5018 */
|
||||
qcom,multipd_arch;
|
||||
qcom,rproc = <&q6_wcss_pd1>;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd1";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0x24>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,bdf-addr = <0x4C400000 0x4C400000 0x4C400000 0x0 0x0>;
|
||||
qcom,caldb-addr = <0x4D400000 0x4D400000 0 0 0>;
|
||||
qcom,caldb-size = <0x200000>;
|
||||
mem-region = <&q6_ipq5018_data>;
|
||||
#else
|
||||
memory-region = <&q6_ipq5018_data>;
|
||||
#endif
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&wifi1 {
|
||||
/* QCN6122 5G */
|
||||
qcom,multipd_arch;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd2";
|
||||
qcom,rproc = <&q6_wcss_pd2>;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0x50>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,bdf-addr = <0x4D600000 0x4D600000 0x4D300000 0x0 0x0>;
|
||||
qcom,caldb-addr = <0x4E800000 0x4E800000 0 0 0>;
|
||||
qcom,caldb-size = <0x500000>;
|
||||
mem-region = <&q6_qcn6122_data1>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data1>;
|
||||
#endif
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&wifi2 {
|
||||
/* QCN6122 6G */
|
||||
qcom,multipd_arch;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd3";
|
||||
qcom,rproc = <&q6_wcss_pd3>;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0xb0>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,bdf-addr = <0x4ED00000 0x4ED00000 0x4E400000 0x0 0x0>;
|
||||
qcom,caldb-addr = <0x4FF00000 0x4FF00000 0 0 0>;
|
||||
qcom,caldb-size = <0x500000>;
|
||||
mem-region = <&q6_qcn6122_data2>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data2>;
|
||||
#endif
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
|
||||
&usb3 {
|
||||
status = "ok";
|
||||
device-power-gpio = <&tlmm 24 1>;
|
||||
};
|
||||
|
||||
&dwc_0 {
|
||||
/delete-property/ #phy-cells;
|
||||
/delete-property/ phys;
|
||||
/delete-property/ phy-names;
|
||||
};
|
||||
&hs_m31phy_0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&eud {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&pcie_x1 {
|
||||
#status = "disabled";
|
||||
#perst-gpio = <&tlmm 18 1>;
|
||||
perst-gpio = <&tlmm 18 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
&pcie_x2 {
|
||||
#status = "disabled";
|
||||
#perst-gpio = <&tlmm 15 1>;
|
||||
perst-gpio = <&tlmm 15 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
&pcie_x1_rp {
|
||||
status = "disabled";
|
||||
|
||||
mhi_0: qcom,mhi@0 {
|
||||
reg = <0 0 0 0 0 >;
|
||||
};
|
||||
};
|
||||
|
||||
&pcie_x2_rp {
|
||||
status = "disabled";
|
||||
|
||||
mhi_1: qcom,mhi@1 {
|
||||
reg = <0 0 0 0 0 >;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,941 +0,0 @@
|
||||
/dts-v1/;
|
||||
/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ipq5018.dtsi"
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
/ {
|
||||
#address-cells = <0x2>;
|
||||
#size-cells = <0x2>;
|
||||
model = "Indio UM-525AXP";
|
||||
compatible = "indio,um-525axp", "qcom,ipq5018-mp03.5-c1", "qcom,ipq5018";
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
aliases {
|
||||
sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
|
||||
serial0 = &blsp1_uart1;
|
||||
serial1 = &blsp1_uart2;
|
||||
ethernet0 = "/soc/dp1";
|
||||
ethernet1 = "/soc/dp2";
|
||||
//led-failsafe = &led_red;
|
||||
//led-running = &led_green;
|
||||
//led-upgrade = &led_green;
|
||||
//led-gateway = &led_blue;
|
||||
//led-factory = &led_blue;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyMSM0,115200,n8 rw init=/init";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
bootargs-append = " swiotlb=1";
|
||||
#else
|
||||
bootargs-append = " swiotlb=1 coherent_pool=2M";
|
||||
#endif
|
||||
stdout-path = "serial0";
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
/* 256 MB Profile
|
||||
* +==========+==============+=========================+
|
||||
* | | | |
|
||||
* | Region | Start Offset | Size |
|
||||
* | | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | NSS | 0x40000000 | 8MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Linux | 0x40800000 | Depends on total memory |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | uboot | 0x4A600000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | SBL | 0x4AA00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | smem | 0x4AB00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | TZ | 0x4AC00000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Q6 | | |
|
||||
* | code/ | 0x4B000000 | 20MB |
|
||||
* | data | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | data | 0x4C400000 | 13MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | M3 Dump | 0x4D100000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | QDSS | 0x4D200000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | data | 0x4D300000 | 15MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | M3 Dump | 0x4E200000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | QDSS | 0x4E300000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | data | 0x4E400000 | 15MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | M3 Dump | 0x4F300000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | QDSS | 0x4F400000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | |
|
||||
* | Rest of the memory for Linux |
|
||||
* | |
|
||||
* +===================================================+
|
||||
*/
|
||||
q6_mem_regions: q6_mem_regions@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x4500000>;
|
||||
};
|
||||
|
||||
q6_code_data: q6_code_data@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x1400000>;
|
||||
};
|
||||
|
||||
q6_ipq5018_data: q6_ipq5018_data@4C400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4C400000 0x0 0xD00000>;
|
||||
};
|
||||
|
||||
m3_dump: m3_dump@4D100000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D100000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_etr_region: q6_etr_dump@4D200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data1: q6_qcn6122_data1@4D300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D300000 0x0 0xF00000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data2: q6_qcn6122_data2@4E400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E400000 0x0 0xF00000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_2: m3_dump_qcn6122_2@4F300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4F300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_2: q6_qcn6122_etr_2@4F400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4F400000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
#else
|
||||
/* 512MB/1GB Profiles
|
||||
* +==========+==============+=========================+
|
||||
* | | | |
|
||||
* | Region | Start Offset | Size |
|
||||
* | | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | NSS | 0x40000000 | 16MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Linux | 0x41000000 | Depends on total memory |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | uboot | 0x4A600000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | SBL | 0x4AA00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | smem | 0x4AB00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | TZ | 0x4AC00000 | 4MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | Q6 | | |
|
||||
* | code/ | 0x4B000000 | 20MB |
|
||||
* | data | | |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | data | 0x4C400000 | 14MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | M3 Dump | 0x4D200000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | QDSS | 0x4D300000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | IPQ5018 | | |
|
||||
* | Caldb | 0x4D400000 | 2MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | data | 0x4D600000 | 16MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | M3 Dump | 0x4E600000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | QDSS | 0x4E700000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_1| | |
|
||||
* | Caldb | 0x4E800000 | 5MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | data | 0x4ED00000 | 16MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | M3 Dump | 0x4FD00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | QDSS | 0x4FE00000 | 1MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | QCN6122_2| | |
|
||||
* | Caldb | 0x4FF00000 | 5MB |
|
||||
* +----------+--------------+-------------------------+
|
||||
* | |
|
||||
* | Rest of the memory for Linux |
|
||||
* | |
|
||||
* +===================================================+
|
||||
*/
|
||||
q6_mem_regions: q6_mem_regions@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x5400000>;
|
||||
};
|
||||
|
||||
q6_code_data: q6_code_data@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 01400000>;
|
||||
};
|
||||
|
||||
q6_ipq5018_data: q6_ipq5018_data@4C400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4C400000 0x0 0xE00000>;
|
||||
};
|
||||
|
||||
m3_dump: m3_dump@4D200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_etr_region: q6_etr_dump@4D300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_caldb_region: q6_caldb_region@4D400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D400000 0x0 0x200000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data1: q6_qcn6122_data1@4D600000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D600000 0x0 0x1000000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E600000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E600000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E700000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E700000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_caldb_1: q6_qcn6122_caldb_1@4E800000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E800000 0x0 0x500000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data2: q6_qcn6122_data2@4E900000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4ED00000 0x0 0x1000000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_2: m3_dump_qcn6122_2@4FD00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4FD00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_2: q6_qcn6122_etr_2@4FE00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4FE00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_caldb_2: q6_qcn6122_caldb_2@4FF00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4FF00000 0x0 0x500000>;
|
||||
};
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
soc {
|
||||
gpio-watchdog {
|
||||
compatible = "linux,wdt-gpio";
|
||||
gpios = <&tlmm 27 GPIO_ACTIVE_LOW>;
|
||||
hw_algo = "toggle";
|
||||
hw_margin_ms = <5000>;
|
||||
always-running;
|
||||
};
|
||||
|
||||
serial@78af000 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
blsp1_uart2: serial@78b0000 {
|
||||
pinctrl-0 = <&blsp1_uart_pins>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
qpic_bam: dma@7984000{
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
nand: qpic-nand@79b0000 {
|
||||
pinctrl-0 = <&qspi_nand_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
spi_0: spi@78b5000 { /* BLSP1 QUP0 */
|
||||
pinctrl-0 = <&blsp0_spi_pins>;
|
||||
pinctrl-names = "default";
|
||||
cs-select = <0>;
|
||||
status = "ok";
|
||||
|
||||
m25p80@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0>;
|
||||
compatible = "n25q128a11";
|
||||
linux,modalias = "m25p80", "n25q128a11";
|
||||
spi-max-frequency = <50000000>;
|
||||
use-default-sizes;
|
||||
};
|
||||
};
|
||||
|
||||
mdio0: mdio@88000 {
|
||||
status = "ok";
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <7>;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1: mdio@90000 {
|
||||
status = "ok";
|
||||
pinctrl-0 = <&mdio1_pins>;
|
||||
pinctrl-names = "default";
|
||||
phy-reset-gpio = <&tlmm 39 0>;
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <28>;
|
||||
};
|
||||
};
|
||||
|
||||
ess-instance {
|
||||
num_devices = <0x1>;
|
||||
ess-switch@0x39c00000 {
|
||||
switch_mac_mode = <0xf>; /* mac mode for uniphy instance*/
|
||||
cmnblk_clk = "internal_96MHz"; /* cmnblk clk*/
|
||||
qcom,port_phyinfo {
|
||||
port@0 {
|
||||
port_id = <1>;
|
||||
phy_address = <7>;
|
||||
mdiobus = <&mdio0>;
|
||||
};
|
||||
port@1 {
|
||||
port_id = <2>;
|
||||
phy_address = <0x1c>;
|
||||
mdiobus = <&mdio1>;
|
||||
port_mac_sel = "QGMAC_PORT";
|
||||
};
|
||||
};
|
||||
led_source@0 {
|
||||
source = <0>;
|
||||
mode = "normal";
|
||||
speed = "all";
|
||||
blink_en = "enable";
|
||||
active = "high";
|
||||
};
|
||||
};
|
||||
ess-switch1@1 {
|
||||
compatible = "qcom,ess-switch-qca83xx";
|
||||
device_id = <1>;
|
||||
switch_access_mode = "mdio";
|
||||
mdio-bus = <&mdio1>;
|
||||
reset_gpio = <0x28>;
|
||||
switch_cpu_bmp = <0x40>; /* cpu port bitmap */
|
||||
switch_lan_bmp = <0x1e>; /* lan port bitmap */
|
||||
switch_wan_bmp = <0x0>; /* wan port bitmap */
|
||||
qca,ar8327-initvals = <
|
||||
0x00004 0x7600000 /* PAD0_MODE */
|
||||
0x00008 0x1000000 /* PAD5_MODE */
|
||||
0x0000c 0x80 /* PAD6_MODE */
|
||||
0x00010 0x2613a0 /* PORT6 FORCE MODE*/
|
||||
0x000e4 0xaa545 /* MAC_POWER_SEL */
|
||||
0x000e0 0xc74164de /* SGMII_CTRL */
|
||||
0x0007c 0x4e /* PORT0_STATUS */
|
||||
0x00094 0x4e /* PORT6_STATUS */
|
||||
>;
|
||||
qcom,port_phyinfo {
|
||||
port@0 {
|
||||
port_id = <1>;
|
||||
phy_address = <28>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dp1 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
qcom,id = <1>;
|
||||
reg = <0x39C00000 0x10000>;
|
||||
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
|
||||
qcom,mactype = <2>;
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <7>;
|
||||
mdio-bus = <&mdio0>;
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
dp2 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
qcom,id = <2>;
|
||||
reg = <0x39D00000 0x10000>;
|
||||
interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
|
||||
qcom,mactype = <2>;
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <28>;
|
||||
mdio-bus = <&mdio1>;
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
qcom,test@0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
nss-macsec1 {
|
||||
compatible = "qcom,nss-macsec";
|
||||
phy_addr = <0x1c>;
|
||||
mdiobus = <&mdio1>;
|
||||
};
|
||||
|
||||
lpass: lpass@0xA000000{
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcm: pcm@0xA3C0000{
|
||||
pinctrl-0 = <&audio_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcm_lb: pcm_lb@0 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
pinctrl-0 = <&blsp0_uart_pins &phy_led_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
blsp0_uart_pins: uart_pins {
|
||||
blsp0_uart_rx_tx {
|
||||
pins = "gpio20", "gpio21";
|
||||
function = "blsp0_uart0";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
blsp1_uart_pins: blsp1_uart_pins {
|
||||
blsp1_uart_rx_tx {
|
||||
pins = "gpio22", "gpio24", "gpio23", "gpio25";
|
||||
function = "blsp1_uart2";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
blsp0_spi_pins: blsp0_spi_pins {
|
||||
mux {
|
||||
pins = "gpio10", "gpio11", "gpio12", "gpio13";
|
||||
function = "blsp0_spi";
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
qspi_nand_pins: qspi_nand_pins {
|
||||
qspi_clock {
|
||||
pins = "gpio9";
|
||||
function = "qspi_clk";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_cs {
|
||||
pins = "gpio8";
|
||||
function = "qspi_cs";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_0 {
|
||||
pins = "gpio7";
|
||||
function = "qspi0";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_1 {
|
||||
pins = "gpio6";
|
||||
function = "qspi1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_2 {
|
||||
pins = "gpio5";
|
||||
function = "qspi2";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_3 {
|
||||
pins = "gpio4";
|
||||
function = "qspi3";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1_pins: mdio_pinmux {
|
||||
mux_0 {
|
||||
pins = "gpio36";
|
||||
function = "mdc";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
mux_1 {
|
||||
pins = "gpio37";
|
||||
function = "mdio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
phy_led_pins: phy_led_pins {
|
||||
gephy_led_pin {
|
||||
pins = "gpio46";
|
||||
function = "led0";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
i2c_pins: i2c_pins {
|
||||
i2c_scl {
|
||||
pins = "gpio25";
|
||||
function = "blsp2_i2c1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
i2c_sda {
|
||||
pins = "gpio26";
|
||||
function = "blsp2_i2c1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
button_pins: button_pins {
|
||||
reset_button {
|
||||
pins = "gpio38";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
audio_pins: audio_pinmux {
|
||||
};
|
||||
leds_pins: leds_pins {
|
||||
led_5g {
|
||||
pins = "gpio34";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
led_2g {
|
||||
pins = "gpio33";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
led_sys {
|
||||
pins = "gpio26";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
led_onekey {
|
||||
pins = "gpio28";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&soc {
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
pinctrl-0 = <&button_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
button@1 {
|
||||
label = "reset";
|
||||
linux,code = <KEY_RESTART>;
|
||||
gpios = <&tlmm 38 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
pinctrl-0 = <&leds_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
led_blue: led@34 {
|
||||
label = "led_5g";
|
||||
gpios = <&tlmm 34 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_5g";
|
||||
default-state = "off";
|
||||
};
|
||||
led_green: led@33 {
|
||||
label = "led_2g";
|
||||
gpios = <&tlmm 33 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_2g";
|
||||
default-state = "off";
|
||||
};
|
||||
led_red: led@26 {
|
||||
label = "led_sys";
|
||||
gpios = <&tlmm 26 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_sys";
|
||||
default-state = "off";
|
||||
};
|
||||
led@28 {
|
||||
label = "led_onekey";
|
||||
gpios = <&tlmm 28 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "led_onekey";
|
||||
default-state = "off";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&q6v5_wcss {
|
||||
compatible = "qcom,ipq5018-q6-mpd";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
reg = <0x0cd00000 0x4040>,
|
||||
<0x1938000 0x8>,
|
||||
<0x193d204 0x4>;
|
||||
reg-names = "qdsp6",
|
||||
"tcsr-msip",
|
||||
"tcsr-q6";
|
||||
resets = <&gcc GCC_WCSSAON_RESET>,
|
||||
<&gcc GCC_WCSS_Q6_BCR>;
|
||||
|
||||
reset-names = "wcss_aon_reset",
|
||||
"wcss_q6_reset";
|
||||
|
||||
clocks = <&gcc GCC_Q6_AXIS_CLK>,
|
||||
<&gcc GCC_WCSS_ECAHB_CLK>,
|
||||
<&gcc GCC_Q6_AXIM_CLK>,
|
||||
<&gcc GCC_Q6_AXIM2_CLK>,
|
||||
<&gcc GCC_Q6_AHB_CLK>,
|
||||
<&gcc GCC_Q6_AHB_S_CLK>,
|
||||
<&gcc GCC_WCSS_AXI_S_CLK>;
|
||||
clock-names = "gcc_q6_axis_clk",
|
||||
"gcc_wcss_ecahb_clk",
|
||||
"gcc_q6_axim_clk",
|
||||
"gcc_q6_axim2_clk",
|
||||
"gcc_q6_ahb_clk",
|
||||
"gcc_q6_ahb_s_clk",
|
||||
"gcc_wcss_axi_s_clk";
|
||||
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_mem_regions>, <&q6_etr_region>;
|
||||
#else
|
||||
memory-region = <&q6_mem_regions>, <&q6_etr_region>,
|
||||
<&q6_caldb_region>;
|
||||
#endif
|
||||
|
||||
qcom,rproc = <&q6v5_wcss>;
|
||||
qcom,bootargs_smem = <507>;
|
||||
boot-args = <0x1 0x4 0x3 0x0F 0x0 0x0>,
|
||||
<0x2 0x4 0x2 0x12 0x0 0x0>;
|
||||
status = "ok";
|
||||
q6_wcss_pd1: remoteproc_pd1@4ab000 {
|
||||
compatible = "qcom,ipq5018-wcss-ahb-mpd";
|
||||
reg = <0x4ab000 0x20>;
|
||||
reg-names = "rmb";
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
m3_firmware = "IPQ5018/m3_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 8 0>,
|
||||
<&wcss_smp2p_in 9 0>,
|
||||
<&wcss_smp2p_in 12 0>,
|
||||
<&wcss_smp2p_in 11 0>;
|
||||
interrupt-names = "fatal",
|
||||
"ready",
|
||||
"spawn-ack",
|
||||
"stop-ack";
|
||||
|
||||
resets = <&gcc GCC_WCSSAON_RESET>,
|
||||
<&gcc GCC_WCSS_BCR>,
|
||||
<&gcc GCC_CE_BCR>;
|
||||
reset-names = "wcss_aon_reset",
|
||||
"wcss_reset",
|
||||
"ce_reset";
|
||||
|
||||
clocks = <&gcc GCC_WCSS_AHB_S_CLK>,
|
||||
<&gcc GCC_WCSS_ACMT_CLK>,
|
||||
<&gcc GCC_WCSS_AXI_M_CLK>;
|
||||
clock-names = "gcc_wcss_ahb_s_clk",
|
||||
"gcc_wcss_acmt_clk",
|
||||
"gcc_wcss_axi_m_clk";
|
||||
|
||||
qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>;
|
||||
|
||||
qcom,smem-states = <&wcss_smp2p_out 8>,
|
||||
<&wcss_smp2p_out 9>,
|
||||
<&wcss_smp2p_out 10>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_ipq5018_data>, <&m3_dump>,
|
||||
<&q6_etr_region>;
|
||||
#else
|
||||
memory-region = <&q6_ipq5018_data>, <&m3_dump>,
|
||||
<&q6_etr_region>, <&q6_caldb_region>;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
q6_wcss_pd2: remoteproc_pd2 {
|
||||
compatible = "qcom,ipq5018-wcss-pcie-mpd";
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
m3_firmware = "qcn6122/m3_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 16 0>,
|
||||
<&wcss_smp2p_in 17 0>,
|
||||
<&wcss_smp2p_in 20 0>,
|
||||
<&wcss_smp2p_in 19 0>;
|
||||
interrupt-names = "fatal",
|
||||
"ready",
|
||||
"spawn-ack",
|
||||
"stop-ack";
|
||||
|
||||
qcom,smem-states = <&wcss_smp2p_out 16>,
|
||||
<&wcss_smp2p_out 17>,
|
||||
<&wcss_smp2p_out 18>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>,
|
||||
<&q6_qcn6122_etr_1>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>,
|
||||
<&q6_qcn6122_etr_1>, <&q6_qcn6122_caldb_1>;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
q6_wcss_pd3: remoteproc_pd3 {
|
||||
compatible = "qcom,ipq5018-wcss-pcie-mpd";
|
||||
firmware = "IPQ5018/q6_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 24 0>,
|
||||
<&wcss_smp2p_in 25 0>,
|
||||
<&wcss_smp2p_in 28 0>,
|
||||
<&wcss_smp2p_in 27 0>;
|
||||
interrupt-names = "fatal",
|
||||
"ready",
|
||||
"spawn-ack",
|
||||
"stop-ack";
|
||||
|
||||
qcom,smem-states = <&wcss_smp2p_out 24>,
|
||||
<&wcss_smp2p_out 25>,
|
||||
<&wcss_smp2p_out 26>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>,
|
||||
<&q6_qcn6122_etr_2>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>,
|
||||
<&q6_qcn6122_etr_2>, <&q6_qcn6122_caldb_2>;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_0 {
|
||||
pinctrl-0 = <&i2c_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&wifi0 {
|
||||
/* IPQ5018 */
|
||||
qcom,multipd_arch;
|
||||
qcom,rproc = <&q6_wcss_pd1>;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd1";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0x24>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,bdf-addr = <0x4C400000 0x4C400000 0x4C400000 0x0 0x0>;
|
||||
qcom,caldb-addr = <0x4D400000 0x4D400000 0 0 0>;
|
||||
qcom,caldb-size = <0x200000>;
|
||||
mem-region = <&q6_ipq5018_data>;
|
||||
#else
|
||||
memory-region = <&q6_ipq5018_data>;
|
||||
#endif
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&wifi1 {
|
||||
/* QCN6122 5G */
|
||||
qcom,multipd_arch;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd2";
|
||||
qcom,rproc = <&q6_wcss_pd2>;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0x50>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,bdf-addr = <0x4D600000 0x4D600000 0x4D300000 0x0 0x0>;
|
||||
qcom,caldb-addr = <0x4E800000 0x4E800000 0 0 0>;
|
||||
qcom,caldb-size = <0x500000>;
|
||||
mem-region = <&q6_qcn6122_data1>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data1>;
|
||||
#endif
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&wifi2 {
|
||||
/* QCN6122 6G */
|
||||
qcom,multipd_arch;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd3";
|
||||
qcom,rproc = <&q6_wcss_pd3>;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0xb0>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,bdf-addr = <0x4ED00000 0x4ED00000 0x4E400000 0x0 0x0>;
|
||||
qcom,caldb-addr = <0x4FF00000 0x4FF00000 0 0 0>;
|
||||
qcom,caldb-size = <0x500000>;
|
||||
mem-region = <&q6_qcn6122_data2>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data2>;
|
||||
#endif
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
|
||||
&usb3 {
|
||||
status = "ok";
|
||||
device-power-gpio = <&tlmm 24 1>;
|
||||
};
|
||||
|
||||
&dwc_0 {
|
||||
/delete-property/ #phy-cells;
|
||||
/delete-property/ phys;
|
||||
/delete-property/ phy-names;
|
||||
};
|
||||
&hs_m31phy_0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&eud {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&pcie_x1 {
|
||||
#status = "disabled";
|
||||
#perst-gpio = <&tlmm 18 1>;
|
||||
perst-gpio = <&tlmm 18 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
&pcie_x2 {
|
||||
#status = "disabled";
|
||||
#perst-gpio = <&tlmm 15 1>;
|
||||
perst-gpio = <&tlmm 15 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
&pcie_x1_rp {
|
||||
status = "disabled";
|
||||
|
||||
mhi_0: qcom,mhi@0 {
|
||||
reg = <0 0 0 0 0 >;
|
||||
};
|
||||
};
|
||||
|
||||
&pcie_x2_rp {
|
||||
status = "disabled";
|
||||
|
||||
mhi_1: qcom,mhi@1 {
|
||||
reg = <0 0 0 0 0 >;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@@ -151,14 +151,6 @@
|
||||
no-map;
|
||||
reg = <0x0 0x4F000000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
ramoops: ramoops@4f100000 {
|
||||
compatible = "ramoops";
|
||||
reg = <0x0 0x4f100000 0x0 0x80000>;
|
||||
record-size = <0x20000>;
|
||||
console-size = <0x20000>;
|
||||
pmsg-size = <0x20000>;
|
||||
};
|
||||
#else
|
||||
/* 512MB/1GB Profiles
|
||||
* +==========+==============+=========================+
|
||||
@@ -293,13 +285,6 @@
|
||||
reg = <0x0 0x4F800000 0x0 0x500000>;
|
||||
};
|
||||
|
||||
ramoops: ramoops@4fd00000 {
|
||||
compatible = "ramoops";
|
||||
reg = <0x0 0x4fd00000 0x0 0x80000>;
|
||||
record-size = <0x20000>;
|
||||
console-size = <0x20000>;
|
||||
pmsg-size = <0x20000>;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -151,14 +151,6 @@
|
||||
no-map;
|
||||
reg = <0x0 0x4F000000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
ramoops: ramoops@4f100000 {
|
||||
compatible = "ramoops";
|
||||
reg = <0x0 0x4f100000 0x0 0x80000>;
|
||||
record-size = <0x20000>;
|
||||
console-size = <0x20000>;
|
||||
pmsg-size = <0x20000>;
|
||||
};
|
||||
#else
|
||||
/* 512MB/1GB Profiles
|
||||
* +==========+==============+=========================+
|
||||
@@ -293,13 +285,6 @@
|
||||
reg = <0x0 0x4F800000 0x0 0x500000>;
|
||||
};
|
||||
|
||||
ramoops: ramoops@4fd00000 {
|
||||
compatible = "ramoops";
|
||||
reg = <0x0 0x4fd00000 0x0 0x80000>;
|
||||
record-size = <0x20000>;
|
||||
console-size = <0x20000>;
|
||||
pmsg-size = <0x20000>;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -154,14 +154,6 @@
|
||||
no-map;
|
||||
reg = <0x0 0x4F000000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
ramoops: ramoops@4f100000 {
|
||||
compatible = "ramoops";
|
||||
reg = <0x0 0x4f100000 0x0 0x80000>;
|
||||
record-size = <0x20000>;
|
||||
console-size = <0x20000>;
|
||||
pmsg-size = <0x20000>;
|
||||
};
|
||||
#else
|
||||
/* 512MB/1GB Profiles
|
||||
* +==========+==============+=========================+
|
||||
@@ -296,13 +288,6 @@
|
||||
reg = <0x0 0x4F800000 0x0 0x500000>;
|
||||
};
|
||||
|
||||
ramoops: ramoops@4fd00000 {
|
||||
compatible = "ramoops";
|
||||
reg = <0x0 0x4fd00000 0x0 0x80000>;
|
||||
record-size = <0x20000>;
|
||||
console-size = <0x20000>;
|
||||
pmsg-size = <0x20000>;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -93,42 +93,6 @@ define Device/edgecore_eap104
|
||||
endef
|
||||
TARGET_DEVICES += edgecore_eap104
|
||||
|
||||
define Device/indio_um-325ax-v2
|
||||
DEVICE_TITLE := Indio UM-325ax-V2
|
||||
DEVICE_DTS := qcom-ipq5018-indio-um-325ax-v2
|
||||
SUPPORTED_DEVICES := indio,um-325ax-v2
|
||||
DEVICE_PACKAGES := ath11k-wifi-indio-um-325ax-v2 ath11k-firmware-ipq50xx-spruce ath11k-firmware-qcn6122
|
||||
DEVICE_DTS_CONFIG := config@mp03.5-c1
|
||||
endef
|
||||
TARGET_DEVICES += indio_um-325ax-v2
|
||||
|
||||
define Device/indio_um-335ax
|
||||
DEVICE_TITLE := Indio UM-335ax
|
||||
DEVICE_DTS := qcom-ipq5018-indio-um-335ax
|
||||
SUPPORTED_DEVICES := indio,um-335ax
|
||||
DEVICE_PACKAGES := ath11k-wifi-indio-um-335ax ath11k-firmware-qcn9000 ath11k-firmware-ipq50xx-spruce
|
||||
DEVICE_DTS_CONFIG := config@mp03.1
|
||||
endef
|
||||
TARGET_DEVICES += indio_um-335ax
|
||||
|
||||
define Device/indio_um-525axp
|
||||
DEVICE_TITLE := Indio UM-525axp
|
||||
DEVICE_DTS := qcom-ipq5018-indio-um-525axp
|
||||
SUPPORTED_DEVICES := indio,um-525axp
|
||||
DEVICE_PACKAGES := ath11k-wifi-indio-um-525axp ath11k-firmware-ipq50xx-spruce ath11k-firmware-qcn6122
|
||||
DEVICE_DTS_CONFIG := config@mp03.5-c1
|
||||
endef
|
||||
TARGET_DEVICES += indio_um-525axp
|
||||
|
||||
define Device/indio_um-525axm
|
||||
DEVICE_TITLE := Indio UM-525axm
|
||||
DEVICE_DTS := qcom-ipq5018-indio-um-525axm
|
||||
SUPPORTED_DEVICES := indio,um-525axm
|
||||
DEVICE_PACKAGES := ath11k-wifi-indio-um-525axm ath11k-firmware-ipq50xx-spruce ath11k-firmware-qcn6122
|
||||
DEVICE_DTS_CONFIG := config@mp03.5-c1
|
||||
endef
|
||||
TARGET_DEVICES += indio_um-525axm
|
||||
|
||||
define Device/udaya_a6_id2
|
||||
DEVICE_TITLE := Udaya A6 - ID2
|
||||
DEVICE_DTS := qcom-ipq5018-udaya-a6-id2
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
--- a/include/init/ssdk_plat.h
|
||||
+++ b/include/init/ssdk_plat.h
|
||||
@@ -330,6 +330,7 @@ struct qca_phy_priv {
|
||||
struct mii_bus *miibus;
|
||||
/*qca808x_end*/
|
||||
u64 *mib_counters;
|
||||
+ a_uint32_t mib_loop_cnt;
|
||||
/* dump buf */
|
||||
a_uint8_t buf[2048];
|
||||
a_uint32_t link_polling_required;
|
||||
--- a/src/ref/ref_mib.c
|
||||
+++ b/src/ref/ref_mib.c
|
||||
@@ -479,39 +479,37 @@ qca_ar8327_sw_get_port_mib(struct switch
|
||||
#endif
|
||||
|
||||
int
|
||||
-_qca_ar8327_sw_capture_port_tx_counter(struct qca_phy_priv *priv, int port)
|
||||
+_qca_ar8327_sw_capture_port_tx_counter(a_uint32_t dev_id, int port)
|
||||
{
|
||||
fal_mib_info_t mib_Info;
|
||||
|
||||
memset(&mib_Info, 0, sizeof(fal_mib_info_t));
|
||||
- fal_get_tx_mib_info(priv->device_id, port, &mib_Info);
|
||||
+ fal_get_tx_mib_info(dev_id, port, &mib_Info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
-_qca_ar8327_sw_capture_port_rx_counter(struct qca_phy_priv *priv, int port)
|
||||
+_qca_ar8327_sw_capture_port_rx_counter(a_uint32_t dev_id, int port)
|
||||
{
|
||||
fal_mib_info_t mib_Info;
|
||||
|
||||
memset(&mib_Info, 0, sizeof(fal_mib_info_t));
|
||||
- fal_get_rx_mib_info(priv->device_id, port, &mib_Info);
|
||||
+ fal_get_rx_mib_info(dev_id, port, &mib_Info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
qca_ar8327_sw_mib_task(struct qca_phy_priv *priv)
|
||||
{
|
||||
- static int loop = 0;
|
||||
-
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
- if ((loop % 2) == 0)
|
||||
- _qca_ar8327_sw_capture_port_rx_counter(priv, loop/2);
|
||||
+ if ((priv->mib_loop_cnt % 2) == 0)
|
||||
+ _qca_ar8327_sw_capture_port_rx_counter(priv->device_id, priv->mib_loop_cnt/2);
|
||||
else
|
||||
- _qca_ar8327_sw_capture_port_tx_counter(priv, loop/2);
|
||||
+ _qca_ar8327_sw_capture_port_tx_counter(priv->device_id, priv->mib_loop_cnt/2);
|
||||
|
||||
- if(++loop == (2 * (priv->ports))) {
|
||||
- loop = 0;
|
||||
+ if(++priv->mib_loop_cnt == (2 * (priv->ports))) {
|
||||
+ priv->mib_loop_cnt = 0;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
@@ -1,15 +1,15 @@
|
||||
From 5c8d90efe02c47ce76a6d5383ea6aa90eb0c73d8 Mon Sep 17 00:00:00 2001
|
||||
From 991886a6f8840802d611e0f75e79aa4ec5e68ccc Mon Sep 17 00:00:00 2001
|
||||
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
|
||||
Date: Mon, 20 Feb 2023 14:25:24 +0800
|
||||
Subject: [PATCH] mac80211: mtk: add sta-assisted DFS state update mechanism
|
||||
|
||||
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
|
||||
---
|
||||
include/net/cfg80211.h | 14 +++++++++
|
||||
include/uapi/linux/nl80211.h | 6 ++++
|
||||
net/mac80211/mlme.c | 11 +++++++
|
||||
net/wireless/chan.c | 60 ++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 91 insertions(+)
|
||||
include/net/cfg80211.h | 14 ++++++
|
||||
include/uapi/linux/nl80211.h | 6 +++
|
||||
net/mac80211/mlme.c | 11 +++++
|
||||
net/wireless/chan.c | 92 ++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 123 insertions(+)
|
||||
|
||||
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
|
||||
index 77276db..03f072f 100644
|
||||
@@ -97,7 +97,7 @@ index 8ee325a..2dbc18c 100644
|
||||
drv_event_callback(sdata->local, sdata, &event);
|
||||
sdata_info(sdata, "associated\n");
|
||||
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
|
||||
index c217276..9f651f9 100644
|
||||
index c217276..f48995c 100644
|
||||
--- a/net/wireless/chan.c
|
||||
+++ b/net/wireless/chan.c
|
||||
@@ -14,6 +14,7 @@
|
||||
@@ -108,7 +108,7 @@ index c217276..9f651f9 100644
|
||||
|
||||
static bool cfg80211_valid_60g_freq(u32 freq)
|
||||
{
|
||||
@@ -1393,3 +1394,62 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
|
||||
@@ -1393,3 +1394,94 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_any_usable_channels);
|
||||
@@ -133,26 +133,29 @@ index c217276..9f651f9 100644
|
||||
+ const struct cfg80211_chan_def *csa_chandef,
|
||||
+ bool associated)
|
||||
+{
|
||||
+ struct wiphy *wiphy = wdev->wiphy;
|
||||
+ bool csa_active = !!csa_chandef;
|
||||
+ enum nl80211_dfs_state dfs_state = NL80211_DFS_USABLE;
|
||||
+ enum nl80211_radar_event event = NL80211_RADAR_STA_CAC_EXPIRED;
|
||||
+
|
||||
+ ASSERT_WDEV_LOCK(wdev);
|
||||
+
|
||||
+ if (!bss_chandef)
|
||||
+ return;
|
||||
+
|
||||
+ /* assume csa channel is cac completed */
|
||||
+ if (csa_active &&
|
||||
+ (cfg80211_chandef_dfs_usable(wdev->wiphy, csa_chandef) ||
|
||||
+ cfg80211_chandef_dfs_available(wdev->wiphy, csa_chandef))) {
|
||||
+ cfg80211_set_dfs_state(wdev->wiphy, csa_chandef, NL80211_DFS_AVAILABLE);
|
||||
+ cfg80211_sta_radar_notify(wdev->wiphy, csa_chandef,
|
||||
+ (cfg80211_chandef_dfs_usable(wiphy, csa_chandef) ||
|
||||
+ cfg80211_chandef_dfs_available(wiphy, csa_chandef))) {
|
||||
+ cfg80211_set_dfs_state(wiphy, csa_chandef, NL80211_DFS_AVAILABLE);
|
||||
+ cfg80211_sta_radar_notify(wiphy, csa_chandef,
|
||||
+ NL80211_RADAR_STA_CAC_SKIPPED);
|
||||
+ netdev_info(wdev->netdev, "Set CSA channel's DFS state to available\n");
|
||||
+ }
|
||||
+
|
||||
+ /* avoid updating the dfs state during nop */
|
||||
+ if (!cfg80211_chandef_dfs_usable(wdev->wiphy, bss_chandef) &&
|
||||
+ !cfg80211_chandef_dfs_available(wdev->wiphy, bss_chandef))
|
||||
+ if (!cfg80211_chandef_dfs_usable(wiphy, bss_chandef) &&
|
||||
+ !cfg80211_chandef_dfs_available(wiphy, bss_chandef))
|
||||
+ return;
|
||||
+
|
||||
+ if (associated && !csa_active) {
|
||||
@@ -160,8 +163,37 @@ index c217276..9f651f9 100644
|
||||
+ event = NL80211_RADAR_STA_CAC_SKIPPED;
|
||||
+ }
|
||||
+
|
||||
+ cfg80211_set_dfs_state(wdev->wiphy, bss_chandef, dfs_state);
|
||||
+ cfg80211_sta_radar_notify(wdev->wiphy, bss_chandef, event);
|
||||
+ /* avoid setting the dfs state to usable
|
||||
+ * when other interfaces still operate on this channel
|
||||
+ */
|
||||
+ if (dfs_state == NL80211_DFS_USABLE) {
|
||||
+ struct wireless_dev *tmp_wdev;
|
||||
+
|
||||
+ if (cfg80211_offchan_chain_is_active(wiphy_to_rdev(wiphy),
|
||||
+ bss_chandef->chan))
|
||||
+ return;
|
||||
+
|
||||
+ list_for_each_entry(tmp_wdev, &wiphy->wdev_list, list) {
|
||||
+ /* avoid ABBA deadlock between two stations */
|
||||
+ if (tmp_wdev->iftype == NL80211_IFTYPE_STATION)
|
||||
+ continue;
|
||||
+
|
||||
+ wdev_lock(tmp_wdev);
|
||||
+ if (!cfg80211_beaconing_iface_active(tmp_wdev)) {
|
||||
+ wdev_unlock(tmp_wdev);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (cfg80211_is_sub_chan(&tmp_wdev->chandef, bss_chandef->chan)) {
|
||||
+ wdev_unlock(tmp_wdev);
|
||||
+ return;
|
||||
+ }
|
||||
+ wdev_unlock(tmp_wdev);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ cfg80211_set_dfs_state(wiphy, bss_chandef, dfs_state);
|
||||
+ cfg80211_sta_radar_notify(wiphy, bss_chandef, event);
|
||||
+
|
||||
+ if (csa_active)
|
||||
+ netdev_info(wdev->netdev, "Set origin channel's DFS state to usable\n");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
From bb918e40dcc7d082f898234cf29cd545de78621e Mon Sep 17 00:00:00 2001
|
||||
From 70526aabf704d778796dfbaa042fe48e03aa7d61 Mon Sep 17 00:00:00 2001
|
||||
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
|
||||
Date: Wed, 15 Nov 2023 15:05:17 +0800
|
||||
Subject: [PATCH] mac80211: mtk: add DFS CAC countdown in CSA flow
|
||||
@@ -10,11 +10,11 @@ Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
|
||||
net/mac80211/ieee80211_i.h | 2 +
|
||||
net/mac80211/iface.c | 2 +
|
||||
net/mac80211/mlme.c | 6 ++-
|
||||
net/mac80211/util.c | 11 ++++-
|
||||
net/mac80211/util.c | 16 +++++++-
|
||||
net/wireless/chan.c | 72 ++++++++++++++++++++++++++++++++
|
||||
net/wireless/nl80211.c | 5 ++-
|
||||
net/wireless/rdev-ops.h | 17 ++++++++
|
||||
9 files changed, 221 insertions(+), 10 deletions(-)
|
||||
9 files changed, 226 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
|
||||
index 03f072f..a443b0d 100644
|
||||
@@ -272,16 +272,21 @@ index 2dbc18c..ed81ebf 100644
|
||||
NL80211_RADAR_CAC_FINISHED,
|
||||
GFP_KERNEL);
|
||||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
|
||||
index 26cd627..e07fe73 100644
|
||||
index 26cd627..1e8420d 100644
|
||||
--- a/net/mac80211/util.c
|
||||
+++ b/net/mac80211/util.c
|
||||
@@ -3873,7 +3873,16 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
|
||||
@@ -3873,7 +3873,21 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
|
||||
|
||||
if (sdata->wdev.cac_started) {
|
||||
chandef = sdata->vif.bss_conf.chandef;
|
||||
- ieee80211_vif_release_channel(sdata);
|
||||
+ if (sdata->vif.csa_active) {
|
||||
+ sdata->vif.csa_active = false;
|
||||
+ if (sdata->csa_block_tx) {
|
||||
+ ieee80211_wake_vif_queues(local, sdata,
|
||||
+ IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
+ sdata->csa_block_tx = false;
|
||||
+ }
|
||||
+ if (sdata->u.ap.next_beacon) {
|
||||
+ kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
+ kfree(sdata->u.ap.next_beacon);
|
||||
@@ -294,7 +299,7 @@ index 26cd627..e07fe73 100644
|
||||
&chandef,
|
||||
NL80211_RADAR_CAC_ABORTED,
|
||||
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
|
||||
index 9f651f9..f02598b 100644
|
||||
index f48995c..c7bfa6b 100644
|
||||
--- a/net/wireless/chan.c
|
||||
+++ b/net/wireless/chan.c
|
||||
@@ -1262,6 +1262,78 @@ bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
From 08661908d4c2fb5f8d7ca00e0e7e6b33a6ae6e31 Mon Sep 17 00:00:00 2001
|
||||
From b43f0f6528bff00b4fbb25e0cbb9ac88577d1467 Mon Sep 17 00:00:00 2001
|
||||
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
|
||||
Date: Wed, 27 Dec 2023 14:26:22 +0800
|
||||
Subject: [PATCH] mac80211: mtk: send deauth frame if CAC is required during
|
||||
CSA
|
||||
|
||||
Avoid sending deauth in cert mode (11AC VHT4-2.16h-DFS).
|
||||
|
||||
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
|
||||
---
|
||||
net/mac80211/cfg.c | 27 +++++++++++++++++++++++++++
|
||||
1 file changed, 27 insertions(+)
|
||||
net/mac80211/cfg.c | 28 ++++++++++++++++++++++++++++
|
||||
1 file changed, 28 insertions(+)
|
||||
|
||||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
|
||||
index 3e6e903..eb73834 100644
|
||||
index 7a30ca6..2ee5b63 100644
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -3361,6 +3361,31 @@ static int ieee80211_start_radar_detection_post_csa(struct wiphy *wiphy,
|
||||
@@ -3361,6 +3361,32 @@ static int ieee80211_start_radar_detection_post_csa(struct wiphy *wiphy,
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -28,7 +30,8 @@ index 3e6e903..eb73834 100644
|
||||
+ &sdata->csa_chandef) &&
|
||||
+ !cfg80211_reg_can_beacon_relax(local->hw.wiphy,
|
||||
+ &sdata->csa_chandef,
|
||||
+ sdata->wdev.iftype);
|
||||
+ sdata->wdev.iftype) &&
|
||||
+ !ieee80211_is_cert_mode(&local->hw);
|
||||
+ /* broadcast deauth frame if CAC is required */
|
||||
+ if (!send_deauth)
|
||||
+ return;
|
||||
@@ -45,7 +48,7 @@ index 3e6e903..eb73834 100644
|
||||
static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
@@ -3371,6 +3396,8 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
|
||||
@@ -3371,6 +3397,8 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
|
||||
lockdep_assert_held(&local->mtx);
|
||||
lockdep_assert_held(&local->chanctx_mtx);
|
||||
|
||||
@@ -55,5 +58,5 @@ index 3e6e903..eb73834 100644
|
||||
* using reservation isn't immediate as it may be deferred until later
|
||||
* with multi-vif. once reservation is complete it will re-schedule the
|
||||
--
|
||||
2.18.0
|
||||
2.45.2
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
From 843e2b25433dc6c3cbc2ff4a754bef091cabe54b Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
|
||||
Date: Mon, 24 Jun 2024 17:50:08 +0800
|
||||
Subject: [PATCH] mac80211: mtk: add callback function to set QoS map in HW
|
||||
|
||||
The mapping from IP DSCP to IEEE 802.11 user priority may be customized.
|
||||
Therefore, the mapping needs to be passed to HW, so that the QoS type of traffic can be mapped in a consistent manner for both SW and HW paths.
|
||||
|
||||
Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
|
||||
---
|
||||
include/net/mac80211.h | 3 +++
|
||||
net/mac80211/cfg.c | 2 +-
|
||||
net/mac80211/driver-ops.h | 16 ++++++++++++++++
|
||||
net/mac80211/trace.h | 6 ++++++
|
||||
4 files changed, 26 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
|
||||
index 5c26752..b622c76 100644
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -3982,6 +3982,7 @@ struct ieee80211_prep_tx_info {
|
||||
* disable background CAC/radar detection.
|
||||
* @net_fill_forward_path: Called from .ndo_fill_forward_path in order to
|
||||
* resolve a path for hardware flow offloading
|
||||
+ * @set_qos_map: Set QoS mapping information to driver.
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
void (*tx)(struct ieee80211_hw *hw,
|
||||
@@ -4321,6 +4322,8 @@ struct ieee80211_ops {
|
||||
struct net_device_path_ctx *ctx,
|
||||
struct net_device_path *path);
|
||||
#endif
|
||||
+ int (*set_qos_map)(struct ieee80211_vif *vif,
|
||||
+ struct cfg80211_qos_map *qos_map);
|
||||
};
|
||||
|
||||
/**
|
||||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
|
||||
index ffb60a2..80fba54 100644
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -4040,7 +4040,7 @@ static int ieee80211_set_qos_map(struct wiphy *wiphy,
|
||||
if (old_qos_map)
|
||||
kfree_rcu(old_qos_map, rcu_head);
|
||||
|
||||
- return 0;
|
||||
+ return drv_set_qos_map(sdata->local, sdata, qos_map);
|
||||
}
|
||||
|
||||
static int ieee80211_set_ap_chanwidth(struct wiphy *wiphy,
|
||||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
|
||||
index 9e8003f..d4723dc 100644
|
||||
--- a/net/mac80211/driver-ops.h
|
||||
+++ b/net/mac80211/driver-ops.h
|
||||
@@ -1525,4 +1525,20 @@ static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
|
||||
}
|
||||
#endif
|
||||
|
||||
+static inline int drv_set_qos_map(struct ieee80211_local *local,
|
||||
+ struct ieee80211_sub_if_data *sdata,
|
||||
+ struct cfg80211_qos_map *qos_map)
|
||||
+{
|
||||
+ int ret = -EOPNOTSUPP;
|
||||
+
|
||||
+ might_sleep();
|
||||
+
|
||||
+ trace_drv_set_qos_map(local, sdata);
|
||||
+ if (local->ops->set_qos_map)
|
||||
+ ret = local->ops->set_qos_map(&sdata->vif, qos_map);
|
||||
+ trace_drv_return_int(local, ret);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
#endif /* __MAC80211_DRIVER_OPS */
|
||||
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
|
||||
index d15dadd..c6fc75e 100644
|
||||
--- a/net/mac80211/trace.h
|
||||
+++ b/net/mac80211/trace.h
|
||||
@@ -2929,6 +2929,12 @@ TRACE_EVENT(bss_color_bitmap,
|
||||
)
|
||||
);
|
||||
|
||||
+DEFINE_EVENT(local_sdata_evt, drv_set_qos_map,
|
||||
+ TP_PROTO(struct ieee80211_local *local,
|
||||
+ struct ieee80211_sub_if_data *sdata),
|
||||
+ TP_ARGS(local, sdata)
|
||||
+);
|
||||
+
|
||||
#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
--
|
||||
2.18.0
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
From ac1e8443a250f418b6124e7b4f4ea65a03c4d02b Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
|
||||
Date: Fri, 26 Apr 2024 09:29:39 +0800
|
||||
Subject: [PATCH] mac80211: mtk: add exported function for SoftMAC driver to
|
||||
get QoS map
|
||||
|
||||
The mapping from IP DSCP to IEEE 802.11 user priority may be customized.
|
||||
Therefore, driver needs to pass the mapping to HW, so that the QoS type of traffic can be mapped in a consistent manner for both SW and HW paths.
|
||||
|
||||
Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
|
||||
---
|
||||
include/net/mac80211.h | 12 ++++++++++++
|
||||
net/mac80211/util.c | 10 +++++++++-
|
||||
2 files changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
|
||||
index 5c26752..420963f 100644
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -6942,4 +6942,16 @@ static inline bool ieee80211_is_tx_data(struct sk_buff *skb)
|
||||
* @hw: pointer as obtained from ieee80211_alloc_hw()
|
||||
*/
|
||||
unsigned long ieee80211_get_scanning(struct ieee80211_hw *hw);
|
||||
+
|
||||
+/**
|
||||
+ * ieee80211_get_qos_map - get QoS mapping information.
|
||||
+ *
|
||||
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
+ *
|
||||
+ * Return: Pointer to the QoS mapping information.
|
||||
+ *
|
||||
+ * Note that the return value is an RCU-protected pointer, so rcu_read_lock()
|
||||
+ * must be held when calling this function.
|
||||
+ */
|
||||
+struct cfg80211_qos_map *ieee80211_get_qos_map(struct ieee80211_vif *vif);
|
||||
#endif /* MAC80211_H */
|
||||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
|
||||
index e07fe73..865c4ac 100644
|
||||
--- a/net/mac80211/util.c
|
||||
+++ b/net/mac80211/util.c
|
||||
@@ -4643,4 +4643,12 @@ unsigned long ieee80211_get_scanning(struct ieee80211_hw *hw)
|
||||
|
||||
return local->scanning;
|
||||
}
|
||||
-EXPORT_SYMBOL(ieee80211_get_scanning);
|
||||
\ No newline at end of file
|
||||
+EXPORT_SYMBOL(ieee80211_get_scanning);
|
||||
+
|
||||
+struct cfg80211_qos_map *ieee80211_get_qos_map(struct ieee80211_vif *vif)
|
||||
+{
|
||||
+ struct mac80211_qos_map *qos_map = rcu_dereference(vif_to_sdata(vif)->qos_map);
|
||||
+
|
||||
+ return qos_map ? &qos_map->qos_map : NULL;
|
||||
+}
|
||||
+EXPORT_SYMBOL(ieee80211_get_qos_map);
|
||||
--
|
||||
2.18.0
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
From de4d3e25a555dedd70793d0362b1e501ed1a77f1 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
|
||||
Date: Tue, 30 Apr 2024 10:28:29 +0800
|
||||
Subject: [PATCH] mac80211: mtk: fix inconsistent QoS mapping between AP and
|
||||
AP_VLAN VIFs
|
||||
|
||||
Fix inconsistent QoS mapping between AP and AP_VLAN IFs.
|
||||
Specifically, when WDS AP IF is connected by a WDS STA, the QoS map of the AP_VLAN VIF is NULL.
|
||||
So the QoS types of packets to the WDS STA will be determined using the default mapping rule.
|
||||
However, SoftMAC driver uses the QoS map of the AP VIF, which may already be set.
|
||||
Therefore, it is possible that the QoS mappings of SW and HW are inconsistent.
|
||||
Thus, sync QoS map of AP VIF to that of AP_VLAN VIF.
|
||||
|
||||
Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
|
||||
---
|
||||
net/mac80211/iface.c | 23 ++++++++++++++++++++++-
|
||||
1 file changed, 22 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
|
||||
index ef32d53..138ad79 100644
|
||||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -297,8 +297,29 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
|
||||
* can only add VLANs to enabled APs
|
||||
*/
|
||||
if (iftype == NL80211_IFTYPE_AP_VLAN &&
|
||||
- nsdata->vif.type == NL80211_IFTYPE_AP)
|
||||
+ nsdata->vif.type == NL80211_IFTYPE_AP) {
|
||||
+ struct mac80211_qos_map *old_qos_map, *new_qos_map = NULL;
|
||||
+
|
||||
sdata->bss = &nsdata->u.ap;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ old_qos_map = rcu_dereference(nsdata->qos_map);
|
||||
+ if (old_qos_map) {
|
||||
+ new_qos_map = kzalloc(sizeof(*new_qos_map), GFP_KERNEL);
|
||||
+ if (!new_qos_map) {
|
||||
+ rcu_read_unlock();
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ memcpy(&new_qos_map->qos_map, &old_qos_map->qos_map,
|
||||
+ sizeof(new_qos_map->qos_map));
|
||||
+ }
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ old_qos_map = sdata_dereference(sdata->qos_map, sdata);
|
||||
+ rcu_assign_pointer(sdata->qos_map, new_qos_map);
|
||||
+ if (old_qos_map)
|
||||
+ kfree_rcu(old_qos_map, rcu_head);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.18.0
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
From 9c1bd48929ad7c6b55d4486e7c519c778f9900d6 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Chiu <chui-hao.chiu@mediatek.com>
|
||||
Date: Mon, 14 Oct 2024 15:27:28 +0800
|
||||
Subject: [PATCH] mac80211: mtk: set IEEE80211_TX_CTL_USE_MINRATE when probing
|
||||
station
|
||||
|
||||
The TxS may not be reported to driver correctly when we set BA_DISALBE = 0.
|
||||
|
||||
When mac80211 set IEEE80211_TX_CTL_USE_MINRATE, mt76 would use fixed rate
|
||||
and set BA_DISABLE = 1 to transmit the packet. So mt76 can receive TxS
|
||||
correctly.
|
||||
|
||||
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
|
||||
---
|
||||
net/mac80211/cfg.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
|
||||
index 80fba54..4818dca 100644
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -3957,7 +3957,8 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||
- IEEE80211_TX_INTFL_NL80211_FRAME_TX;
|
||||
+ IEEE80211_TX_INTFL_NL80211_FRAME_TX |
|
||||
+ IEEE80211_TX_CTL_USE_MINRATE;
|
||||
info->band = band;
|
||||
|
||||
skb_set_queue_mapping(skb, IEEE80211_AC_VO);
|
||||
--
|
||||
2.45.2
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
From d873d195bcb481b7b82be195cb17e3fc7f7ecf58 Mon Sep 17 00:00:00 2001
|
||||
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
|
||||
Date: Wed, 11 Dec 2024 13:21:21 +0800
|
||||
Subject: [PATCH] mac80211: mtk: add dfs relax flag for scanning without dfs
|
||||
restrictions
|
||||
|
||||
Add dfs relax flag for scanning without dfs restrictions.
|
||||
If user turn on the dfs relax flag by entering the following command:
|
||||
echo 1 > /sys/kernel/debug/ieee80211/phyX/scan_dfs_relax
|
||||
Then, allow AP/STA to scan while operating on a DFS channel.
|
||||
|
||||
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
|
||||
---
|
||||
include/net/cfg80211.h | 4 +++
|
||||
net/mac80211/offchannel.c | 4 +--
|
||||
net/mac80211/scan.c | 3 ++-
|
||||
net/wireless/debugfs.c | 53 +++++++++++++++++++++++++++++++++++++++
|
||||
net/wireless/nl80211.c | 14 ++++++++---
|
||||
5 files changed, 71 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
|
||||
index 67b0e6c..f159340 100644
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -5047,6 +5047,8 @@ struct wiphy_iftype_akm_suites {
|
||||
* @mbssid_max_ema_profile_periodicity: maximum profile periodicity supported by
|
||||
* the driver. Setting this field to a non-zero value indicates that the
|
||||
* driver supports enhanced multi-BSSID advertisements (EMA AP).
|
||||
+ *
|
||||
+ * @dfs_relax: a flag to relax the DFS restrictions during scanning
|
||||
*/
|
||||
struct wiphy {
|
||||
struct mutex mtx;
|
||||
@@ -5197,6 +5199,8 @@ struct wiphy {
|
||||
u8 mbssid_max_interfaces;
|
||||
u8 ema_max_profile_periodicity;
|
||||
|
||||
+ bool dfs_relax;
|
||||
+
|
||||
char priv[] __aligned(NETDEV_ALIGN);
|
||||
};
|
||||
|
||||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
|
||||
index 042b6fb..2cd8454 100644
|
||||
--- a/net/mac80211/offchannel.c
|
||||
+++ b/net/mac80211/offchannel.c
|
||||
@@ -579,8 +579,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
|
||||
}
|
||||
|
||||
/* if there's no need to queue, handle it immediately */
|
||||
- if (list_empty(&local->roc_list) &&
|
||||
- !local->scanning && !ieee80211_is_radar_required(local)) {
|
||||
+ if (list_empty(&local->roc_list) && !local->scanning &&
|
||||
+ (local->hw.wiphy->dfs_relax || !ieee80211_is_radar_required(local))) {
|
||||
/* if not HW assist, just queue & schedule work */
|
||||
if (!local->ops->remain_on_channel) {
|
||||
list_add_tail(&roc->list, &local->roc_list);
|
||||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
|
||||
index 9d53f1a..9ef5179 100644
|
||||
--- a/net/mac80211/scan.c
|
||||
+++ b/net/mac80211/scan.c
|
||||
@@ -572,7 +572,8 @@ static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata)
|
||||
if (!ieee80211_is_radar_required(local))
|
||||
return true;
|
||||
|
||||
- if (!regulatory_pre_cac_allowed(local->hw.wiphy))
|
||||
+ if (!local->hw.wiphy->dfs_relax &&
|
||||
+ !regulatory_pre_cac_allowed(local->hw.wiphy))
|
||||
return false;
|
||||
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
|
||||
index 0637ed4..9fecbef 100644
|
||||
--- a/net/wireless/debugfs.c
|
||||
+++ b/net/wireless/debugfs.c
|
||||
@@ -388,6 +388,58 @@ dfs_available_reset(void *data, u64 val)
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(dfs_available_reset_ops, NULL,
|
||||
dfs_available_reset, "0x%08llx\n");
|
||||
|
||||
+
|
||||
+static ssize_t scan_dfs_relax_write(struct file *file,
|
||||
+ const char __user *user_buf,
|
||||
+ size_t count, loff_t *ppos)
|
||||
+{
|
||||
+ struct wiphy *wiphy = file->private_data;
|
||||
+ char buf[16];
|
||||
+
|
||||
+ if (count >= sizeof(buf))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (copy_from_user(buf, user_buf, count))
|
||||
+ return -EFAULT;
|
||||
+
|
||||
+ if (count && buf[count - 1] == '\n')
|
||||
+ buf[count - 1] = '\0';
|
||||
+ else
|
||||
+ buf[count] = '\0';
|
||||
+
|
||||
+ if (kstrtobool(buf, &wiphy->dfs_relax))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t scan_dfs_relax_read(struct file *file, char __user *user_buf,
|
||||
+ size_t count, loff_t *ppos)
|
||||
+{
|
||||
+ struct wiphy *wiphy = file->private_data;
|
||||
+ unsigned int r, offset, buf_size = PAGE_SIZE;
|
||||
+ char *buf;
|
||||
+
|
||||
+ buf = kzalloc(buf_size, GFP_KERNEL);
|
||||
+ if (!buf)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ offset = scnprintf(buf, buf_size, "dfs relax: %u\n", wiphy->dfs_relax);
|
||||
+
|
||||
+ r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
|
||||
+
|
||||
+ kfree(buf);
|
||||
+
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations scan_dfs_relax_ops = {
|
||||
+ .write = scan_dfs_relax_write,
|
||||
+ .read = scan_dfs_relax_read,
|
||||
+ .open = simple_open,
|
||||
+ .llseek = default_llseek,
|
||||
+};
|
||||
+
|
||||
#define DEBUGFS_ADD(name, chmod) \
|
||||
debugfs_create_file(#name, chmod, phyd, &rdev->wiphy, &name## _ops)
|
||||
|
||||
@@ -404,4 +456,5 @@ void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev)
|
||||
DEBUGFS_ADD(dfs_skip_nop, 0600);
|
||||
DEBUGFS_ADD(dfs_skip_cac, 0600);
|
||||
DEBUGFS_ADD(dfs_available_reset, 0600);
|
||||
+ DEBUGFS_ADD(scan_dfs_relax, 0644);
|
||||
}
|
||||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
|
||||
index 4883b1f..3d22429 100644
|
||||
--- a/net/wireless/nl80211.c
|
||||
+++ b/net/wireless/nl80211.c
|
||||
@@ -8400,13 +8400,16 @@ int nl80211_parse_random_mac(struct nlattr **attrs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev)
|
||||
+static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, bool dfs_relax)
|
||||
{
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
if (!cfg80211_beaconing_iface_active(wdev))
|
||||
return true;
|
||||
|
||||
+ if (dfs_relax)
|
||||
+ return true;
|
||||
+
|
||||
if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR))
|
||||
return true;
|
||||
|
||||
@@ -8627,7 +8630,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
||||
request->n_channels = i;
|
||||
|
||||
wdev_lock(wdev);
|
||||
- if (!cfg80211_off_channel_oper_allowed(wdev)) {
|
||||
+ if (!cfg80211_off_channel_oper_allowed(wdev, wiphy->dfs_relax)) {
|
||||
struct ieee80211_channel *chan;
|
||||
|
||||
if (request->n_channels != 1) {
|
||||
@@ -11549,8 +11552,11 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
+ if (wdev->cac_started)
|
||||
+ return -EBUSY;
|
||||
+
|
||||
wdev_lock(wdev);
|
||||
- if (!cfg80211_off_channel_oper_allowed(wdev) &&
|
||||
+ if (!cfg80211_off_channel_oper_allowed(wdev, rdev->wiphy.dfs_relax) &&
|
||||
!cfg80211_chandef_identical(&wdev->chandef, &chandef)) {
|
||||
compat_chandef = cfg80211_chandef_compatible(&wdev->chandef,
|
||||
&chandef);
|
||||
@@ -11755,7 +11761,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
||||
return -EINVAL;
|
||||
|
||||
wdev_lock(wdev);
|
||||
- if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev)) {
|
||||
+ if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev, false)) {
|
||||
wdev_unlock(wdev);
|
||||
return -EBUSY;
|
||||
}
|
||||
--
|
||||
2.45.2
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From bad36168042569eb4c7ab6a549f7444a40e299c3 Mon Sep 17 00:00:00 2001
|
||||
From 026c9872e3460f1632b60324e062016887b31134 Mon Sep 17 00:00:00 2001
|
||||
From: Sujuan Chen <sujuan.chen@mediatek.com>
|
||||
Date: Fri, 11 Mar 2022 11:34:11 +0800
|
||||
Subject: [PATCH 9900/9903] mac80211: mtk: mask kernel version limitation and
|
||||
Subject: [PATCH 9900/9902] mac80211: mtk: mask kernel version limitation and
|
||||
fill forward path in kernel 5.4
|
||||
|
||||
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
|
||||
@@ -13,10 +13,10 @@ Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
|
||||
4 files changed, 10 deletions(-)
|
||||
|
||||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
|
||||
index 91affd5..42192cd 100644
|
||||
index b622c76..c6625c2 100644
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -4307,13 +4307,11 @@ struct ieee80211_ops {
|
||||
@@ -4315,13 +4315,11 @@ struct ieee80211_ops {
|
||||
struct ieee80211_sta *sta, u8 flowid);
|
||||
int (*set_radar_background)(struct ieee80211_hw *hw,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
@@ -27,11 +27,11 @@ index 91affd5..42192cd 100644
|
||||
struct net_device_path_ctx *ctx,
|
||||
struct net_device_path *path);
|
||||
-#endif
|
||||
int (*set_qos_map)(struct ieee80211_vif *vif,
|
||||
struct cfg80211_qos_map *qos_map);
|
||||
};
|
||||
|
||||
/**
|
||||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
|
||||
index 9e8003f..19e2ada 100644
|
||||
index d4723dc..91ea8b2 100644
|
||||
--- a/net/mac80211/driver-ops.h
|
||||
+++ b/net/mac80211/driver-ops.h
|
||||
@@ -1501,7 +1501,6 @@ static inline void drv_twt_teardown_request(struct ieee80211_local *local,
|
||||
@@ -42,18 +42,19 @@ index 9e8003f..19e2ada 100644
|
||||
static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_sta *sta,
|
||||
@@ -1523,6 +1522,5 @@ static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
|
||||
@@ -1523,7 +1522,6 @@ static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
|
||||
|
||||
return ret;
|
||||
}
|
||||
-#endif
|
||||
|
||||
#endif /* __MAC80211_DRIVER_OPS */
|
||||
static inline int drv_set_qos_map(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
|
||||
index 00b0443..a7169a5 100644
|
||||
index 138ad79..4b92867 100644
|
||||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -853,7 +853,6 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
|
||||
@@ -875,7 +875,6 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
|
||||
|
||||
};
|
||||
|
||||
@@ -61,7 +62,7 @@ index 00b0443..a7169a5 100644
|
||||
static int ieee80211_netdev_fill_forward_path(struct net_device_path_ctx *ctx,
|
||||
struct net_device_path *path)
|
||||
{
|
||||
@@ -911,7 +910,6 @@ out:
|
||||
@@ -933,7 +932,6 @@ out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -69,7 +70,7 @@ index 00b0443..a7169a5 100644
|
||||
|
||||
static const struct net_device_ops ieee80211_dataif_8023_ops = {
|
||||
#if LINUX_VERSION_IS_LESS(4,10,0)
|
||||
@@ -930,9 +928,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
|
||||
@@ -952,9 +950,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
|
||||
#else
|
||||
.ndo_get_stats64 = bp_ieee80211_get_stats64,
|
||||
#endif
|
||||
@@ -80,7 +81,7 @@ index 00b0443..a7169a5 100644
|
||||
|
||||
static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype)
|
||||
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
|
||||
index d15dadd..8770033 100644
|
||||
index c6fc75e..6b7b46b 100644
|
||||
--- a/net/mac80211/trace.h
|
||||
+++ b/net/mac80211/trace.h
|
||||
@@ -2899,14 +2899,12 @@ TRACE_EVENT(drv_twt_teardown_request,
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
From 0161154c18a464bbb350bcb5ef620bd255940640 Mon Sep 17 00:00:00 2001
|
||||
From e5612cde83ef67f8fa4633f7d364e05bac6e02a3 Mon Sep 17 00:00:00 2001
|
||||
From: Sujuan Chen <sujuan.chen@mediatek.com>
|
||||
Date: Wed, 18 May 2022 15:10:22 +0800
|
||||
Subject: [PATCH 9901/9903] mac80211: mtk: add fill receive path ops to get wed
|
||||
Subject: [PATCH 9901/9902] mac80211: mtk: add fill receive path ops to get wed
|
||||
idx
|
||||
|
||||
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
|
||||
---
|
||||
include/net/mac80211.h | 12 ++++++++++++
|
||||
net/mac80211/driver-ops.h | 13 +++++++++++++
|
||||
net/mac80211/driver-ops.h | 14 +++++++++++++-
|
||||
net/mac80211/iface.c | 24 ++++++++++++++++++++++++
|
||||
net/mac80211/util.c | 9 +++++++++
|
||||
4 files changed, 58 insertions(+)
|
||||
4 files changed, 58 insertions(+), 1 deletion(-)
|
||||
mode change 100644 => 100755 include/net/mac80211.h
|
||||
mode change 100644 => 100755 net/mac80211/util.c
|
||||
|
||||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
|
||||
old mode 100644
|
||||
new mode 100755
|
||||
index 42192cd..8a71026
|
||||
index c6625c2..cb8b28d
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -1798,6 +1798,13 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
|
||||
@@ -34,30 +34,30 @@ index 42192cd..8a71026
|
||||
/**
|
||||
* enum ieee80211_key_flags - key flags
|
||||
*
|
||||
@@ -3975,6 +3982,8 @@ struct ieee80211_prep_tx_info {
|
||||
@@ -3982,6 +3989,8 @@ struct ieee80211_prep_tx_info {
|
||||
* disable background CAC/radar detection.
|
||||
* @net_fill_forward_path: Called from .ndo_fill_forward_path in order to
|
||||
* resolve a path for hardware flow offloading
|
||||
+ * @net_fill_receive_path: Called from .ndo_fill_receive_path in order to
|
||||
+ * get a path for hardware flow offloading
|
||||
* @set_qos_map: Set QoS mapping information to driver.
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
void (*tx)(struct ieee80211_hw *hw,
|
||||
@@ -4312,6 +4321,9 @@ struct ieee80211_ops {
|
||||
@@ -4320,6 +4329,9 @@ struct ieee80211_ops {
|
||||
struct ieee80211_sta *sta,
|
||||
struct net_device_path_ctx *ctx,
|
||||
struct net_device_path *path);
|
||||
+ int (*net_fill_receive_path)(struct ieee80211_hw *hw,
|
||||
+ struct net_device_path_ctx *ctx,
|
||||
+ struct net_device_path *path);
|
||||
int (*set_qos_map)(struct ieee80211_vif *vif,
|
||||
struct cfg80211_qos_map *qos_map);
|
||||
};
|
||||
|
||||
/**
|
||||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
|
||||
index 19e2ada..88dedfc 100644
|
||||
index 91ea8b2..348f815 100644
|
||||
--- a/net/mac80211/driver-ops.h
|
||||
+++ b/net/mac80211/driver-ops.h
|
||||
@@ -1523,4 +1523,17 @@ static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
|
||||
@@ -1523,6 +1523,19 @@ static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -74,12 +74,20 @@ index 19e2ada..88dedfc 100644
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static inline int drv_set_qos_map(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_qos_map *qos_map)
|
||||
@@ -1538,5 +1551,4 @@ static inline int drv_set_qos_map(struct ieee80211_local *local,
|
||||
|
||||
return ret;
|
||||
}
|
||||
-
|
||||
#endif /* __MAC80211_DRIVER_OPS */
|
||||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
|
||||
index a7169a5..8a4f4e1 100644
|
||||
index 4b92867..c08bfbe 100644
|
||||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -911,6 +911,29 @@ out:
|
||||
@@ -933,6 +933,29 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -109,7 +117,7 @@ index a7169a5..8a4f4e1 100644
|
||||
static const struct net_device_ops ieee80211_dataif_8023_ops = {
|
||||
#if LINUX_VERSION_IS_LESS(4,10,0)
|
||||
.ndo_change_mtu = __change_mtu,
|
||||
@@ -929,6 +952,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
|
||||
@@ -951,6 +974,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
|
||||
.ndo_get_stats64 = bp_ieee80211_get_stats64,
|
||||
#endif
|
||||
.ndo_fill_forward_path = ieee80211_netdev_fill_forward_path,
|
||||
@@ -120,7 +128,7 @@ index a7169a5..8a4f4e1 100644
|
||||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
|
||||
old mode 100644
|
||||
new mode 100755
|
||||
index 8d36b05..d26a2b8
|
||||
index e07fe73..809eb37
|
||||
--- a/net/mac80211/util.c
|
||||
+++ b/net/mac80211/util.c
|
||||
@@ -898,6 +898,15 @@ struct wireless_dev *ieee80211_vif_to_wdev(struct ieee80211_vif *vif)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From fdc7f27785b716eae1e02df73c095ecfe2677d9f Mon Sep 17 00:00:00 2001
|
||||
From d62db23d46d1887aff58c76b0eb9960a46afb9bf Mon Sep 17 00:00:00 2001
|
||||
From: Sujuan Chen <sujuan.chen@mediatek.com>
|
||||
Date: Tue, 28 Mar 2023 10:53:31 +0800
|
||||
Subject: [PATCH 9902/9903] mac80211: mtk: add support for letting drivers
|
||||
Subject: [PATCH 9902/9902] mac80211: mtk: add support for letting drivers
|
||||
register tc offload support
|
||||
|
||||
On newer MediaTek SoCs (e.g. MT7986), WLAN->WLAN or WLAN->Ethernet flows can
|
||||
@@ -18,10 +18,10 @@ Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
|
||||
5 files changed, 70 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
|
||||
index 8a71026..861bc9a 100755
|
||||
index cb8b28d..6104072 100755
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -3984,6 +3984,10 @@ struct ieee80211_prep_tx_info {
|
||||
@@ -3991,6 +3991,10 @@ struct ieee80211_prep_tx_info {
|
||||
* resolve a path for hardware flow offloading
|
||||
* @net_fill_receive_path: Called from .ndo_fill_receive_path in order to
|
||||
* get a path for hardware flow offloading
|
||||
@@ -29,10 +29,10 @@ index 8a71026..861bc9a 100755
|
||||
+ * flow offloading for flows originating from the vif.
|
||||
+ * Note that the driver must not assume that the vif driver_data is valid
|
||||
+ * at this point, since the callback can be called during netdev teardown.
|
||||
* @set_qos_map: Set QoS mapping information to driver.
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
void (*tx)(struct ieee80211_hw *hw,
|
||||
@@ -4324,6 +4328,11 @@ struct ieee80211_ops {
|
||||
@@ -4332,6 +4336,11 @@ struct ieee80211_ops {
|
||||
int (*net_fill_receive_path)(struct ieee80211_hw *hw,
|
||||
struct net_device_path_ctx *ctx,
|
||||
struct net_device_path *path);
|
||||
@@ -41,14 +41,14 @@ index 8a71026..861bc9a 100755
|
||||
+ struct net_device *dev,
|
||||
+ enum tc_setup_type type,
|
||||
+ void *type_data);
|
||||
int (*set_qos_map)(struct ieee80211_vif *vif,
|
||||
struct cfg80211_qos_map *qos_map);
|
||||
};
|
||||
|
||||
/**
|
||||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
|
||||
index 88dedfc..3ceba5e 100644
|
||||
index 348f815..f56a71f 100644
|
||||
--- a/net/mac80211/driver-ops.h
|
||||
+++ b/net/mac80211/driver-ops.h
|
||||
@@ -1536,4 +1536,21 @@ static inline int drv_net_fill_receive_path(struct ieee80211_local *local,
|
||||
@@ -1536,6 +1536,23 @@ static inline int drv_net_fill_receive_path(struct ieee80211_local *local,
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -69,12 +69,14 @@ index 88dedfc..3ceba5e 100644
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
#endif /* __MAC80211_DRIVER_OPS */
|
||||
static inline int drv_set_qos_map(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_qos_map *qos_map)
|
||||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
|
||||
index 2519c14..fe7a03a 100644
|
||||
index bb5906d..b02ca21 100644
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -1822,7 +1822,8 @@ void ieee80211_color_aging_work(struct work_struct *work);
|
||||
@@ -1824,7 +1824,8 @@ void ieee80211_color_aging_work(struct work_struct *work);
|
||||
/* interface handling */
|
||||
#define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
|
||||
NETIF_F_HW_CSUM | NETIF_F_SG | \
|
||||
@@ -85,10 +87,10 @@ index 2519c14..fe7a03a 100644
|
||||
#define MAC80211_SUPPORTED_FEATURES (MAC80211_SUPPORTED_FEATURES_TX | \
|
||||
MAC80211_SUPPORTED_FEATURES_RX)
|
||||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
|
||||
index 8a4f4e1..f3bf837 100644
|
||||
index c08bfbe..ddeaa8f 100644
|
||||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -773,6 +773,21 @@ static int __change_mtu(struct net_device *ndev, int new_mtu){
|
||||
@@ -795,6 +795,21 @@ static int __change_mtu(struct net_device *ndev, int new_mtu){
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -110,7 +112,7 @@ index 8a4f4e1..f3bf837 100644
|
||||
static const struct net_device_ops ieee80211_dataif_ops = {
|
||||
#if LINUX_VERSION_IS_LESS(4,10,0)
|
||||
.ndo_change_mtu = __change_mtu,
|
||||
@@ -790,6 +805,7 @@ static const struct net_device_ops ieee80211_dataif_ops = {
|
||||
@@ -812,6 +827,7 @@ static const struct net_device_ops ieee80211_dataif_ops = {
|
||||
#else
|
||||
.ndo_get_stats64 = bp_ieee80211_get_stats64,
|
||||
#endif
|
||||
@@ -118,7 +120,7 @@ index 8a4f4e1..f3bf837 100644
|
||||
|
||||
};
|
||||
|
||||
@@ -953,6 +969,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
|
||||
@@ -975,6 +991,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
|
||||
#endif
|
||||
.ndo_fill_forward_path = ieee80211_netdev_fill_forward_path,
|
||||
.ndo_fill_receive_path = ieee80211_netdev_fill_receive_path,
|
||||
@@ -127,7 +129,7 @@ index 8a4f4e1..f3bf837 100644
|
||||
|
||||
static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype)
|
||||
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
|
||||
index 8770033..78d9803 100644
|
||||
index 6b7b46b..5aea24a 100644
|
||||
--- a/net/mac80211/trace.h
|
||||
+++ b/net/mac80211/trace.h
|
||||
@@ -2906,6 +2906,31 @@ DEFINE_EVENT(sta_event, drv_net_fill_forward_path,
|
||||
|
||||
@@ -200,7 +200,7 @@
|
||||
phy-mode = "sgmii";
|
||||
full-duplex;
|
||||
pause;
|
||||
airoha,surge = <0>;
|
||||
airoha,surge = <1>;
|
||||
airoha,polarity = <2>;
|
||||
};
|
||||
|
||||
|
||||
@@ -169,8 +169,7 @@
|
||||
compatible = "mediatek,eth-mac";
|
||||
reg = <0>;
|
||||
phy-mode = "sgmii";
|
||||
phy-handle = <&phy30>;
|
||||
phy-handle2 = <&phy1>;
|
||||
phy-handle = <&phy1>; // add phy handler
|
||||
mtd-mac-address = <&factory 0x24>;
|
||||
};
|
||||
|
||||
@@ -194,16 +193,6 @@
|
||||
nvmem-cell-names = "phy-cal-data";
|
||||
};
|
||||
|
||||
phy30: ethernet-phy@30 { // AN8801SB
|
||||
compatible = "ethernet-phy-idc0ff.0421";
|
||||
reg = <30>; //0x1e
|
||||
phy-mode = "sgmii";
|
||||
full-duplex;
|
||||
pause;
|
||||
airoha,surge = <0>;
|
||||
airoha,polarity = <2>;
|
||||
};
|
||||
|
||||
phy1: ethernet-phy@1 {
|
||||
compatible = "ethernet-phy-id03a2.9471";
|
||||
reg = <24>; // set phy address to 0x18
|
||||
@@ -211,8 +200,9 @@
|
||||
reset-assert-us = <600>;
|
||||
reset-deassert-us = <20000>;
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
&hnat {
|
||||
|
||||
@@ -483,20 +483,21 @@
|
||||
};
|
||||
|
||||
mmc0: mmc@11230000 {
|
||||
compatible = "mediatek,mt7986-mmc",
|
||||
"mediatek,mt7981-mmc";
|
||||
reg = <0 0x11230000 0 0x1000>, <0 0x11c20000 0 0x1000>;
|
||||
interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&topckgen CK_TOP_EMMC_208M>,
|
||||
<&topckgen CK_TOP_EMMC_400M>,
|
||||
<&infracfg_ao CK_INFRA_MSDC_CK>;
|
||||
assigned-clocks = <&topckgen CK_TOP_EMMC_208M_SEL>,
|
||||
<&topckgen CK_TOP_EMMC_400M_SEL>;
|
||||
assigned-clock-parents = <&topckgen CK_TOP_CB_M_D2>,
|
||||
<&topckgen CK_TOP_CB_NET2_D2>;
|
||||
clock-names = "source", "hclk", "source_cg";
|
||||
status = "disabled";
|
||||
};
|
||||
compatible = "mediatek,mt7986-mmc",
|
||||
"mediatek,mt7981-mmc";
|
||||
reg = <0 0x11230000 0 0x1000>, <0 0x11c20000 0 0x1000>;
|
||||
interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&topckgen CK_TOP_EMMC_208M>,
|
||||
<&topckgen CK_TOP_EMMC_400M>,
|
||||
<&infracfg_ao CK_INFRA_MSDC_66M_CK>,
|
||||
<&infracfg_ao CK_INFRA_MSDC_CK>;
|
||||
assigned-clocks = <&topckgen CK_TOP_EMMC_208M_SEL>,
|
||||
<&topckgen CK_TOP_EMMC_400M_SEL>;
|
||||
assigned-clock-parents = <&topckgen CK_TOP_CB_M_D2>,
|
||||
<&topckgen CK_TOP_CB_NET2_D2>;
|
||||
clock-names = "source", "hclk", "bus_clk", "source_cg";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
wbsys: wbsys@18000000 {
|
||||
compatible = "mediatek,wbsys",
|
||||
|
||||
@@ -55,7 +55,7 @@ static const struct mtk_fixed_factor infra_divs[] __initconst = {
|
||||
FACTOR(CK_INFRA_MUX_SPI1, "infra_mux_spi1", "infra_spi1_sel", 1, 1),
|
||||
FACTOR(CK_INFRA_MUX_SPI2, "infra_mux_spi2", "infra_spi2_sel", 1, 1),
|
||||
FACTOR(CK_INFRA_RTC_32K, "infra_rtc_32k", "cb_rtc_32k", 1, 1),
|
||||
FACTOR(CK_INFRA_FMSDC_CK, "infra_fmsdc", "emmc_400m", 1, 1),
|
||||
FACTOR(CK_INFRA_FMSDC_CK, "infra_fmsdc", "emmc_208m", 1, 1),
|
||||
FACTOR(CK_INFRA_FMSDC_HCK_CK, "infra_fmsdc_hck", "emmc_208m", 1, 1),
|
||||
FACTOR(CK_INFRA_PERI_133M, "infra_peri_133m", "sysaxi", 1, 1),
|
||||
FACTOR(CK_INFRA_133M_PHCK, "infra_133m_phck", "sysaxi", 1, 1),
|
||||
|
||||
@@ -488,6 +488,16 @@ static const struct mtk_gate_regs infra2_cg_regs = {
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_INFRA0_FLAGS(_id, _name, _parent, _shift, _flags) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &infra0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.flags = _flags, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate infra_clks[] __initconst = {
|
||||
/* INFRA0 */
|
||||
GATE_INFRA0(CK_INFRA_PWM_HCK, "infra_pwm_hck", "infra_66m_mck", 1),
|
||||
@@ -506,7 +516,7 @@ static const struct mtk_gate infra_clks[] __initconst = {
|
||||
GATE_INFRA0(CK_INFRA_AP_DMA_CK, "infra_ap_dma", "infra_66m_mck", 16),
|
||||
GATE_INFRA0(CK_INFRA_SEJ_CK, "infra_sej", "infra_66m_mck", 24),
|
||||
GATE_INFRA0(CK_INFRA_SEJ_13M_CK, "infra_sej_13m", "infra_ck_f26m", 25),
|
||||
GATE_INFRA0(CK_INFRA_TRNG_CK, "infra_trng", "infra_hd_133m", 26),
|
||||
GATE_INFRA0_FLAGS(CK_INFRA_TRNG_CK, "infra_trng", "infra_hd_133m", 26, CLK_IS_CRITICAL),
|
||||
/* INFRA1 */
|
||||
GATE_INFRA1(CK_INFRA_THERM_CK, "infra_therm", "infra_ck_f26m", 0),
|
||||
GATE_INFRA1(CK_INFRA_I2CO_CK, "infra_i2co", "infra_i2cs", 1),
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2024 MediaTek Inc.
|
||||
* Author: Lu Tang <Lu.Tang@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
#include "clk-mux.h"
|
||||
#include <dt-bindings/clock/mediatek,mt7987-clk.h>
|
||||
|
||||
#define MT7987_PLL_FMAX (2500UL * MHZ)
|
||||
#define MT7987_PCW_CHG_SHIFT 2
|
||||
|
||||
#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \
|
||||
_pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \
|
||||
_tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, _div_table, \
|
||||
_parent_name) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \
|
||||
.en_mask = _en_mask, .flags = _flags, \
|
||||
.rst_bar_mask = BIT(_rst_bar_mask), .fmax = MT7987_PLL_FMAX, \
|
||||
.pcwbits = _pcwbits, .pd_reg = _pd_reg, .pd_shift = _pd_shift, \
|
||||
.tuner_reg = _tuner_reg, .tuner_en_reg = _tuner_en_reg, \
|
||||
.tuner_en_bit = _tuner_en_bit, .pcw_reg = _pcw_reg, \
|
||||
.pcw_shift = _pcw_shift, .pcw_chg_reg = _pcw_chg_reg, \
|
||||
.pcw_chg_shift = MT7987_PCW_CHG_SHIFT, \
|
||||
.div_table = _div_table, .parent_name = _parent_name, \
|
||||
}
|
||||
|
||||
#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \
|
||||
_pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \
|
||||
_tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, _parent_name) \
|
||||
PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \
|
||||
_pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \
|
||||
_tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, NULL, \
|
||||
_parent_name)
|
||||
|
||||
static const struct mtk_pll_div_table mt7987_arm_ll_div[] = {
|
||||
{ .div = 0, .freq = 2000000000 },
|
||||
{ .div = 1, .freq = 1500000000 },
|
||||
{ .div = 2, .freq = 750000000 },
|
||||
{ .div = 3, .freq = 375000000 },
|
||||
{} /* sentinel */
|
||||
};
|
||||
|
||||
static const struct mtk_pll_data plls[] = {
|
||||
PLL(CK_APMIXED_MPLL, "mpll", 0x0114, 0x0120, 0xff000001, HAVE_RST_BAR,
|
||||
23, 32, 0x0114, 4, 0, 0, 0, 0x0118, 0, 0x0114, "clkxtal"),
|
||||
PLL(CK_APMIXED_APLL2, "apll2", 0x0134, 0x0140, 0x00000001, 0, 0, 32,
|
||||
0x0134, 4, 0x0704, 0x0700, 1, 0x0138, 0, 0x0134, "clkxtal"),
|
||||
PLL(CK_APMIXED_NET1PLL, "net1pll", 0x0144, 0x0150, 0xff000001,
|
||||
HAVE_RST_BAR, 23, 32, 0x0144, 4, 0, 0, 0, 0x0148, 0, 0x0144,
|
||||
"clkxtal"),
|
||||
PLL(CK_APMIXED_NET2PLL, "net2pll", 0x0154, 0x0160, 0xff000001,
|
||||
HAVE_RST_BAR | PLL_AO, 23, 32, 0x0154, 4, 0, 0, 0, 0x0158, 0,
|
||||
0x0154, "clkxtal"),
|
||||
PLL(CK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0164, 0x0170, 0x00000001, 0, 0,
|
||||
32, 0x0164, 4, 0, 0, 0, 0x0168, 0, 0x0164, "clkxtal"),
|
||||
PLL(CK_APMIXED_SGMPLL, "sgmpll", 0x0174, 0x0180, 0x00000001, 0, 0, 32,
|
||||
0x0174, 4, 0, 0, 0, 0x0178, 0, 0x0174, "clkxtal"),
|
||||
PLL_B(CK_APMIXED_ARM_LL, "arm_ll", 0x0104, 0x0110, 0x00000001,
|
||||
PLL_AO, 0, 32, 0x0104, 4, 0, 0, 0, 0x0108, 0, 0x0104,
|
||||
mt7987_arm_ll_div, "clkxtal"),
|
||||
PLL(CK_APMIXED_MSDCPLL, "msdcpll", 0x0124, 0x0130, 0x00000001, 0, 0, 32,
|
||||
0x0124, 4, 0, 0, 0, 0x0128, 0, 0x0124, "clkxtal"),
|
||||
};
|
||||
|
||||
static struct clk_onecell_data *mt7987_pll_clk_data __initdata;
|
||||
|
||||
static void __init mtk_apmixedsys_init(struct device_node *node)
|
||||
{
|
||||
int r;
|
||||
|
||||
mt7987_pll_clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
|
||||
|
||||
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls),
|
||||
mt7987_pll_clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get,
|
||||
mt7987_pll_clk_data);
|
||||
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt7987-apmixedsys",
|
||||
mtk_apmixedsys_init);
|
||||
@@ -0,0 +1,113 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2024 MediaTek Inc.
|
||||
* Author: Lu Tang <Lu.Tang@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
#include <dt-bindings/clock/mediatek,mt7987-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs ethdma_cg_regs = {
|
||||
.set_ofs = 0x30,
|
||||
.clr_ofs = 0x30,
|
||||
.sta_ofs = 0x30,
|
||||
};
|
||||
|
||||
#define GATE_ETHDMA(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = ðdma_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate ethdma_clks[] = {
|
||||
GATE_ETHDMA(CK_ETHDMA_FE_EN, "ethdma_fe_en", "netsys_2x_sel", 6),
|
||||
GATE_ETHDMA(CK_ETHDMA_GP2_EN, "ethdma_gp2_en", "netsys_500m_sel", 7),
|
||||
GATE_ETHDMA(CK_ETHDMA_GP1_EN, "ethdma_gp1_en", "netsys_500m_sel", 8),
|
||||
GATE_ETHDMA(CK_ETHDMA_GP3_EN, "ethdma_gp3_en", "netsys_500m_sel", 10),
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs sgmii_cg_regs = {
|
||||
.set_ofs = 0xe4,
|
||||
.clr_ofs = 0xe4,
|
||||
.sta_ofs = 0xe4,
|
||||
};
|
||||
|
||||
#define GATE_SGMII(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &sgmii_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate sgmii0_clks[] = {
|
||||
GATE_SGMII(CK_SGM0_TX_EN, "sgm0_tx_en", "clkxtal", 2),
|
||||
GATE_SGMII(CK_SGM0_RX_EN, "sgm0_rx_en", "clkxtal", 3),
|
||||
};
|
||||
|
||||
static const struct mtk_gate sgmii1_clks[] = {
|
||||
GATE_SGMII(CK_SGM1_TX_EN, "sgm1_tx_en", "clkxtal", 2),
|
||||
GATE_SGMII(CK_SGM1_RX_EN, "sgm1_rx_en", "clkxtal", 3),
|
||||
};
|
||||
|
||||
static void __init mtk_sgmiisys_0_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_SGMII0_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_sgmiisys_0, "mediatek,mt7987-sgmiisys_0",
|
||||
mtk_sgmiisys_0_init);
|
||||
|
||||
static void __init mtk_sgmiisys_1_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_SGMII1_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_sgmiisys_1, "mediatek,mt7987-sgmiisys_1",
|
||||
mtk_sgmiisys_1_init);
|
||||
|
||||
static void __init mtk_ethdma_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_ETHDMA_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, ethdma_clks, ARRAY_SIZE(ethdma_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_ethdma, "mediatek,mt7987-ethsys", mtk_ethdma_init);
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Copyright (c) 2024 MediaTek Inc.
|
||||
* Author: Lu Tang <Lu.Tang@mediatek.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-mux.h"
|
||||
#include "clk-gate.h"
|
||||
#include <dt-bindings/clock/mediatek,mt7987-clk.h>
|
||||
|
||||
static DEFINE_SPINLOCK(mt7987_clk_lock);
|
||||
|
||||
static const char *const infra_mux_uart0_parents[] = { "csw_infra_f26m_sel",
|
||||
"uart_sel" };
|
||||
|
||||
static const char *const infra_mux_uart1_parents[] = { "csw_infra_f26m_sel",
|
||||
"uart_sel" };
|
||||
|
||||
static const char *const infra_mux_uart2_parents[] = { "csw_infra_f26m_sel",
|
||||
"uart_sel" };
|
||||
|
||||
static const char *const infra_mux_spi0_parents[] = {
|
||||
"i2c_sel",
|
||||
"spi_sel"
|
||||
};
|
||||
|
||||
static const char *const infra_mux_spi1_parents[] = {
|
||||
"i2c_sel",
|
||||
"spim_mst_sel"
|
||||
};
|
||||
|
||||
static const char *const infra_mux_spi2_bck_parents[] = {
|
||||
"i2c_sel",
|
||||
"spi_sel"
|
||||
};
|
||||
|
||||
static const char *const infra_pwm_bck_parents[] = { "cb_rtc_32p7k",
|
||||
"csw_infra_f26m_sel",
|
||||
"sysaxi_sel", "pwm_sel" };
|
||||
|
||||
static const char *const infra_pcie_gfmux_tl_ck_o_p0_parents[] = {
|
||||
"cb_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel",
|
||||
"pextp_tl_ck_sel"
|
||||
};
|
||||
|
||||
static const char *const infra_pcie_gfmux_tl_ck_o_p1_parents[] = {
|
||||
"cb_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel",
|
||||
"pextp_tl_ck_p1_sel"
|
||||
};
|
||||
|
||||
static struct mtk_mux infra_muxes[] = {
|
||||
/* MODULE_CLK_SEL_0 */
|
||||
MUX_GATE_CLR_SET_UPD(CK_INFRA_MUX_UART0_SEL, "infra_mux_uart0_sel",
|
||||
infra_mux_uart0_parents, 0x0018, 0x0010, 0x0014, 0,
|
||||
1, -1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CK_INFRA_MUX_UART1_SEL, "infra_mux_uart1_sel",
|
||||
infra_mux_uart1_parents, 0x0018, 0x0010, 0x0014, 1,
|
||||
1, -1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CK_INFRA_MUX_UART2_SEL, "infra_mux_uart2_sel",
|
||||
infra_mux_uart2_parents, 0x0018, 0x0010, 0x0014, 2,
|
||||
1, -1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CK_INFRA_MUX_SPI0_SEL, "infra_mux_spi0_sel",
|
||||
infra_mux_spi0_parents, 0x0018, 0x0010, 0x0014, 4,
|
||||
1, -1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CK_INFRA_MUX_SPI1_SEL, "infra_mux_spi1_sel",
|
||||
infra_mux_spi1_parents, 0x0018, 0x0010, 0x0014, 5,
|
||||
1, -1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CK_INFRA_MUX_SPI2_BCK_SEL,
|
||||
"infra_mux_spi2_bck_sel",
|
||||
infra_mux_spi2_bck_parents, 0x0018, 0x0010, 0x0014,
|
||||
6, 1, -1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CK_INFRA_PWM_BCK_SEL, "infra_pwm_bck_sel",
|
||||
infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 14,
|
||||
2, -1, -1, -1),
|
||||
/* MODULE_CLK_SEL_1 */
|
||||
MUX_GATE_CLR_SET_UPD(CK_INFRA_PCIE_GFMUX_TL_O_P0_SEL,
|
||||
"infra_pcie_gfmux_tl_ck_o_p0_sel",
|
||||
infra_pcie_gfmux_tl_ck_o_p0_parents, 0x0028,
|
||||
0x0020, 0x0024, 0, 2, -1, -1, -1),
|
||||
MUX_GATE_CLR_SET_UPD(CK_INFRA_PCIE_GFMUX_TL_O_P1_SEL,
|
||||
"infra_pcie_gfmux_tl_ck_o_p1_sel",
|
||||
infra_pcie_gfmux_tl_ck_o_p1_parents, 0x0028,
|
||||
0x0020, 0x0024, 2, 2, -1, -1, -1),
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra0_cg_regs = {
|
||||
.set_ofs = 0x10,
|
||||
.clr_ofs = 0x14,
|
||||
.sta_ofs = 0x18,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra1_cg_regs = {
|
||||
.set_ofs = 0x40,
|
||||
.clr_ofs = 0x44,
|
||||
.sta_ofs = 0x48,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra2_cg_regs = {
|
||||
.set_ofs = 0x50,
|
||||
.clr_ofs = 0x54,
|
||||
.sta_ofs = 0x58,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra3_cg_regs = {
|
||||
.set_ofs = 0x60,
|
||||
.clr_ofs = 0x64,
|
||||
.sta_ofs = 0x68,
|
||||
};
|
||||
|
||||
#define GATE_INFRA0(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &infra0_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_INFRA1(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &infra1_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_INFRA2(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &infra2_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_INFRA3(_id, _name, _parent, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = &infra3_cg_regs, .shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_CRITICAL(_id, _name, _parent, _regs, _shift) \
|
||||
{ \
|
||||
.id = _id, .name = _name, .parent_name = _parent, \
|
||||
.regs = _regs, .shift = _shift, .flags = CLK_IS_CRITICAL, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate infra_clks[] __initconst = {
|
||||
/* INFRA1 */
|
||||
GATE_INFRA1(CK_INFRA_66M_GPT_BCK, "infra_hf_66m_gpt_bck", "sysaxi_sel",
|
||||
0),
|
||||
GATE_INFRA1(CK_INFRA_66M_PWM_HCK, "infra_hf_66m_pwm_hck", "sysaxi_sel",
|
||||
1),
|
||||
GATE_INFRA1(CK_INFRA_66M_PWM_BCK, "infra_hf_66m_pwm_bck",
|
||||
"infra_pwm_bck_sel", 2),
|
||||
GATE_INFRA1(CK_INFRA_133M_CQDMA_BCK, "infra_hf_133m_cqdma_bck",
|
||||
"sysaxi_sel", 12),
|
||||
GATE_INFRA1(CK_INFRA_66M_AUD_SLV_BCK, "infra_66m_aud_slv_bck",
|
||||
"sysaxi_sel", 13),
|
||||
GATE_INFRA1(CK_INFRA_AUD_26M, "infra_f_faud_26m", "csw_infra_f26m_sel",
|
||||
14),
|
||||
GATE_INFRA1(CK_INFRA_AUD_L, "infra_f_faud_l", "aud_l_sel", 15),
|
||||
GATE_INFRA1(CK_INFRA_AUD_AUD, "infra_f_aud_aud", "a1sys_sel", 16),
|
||||
GATE_INFRA1(CK_INFRA_AUD_EG2, "infra_f_faud_eg2", "a_tuner_sel", 18),
|
||||
GATE_INFRA1(CK_INFRA_DRAMC_F26M, "infra_dramc_f26m",
|
||||
"csw_infra_f26m_sel", 19),
|
||||
GATE_CRITICAL(CK_INFRA_133M_DBG_ACKM, "infra_hf_133m_dbg_ackm",
|
||||
"sysaxi_sel", &infra1_cg_regs, 20),
|
||||
GATE_INFRA1(CK_INFRA_66M_AP_DMA_BCK, "infra_66m_ap_dma_bck",
|
||||
"sysaxi_sel", 21),
|
||||
GATE_INFRA1(CK_INFRA_MSDC200_SRC, "infra_f_fmsdc200_src",
|
||||
"emmc_200m_sel", 28),
|
||||
GATE_CRITICAL(CK_INFRA_66M_SEJ_BCK, "infra_hf_66m_sej_bck", "sysaxi_sel",
|
||||
&infra1_cg_regs, 29),
|
||||
GATE_CRITICAL(CK_INFRA_PRE_CK_SEJ_F13M, "infra_pre_ck_sej_f13m",
|
||||
"csw_infra_f26m_sel", &infra1_cg_regs, 30),
|
||||
GATE_CRITICAL(CK_INFRA_66M_TRNG, "infra_hf_66m_trng", "sysaxi_sel",
|
||||
&infra1_cg_regs, 31),
|
||||
/* INFRA2 */
|
||||
GATE_INFRA2(CK_INFRA_26M_THERM_SYSTEM, "infra_hf_26m_therm_system",
|
||||
"csw_infra_f26m_sel", 0),
|
||||
GATE_INFRA2(CK_INFRA_I2C_BCK, "infra_i2c_bck", "i2c_sel", 1),
|
||||
GATE_INFRA2(CK_INFRA_66M_UART0_PCK, "infra_hf_66m_uart0_pck",
|
||||
"sysaxi_sel", 3),
|
||||
GATE_INFRA2(CK_INFRA_66M_UART1_PCK, "infra_hf_66m_uart1_pck",
|
||||
"sysaxi_sel", 4),
|
||||
GATE_INFRA2(CK_INFRA_66M_UART2_PCK, "infra_hf_66m_uart2_pck",
|
||||
"sysaxi_sel", 5),
|
||||
GATE_INFRA2(CK_INFRA_52M_UART0_CK, "infra_f_52m_uart0",
|
||||
"infra_mux_uart0_sel", 3),
|
||||
GATE_INFRA2(CK_INFRA_52M_UART1_CK, "infra_f_52m_uart1",
|
||||
"infra_mux_uart1_sel", 4),
|
||||
GATE_INFRA2(CK_INFRA_52M_UART2_CK, "infra_f_52m_uart2",
|
||||
"infra_mux_uart2_sel", 5),
|
||||
GATE_INFRA2(CK_INFRA_NFI, "infra_f_fnfi", "nfi_sel", 9),
|
||||
GATE_CRITICAL(CK_INFRA_66M_NFI_HCK, "infra_hf_66m_nfi_hck",
|
||||
"sysaxi_sel", &infra2_cg_regs, 11),
|
||||
GATE_INFRA2(CK_INFRA_104M_SPI0, "infra_hf_104m_spi0",
|
||||
"infra_mux_spi0_sel", 12),
|
||||
GATE_INFRA2(CK_INFRA_104M_SPI1, "infra_hf_104m_spi1",
|
||||
"infra_mux_spi1_sel", 13),
|
||||
GATE_INFRA2(CK_INFRA_104M_SPI2_BCK, "infra_hf_104m_spi2_bck",
|
||||
"infra_mux_spi2_bck_sel", 14),
|
||||
GATE_INFRA2(CK_INFRA_66M_SPI0_HCK, "infra_hf_66m_spi0_hck",
|
||||
"sysaxi_sel", 15),
|
||||
GATE_INFRA2(CK_INFRA_66M_SPI1_HCK, "infra_hf_66m_spi1_hck",
|
||||
"sysaxi_sel", 16),
|
||||
GATE_INFRA2(CK_INFRA_66M_SPI2_HCK, "infra_hf_66m_spi2_hck",
|
||||
"sysaxi_sel", 17),
|
||||
GATE_INFRA2(CK_INFRA_66M_FLASHIF_AXI, "infra_hf_66m_flashif_axi",
|
||||
"sysaxi_sel", 18),
|
||||
GATE_CRITICAL(CK_INFRA_RTC, "infra_f_frtc", "cb_rtc_32k",
|
||||
&infra2_cg_regs, 19),
|
||||
GATE_INFRA2(CK_INFRA_26M_ADC_BCK, "infra_f_26m_adc_bck",
|
||||
"csw_infra_f26m_sel", 20),
|
||||
GATE_INFRA2(CK_INFRA_RC_ADC, "infra_f_frc_adc", "infra_f_26m_adc_bck",
|
||||
21),
|
||||
GATE_INFRA2(CK_INFRA_MSDC400, "infra_f_fmsdc400", "emmc_400m_sel", 22),
|
||||
GATE_INFRA2(CK_INFRA_MSDC2_HCK, "infra_f_fmsdc2_hck", "emmc_250m_sel",
|
||||
23),
|
||||
GATE_INFRA2(CK_INFRA_133M_MSDC_0_HCK, "infra_hf_133m_msdc_0_hck",
|
||||
"sysaxi_sel", 24),
|
||||
GATE_INFRA2(CK_INFRA_66M_MSDC_0_HCK, "infra_66m_msdc_0_hck",
|
||||
"sysaxi_sel", 25),
|
||||
GATE_INFRA2(CK_INFRA_133M_CPUM_BCK, "infra_hf_133m_cpum_bck",
|
||||
"sysaxi_sel", 26),
|
||||
GATE_INFRA2(CK_INFRA_BIST2FPC, "infra_hf_fbist2fpc", "nfi_sel", 27),
|
||||
GATE_INFRA2(CK_INFRA_I2C_X16W_MCK_CK_P1, "infra_hf_i2c_x16w_mck_ck_p1",
|
||||
"sysaxi_sel", 29),
|
||||
GATE_INFRA2(CK_INFRA_I2C_X16W_PCK_CK_P1, "infra_hf_i2c_x16w_pck_ck_p1",
|
||||
"sysaxi_sel", 31),
|
||||
/* INFRA3 */
|
||||
GATE_INFRA3(CK_INFRA_133M_USB_HCK, "infra_133m_usb_hck", "sysaxi_sel",
|
||||
0),
|
||||
GATE_INFRA3(CK_INFRA_133M_USB_HCK_CK_P1, "infra_133m_usb_hck_ck_p1",
|
||||
"sysaxi_sel", 1),
|
||||
GATE_INFRA3(CK_INFRA_66M_USB_HCK, "infra_66m_usb_hck", "sysaxi_sel", 2),
|
||||
GATE_INFRA3(CK_INFRA_66M_USB_HCK_CK_P1, "infra_66m_usb_hck_ck_p1",
|
||||
"sysaxi_sel", 3),
|
||||
GATE_INFRA3(CK_INFRA_USB_SYS_CK_P1, "infra_usb_sys_ck_p1",
|
||||
"usb_sys_p1_sel", 5),
|
||||
GATE_INFRA3(CK_INFRA_USB_CK_P1, "infra_usb_ck_p1", "cb_cksq_40m", 7),
|
||||
GATE_CRITICAL(CK_INFRA_USB_FRMCNT_CK_P1, "infra_usb_frmcnt_ck_p1",
|
||||
"cksq_40m_d2", &infra3_cg_regs, 9),
|
||||
GATE_CRITICAL(CK_INFRA_USB_PIPE_CK_P1, "infra_usb_pipe_ck_p1",
|
||||
"usb_phy_sel", &infra3_cg_regs, 11),
|
||||
GATE_INFRA3(CK_INFRA_USB_UTMI_CK_P1, "infra_usb_utmi_ck_p1", "clkxtal",
|
||||
13),
|
||||
GATE_INFRA3(CK_INFRA_USB_XHCI_CK_P1, "infra_usb_xhci_ck_p1",
|
||||
"usb_xhci_p1_sel", 15),
|
||||
GATE_INFRA3(CK_INFRA_PCIE_GFMUX_TL_P0, "infra_pcie_gfmux_tl_ck_p0",
|
||||
"infra_pcie_gfmux_tl_ck_o_p0_sel", 20),
|
||||
GATE_INFRA3(CK_INFRA_PCIE_GFMUX_TL_P1, "infra_pcie_gfmux_tl_ck_p1",
|
||||
"infra_pcie_gfmux_tl_ck_o_p1_sel", 21),
|
||||
GATE_INFRA3(CK_INFRA_PCIE_PIPE_P0, "infra_pcie_pipe_ck_p0", "clkxtal",
|
||||
24),
|
||||
GATE_INFRA3(CK_INFRA_PCIE_PIPE_P1, "infra_pcie_pipe_ck_p1", "clkxtal",
|
||||
25),
|
||||
GATE_INFRA3(CK_INFRA_133M_PCIE_CK_P0, "infra_133m_pcie_ck_p0",
|
||||
"sysaxi_sel", 28),
|
||||
GATE_INFRA3(CK_INFRA_133M_PCIE_CK_P1, "infra_133m_pcie_ck_p1",
|
||||
"sysaxi_sel", 29),
|
||||
/* INFRA0 */
|
||||
GATE_INFRA0(CK_INFRA_PCIE_PERI_26M_CK_P0,
|
||||
"infra_pcie_peri_ck_26m_ck_p0", "csw_infra_f26m_sel", 7),
|
||||
GATE_INFRA0(CK_INFRA_PCIE_PERI_26M_CK_P1,
|
||||
"infra_pcie_peri_ck_26m_ck_p1", "csw_infra_f26m_sel", 8),
|
||||
};
|
||||
|
||||
static struct clk_onecell_data *mt7987_infra_ao_clk_data __initdata;
|
||||
|
||||
static void __init mtk_infracfg_ao_init(struct device_node *node)
|
||||
{
|
||||
int r;
|
||||
void __iomem *base;
|
||||
|
||||
base = of_iomap(node, 0);
|
||||
if (!base) {
|
||||
pr_err("%s(): ioremap failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
mt7987_infra_ao_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
|
||||
|
||||
mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node,
|
||||
&mt7987_clk_lock, mt7987_infra_ao_clk_data);
|
||||
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
|
||||
mt7987_infra_ao_clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get,
|
||||
mt7987_infra_ao_clk_data);
|
||||
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_infracfg_ao, "mediatek,mt7987-infracfg_ao",
|
||||
mtk_infracfg_ao_init);
|
||||
@@ -0,0 +1,57 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2024 MediaTek Inc.
|
||||
* Author: Sam Shih <sam.shih@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
#include "clk-mux.h"
|
||||
#include <dt-bindings/clock/mediatek,mt7987-clk.h>
|
||||
|
||||
static DEFINE_SPINLOCK(mt7987_clk_lock);
|
||||
static const char *const mcu_bus_div_parents[] = { "cb_cksq_40m", "arm_ll" };
|
||||
|
||||
static struct mtk_mux mcu_muxes[] = {
|
||||
{
|
||||
.id = CK_MCU_BUS_DIV_SEL,
|
||||
.name = "mcu_bus_div_sel",
|
||||
.mux_ofs = 0x7C0,
|
||||
.mux_shift = 9,
|
||||
.mux_width = 1,
|
||||
.parent_names = mcu_bus_div_parents,
|
||||
.num_parents = ARRAY_SIZE(mcu_bus_div_parents),
|
||||
.ops = &mtk_mux_ops,
|
||||
.flags = CLK_IS_CRITICAL,
|
||||
}
|
||||
};
|
||||
|
||||
static void __init mtk_mcusys_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
void __iomem *base;
|
||||
|
||||
base = of_iomap(node, 0);
|
||||
if (!base) {
|
||||
pr_err("%s(): ioremap failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK);
|
||||
|
||||
mtk_clk_register_muxes(mcu_muxes, ARRAY_SIZE(mcu_muxes), node,
|
||||
&mt7987_clk_lock, clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_mcusys, "mediatek,mt7987-mcusys", mtk_mcusys_init);
|
||||
@@ -0,0 +1,310 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2024 MediaTek Inc.
|
||||
* Author: Lu Tang <Lu.Tang@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
#include "clk-mux.h"
|
||||
#include <dt-bindings/clock/mediatek,mt7987-clk.h>
|
||||
|
||||
static DEFINE_SPINLOCK(mt7987_clk_lock);
|
||||
|
||||
static const struct mtk_fixed_factor top_divs[] __initconst = {
|
||||
FACTOR(CK_TOP_CB_M_D2, "cb_m_d2", "mpll", 1, 2),
|
||||
FACTOR(CK_TOP_CB_M_D3, "cb_m_d3", "mpll", 1, 3),
|
||||
FACTOR(CK_TOP_M_D3_D2, "m_d3_d2", "mpll", 1, 6),
|
||||
FACTOR(CK_TOP_CB_M_D4, "cb_m_d4", "mpll", 1, 4),
|
||||
FACTOR(CK_TOP_CB_M_D8, "cb_m_d8", "mpll", 1, 8),
|
||||
FACTOR(CK_TOP_M_D8_D2, "m_d8_d2", "mpll", 1, 16),
|
||||
FACTOR(CK_TOP_CB_APLL2_D4, "cb_apll2_d4", "apll2", 1, 4),
|
||||
FACTOR(CK_TOP_CB_NET1_D3, "cb_net1_d3", "net1pll", 1, 3),
|
||||
FACTOR(CK_TOP_CB_NET1_D4, "cb_net1_d4", "net1pll", 1, 4),
|
||||
FACTOR(CK_TOP_CB_NET1_D5, "cb_net1_d5", "net1pll", 1, 5),
|
||||
FACTOR(CK_TOP_NET1_D5_D2, "net1_d5_d2", "net1pll", 1, 10),
|
||||
FACTOR(CK_TOP_NET1_D5_D4, "net1_d5_d4", "net1pll", 1, 20),
|
||||
FACTOR(CK_TOP_CB_NET1_D7, "cb_net1_d7", "net1pll", 1, 7),
|
||||
FACTOR(CK_TOP_NET1_D7_D2, "net1_d7_d2", "net1pll", 1, 14),
|
||||
FACTOR(CK_TOP_NET1_D7_D4, "net1_d7_d4", "net1pll", 1, 28),
|
||||
FACTOR(CK_TOP_NET1_D8_D2, "net1_d8_d2", "net1pll", 1, 16),
|
||||
FACTOR(CK_TOP_NET1_D8_D4, "net1_d8_d4", "net1pll", 1, 32),
|
||||
FACTOR(CK_TOP_NET1_D8_D8, "net1_d8_d8", "net1pll", 1, 64),
|
||||
FACTOR(CK_TOP_NET1_D8_D16, "net1_d8_d16", "net1pll", 1, 128),
|
||||
FACTOR(CK_TOP_CB_NET2_D2, "cb_net2_d2", "net2pll", 1, 2),
|
||||
FACTOR(CK_TOP_CB_NET2_D4, "cb_net2_d4", "net2pll", 1, 4),
|
||||
FACTOR(CK_TOP_NET2_D4_D4, "net2_d4_d4", "net2pll", 1, 16),
|
||||
FACTOR(CK_TOP_NET2_D4_D8, "net2_d4_d8", "net2pll", 1, 32),
|
||||
FACTOR(CK_TOP_CB_NET2_D6, "cb_net2_d6", "net2pll", 1, 6),
|
||||
FACTOR(CK_TOP_NET2_D7_D2, "net2_d7_d2", "net2pll", 1, 14),
|
||||
FACTOR(CK_TOP_CB_NET2_D8, "cb_net2_d8", "net2pll", 1, 8),
|
||||
FACTOR(CK_TOP_MSDC_D2, "msdc_d2", "msdcpll", 1, 2),
|
||||
FACTOR(CK_TOP_CB_CKSQ_40M, "cb_cksq_40m", "clkxtal", 1, 1),
|
||||
FACTOR(CK_TOP_CKSQ_40M_D2, "cksq_40m_d2", "cb_cksq_40m", 1, 2),
|
||||
FACTOR(CK_TOP_CB_RTC_32K, "cb_rtc_32k", "cb_cksq_40m", 1, 1250),
|
||||
FACTOR(CK_TOP_CB_RTC_32P7K, "cb_rtc_32p7k", "cb_cksq_40m", 1, 1221),
|
||||
};
|
||||
|
||||
static const char *const netsys_parents[] = { "cb_cksq_40m", "cb_net2_d2" };
|
||||
|
||||
static const char *const netsys_500m_parents[] = { "cb_cksq_40m", "cb_net1_d5",
|
||||
"net1_d5_d2" };
|
||||
|
||||
static const char *const netsys_2x_parents[] = { "cb_cksq_40m", "net2pll" };
|
||||
|
||||
static const char *const eth_gmii_parents[] = { "cb_cksq_40m", "net1_d5_d4" };
|
||||
|
||||
static const char *const eip_parents[] = { "cb_cksq_40m", "cb_net1_d3",
|
||||
"net2pll", "cb_net1_d4",
|
||||
"cb_net1_d5" };
|
||||
|
||||
static const char *const axi_infra_parents[] = { "cb_cksq_40m", "net1_d8_d2" };
|
||||
|
||||
static const char *const uart_parents[] = { "cb_cksq_40m", "cb_m_d8",
|
||||
"m_d8_d2" };
|
||||
|
||||
static const char *const emmc_250m_parents[] = { "cb_cksq_40m", "net1_d5_d2",
|
||||
"net1_d7_d2" };
|
||||
|
||||
static const char *const emmc_400m_parents[] = { "cb_cksq_40m", "msdcpll",
|
||||
"cb_net1_d7", "cb_m_d2",
|
||||
"net1_d7_d2", "cb_net2_d6" };
|
||||
|
||||
static const char *const spi_parents[] = { "cb_cksq_40m", "cb_m_d2",
|
||||
"net1_d7_d2", "net1_d8_d2",
|
||||
"cb_net2_d6", "net1_d5_d4",
|
||||
"cb_m_d4", "net1_d8_d4" };
|
||||
|
||||
static const char *const nfi_parents[] = {
|
||||
"cksq_40m_d2", "net1_d8_d2", "cb_m_d3", "net1_d5_d4", "cb_m_d4",
|
||||
"net1_d7_d4", "net1_d8_d4", "m_d3_d2", "net2_d7_d2", "cb_m_d8"
|
||||
};
|
||||
|
||||
static const char *const pwm_parents[] = { "cb_cksq_40m", "net1_d8_d2",
|
||||
"net1_d5_d4", "cb_m_d4",
|
||||
"m_d8_d2", "cb_rtc_32k" };
|
||||
|
||||
static const char *const i2c_parents[] = { "cb_cksq_40m", "net1_d5_d4",
|
||||
"cb_m_d4", "net1_d8_d4" };
|
||||
|
||||
static const char *const pcie_mbist_250m_parents[] = { "cb_cksq_40m",
|
||||
"net1_d5_d2" };
|
||||
|
||||
static const char *const pextp_tl_ck_parents[] = { "cb_cksq_40m", "cb_net2_d6",
|
||||
"net1_d7_d4", "m_d8_d2",
|
||||
"cb_rtc_32k" };
|
||||
|
||||
static const char *const aud_parents[] = { "cb_cksq_40m", "apll2" };
|
||||
|
||||
static const char *const a1sys_parents[] = { "cb_cksq_40m", "cb_apll2_d4" };
|
||||
|
||||
static const char *const aud_l_parents[] = { "cb_cksq_40m", "apll2",
|
||||
"m_d8_d2" };
|
||||
|
||||
static const char *const usb_phy_parents[] = { "cksq_40m_d2", "m_d8_d2" };
|
||||
|
||||
static const char *const sgm_0_parents[] = { "cb_cksq_40m", "sgmpll" };
|
||||
|
||||
static const char *const sgm_sbus_0_parents[] = { "cb_cksq_40m", "net1_d8_d4" };
|
||||
|
||||
static const char *const sysapb_parents[] = { "cb_cksq_40m", "m_d3_d2" };
|
||||
|
||||
static const char *const eth_refck_50m_parents[] = { "cb_cksq_40m",
|
||||
"net2_d4_d4" };
|
||||
|
||||
static const char *const eth_sys_200m_parents[] = { "cb_cksq_40m",
|
||||
"cb_net2_d4" };
|
||||
|
||||
static const char *const eth_xgmii_parents[] = { "cksq_40m_d2", "net1_d8_d8",
|
||||
"net1_d8_d16" };
|
||||
|
||||
static const char *const dramc_md32_parents[] = { "cb_cksq_40m", "cb_m_d2",
|
||||
"wedmcupll" };
|
||||
|
||||
static const char *const da_xtp_glb_p0_parents[] = { "cb_cksq_40m",
|
||||
"cb_net2_d8" };
|
||||
|
||||
static const char *const da_ckm_xtal_parents[] = { "cb_cksq_40m", "m_d8_d2" };
|
||||
|
||||
static const char *const eth_mii_parents[] = { "cksq_40m_d2", "net2_d4_d8" };
|
||||
|
||||
static const char *const emmc_200m_parents[] = { "cb_cksq_40m", "msdc_d2",
|
||||
"net1_d7_d2", "cb_net2_d6",
|
||||
"net1_d7_d4" };
|
||||
|
||||
static struct mtk_mux top_muxes[] = {
|
||||
/* CLK_CFG_0 */
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents,
|
||||
0x000, 0x004, 0x008, 0, 1, 7, 0x1C0, 0),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_NETSYS_500M_SEL, "netsys_500m_sel",
|
||||
netsys_500m_parents, 0x000, 0x004, 0x008, 8, 2, 15,
|
||||
0x1C0, 1),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_NETSYS_2X_SEL, "netsys_2x_sel",
|
||||
netsys_2x_parents, 0x000, 0x004, 0x008, 16, 1, 23,
|
||||
0x1C0, 2),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_ETH_GMII_SEL, "eth_gmii_sel",
|
||||
eth_gmii_parents, 0x000, 0x004, 0x008, 24, 1, 31,
|
||||
0x1C0, 3),
|
||||
/* CLK_CFG_1 */
|
||||
MUX_GATE_CLR_SET_UPD_FLAGS(CK_TOP_EIP_SEL, "eip_sel", eip_parents,
|
||||
0x010, 0x014, 0x018, 0, 3, 7, 0x1C0, 4,
|
||||
CLK_IS_CRITICAL),
|
||||
MUX_GATE_CLR_SET_UPD_FLAGS(CK_TOP_AXI_INFRA_SEL, "axi_infra_sel",
|
||||
axi_infra_parents, 0x010, 0x014, 0x018, 8,
|
||||
1, 15, 0x1C0, 5, CLK_IS_CRITICAL),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_UART_SEL, "uart_sel", uart_parents, 0x010,
|
||||
0x014, 0x018, 16, 2, 23, 0x1C0, 6),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_EMMC_250M_SEL, "emmc_250m_sel",
|
||||
emmc_250m_parents, 0x010, 0x014, 0x018, 24, 2, 31,
|
||||
0x1C0, 7),
|
||||
/* CLK_CFG_2 */
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_EMMC_400M_SEL, "emmc_400m_sel",
|
||||
emmc_400m_parents, 0x020, 0x024, 0x028, 0, 3, 7,
|
||||
0x1C0, 8),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x020,
|
||||
0x024, 0x028, 8, 3, 15, 0x1C0, 9),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents,
|
||||
0x020, 0x024, 0x028, 16, 3, 23, 0x1C0, 10),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_NFI_SEL, "nfi_sel", nfi_parents, 0x020,
|
||||
0x024, 0x028, 24, 4, 31, 0x1C0, 11),
|
||||
/* CLK_CFG_3 */
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x030,
|
||||
0x034, 0x038, 0, 3, 7, 0x1C0, 12),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x030,
|
||||
0x034, 0x038, 8, 2, 15, 0x1C0, 13),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_PCIE_MBIST_250M_SEL, "pcie_mbist_250m_sel",
|
||||
pcie_mbist_250m_parents, 0x030, 0x034, 0x038, 16,
|
||||
1, 23, 0x1C0, 14),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel",
|
||||
pextp_tl_ck_parents, 0x030, 0x034, 0x038, 24, 3,
|
||||
31, 0x1C0, 15),
|
||||
/* CLK_CFG_4 */
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_PEXTP_TL_P1_SEL, "pextp_tl_ck_p1_sel",
|
||||
pextp_tl_ck_parents, 0x040, 0x044, 0x048, 0, 3, 7,
|
||||
0x1C0, 16),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_USB_SYS_P1_SEL, "usb_sys_p1_sel",
|
||||
eth_gmii_parents, 0x040, 0x044, 0x048, 8, 1, 15,
|
||||
0x1C0, 17),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_USB_XHCI_P1_SEL, "usb_xhci_p1_sel",
|
||||
eth_gmii_parents, 0x040, 0x044, 0x048, 16, 1, 23,
|
||||
0x1C0, 18),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_AUD_SEL, "aud_sel", aud_parents, 0x040,
|
||||
0x044, 0x048, 24, 1, 31, 0x1C0, 19),
|
||||
/* CLK_CFG_5 */
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents,
|
||||
0x050, 0x054, 0x058, 0, 1, 7, 0x1C0, 20),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents,
|
||||
0x050, 0x054, 0x058, 8, 2, 15, 0x1C0, 21),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_A_TUNER_SEL, "a_tuner_sel", a1sys_parents,
|
||||
0x050, 0x054, 0x058, 16, 1, 23, 0x1C0, 22),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_USB_PHY_SEL, "usb_phy_sel", usb_phy_parents,
|
||||
0x050, 0x054, 0x058, 24, 1, 31, 0x1C0, 23),
|
||||
/* CLK_CFG_6 */
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_SGM_0_SEL, "sgm_0_sel", sgm_0_parents,
|
||||
0x060, 0x064, 0x068, 0, 1, 7, 0x1C0, 24),
|
||||
MUX_GATE_CLR_SET_UPD_FLAGS(CK_TOP_SGM_SBUS_0_SEL, "sgm_sbus_0_sel",
|
||||
sgm_sbus_0_parents, 0x060, 0x064, 0x068, 8,
|
||||
1, 15, 0x1C0, 25, CLK_IS_CRITICAL),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_SGM_1_SEL, "sgm_1_sel", sgm_0_parents,
|
||||
0x060, 0x064, 0x068, 16, 1, 23, 0x1C0, 26),
|
||||
MUX_GATE_CLR_SET_UPD_FLAGS(CK_TOP_SGM_SBUS_1_SEL, "sgm_sbus_1_sel",
|
||||
sgm_sbus_0_parents, 0x060, 0x064, 0x068, 24,
|
||||
1, 31, 0x1C0, 27, CLK_IS_CRITICAL),
|
||||
/* CLK_CFG_7 */
|
||||
MUX_GATE_CLR_SET_UPD_FLAGS(CK_TOP_SYSAXI_SEL, "sysaxi_sel",
|
||||
axi_infra_parents, 0x070, 0x074, 0x078, 0, 1,
|
||||
7, 0x1C0, 28, CLK_IS_CRITICAL),
|
||||
MUX_GATE_CLR_SET_UPD_FLAGS(CK_TOP_SYSAPB_SEL, "sysapb_sel",
|
||||
sysapb_parents, 0x070, 0x074, 0x078, 8, 1,
|
||||
15, 0x1C0, 29, CLK_IS_CRITICAL),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_ETH_REFCK_50M_SEL, "eth_refck_50m_sel",
|
||||
eth_refck_50m_parents, 0x070, 0x074, 0x078, 16, 1,
|
||||
23, 0x1C0, 30),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_ETH_SYS_200M_SEL, "eth_sys_200m_sel",
|
||||
eth_sys_200m_parents, 0x070, 0x074, 0x078, 24, 1,
|
||||
31, 0x1C4, 0),
|
||||
/* CLK_CFG_8 */
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_ETH_SYS_SEL, "eth_sys_sel",
|
||||
pcie_mbist_250m_parents, 0x080, 0x084, 0x088, 0, 1,
|
||||
7, 0x1C4, 1),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_ETH_XGMII_SEL, "eth_xgmii_sel",
|
||||
eth_xgmii_parents, 0x080, 0x084, 0x088, 8, 2, 15,
|
||||
0x1C4, 2),
|
||||
MUX_GATE_CLR_SET_UPD_FLAGS(CK_TOP_DRAMC_SEL, "dramc_sel",
|
||||
usb_phy_parents, 0x080, 0x084, 0x088, 16, 1,
|
||||
23, 0x1C4, 3, CLK_IS_CRITICAL),
|
||||
MUX_GATE_CLR_SET_UPD_FLAGS(CK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel",
|
||||
dramc_md32_parents, 0x080, 0x084, 0x088, 24,
|
||||
2, 31, 0x1C4, 4, CLK_IS_CRITICAL),
|
||||
/* CLK_CFG_9 */
|
||||
MUX_GATE_CLR_SET_UPD_FLAGS(CK_TOP_INFRA_F26M_SEL, "csw_infra_f26m_sel",
|
||||
usb_phy_parents, 0x090, 0x094, 0x098, 0, 1,
|
||||
7, 0x1C4, 5, CLK_IS_CRITICAL),
|
||||
MUX_GATE_CLR_SET_UPD_FLAGS(CK_TOP_PEXTP_P0_SEL, "pextp_p0_sel",
|
||||
usb_phy_parents, 0x090, 0x094, 0x098, 8, 1,
|
||||
15, 0x1C4, 6, CLK_IS_CRITICAL),
|
||||
MUX_GATE_CLR_SET_UPD_FLAGS(CK_TOP_PEXTP_P1_SEL, "pextp_p1_sel",
|
||||
usb_phy_parents, 0x090, 0x094, 0x098, 16, 1,
|
||||
23, 0x1C4, 7, CLK_IS_CRITICAL),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_DA_XTP_GLB_P0_SEL, "da_xtp_glb_p0_sel",
|
||||
da_xtp_glb_p0_parents, 0x090, 0x094, 0x098, 24, 1,
|
||||
31, 0x1C4, 8),
|
||||
/* CLK_CFG_10 */
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_DA_XTP_GLB_P1_SEL, "da_xtp_glb_p1_sel",
|
||||
da_xtp_glb_p0_parents, 0x0A0, 0x0A4, 0x0A8, 0, 1,
|
||||
7, 0x1C4, 9),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_CKM_SEL, "ckm_sel", usb_phy_parents, 0x0A0,
|
||||
0x0A4, 0x0A8, 8, 1, 15, 0x1C4, 10),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_DA_CKM_XTAL_SEL, "da_ckm_xtal_sel",
|
||||
da_ckm_xtal_parents, 0x0A0, 0x0A4, 0x0A8, 16, 1,
|
||||
23, 0x1C4, 11),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_PEXTP_SEL, "pextp_sel", usb_phy_parents,
|
||||
0x0A0, 0x0A4, 0x0A8, 24, 1, 31, 0x1C4, 12),
|
||||
/* CLK_CFG_11 */
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_ETH_MII_SEL, "eth_mii_sel", eth_mii_parents,
|
||||
0x0B0, 0x0B4, 0x0B8, 0, 1, 7, 0x1C4, 13),
|
||||
MUX_GATE_CLR_SET_UPD(CK_TOP_EMMC_200M_SEL, "emmc_200m_sel",
|
||||
emmc_200m_parents, 0x0B0, 0x0B4, 0x0B8, 8, 3, 15,
|
||||
0x1C4, 14),
|
||||
};
|
||||
|
||||
static const struct mtk_composite top_adj_divs[] = {
|
||||
DIV_GATE(CK_TOP_AUD_I2S_M, "aud_i2s_m", "aud_sel", 0x0420, 0, 0x0420, 8,
|
||||
8),
|
||||
};
|
||||
|
||||
static struct clk_onecell_data *mt7987_top_clk_data __initdata;
|
||||
|
||||
static void __init mtk_topckgen_init(struct device_node *node)
|
||||
{
|
||||
int r;
|
||||
void __iomem *base;
|
||||
|
||||
base = of_iomap(node, 0);
|
||||
if (!base) {
|
||||
pr_err("%s(): ioremap failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
mt7987_top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
|
||||
|
||||
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs),
|
||||
mt7987_top_clk_data);
|
||||
mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node,
|
||||
&mt7987_clk_lock, mt7987_top_clk_data);
|
||||
mtk_clk_register_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs),
|
||||
base, &mt7987_clk_lock,
|
||||
mt7987_top_clk_data);
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get,
|
||||
mt7987_top_clk_data);
|
||||
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt7987-topckgen", mtk_topckgen_init);
|
||||
@@ -741,10 +741,10 @@ static const struct mtk_gate infra_clks[] __initconst = {
|
||||
"infra_133m_mck", &infra1_cg_regs, 20),
|
||||
GATE_INFRA1(CK_INFRA_66M_AP_DMA_BCK, "infra_66m_ap_dma_bck",
|
||||
"infra_66m_mck", 21),
|
||||
GATE_INFRA1(CK_INFRA_66M_SEJ_BCK, "infra_hf_66m_sej_bck",
|
||||
"infra_66m_mck", 29),
|
||||
GATE_INFRA1(CK_INFRA_PRE_CK_SEJ_F13M, "infra_pre_ck_sej_f13m",
|
||||
"infra_ck_f26m", 30),
|
||||
GATE_CRITICAL(CK_INFRA_66M_SEJ_BCK, "infra_hf_66m_sej_bck",
|
||||
"infra_66m_mck", &infra1_cg_regs, 29),
|
||||
GATE_CRITICAL(CK_INFRA_PRE_CK_SEJ_F13M, "infra_pre_ck_sej_f13m",
|
||||
"infra_ck_f26m", &infra1_cg_regs, 30),
|
||||
/* INFRA2 */
|
||||
GATE_INFRA2(CK_INFRA_26M_THERM_SYSTEM, "infra_hf_26m_therm_system",
|
||||
"infra_ck_f26m", 0),
|
||||
@@ -812,10 +812,10 @@ static const struct mtk_gate infra_clks[] __initconst = {
|
||||
"infra_usb_frmcnt_o", &infra3_cg_regs, 8),
|
||||
GATE_CRITICAL(CK_INFRA_USB_FRMCNT_CK_P1, "infra_usb_frmcnt_ck_p1",
|
||||
"infra_usb_frmcnt_o_p1", &infra3_cg_regs, 9),
|
||||
GATE_INFRA3(CK_INFRA_USB_PIPE, "infra_usb_pipe", "infra_usb_pipe_o",
|
||||
10),
|
||||
GATE_INFRA3(CK_INFRA_USB_PIPE_CK_P1, "infra_usb_pipe_ck_p1",
|
||||
"infra_usb_pipe_o_p1", 11),
|
||||
GATE_CRITICAL(CK_INFRA_USB_PIPE, "infra_usb_pipe", "infra_usb_pipe_o",
|
||||
&infra3_cg_regs, 10),
|
||||
GATE_CRITICAL(CK_INFRA_USB_PIPE_CK_P1, "infra_usb_pipe_ck_p1",
|
||||
"infra_usb_pipe_o_p1", &infra3_cg_regs, 11),
|
||||
GATE_INFRA3(CK_INFRA_USB_UTMI, "infra_usb_utmi", "infra_usb_utmi_o",
|
||||
12),
|
||||
GATE_INFRA3(CK_INFRA_USB_UTMI_CK_P1, "infra_usb_utmi_ck_p1",
|
||||
|
||||
1218
feeds/mediatek-sdk/mediatek/files-5.4/drivers/iio/pressure/zts8232.c
Normal file
1218
feeds/mediatek-sdk/mediatek/files-5.4/drivers/iio/pressure/zts8232.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -20,12 +20,72 @@
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <net/dsa.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "an8855.h"
|
||||
#include "an8855_nl.h"
|
||||
#include "an8855_phy.h"
|
||||
|
||||
/* AN8855 driver version */
|
||||
#define ARHT_AN8855_DSA_DRIVER_VER "1.0.1-L5.4"
|
||||
#define ARHT_AN8855_DSA_DRIVER_VER "1.0.2"
|
||||
|
||||
#define ARHT_CHIP_NAME "an8855"
|
||||
#define ARHT_PROC_DIR "air_sw"
|
||||
#define ARHT_PROC_NODE_DEVICE "device"
|
||||
|
||||
struct proc_dir_entry *proc_an8855_dsa_dir;
|
||||
|
||||
/* T830 AN8855 Reference Board */
|
||||
static const struct an8855_led_cfg led_cfg[] = {
|
||||
/*************************************************************************
|
||||
* Enable, LED idx, LED Polarity, LED ON event, LED Blink event LED Freq
|
||||
*************************************************************************
|
||||
*/
|
||||
/* GPIO0 */
|
||||
{1, P4_LED0, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO1 */
|
||||
{1, P4_LED1, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO2 */
|
||||
{1, P0_LED0, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO3 */
|
||||
{1, P0_LED1, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO4 */
|
||||
{1, P1_LED0, LED_LOW, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO5 */
|
||||
{1, P1_LED1, LED_LOW, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO6 */
|
||||
{0, PHY_LED_MAX, LED_LOW, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO7 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO8 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO9 */
|
||||
{1, P2_LED0, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO10 */
|
||||
{1, P2_LED1, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO11 */
|
||||
{1, P3_LED0, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO12 */
|
||||
{1, P3_LED1, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO13 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO14 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO15 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO16 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO17 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO18 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO19 */
|
||||
{0, PHY_LED_MAX, LED_LOW, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO20 */
|
||||
{0, PHY_LED_MAX, LED_LOW, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
};
|
||||
|
||||
/* String, offset, and register size in bytes if different from 4 bytes */
|
||||
static const struct an8855_mib_desc an8855_mib[] = {
|
||||
@@ -99,7 +159,6 @@ an8855_mii_write(struct an8855_priv *priv, u32 reg, u32 val)
|
||||
ret = bus->write(bus, priv->phy_base, 0x14, (val & 0xFFFF));
|
||||
|
||||
ret = bus->write(bus, priv->phy_base, 0x1f, 0);
|
||||
ret = bus->write(bus, priv->phy_base, 0x10, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(&bus->dev, "failed to write an8855 register\n");
|
||||
@@ -130,7 +189,6 @@ an8855_mii_read(struct an8855_priv *priv, u32 reg)
|
||||
hi = bus->read(bus, priv->phy_base, 0x17);
|
||||
|
||||
ret = bus->write(bus, priv->phy_base, 0x1f, 0);
|
||||
ret = bus->write(bus, priv->phy_base, 0x10, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(&bus->dev, "failed to read an8855 register\n");
|
||||
return ret;
|
||||
@@ -327,16 +385,22 @@ an8855_phy_write(struct dsa_switch *ds, int port, int regnum,
|
||||
static int
|
||||
an8855_cl45_read(struct an8855_priv *priv, int port, int devad, int regnum)
|
||||
{
|
||||
regnum = MII_ADDR_C45 | (devad << 16) | regnum;
|
||||
return mdiobus_read_nested(priv->bus, port, regnum);
|
||||
an8855_cl22_write(priv, port, 0x0d, devad);
|
||||
an8855_cl22_write(priv, port, 0x0e, regnum);
|
||||
an8855_cl22_write(priv, port, 0x0d, devad | (0x4000));
|
||||
return an8855_cl22_read(priv, port, 0x0e);
|
||||
}
|
||||
|
||||
static int
|
||||
an8855_cl45_write(struct an8855_priv *priv, int port, int devad, int regnum,
|
||||
u16 val)
|
||||
{
|
||||
regnum = MII_ADDR_C45 | (devad << 16) | regnum;
|
||||
return mdiobus_write_nested(priv->bus, port, regnum, val);
|
||||
an8855_cl22_write(priv, port, 0x0d, devad);
|
||||
an8855_cl22_write(priv, port, 0x0e, regnum);
|
||||
an8855_cl22_write(priv, port, 0x0d, devad | (0x4000));
|
||||
an8855_cl22_write(priv, port, 0x0e, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -457,7 +521,6 @@ an8855_port_enable(struct dsa_switch *ds, int port, struct phy_device *phy)
|
||||
priv->ports[port].pm |= PORTMATRIX_MATRIX(BIT(AN8855_CPU_PORT));
|
||||
priv->ports[port].enable = true;
|
||||
an8855_write(priv, AN8855_PORTMATRIX_P(port), priv->ports[port].pm);
|
||||
an8855_clear(priv, AN8855_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
@@ -479,7 +542,6 @@ an8855_port_disable(struct dsa_switch *ds, int port)
|
||||
*/
|
||||
priv->ports[port].enable = false;
|
||||
an8855_write(priv, AN8855_PORTMATRIX_P(port), PORTMATRIX_CLR);
|
||||
an8855_clear(priv, AN8855_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
}
|
||||
@@ -1089,13 +1151,223 @@ setup_unused_ports(struct dsa_switch *ds, u32 pm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_led_set_usr_def(struct dsa_switch *ds, u8 entity,
|
||||
int polar, u16 on_evt, u16 blk_evt, u8 led_freq)
|
||||
{
|
||||
struct an8855_priv *priv = ds->priv;
|
||||
u32 cl45_data = 0;
|
||||
|
||||
if (polar == LED_HIGH)
|
||||
on_evt |= LED_ON_POL;
|
||||
else
|
||||
on_evt &= ~LED_ON_POL;
|
||||
|
||||
/* LED on event */
|
||||
an8855_phy_cl45_write(priv, (entity / 4), PHY_DEV1E,
|
||||
PHY_SINGLE_LED_ON_CTRL(entity % 4), on_evt | LED_ON_EN);
|
||||
|
||||
/* LED blink event */
|
||||
an8855_phy_cl45_write(priv, (entity / 4), PHY_DEV1E,
|
||||
PHY_SINGLE_LED_BLK_CTRL(entity % 4), blk_evt);
|
||||
|
||||
/* LED freq */
|
||||
switch (led_freq) {
|
||||
case AIR_LED_BLK_DUR_32M:
|
||||
cl45_data = 0x30e;
|
||||
break;
|
||||
case AIR_LED_BLK_DUR_64M:
|
||||
cl45_data = 0x61a;
|
||||
break;
|
||||
case AIR_LED_BLK_DUR_128M:
|
||||
cl45_data = 0xc35;
|
||||
break;
|
||||
case AIR_LED_BLK_DUR_256M:
|
||||
cl45_data = 0x186a;
|
||||
break;
|
||||
case AIR_LED_BLK_DUR_512M:
|
||||
cl45_data = 0x30d4;
|
||||
break;
|
||||
case AIR_LED_BLK_DUR_1024M:
|
||||
cl45_data = 0x61a8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
an8855_phy_cl45_write(priv, (entity / 4), PHY_DEV1E,
|
||||
PHY_SINGLE_LED_BLK_DUR(entity % 4), cl45_data);
|
||||
|
||||
an8855_phy_cl45_write(priv, (entity / 4), PHY_DEV1E,
|
||||
PHY_SINGLE_LED_ON_DUR(entity % 4), (cl45_data >> 1));
|
||||
|
||||
/* Disable DATA & BAD_SSD for port LED blink behavior */
|
||||
cl45_data = an8855_phy_cl45_read(priv, (entity / 4), PHY_DEV1E,
|
||||
PHY_PMA_CTRL);
|
||||
cl45_data &= ~BIT(0);
|
||||
cl45_data &= ~BIT(15);
|
||||
an8855_phy_cl45_write(priv, (entity / 4), PHY_DEV1E,
|
||||
PHY_PMA_CTRL, cl45_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_led_set_mode(struct dsa_switch *ds, u8 mode)
|
||||
{
|
||||
struct an8855_priv *priv = ds->priv;
|
||||
u16 cl45_data;
|
||||
|
||||
cl45_data = an8855_phy_cl45_read(priv, 0, PHY_DEV1F, PHY_LED_BCR);
|
||||
switch (mode) {
|
||||
case AN8855_LED_MODE_DISABLE:
|
||||
cl45_data &= ~LED_BCR_EXT_CTRL;
|
||||
cl45_data &= ~LED_BCR_MODE_MASK;
|
||||
cl45_data |= LED_BCR_MODE_DISABLE;
|
||||
break;
|
||||
case AN8855_LED_MODE_USER_DEFINE:
|
||||
cl45_data |= LED_BCR_EXT_CTRL;
|
||||
cl45_data |= LED_BCR_CLK_EN;
|
||||
break;
|
||||
default:
|
||||
dev_err(priv->dev, "LED mode%d is not supported!\n", mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
an8855_phy_cl45_write(priv, 0, PHY_DEV1F, PHY_LED_BCR, cl45_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_led_set_state(struct dsa_switch *ds, u8 entity, u8 state)
|
||||
{
|
||||
struct an8855_priv *priv = ds->priv;
|
||||
u16 cl45_data = 0;
|
||||
|
||||
/* Change to per port contorl */
|
||||
cl45_data = an8855_phy_cl45_read(priv, (entity / 4), PHY_DEV1E,
|
||||
PHY_LED_CTRL_SELECT);
|
||||
|
||||
if (state == 1)
|
||||
cl45_data |= (1 << (entity % 4));
|
||||
else
|
||||
cl45_data &= ~(1 << (entity % 4));
|
||||
|
||||
an8855_phy_cl45_write(priv, (entity / 4), PHY_DEV1E,
|
||||
PHY_LED_CTRL_SELECT, cl45_data);
|
||||
|
||||
/* LED enable setting */
|
||||
cl45_data = an8855_phy_cl45_read(priv, (entity / 4),
|
||||
PHY_DEV1E, PHY_SINGLE_LED_ON_CTRL(entity % 4));
|
||||
|
||||
if (state == 1)
|
||||
cl45_data |= LED_ON_EN;
|
||||
else
|
||||
cl45_data &= ~LED_ON_EN;
|
||||
|
||||
an8855_phy_cl45_write(priv, (entity / 4), PHY_DEV1E,
|
||||
PHY_SINGLE_LED_ON_CTRL(entity % 4), cl45_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_led_init(struct dsa_switch *ds)
|
||||
{
|
||||
struct an8855_priv *priv = ds->priv;
|
||||
u32 val, led_count = ARRAY_SIZE(led_cfg);
|
||||
int ret = 0, id;
|
||||
u32 tmp_val = 0;
|
||||
u32 tmp_id = 0;
|
||||
|
||||
ret = an8855_led_set_mode(ds, AN8855_LED_MODE_USER_DEFINE);
|
||||
if (ret != 0) {
|
||||
dev_err(priv->dev, "led_set_mode fail(ret:%d)!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (id = 0; id < led_count; id++) {
|
||||
ret = an8855_led_set_state(ds,
|
||||
led_cfg[id].phy_led_idx, led_cfg[id].en);
|
||||
if (ret != 0) {
|
||||
dev_err(priv->dev, "led_set_state fail(ret:%d)!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (led_cfg[id].en == 1) {
|
||||
ret = an8855_led_set_usr_def(ds,
|
||||
led_cfg[id].phy_led_idx,
|
||||
led_cfg[id].pol, led_cfg[id].on_cfg,
|
||||
led_cfg[id].blk_cfg,
|
||||
led_cfg[id].led_freq);
|
||||
if (ret != 0) {
|
||||
dev_err(priv->dev, "led_set_usr_def fail!\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Setting for System LED & Loop LED */
|
||||
an8855_write(priv, RG_GPIO_OE, 0x0);
|
||||
an8855_write(priv, RG_GPIO_CTRL, 0x0);
|
||||
val = 0;
|
||||
an8855_write(priv, RG_GPIO_L_INV, val);
|
||||
|
||||
val = 0x1001;
|
||||
an8855_write(priv, RG_GPIO_CTRL, val);
|
||||
val = an8855_read(priv, RG_GPIO_DATA);
|
||||
val |= BITS(1, 3);
|
||||
val &= ~(BIT(0));
|
||||
val &= ~(BIT(6));
|
||||
|
||||
an8855_write(priv, RG_GPIO_DATA, val);
|
||||
val = an8855_read(priv, RG_GPIO_OE);
|
||||
val |= 0x41;
|
||||
an8855_write(priv, RG_GPIO_OE, val);
|
||||
|
||||
/* Mapping between GPIO & LED */
|
||||
val = 0;
|
||||
for (id = 0; id < led_count; id++) {
|
||||
/* Skip GPIO6, due to GPIO6 does not support PORT LED */
|
||||
if (id == 6)
|
||||
continue;
|
||||
|
||||
if (led_cfg[id].en == 1) {
|
||||
if (id < 7)
|
||||
val |= led_cfg[id].phy_led_idx << ((id % 4) * 8);
|
||||
else
|
||||
val |= led_cfg[id].phy_led_idx << (((id - 1) % 4) * 8);
|
||||
}
|
||||
|
||||
if (id < 7)
|
||||
tmp_id = id;
|
||||
else
|
||||
tmp_id = id - 1;
|
||||
|
||||
if ((tmp_id % 4) == 0x3) {
|
||||
an8855_write(priv, RG_GPIO_LED_SEL(tmp_id / 4), val);
|
||||
tmp_val = an8855_read(priv, RG_GPIO_LED_SEL(tmp_id / 4));
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Turn on LAN LED mode */
|
||||
val = 0;
|
||||
for (id = 0; id < led_count; id++) {
|
||||
if (led_cfg[id].en == 1)
|
||||
val |= 0x1 << id;
|
||||
}
|
||||
an8855_write(priv, RG_GPIO_LED_MODE, val);
|
||||
|
||||
/* Force clear blink pulse for per port LED */
|
||||
an8855_phy_cl45_write(priv, 0, PHY_DEV1F, PHY_LED_BLINK_DUR_CTRL, 0x1f);
|
||||
usleep_range(1000, 5000);
|
||||
an8855_phy_cl45_write(priv, 0, PHY_DEV1F, PHY_LED_BLINK_DUR_CTRL, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
an8855_setup(struct dsa_switch *ds)
|
||||
{
|
||||
struct an8855_priv *priv = ds->priv;
|
||||
struct an8855_dummy_poll p;
|
||||
u32 unused_pm = 0;
|
||||
u32 val, id;
|
||||
u32 val, id, led_count = ARRAY_SIZE(led_cfg);
|
||||
int ret, i;
|
||||
|
||||
/* Reset whole chip through gpio pin or memory-mapped registers for
|
||||
@@ -1130,6 +1402,63 @@ an8855_setup(struct dsa_switch *ds)
|
||||
priv->phy_base = priv->phy_base_new;
|
||||
}
|
||||
|
||||
for (i = 0; i < AN8855_NUM_PHYS; i++) {
|
||||
val = an8855_phy_read(ds, i, MII_BMCR);
|
||||
val |= BMCR_ISOLATE;
|
||||
an8855_phy_write(ds, i, MII_BMCR, val);
|
||||
}
|
||||
|
||||
/* AN8855H need to setup before switch init */
|
||||
val = an8855_read(priv, PKG_SEL);
|
||||
if ((val & 0x7) == PAG_SEL_AN8855H) {
|
||||
/* Invert for LED activity change */
|
||||
val = an8855_read(priv, RG_GPIO_L_INV);
|
||||
for (id = 0; id < led_count; id++) {
|
||||
if ((led_cfg[id].pol == LED_HIGH) &&
|
||||
(led_cfg[id].en == 1))
|
||||
val |= 0x1 << id;
|
||||
}
|
||||
an8855_write(priv, RG_GPIO_L_INV, (val | 0x1));
|
||||
|
||||
/* MCU NOP CMD */
|
||||
an8855_write(priv, RG_GDMP_RAM, 0x846);
|
||||
an8855_write(priv, RG_GDMP_RAM + 4, 0x4a);
|
||||
|
||||
/* Enable MCU */
|
||||
val = an8855_read(priv, RG_CLK_CPU_ICG);
|
||||
an8855_write(priv, RG_CLK_CPU_ICG, val | MCU_ENABLE);
|
||||
usleep_range(1000, 5000);
|
||||
|
||||
/* Disable MCU watchdog */
|
||||
val = an8855_read(priv, RG_TIMER_CTL);
|
||||
an8855_write(priv, RG_TIMER_CTL, (val & (~WDOG_ENABLE)));
|
||||
|
||||
/* Configure interrupt */
|
||||
an8855_write(priv, RG_INTB_MODE, (0x1 << priv->intr_pin));
|
||||
|
||||
/* LED settings for T830 reference board */
|
||||
ret = an8855_led_init(ds);
|
||||
if (ret < 0) {
|
||||
dev_err(priv->dev, "an8855_led_init fail. (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust to reduce noise */
|
||||
for (i = 0; i < AN8855_NUM_PHYS; i++) {
|
||||
an8855_phy_cl45_write(priv, i, PHY_DEV1E,
|
||||
PHY_TX_PAIR_DLY_SEL_GBE, 0x4040);
|
||||
|
||||
an8855_phy_cl45_write(priv, i, PHY_DEV1E,
|
||||
PHY_RXADC_CTRL, 0x1010);
|
||||
|
||||
an8855_phy_cl45_write(priv, i, PHY_DEV1E,
|
||||
PHY_RXADC_REV_0, 0x100);
|
||||
|
||||
an8855_phy_cl45_write(priv, i, PHY_DEV1E,
|
||||
PHY_RXADC_REV_1, 0x100);
|
||||
}
|
||||
|
||||
/* Let phylink decide the interface later. */
|
||||
priv->p5_interface = PHY_INTERFACE_MODE_NA;
|
||||
|
||||
@@ -1139,6 +1468,10 @@ an8855_setup(struct dsa_switch *ds)
|
||||
an8855_rmw(priv, AN8855_BPC, AN8855_BPDU_PORT_FW_MASK,
|
||||
AN8855_BPDU_CPU_ONLY);
|
||||
|
||||
val = an8855_read(priv, AN8855_CKGCR);
|
||||
val &= ~(CKG_LNKDN_GLB_STOP | CKG_LNKDN_PORT_STOP);
|
||||
an8855_write(priv, AN8855_CKGCR, val);
|
||||
|
||||
/* Enable and reset MIB counters */
|
||||
an8855_mib_reset(ds);
|
||||
|
||||
@@ -1157,8 +1490,18 @@ an8855_setup(struct dsa_switch *ds)
|
||||
PVC_EG_TAG(AN8855_VLAN_EG_CONSISTENT));
|
||||
}
|
||||
|
||||
for (i = 0; i < AN8855_NUM_PHYS; i++) {
|
||||
val = an8855_phy_read(ds, i, MII_BMCR);
|
||||
val &= ~BMCR_ISOLATE;
|
||||
an8855_phy_write(ds, i, MII_BMCR, val);
|
||||
}
|
||||
|
||||
an8855_phy_setup(ds);
|
||||
|
||||
/* PHY restart AN*/
|
||||
for (i = 0; i < AN8855_NUM_PHYS; i++)
|
||||
an8855_phy_write(ds, i, MII_BMCR, 0x1240);
|
||||
|
||||
/* Group and enable unused ports as a standalone dumb switch. */
|
||||
setup_unused_ports(ds, unused_pm);
|
||||
|
||||
@@ -1255,6 +1598,28 @@ an8855_set_hsgmii_mode(struct an8855_priv *priv)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
/* TX FIR - improve TX EYE */
|
||||
val = an8855_read(priv, INTF_CTRL_10);
|
||||
val &= ~(0x3f << 16);
|
||||
val |= BIT(21);
|
||||
val &= ~(0x1f << 24);
|
||||
val |= (0x4 << 24);
|
||||
val |= BIT(29);
|
||||
an8855_write(priv, INTF_CTRL_10, val);
|
||||
|
||||
val = an8855_read(priv, INTF_CTRL_11);
|
||||
val &= ~(0x3f);
|
||||
val |= BIT(6);
|
||||
an8855_write(priv, INTF_CTRL_11, val);
|
||||
|
||||
/* RX CDR - improve RX Jitter Tolerance */
|
||||
val = an8855_read(priv, RG_QP_CDR_LPF_BOT_LIM);
|
||||
val &= ~(0x7 << 24);
|
||||
val |= (0x5 << 24);
|
||||
val &= ~(0x7 << 20);
|
||||
val |= (0x5 << 20);
|
||||
an8855_write(priv, RG_QP_CDR_LPF_BOT_LIM, val);
|
||||
|
||||
/* PLL */
|
||||
val = an8855_read(priv, QP_DIG_MODE_CTRL_1);
|
||||
val &= ~(0x3 << 2);
|
||||
@@ -1384,7 +1749,7 @@ an8855_set_hsgmii_mode(struct an8855_priv *priv)
|
||||
val &= ~(0xf << 25);
|
||||
val |= (0x1 << 25);
|
||||
val &= ~(0x7 << 29);
|
||||
val |= (0x3 << 29);
|
||||
val |= (0x6 << 29);
|
||||
an8855_write(priv, RG_QP_CDR_LPF_SETVALUE, val);
|
||||
|
||||
val = an8855_read(priv, RG_QP_CDR_PR_CKREF_DIV1);
|
||||
@@ -1415,12 +1780,9 @@ an8855_set_hsgmii_mode(struct an8855_priv *priv)
|
||||
val |= (0x4 << 24);
|
||||
an8855_write(priv, RG_QP_CDR_PR_CKREF_DIV1, val);
|
||||
|
||||
val = an8855_read(priv, PLL_CTRL_0);
|
||||
val |= BIT(0);
|
||||
an8855_write(priv, PLL_CTRL_0, val);
|
||||
|
||||
val = an8855_read(priv, RX_CTRL_26);
|
||||
val &= ~BIT(23);
|
||||
val |= BIT(23);
|
||||
val &= ~BIT(24);
|
||||
val |= BIT(26);
|
||||
an8855_write(priv, RX_CTRL_26, val);
|
||||
|
||||
@@ -1448,8 +1810,8 @@ an8855_set_hsgmii_mode(struct an8855_priv *priv)
|
||||
val = an8855_read(priv, RX_CTRL_8);
|
||||
val &= ~(0xfff << 16);
|
||||
val |= (0x200 << 16);
|
||||
val &= ~(0x7fff << 14);
|
||||
val |= (0xfff << 14);
|
||||
val &= ~(0x7fff << 0);
|
||||
val |= (0xfff << 0);
|
||||
an8855_write(priv, RX_CTRL_8, val);
|
||||
|
||||
/* Frequency memter */
|
||||
@@ -1468,6 +1830,10 @@ an8855_set_hsgmii_mode(struct an8855_priv *priv)
|
||||
val |= (0x2710 << 0);
|
||||
an8855_write(priv, RX_CTRL_7, val);
|
||||
|
||||
val = an8855_read(priv, PLL_CTRL_0);
|
||||
val |= BIT(0);
|
||||
an8855_write(priv, PLL_CTRL_0, val);
|
||||
|
||||
/* PCS Init */
|
||||
val = an8855_read(priv, RG_HSGMII_PCS_CTROL_1);
|
||||
val &= ~BIT(30);
|
||||
@@ -1507,6 +1873,28 @@ an8855_sgmii_setup(struct an8855_priv *priv, int mode)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
/* TX FIR - improve TX EYE */
|
||||
val = an8855_read(priv, INTF_CTRL_10);
|
||||
val &= ~(0x3f << 16);
|
||||
val |= BIT(21);
|
||||
val &= ~(0x1f << 24);
|
||||
val |= BIT(29);
|
||||
an8855_write(priv, INTF_CTRL_10, val);
|
||||
|
||||
val = an8855_read(priv, INTF_CTRL_11);
|
||||
val &= ~(0x3f);
|
||||
val |= (0xd << 0);
|
||||
val |= BIT(6);
|
||||
an8855_write(priv, INTF_CTRL_11, val);
|
||||
|
||||
/* RX CDR - improve RX Jitter Tolerance */
|
||||
val = an8855_read(priv, RG_QP_CDR_LPF_BOT_LIM);
|
||||
val &= ~(0x7 << 24);
|
||||
val |= (0x6 << 24);
|
||||
val &= ~(0x7 << 20);
|
||||
val |= (0x6 << 20);
|
||||
an8855_write(priv, RG_QP_CDR_LPF_BOT_LIM, val);
|
||||
|
||||
/* PMA Init */
|
||||
/* PLL */
|
||||
val = an8855_read(priv, QP_DIG_MODE_CTRL_1);
|
||||
@@ -1666,15 +2054,10 @@ an8855_sgmii_setup(struct an8855_priv *priv, int mode)
|
||||
val |= (0x4 << 24);
|
||||
an8855_write(priv, RG_QP_CDR_PR_CKREF_DIV1, val);
|
||||
|
||||
val = an8855_read(priv, PLL_CTRL_0);
|
||||
val |= BIT(0);
|
||||
an8855_write(priv, PLL_CTRL_0, val);
|
||||
|
||||
val = an8855_read(priv, RX_CTRL_26);
|
||||
val &= ~BIT(23);
|
||||
if (mode == SGMII_MODE_AN)
|
||||
val |= BIT(23);
|
||||
val &= ~BIT(24);
|
||||
val |= BIT(26);
|
||||
|
||||
an8855_write(priv, RX_CTRL_26, val);
|
||||
|
||||
val = an8855_read(priv, RX_DLY_0);
|
||||
@@ -1721,6 +2104,10 @@ an8855_sgmii_setup(struct an8855_priv *priv, int mode)
|
||||
val |= (0x2710 << 0);
|
||||
an8855_write(priv, RX_CTRL_7, val);
|
||||
|
||||
val = an8855_read(priv, PLL_CTRL_0);
|
||||
val |= BIT(0);
|
||||
an8855_write(priv, PLL_CTRL_0, val);
|
||||
|
||||
if (mode == SGMII_MODE_FORCE) {
|
||||
/* PCS Init */
|
||||
val = an8855_read(priv, QP_DIG_MODE_CTRL_0);
|
||||
@@ -1805,7 +2192,6 @@ an8855_sgmii_setup(struct an8855_priv *priv, int mode)
|
||||
/* Restart AN */
|
||||
val = an8855_read(priv, SGMII_REG_AN0);
|
||||
val |= BIT(9);
|
||||
val |= BIT(15);
|
||||
an8855_write(priv, SGMII_REG_AN0, val);
|
||||
}
|
||||
|
||||
@@ -1922,16 +2308,6 @@ unsupported:
|
||||
an8855_write(priv, AN8855_PMCR_P(port), mcr_new);
|
||||
}
|
||||
|
||||
static void
|
||||
an8855_phylink_mac_link_down(struct dsa_switch *ds, int port,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct an8855_priv *priv = ds->priv;
|
||||
|
||||
an8855_clear(priv, AN8855_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
|
||||
}
|
||||
|
||||
static void
|
||||
an8855_phylink_mac_link_up(struct dsa_switch *ds, int port,
|
||||
unsigned int mode,
|
||||
@@ -2194,6 +2570,51 @@ an8855_sw_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
|
||||
return priv->info->phy_write(ds, port, regnum, val);
|
||||
}
|
||||
|
||||
static int an8855_proc_device_read(struct seq_file *seq, void *v)
|
||||
{
|
||||
seq_printf(seq, "%s\n", ARHT_CHIP_NAME);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_proc_device_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, an8855_proc_device_read, 0);
|
||||
}
|
||||
|
||||
#if (KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE)
|
||||
static const struct proc_ops an8855_proc_device_fops = {
|
||||
.proc_open = an8855_proc_device_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
};
|
||||
#else
|
||||
static const struct file_operations an8855_proc_device_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = an8855_proc_device_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int an8855_proc_device_init(void)
|
||||
{
|
||||
if (!proc_an8855_dsa_dir)
|
||||
proc_an8855_dsa_dir = proc_mkdir(ARHT_PROC_DIR, 0);
|
||||
|
||||
proc_create(ARHT_PROC_NODE_DEVICE, 0400, proc_an8855_dsa_dir,
|
||||
&an8855_proc_device_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void an8855_proc_device_exit(void)
|
||||
{
|
||||
remove_proc_entry(ARHT_PROC_NODE_DEVICE, 0);
|
||||
}
|
||||
|
||||
static const struct dsa_switch_ops an8855_switch_ops = {
|
||||
.get_tag_protocol = air_get_tag_protocol,
|
||||
.setup = an8855_sw_setup,
|
||||
@@ -2217,10 +2638,6 @@ static const struct dsa_switch_ops an8855_switch_ops = {
|
||||
.port_mirror_add = an8855_port_mirror_add,
|
||||
.port_mirror_del = an8855_port_mirror_del,
|
||||
.phylink_validate = an8855_phylink_validate,
|
||||
.phylink_mac_link_state = an8855_sw_phylink_mac_link_state,
|
||||
.phylink_mac_config = an8855_phylink_mac_config,
|
||||
.phylink_mac_link_down = an8855_phylink_mac_link_down,
|
||||
.phylink_mac_link_up = an8855_phylink_mac_link_up,
|
||||
.get_mac_eee = an8855_get_mac_eee,
|
||||
.set_mac_eee = an8855_set_mac_eee,
|
||||
};
|
||||
@@ -2308,6 +2725,13 @@ an8855_probe(struct mdio_device *mdiodev)
|
||||
if ((ret < 0) || (priv->phy_base_new > 0x1f))
|
||||
priv->phy_base_new = -1;
|
||||
|
||||
/* Assign AN8855 interrupt pin */
|
||||
if (of_property_read_u32(dn, "airoha,intr", &priv->intr_pin))
|
||||
priv->intr_pin = AN8855_DFL_INTR_ID;
|
||||
|
||||
if (of_property_read_u32(dn, "airoha,extSurge", &priv->extSurge))
|
||||
priv->extSurge = AN8855_DFL_EXT_SURGE;
|
||||
|
||||
priv->bus = mdiodev->bus;
|
||||
priv->dev = &mdiodev->dev;
|
||||
priv->ds->priv = priv;
|
||||
@@ -2324,6 +2748,7 @@ an8855_probe(struct mdio_device *mdiodev)
|
||||
}
|
||||
an8855_nl_init(&priv);
|
||||
|
||||
an8855_proc_device_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2338,6 +2763,8 @@ an8855_remove(struct mdio_device *mdiodev)
|
||||
if (priv->base)
|
||||
iounmap(priv->base);
|
||||
|
||||
an8855_proc_device_exit();
|
||||
|
||||
an8855_nl_exit();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,13 @@
|
||||
|
||||
#define AN8855_NUM_PORTS 6
|
||||
#define AN8855_CPU_PORT 5
|
||||
#define AN8855_WORD_SIZE 4
|
||||
#define AN8855_NUM_FDB_RECORDS 2048
|
||||
#define AN8855_ALL_MEMBERS 0x3f
|
||||
#define AN8855_RESERVED_VLAN 2
|
||||
#define AN8855_GPHY_SMI_ADDR_DEFAULT 1
|
||||
#define AN8855_DFL_INTR_ID 0xd
|
||||
#define AN8855_DFL_EXT_SURGE 0x0
|
||||
|
||||
enum an8855_id {
|
||||
ID_AN8855 = 0,
|
||||
@@ -286,6 +289,8 @@ enum an8855_vlan_port_attr {
|
||||
#define AN8855_CKGCR (0x10213e1c)
|
||||
#define LPI_TXIDLE_THD 14
|
||||
#define LPI_TXIDLE_THD_MASK BITS(14, 31)
|
||||
#define CKG_LNKDN_GLB_STOP 0x01
|
||||
#define CKG_LNKDN_PORT_STOP 0x02
|
||||
|
||||
/* Register for MIB */
|
||||
#define AN8855_PORT_MIB_COUNTER(x) (0x10214000 + (x) * 0x200)
|
||||
@@ -303,18 +308,14 @@ enum an8855_vlan_port_attr {
|
||||
CCR_RX_OCT_CNT_BAD | \
|
||||
CCR_TX_OCT_CNT_GOOD | \
|
||||
CCR_TX_OCT_CNT_BAD | \
|
||||
CCR_RX_OCT_CNT_GOOD_2 | \
|
||||
CCR_RX_OCT_CNT_BAD_2 | \
|
||||
CCR_TX_OCT_CNT_GOOD_2 | \
|
||||
CCR_TX_OCT_CNT_BAD_2)
|
||||
#define CCR_MIB_ACTIVATE (CCR_MIB_ENABLE | \
|
||||
CCR_RX_OCT_CNT_GOOD | \
|
||||
CCR_RX_OCT_CNT_BAD | \
|
||||
CCR_TX_OCT_CNT_GOOD | \
|
||||
CCR_TX_OCT_CNT_BAD | \
|
||||
CCR_RX_OCT_CNT_GOOD_2 | \
|
||||
CCR_RX_OCT_CNT_BAD_2 | \
|
||||
CCR_TX_OCT_CNT_GOOD_2 | \
|
||||
CCR_TX_OCT_CNT_BAD_2)
|
||||
|
||||
/* AN8855 SGMII register group */
|
||||
@@ -331,6 +332,22 @@ enum an8855_vlan_port_attr {
|
||||
#define AN8855_RST_CTRL 0x100050c0
|
||||
#define SYS_CTRL_SYS_RST BIT(31)
|
||||
|
||||
#define INT_MASK 0x100050F0
|
||||
#define INT_SYS_BIT BIT(15)
|
||||
|
||||
#define RG_CLK_CPU_ICG 0x10005034
|
||||
#define MCU_ENABLE BIT(3)
|
||||
|
||||
#define RG_TIMER_CTL 0x1000a100
|
||||
#define WDOG_ENABLE BIT(25)
|
||||
|
||||
#define CKGCR 0x10213E1C
|
||||
#define CKG_LNKDN_GLB_STOP 0x01
|
||||
#define CKG_LNKDN_PORT_STOP 0x02
|
||||
|
||||
#define PKG_SEL 0x10000094
|
||||
#define PAG_SEL_AN8855H 0x2
|
||||
|
||||
/* Register for hw trap status */
|
||||
#define AN8855_HWTRAP 0x1000009c
|
||||
|
||||
@@ -339,6 +356,15 @@ enum an8855_vlan_port_attr {
|
||||
|
||||
#define SCU_BASE 0x10000000
|
||||
#define RG_RGMII_TXCK_C (SCU_BASE + 0x1d0)
|
||||
#define RG_GPIO_LED_MODE (SCU_BASE + 0x0054)
|
||||
#define RG_GPIO_LED_SEL(i) (SCU_BASE + (0x0058 + ((i) * 4)))
|
||||
#define RG_INTB_MODE (SCU_BASE + 0x0080)
|
||||
#define RG_GDMP_RAM (SCU_BASE + 0x10000)
|
||||
|
||||
#define RG_GPIO_L_INV (SCU_BASE + 0x0010)
|
||||
#define RG_GPIO_CTRL (SCU_BASE + 0xa300)
|
||||
#define RG_GPIO_DATA (SCU_BASE + 0xa304)
|
||||
#define RG_GPIO_OE (SCU_BASE + 0xa314)
|
||||
|
||||
#define HSGMII_AN_CSR_BASE 0x10220000
|
||||
#define SGMII_REG_AN0 (HSGMII_AN_CSR_BASE + 0x000)
|
||||
@@ -382,6 +408,8 @@ enum an8855_vlan_port_attr {
|
||||
#define SS_LCPLL_TDC_PCW_1 (QP_PMA_TOP_BASE + 0x248)
|
||||
#define INTF_CTRL_8 (QP_PMA_TOP_BASE + 0x320)
|
||||
#define INTF_CTRL_9 (QP_PMA_TOP_BASE + 0x324)
|
||||
#define INTF_CTRL_10 (QP_PMA_TOP_BASE + 0x328)
|
||||
#define INTF_CTRL_11 (QP_PMA_TOP_BASE + 0x32c)
|
||||
#define PLL_CTRL_0 (QP_PMA_TOP_BASE + 0x400)
|
||||
#define PLL_CTRL_2 (QP_PMA_TOP_BASE + 0x408)
|
||||
#define PLL_CTRL_3 (QP_PMA_TOP_BASE + 0x40c)
|
||||
@@ -399,6 +427,7 @@ enum an8855_vlan_port_attr {
|
||||
#define QP_ANA_CSR_BASE 0x1022f000
|
||||
#define RG_QP_RX_DAC_EN (QP_ANA_CSR_BASE + 0x00)
|
||||
#define RG_QP_RXAFE_RESERVE (QP_ANA_CSR_BASE + 0x04)
|
||||
#define RG_QP_CDR_LPF_BOT_LIM (QP_ANA_CSR_BASE + 0x08)
|
||||
#define RG_QP_CDR_LPF_MJV_LIM (QP_ANA_CSR_BASE + 0x0c)
|
||||
#define RG_QP_CDR_LPF_SETVALUE (QP_ANA_CSR_BASE + 0x14)
|
||||
#define RG_QP_CDR_PR_CKREF_DIV1 (QP_ANA_CSR_BASE + 0x18)
|
||||
@@ -437,6 +466,74 @@ struct an8855_fdb {
|
||||
u8 ivl;
|
||||
};
|
||||
|
||||
/* Definition of LED */
|
||||
#define LED_ON_EVENT (LED_ON_EVT_LINK_1000M | \
|
||||
LED_ON_EVT_LINK_100M | LED_ON_EVT_LINK_10M |\
|
||||
LED_ON_EVT_LINK_HD | LED_ON_EVT_LINK_FD)
|
||||
|
||||
#define LED_BLK_EVENT (LED_BLK_EVT_1000M_TX_ACT | \
|
||||
LED_BLK_EVT_1000M_RX_ACT | \
|
||||
LED_BLK_EVT_100M_TX_ACT | \
|
||||
LED_BLK_EVT_100M_RX_ACT | \
|
||||
LED_BLK_EVT_10M_TX_ACT | \
|
||||
LED_BLK_EVT_10M_RX_ACT)
|
||||
|
||||
#define LED_FREQ AIR_LED_BLK_DUR_64M
|
||||
|
||||
enum phy_led_idx {
|
||||
P0_LED0,
|
||||
P0_LED1,
|
||||
P0_LED2,
|
||||
P0_LED3,
|
||||
P1_LED0,
|
||||
P1_LED1,
|
||||
P1_LED2,
|
||||
P1_LED3,
|
||||
P2_LED0,
|
||||
P2_LED1,
|
||||
P2_LED2,
|
||||
P2_LED3,
|
||||
P3_LED0,
|
||||
P3_LED1,
|
||||
P3_LED2,
|
||||
P3_LED3,
|
||||
P4_LED0,
|
||||
P4_LED1,
|
||||
P4_LED2,
|
||||
P4_LED3,
|
||||
PHY_LED_MAX
|
||||
};
|
||||
|
||||
/* TBD */
|
||||
enum an8855_led_blk_dur {
|
||||
AIR_LED_BLK_DUR_32M,
|
||||
AIR_LED_BLK_DUR_64M,
|
||||
AIR_LED_BLK_DUR_128M,
|
||||
AIR_LED_BLK_DUR_256M,
|
||||
AIR_LED_BLK_DUR_512M,
|
||||
AIR_LED_BLK_DUR_1024M,
|
||||
AIR_LED_BLK_DUR_LAST
|
||||
};
|
||||
|
||||
enum an8855_led_polarity {
|
||||
LED_LOW,
|
||||
LED_HIGH,
|
||||
};
|
||||
enum an8855_led_mode {
|
||||
AN8855_LED_MODE_DISABLE,
|
||||
AN8855_LED_MODE_USER_DEFINE,
|
||||
AN8855_LED_MODE_LAST
|
||||
};
|
||||
|
||||
struct an8855_led_cfg {
|
||||
u16 en;
|
||||
u8 phy_led_idx;
|
||||
u16 pol;
|
||||
u16 on_cfg;
|
||||
u16 blk_cfg;
|
||||
u8 led_freq;
|
||||
};
|
||||
|
||||
/* struct an8855_port - This is the main data structure for holding the state
|
||||
* of the port.
|
||||
* @enable: The status used for show port is enabled or not.
|
||||
@@ -522,11 +619,13 @@ struct an8855_priv {
|
||||
unsigned int phy_base;
|
||||
int phy_base_new;
|
||||
unsigned int id;
|
||||
u32 intr_pin;
|
||||
phy_interface_t p5_interface;
|
||||
unsigned int p5_intf_sel;
|
||||
u8 mirror_rx;
|
||||
u8 mirror_tx;
|
||||
u8 eee_enable;
|
||||
u32 extSurge;
|
||||
|
||||
struct an8855_port ports[AN8855_NUM_PORTS];
|
||||
/* protect among processes for registers access */
|
||||
|
||||
@@ -45,8 +45,8 @@ static int an8855_nl_response(struct sk_buff *skb, struct genl_info *info);
|
||||
static const struct nla_policy an8855_nl_cmd_policy[] = {
|
||||
[AN8855_ATTR_TYPE_MESG] = {.type = NLA_STRING},
|
||||
[AN8855_ATTR_TYPE_PHY] = {.type = NLA_S32},
|
||||
[AN8855_ATTR_TYPE_REG] = {.type = NLA_S32},
|
||||
[AN8855_ATTR_TYPE_VAL] = {.type = NLA_S32},
|
||||
[AN8855_ATTR_TYPE_REG] = {.type = NLA_U32},
|
||||
[AN8855_ATTR_TYPE_VAL] = {.type = NLA_U32},
|
||||
[AN8855_ATTR_TYPE_DEV_NAME] = {.type = NLA_S32},
|
||||
[AN8855_ATTR_TYPE_DEV_ID] = {.type = NLA_S32},
|
||||
[AN8855_ATTR_TYPE_DEVAD] = {.type = NLA_S32},
|
||||
@@ -150,15 +150,15 @@ static int
|
||||
an8855_nl_reply_read(struct genl_info *info)
|
||||
{
|
||||
struct sk_buff *rep_skb = NULL;
|
||||
s32 phy, devad, reg;
|
||||
int value;
|
||||
s32 phy, devad;
|
||||
u32 reg = 0;
|
||||
int value = 0;
|
||||
int ret = 0;
|
||||
|
||||
phy = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_PHY, -1);
|
||||
devad = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_DEVAD, -1);
|
||||
reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1);
|
||||
|
||||
if (reg < 0)
|
||||
if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_REG, ®))
|
||||
goto err;
|
||||
|
||||
ret = an8855_nl_prepare_reply(info, AN8855_CMD_READ, &rep_skb);
|
||||
@@ -172,11 +172,11 @@ an8855_nl_reply_read(struct genl_info *info)
|
||||
devad, reg);
|
||||
} else
|
||||
value = an8855_read(an8855_sw_priv, reg);
|
||||
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
|
||||
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
|
||||
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
@@ -193,18 +193,16 @@ static int
|
||||
an8855_nl_reply_write(struct genl_info *info)
|
||||
{
|
||||
struct sk_buff *rep_skb = NULL;
|
||||
s32 phy, devad, reg;
|
||||
u32 value;
|
||||
s32 phy, devad;
|
||||
u32 value = 0, reg = 0;
|
||||
int ret = 0;
|
||||
|
||||
phy = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_PHY, -1);
|
||||
devad = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_DEVAD, -1);
|
||||
reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1);
|
||||
|
||||
if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_VAL, &value))
|
||||
if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_REG, ®))
|
||||
goto err;
|
||||
|
||||
if (reg < 0)
|
||||
if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_VAL, &value))
|
||||
goto err;
|
||||
|
||||
ret = an8855_nl_prepare_reply(info, AN8855_CMD_WRITE, &rep_skb);
|
||||
@@ -218,11 +216,11 @@ an8855_nl_reply_write(struct genl_info *info)
|
||||
value);
|
||||
} else
|
||||
an8855_write(an8855_sw_priv, reg, value);
|
||||
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
|
||||
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
|
||||
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
|
||||
@@ -14,32 +14,36 @@
|
||||
#include "an8855.h"
|
||||
#include "an8855_phy.h"
|
||||
|
||||
#define AN8855_NUM_PHYS 5
|
||||
#define AN8855_EFUSE_DATA0 0x1000a500
|
||||
|
||||
static u32
|
||||
an8855_phy_read_dev_reg(struct dsa_switch *ds, u32 port_num,
|
||||
u32 dev_addr, u32 reg_addr)
|
||||
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 u8 shift_check(u8 base)
|
||||
{
|
||||
struct an8855_priv *priv = ds->priv;
|
||||
u32 phy_val;
|
||||
u32 addr;
|
||||
u8 i;
|
||||
u32 sz = sizeof(dsa_r50ohm_table)/sizeof(u8);
|
||||
|
||||
addr = MII_ADDR_C45 | (dev_addr << 16) | (reg_addr & 0xffff);
|
||||
phy_val = priv->info->phy_read(ds, port_num, addr);
|
||||
for (i = 0; i < sz; ++i)
|
||||
if (dsa_r50ohm_table[i] == base)
|
||||
break;
|
||||
|
||||
return phy_val;
|
||||
if (i < 8 || i >= sz)
|
||||
return 25; /* index of 94 */
|
||||
|
||||
return (i - 8);
|
||||
}
|
||||
|
||||
static void
|
||||
an8855_phy_write_dev_reg(struct dsa_switch *ds, u32 port_num,
|
||||
u32 dev_addr, u32 reg_addr, u32 write_data)
|
||||
static u8 get_shift_val(u8 idx)
|
||||
{
|
||||
struct an8855_priv *priv = ds->priv;
|
||||
u32 addr;
|
||||
|
||||
addr = MII_ADDR_C45 | (dev_addr << 16) | (reg_addr & 0xffff);
|
||||
|
||||
priv->info->phy_write(ds, port_num, addr, write_data);
|
||||
return dsa_r50ohm_table[idx];
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -64,7 +68,10 @@ static void
|
||||
an8855_phy_setting(struct dsa_switch *ds)
|
||||
{
|
||||
struct an8855_priv *priv = ds->priv;
|
||||
int i;
|
||||
int i, j;
|
||||
u8 shift_sel = 0, rsel_tx_a = 0, rsel_tx_b = 0;
|
||||
u8 rsel_tx_c = 0, rsel_tx_d = 0;
|
||||
u16 cl45_data = 0;
|
||||
u32 val;
|
||||
|
||||
/* Release power down */
|
||||
@@ -82,48 +89,89 @@ an8855_phy_setting(struct dsa_switch *ds)
|
||||
val |= ADVERTISE_PAUSE_ASYM;
|
||||
an8855_switch_phy_write(ds, i, MII_ADVERTISE, val);
|
||||
}
|
||||
|
||||
if (priv->extSurge) {
|
||||
for (i = 0; i < AN8855_NUM_PHYS; i++) {
|
||||
/* Read data */
|
||||
for (j = 0; j < AN8855_WORD_SIZE; j++) {
|
||||
val = an8855_read(priv, AN8855_EFUSE_DATA0 +
|
||||
(AN8855_WORD_SIZE * (3 + j + (4 * i))));
|
||||
|
||||
shift_sel = shift_check((val & 0x7f000000) >> 24);
|
||||
switch (j) {
|
||||
case 0:
|
||||
rsel_tx_a = get_shift_val(shift_sel);
|
||||
break;
|
||||
case 1:
|
||||
rsel_tx_b = get_shift_val(shift_sel);
|
||||
break;
|
||||
case 2:
|
||||
rsel_tx_c = get_shift_val(shift_sel);
|
||||
break;
|
||||
case 3:
|
||||
rsel_tx_d = get_shift_val(shift_sel);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
cl45_data = an8855_phy_cl45_read(priv, i, PHY_DEV1E, 0x174);
|
||||
cl45_data &= ~(0x7f7f);
|
||||
cl45_data |= (rsel_tx_a << 8);
|
||||
cl45_data |= rsel_tx_b;
|
||||
an8855_phy_cl45_write(priv, i, PHY_DEV1E, 0x174, cl45_data);
|
||||
cl45_data = an8855_phy_cl45_read(priv, i, PHY_DEV1E, 0x175);
|
||||
cl45_data &= ~(0x7f7f);
|
||||
cl45_data |= (rsel_tx_c << 8);
|
||||
cl45_data |= rsel_tx_d;
|
||||
an8855_phy_cl45_write(priv, i, PHY_DEV1E, 0x175, cl45_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
an8855_low_power_setting(struct dsa_switch *ds)
|
||||
{
|
||||
int port, addr;
|
||||
struct an8855_priv *priv = ds->priv;
|
||||
|
||||
for (port = 0; port < AN8855_NUM_PHYS; port++) {
|
||||
an8855_phy_write_dev_reg(ds, port, 0x1e, 0x11, 0x0f00);
|
||||
an8855_phy_write_dev_reg(ds, port, 0x1e, 0x3c, 0x0000);
|
||||
an8855_phy_write_dev_reg(ds, port, 0x1e, 0x3d, 0x0000);
|
||||
an8855_phy_write_dev_reg(ds, port, 0x1e, 0x3e, 0x0000);
|
||||
an8855_phy_write_dev_reg(ds, port, 0x1e, 0xc6, 0x53aa);
|
||||
an8855_phy_cl45_write(priv, port, 0x1e, 0x11, 0x0f00);
|
||||
an8855_phy_cl45_write(priv, port, 0x1e, 0x3c, 0x0000);
|
||||
an8855_phy_cl45_write(priv, port, 0x1e, 0x3d, 0x0000);
|
||||
an8855_phy_cl45_write(priv, port, 0x1e, 0x3e, 0x0000);
|
||||
an8855_phy_cl45_write(priv, port, 0x1e, 0xc6, 0x53aa);
|
||||
}
|
||||
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x268, 0x07f1);
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x269, 0x2111);
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x26a, 0x0000);
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x26b, 0x0074);
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x26e, 0x00f6);
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x26f, 0x6666);
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x271, 0x2c02);
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x272, 0x0c22);
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x700, 0x0001);
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x701, 0x0803);
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x702, 0x01b6);
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x703, 0x2111);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, 0x268, 0x07f1);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, 0x269, 0x2111);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, 0x26a, 0x0000);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, 0x26b, 0x0074);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, 0x26e, 0x00f6);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, 0x26f, 0x6666);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, 0x271, 0x2c02);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, 0x272, 0x0c22);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, 0x700, 0x0001);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, 0x701, 0x0803);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, 0x702, 0x01b6);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, 0x703, 0x2111);
|
||||
|
||||
an8855_phy_write_dev_reg(ds, 1, 0x1f, 0x700, 0x0001);
|
||||
an8855_phy_cl45_write(priv, 1, 0x1f, 0x700, 0x0001);
|
||||
|
||||
for (addr = 0x200; addr <= 0x230; addr += 2)
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, addr, 0x2020);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, addr, 0x2020);
|
||||
|
||||
for (addr = 0x201; addr <= 0x231; addr += 2)
|
||||
an8855_phy_write_dev_reg(ds, 0, 0x1f, addr, 0x0020);
|
||||
an8855_phy_cl45_write(priv, 0, 0x1f, addr, 0x0020);
|
||||
}
|
||||
|
||||
static void
|
||||
an8855_eee_setting(struct dsa_switch *ds, u32 port)
|
||||
{
|
||||
struct an8855_priv *priv = ds->priv;
|
||||
|
||||
/* Disable EEE */
|
||||
an8855_phy_write_dev_reg(ds, port, PHY_DEV07, PHY_DEV07_REG_03C, 0);
|
||||
an8855_phy_cl45_write(priv, port, PHY_DEV07, PHY_DEV07_REG_03C, 0);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#define AN8855_NUM_PHYS 5
|
||||
|
||||
/*phy calibration use*/
|
||||
#define DEV_1E 0x1E
|
||||
/*global device 0x1f, always set P0*/
|
||||
@@ -169,11 +171,69 @@
|
||||
/* PHY EEE Register bitmap of define */
|
||||
#define PHY_DEV07 0x07
|
||||
#define PHY_DEV07_REG_03C 0x3c
|
||||
#define ADV_EEE_100 0x2
|
||||
#define ADV_EEE_1000 0x4
|
||||
|
||||
/* PHY DEV 0x1e Register bitmap of define */
|
||||
#define PHY_DEV1E 0x1e
|
||||
/* PHY TX PAIR DELAY SELECT Register */
|
||||
#define PHY_TX_PAIR_DLY_SEL_GBE 0x013
|
||||
/* PHY ADC Register */
|
||||
#define PHY_RXADC_CTRL 0x0d8
|
||||
#define PHY_RXADC_REV_0 0x0d9
|
||||
#define PHY_RXADC_REV_1 0x0da
|
||||
|
||||
/* PHY LED Register bitmap of define */
|
||||
#define PHY_LED_CTRL_SELECT 0x3e8
|
||||
#define PHY_SINGLE_LED_ON_CTRL(i) (0x3e0 + ((i) * 2))
|
||||
#define PHY_SINGLE_LED_BLK_CTRL(i) (0x3e1 + ((i) * 2))
|
||||
#define PHY_SINGLE_LED_ON_DUR(i) (0x3e9 + ((i) * 2))
|
||||
#define PHY_SINGLE_LED_BLK_DUR(i) (0x3ea + ((i) * 2))
|
||||
|
||||
#define PHY_PMA_CTRL (0x340)
|
||||
|
||||
#define PHY_DEV1F 0x1f
|
||||
|
||||
#define PHY_LED_ON_CTRL(i) (0x24 + ((i) * 2))
|
||||
#define LED_ON_EN (1 << 15)
|
||||
#define LED_ON_POL (1 << 14)
|
||||
#define LED_ON_EVT_MASK (0x7f)
|
||||
|
||||
/* LED ON Event */
|
||||
#define LED_ON_EVT_FORCE (1 << 6)
|
||||
#define LED_ON_EVT_LINK_HD (1 << 5)
|
||||
#define LED_ON_EVT_LINK_FD (1 << 4)
|
||||
#define LED_ON_EVT_LINK_DOWN (1 << 3)
|
||||
#define LED_ON_EVT_LINK_10M (1 << 2)
|
||||
#define LED_ON_EVT_LINK_100M (1 << 1)
|
||||
#define LED_ON_EVT_LINK_1000M (1 << 0)
|
||||
|
||||
#define PHY_LED_BLK_CTRL(i) (0x25 + ((i) * 2))
|
||||
#define LED_BLK_EVT_MASK (0x3ff)
|
||||
/* LED Blinking Event */
|
||||
#define LED_BLK_EVT_FORCE (1 << 9)
|
||||
#define LED_BLK_EVT_10M_RX_ACT (1 << 5)
|
||||
#define LED_BLK_EVT_10M_TX_ACT (1 << 4)
|
||||
#define LED_BLK_EVT_100M_RX_ACT (1 << 3)
|
||||
#define LED_BLK_EVT_100M_TX_ACT (1 << 2)
|
||||
#define LED_BLK_EVT_1000M_RX_ACT (1 << 1)
|
||||
#define LED_BLK_EVT_1000M_TX_ACT (1 << 0)
|
||||
|
||||
#define PHY_LED_BCR (0x21)
|
||||
#define LED_BCR_EXT_CTRL (1 << 15)
|
||||
#define LED_BCR_CLK_EN (1 << 3)
|
||||
#define LED_BCR_TIME_TEST (1 << 2)
|
||||
#define LED_BCR_MODE_MASK (3)
|
||||
#define LED_BCR_MODE_DISABLE (0)
|
||||
|
||||
#define PHY_LED_ON_DUR (0x22)
|
||||
#define LED_ON_DUR_MASK (0xffff)
|
||||
|
||||
#define PHY_LED_BLK_DUR (0x23)
|
||||
#define LED_BLK_DUR_MASK (0xffff)
|
||||
|
||||
#define PHY_LED_BLINK_DUR_CTRL (0x720)
|
||||
|
||||
/* Proprietory Control Register of Internal Phy device 0x1e */
|
||||
#define PHY_TX_MLT3_BASE 0x0
|
||||
#define PHY_DEV1E_REG_13 0x13
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config NET_DSA_MXL862
|
||||
tristate "MaxLinear MxL862xx"
|
||||
depends on NET_DSA
|
||||
select NET_DSA_TAG_MXL862
|
||||
help
|
||||
This enables support for the MaxLinear MxL862xx switch family.
|
||||
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_NET_DSA_MXL862) += mxl862xx_dsa.o
|
||||
mxl862xx_dsa-y := mxl862xx.o host_api/mxl862xx_api.o host_api/mxl862xx_host_api_impl.o host_api/mxl862xx_mdio_relay.o
|
||||
@@ -0,0 +1,272 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* drivers/net/dsa/host_api/mxl862xx_api.c - dsa driver for Maxlinear mxl862xx switch chips family
|
||||
*
|
||||
* Copyright (C) 2024 MaxLinear Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mxl862xx_host_api_impl.h"
|
||||
#include "mxl862xx_api.h"
|
||||
#include "mxl862xx_mmd_apis.h"
|
||||
|
||||
int sys_misc_fw_version(const mxl862xx_device_t *dev,
|
||||
struct sys_fw_image_version *sys_img_ver)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, SYS_MISC_FW_VERSION, sys_img_ver,
|
||||
sizeof(*sys_img_ver), 0, sizeof(*sys_img_ver));
|
||||
}
|
||||
|
||||
int mxl862xx_register_mod(const mxl862xx_device_t *dev, mxl862xx_register_mod_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_COMMON_REGISTERMOD, parm, sizeof(*parm), 0,
|
||||
0);
|
||||
}
|
||||
|
||||
int mxl862xx_port_link_cfg_set(const mxl862xx_device_t *dev, mxl862xx_port_link_cfg_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_COMMON_PORTLINKCFGSET, parm, sizeof(*parm),
|
||||
MXL862XX_COMMON_PORTLINKCFGGET, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_port_cfg_get(const mxl862xx_device_t *dev, mxl862xx_port_cfg_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_COMMON_PORTCFGGET, parm, sizeof(*parm), 0,
|
||||
sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_port_cfg_set(const mxl862xx_device_t *dev, mxl862xx_port_cfg_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_COMMON_PORTCFGSET, parm, sizeof(*parm),
|
||||
MXL862XX_COMMON_PORTCFGGET, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_bridge_alloc(const mxl862xx_device_t *dev, mxl862xx_bridge_alloc_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_BRIDGE_ALLOC, parm, sizeof(*parm), 0,
|
||||
sizeof(*parm));
|
||||
}
|
||||
int mxl862xx_bridge_free(const mxl862xx_device_t *dev, mxl862xx_bridge_alloc_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_BRIDGE_FREE, parm, sizeof(*parm), 0, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_bridge_config_set(const mxl862xx_device_t *dev, mxl862xx_bridge_config_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_BRIDGE_CONFIGSET, parm, sizeof(*parm),
|
||||
MXL862XX_BRIDGE_CONFIGGET, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_bridge_config_get(const mxl862xx_device_t *dev, mxl862xx_bridge_config_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_BRIDGE_CONFIGGET, parm, sizeof(*parm), 0,
|
||||
sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_bridge_port_alloc(const mxl862xx_device_t *dev, mxl862xx_bridge_port_alloc_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_BRIDGEPORT_ALLOC, parm, sizeof(*parm), 0,
|
||||
sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_bridge_port_free(const mxl862xx_device_t *dev, mxl862xx_bridge_port_alloc_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_BRIDGEPORT_FREE, parm, sizeof(*parm), 0, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_bridge_port_config_set(const mxl862xx_device_t *dev,
|
||||
mxl862xx_bridge_port_config_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_BRIDGEPORT_CONFIGSET, parm, sizeof(*parm),
|
||||
MXL862XX_BRIDGEPORT_CONFIGGET, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_bridge_port_config_get(const mxl862xx_device_t *dev,
|
||||
mxl862xx_bridge_port_config_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_BRIDGEPORT_CONFIGGET, parm, sizeof(*parm),
|
||||
0, sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_debug_rmon_port_get(const mxl862xx_device_t *dev,
|
||||
mxl862xx_debug_rmon_port_cnt_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_DEBUG_RMON_PORT_GET, parm, sizeof(*parm),
|
||||
0, sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_mac_table_clear(const mxl862xx_device_t *dev)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_MAC_TABLECLEAR, NULL, 0, 0, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_mac_table_clear_cond(const mxl862xx_device_t *dev,
|
||||
mxl862xx_mac_table_clear_cond_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_MAC_TABLECLEARCOND, parm, sizeof(*parm), 0,
|
||||
0);
|
||||
}
|
||||
|
||||
int mxl862xx_mac_table_entry_read(const mxl862xx_device_t *dev,
|
||||
mxl862xx_mac_table_read_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_MAC_TABLEENTRYREAD, parm, sizeof(*parm), 0,
|
||||
sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_mac_table_entry_add(const mxl862xx_device_t *dev,
|
||||
mxl862xx_mac_table_add_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_MAC_TABLEENTRYADD, parm, sizeof(*parm), 0,
|
||||
0);
|
||||
}
|
||||
|
||||
int mxl862xx_mac_table_entry_remove(const mxl862xx_device_t *dev,
|
||||
mxl862xx_mac_table_remove_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_MAC_TABLEENTRYREMOVE, parm, sizeof(*parm),
|
||||
0, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_stp_port_cfg_set(const mxl862xx_device_t *dev, mxl862xx_stp_port_cfg_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_STP_PORTCFGSET, parm, sizeof(*parm),
|
||||
MXL862XX_STP_PORTCFGGET, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_ss_sp_tag_get(const mxl862xx_device_t *dev, mxl862xx_ss_sp_tag_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_SS_SPTAG_GET, parm, sizeof(*parm), 0,
|
||||
sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_ss_sp_tag_set(const mxl862xx_device_t *dev, mxl862xx_ss_sp_tag_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_SS_SPTAG_SET, parm, sizeof(*parm),
|
||||
MXL862XX_SS_SPTAG_GET, sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_ctp_port_config_get(const mxl862xx_device_t *dev,
|
||||
mxl862xx_ctp_port_config_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_CTP_PORTCONFIGGET, parm, sizeof(*parm), 0,
|
||||
sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_ctp_port_config_set(const mxl862xx_device_t *dev,
|
||||
mxl862xx_ctp_port_config_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_CTP_PORTCONFIGSET, parm, sizeof(*parm),
|
||||
MXL862XX_CTP_PORTCONFIGGET, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_ctp_port_assignment_set(const mxl862xx_device_t *dev,
|
||||
mxl862xx_ctp_port_assignment_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_CTP_PORTASSIGNMENTSET, parm, sizeof(*parm),
|
||||
MXL862XX_CTP_PORTASSIGNMENTGET, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_ctp_port_assignment_get(const mxl862xx_device_t *dev,
|
||||
mxl862xx_ctp_port_assignment_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_CTP_PORTASSIGNMENTGET, parm, sizeof(*parm),
|
||||
0, sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_monitor_port_cfg_get(const mxl862xx_device_t *dev,
|
||||
mxl862xx_monitor_port_cfg_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_COMMON_MONITORPORTCFGGET, parm,
|
||||
sizeof(*parm), 0, sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_monitor_port_cfg_set(const mxl862xx_device_t *dev,
|
||||
mxl862xx_monitor_port_cfg_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_COMMON_MONITORPORTCFGSET, parm,
|
||||
sizeof(*parm), MXL862XX_COMMON_MONITORPORTCFGGET, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_extended_vlan_alloc(const mxl862xx_device_t *dev,
|
||||
mxl862xx_extendedvlan_alloc_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_EXTENDEDVLAN_ALLOC, parm, sizeof(*parm), 0,
|
||||
sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_extended_vlan_set(const mxl862xx_device_t *dev,
|
||||
mxl862xx_extendedvlan_config_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_EXTENDEDVLAN_SET, parm, sizeof(*parm),
|
||||
MXL862XX_EXTENDEDVLAN_GET, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_extended_vlan_get(const mxl862xx_device_t *dev,
|
||||
mxl862xx_extendedvlan_config_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_EXTENDEDVLAN_GET, parm, sizeof(*parm), 0,
|
||||
sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_extended_vlan_free(const mxl862xx_device_t *dev,
|
||||
mxl862xx_extendedvlan_alloc_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_EXTENDEDVLAN_FREE, parm, sizeof(*parm), 0,
|
||||
0);
|
||||
}
|
||||
|
||||
int mxl862xx_vlan_filter_alloc(const mxl862xx_device_t *dev,
|
||||
mxl862xx_vlanfilter_alloc_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_VLANFILTER_ALLOC, parm, sizeof(*parm), 0,
|
||||
sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_vlan_filter_set(const mxl862xx_device_t *dev,
|
||||
mxl862xx_vlanfilter_config_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_VLANFILTER_SET, parm, sizeof(*parm),
|
||||
MXL862XX_VLANFILTER_GET, 0);
|
||||
}
|
||||
|
||||
int mxl862xx_vlan_filter_get(const mxl862xx_device_t *dev,
|
||||
mxl862xx_vlanfilter_config_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_VLANFILTER_GET, parm, sizeof(*parm), 0,
|
||||
sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_vlan_filter_free(const mxl862xx_device_t *dev,
|
||||
mxl862xx_vlanfilter_alloc_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_VLANFILTER_FREE, parm, sizeof(*parm), 0,
|
||||
0);
|
||||
}
|
||||
|
||||
int mxl862xx_cfg_get(const mxl862xx_device_t *dev, mxl862xx_cfg_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_COMMON_CFGGET, parm, sizeof(*parm), 0,
|
||||
sizeof(*parm));
|
||||
}
|
||||
|
||||
int mxl862xx_cfg_set(const mxl862xx_device_t *dev, mxl862xx_cfg_t *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, MXL862XX_COMMON_CFGSET, parm, sizeof(*parm),
|
||||
MXL862XX_COMMON_CFGGET, 0);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,336 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* drivers/net/dsa/host_api/mxl862xx_ctp.h - Header file for DSA Driver for MaxLinear Mxl862xx switch chips family
|
||||
*
|
||||
* Copyright (C) 2024 MaxLinear Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef _MXL862XX_CTP_H_
|
||||
#define _MXL862XX_CTP_H_
|
||||
|
||||
#include "mxl862xx_types.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
#pragma scalar_storage_order little-endian
|
||||
|
||||
/** \brief Logical port mode.
|
||||
Used by \ref MXL862XX_CTP_port_assignment_t. */
|
||||
typedef enum {
|
||||
/** WLAN with 8-bit station ID */
|
||||
MXL862XX_LOGICAL_PORT_8BIT_WLAN = 0,
|
||||
/** WLAN with 9-bit station ID */
|
||||
MXL862XX_LOGICAL_PORT_9BIT_WLAN = 1,
|
||||
/** GPON OMCI context */
|
||||
MXL862XX_LOGICAL_PORT_GPON = 2,
|
||||
/** EPON context */
|
||||
MXL862XX_LOGICAL_PORT_EPON = 3,
|
||||
/** G.INT context */
|
||||
MXL862XX_LOGICAL_PORT_GINT = 4,
|
||||
/** Others (sub interface ID is 0 by default) */
|
||||
MXL862XX_LOGICAL_PORT_OTHER = 0xFF,
|
||||
} mxl862xx_logical_port_mode_t;
|
||||
|
||||
/** \brief CTP Port configuration mask.
|
||||
Used by \ref MXL862XX_CTP_port_config_t. */
|
||||
typedef enum {
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::bridge_port_id */
|
||||
MXL862XX_CTP_PORT_CONFIG_MASK_BRIDGE_PORT_ID = 0x00000001,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::b_forced_traffic_class and
|
||||
\ref MXL862XX_CTP_port_config_t::n_default_traffic_class */
|
||||
MXL862XX_CTP_PORT_CONFIG_MASK_FORCE_TRAFFIC_CLASS = 0x00000002,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::b_ingress_extended_vlan_enable and
|
||||
\ref MXL862XX_CTP_port_config_t::n_ingress_extended_vlan_block_id */
|
||||
MXL862XX_CTP_PORT_CONFIG_MASK_INGRESS_VLAN = 0x00000004,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::b_ingress_extended_vlan_igmp_enable and
|
||||
\ref MXL862XX_CTP_port_config_t::n_ingress_extended_vlan_block_id_igmp */
|
||||
MXL862XX_CTP_PORT_CONFIG_MASK_INGRESS_VLAN_IGMP = 0x00000008,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::b_egress_extended_vlan_enable and
|
||||
\ref MXL862XX_CTP_port_config_t::n_egress_extended_vlan_block_id */
|
||||
MXL862XX_CTP_PORT_CONFIG_MASK_EGRESS_VLAN = 0x00000010,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::b_egress_extended_vlan_igmp_enable and
|
||||
\ref MXL862XX_CTP_port_config_t::n_egress_extended_vlan_block_id_igmp */
|
||||
MXL862XX_CTP_PORT_CONFIG_MASK_EGRESS_VLAN_IGMP = 0x00000020,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::b_ingress_nto1Vlan_enable */
|
||||
MXL862XX_CTP_PORT_CONFIG_MASK_INRESS_NTO1_VLAN = 0x00000040,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::b_egress_nto1Vlan_enable */
|
||||
MXL862XX_CTP_PORT_CONFIG_MASK_EGRESS_NTO1_VLAN = 0x00000080,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::e_ingress_marking_mode */
|
||||
MXL862XX_CTP_PORT_CONFIG_INGRESS_MARKING = 0x00000100,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::e_egress_marking_mode */
|
||||
MXL862XX_CTP_PORT_CONFIG_EGRESS_MARKING = 0x00000200,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::b_egress_marking_override_enable and
|
||||
\ref MXL862XX_CTP_port_config_t::e_egress_marking_mode_override */
|
||||
MXL862XX_CTP_PORT_CONFIG_EGRESS_MARKING_OVERRIDE = 0x00000400,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::e_egress_remarking_mode */
|
||||
MXL862XX_CTP_PORT_CONFIG_EGRESS_REMARKING = 0x00000800,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::b_ingress_metering_enable and
|
||||
\ref MXL862XX_CTP_port_config_t::n_ingress_traffic_meter_id */
|
||||
MXL862XX_CTP_PORT_CONFIG_INGRESS_METER = 0x00001000,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::b_egress_metering_enable and
|
||||
\ref MXL862XX_CTP_port_config_t::n_egress_traffic_meter_id */
|
||||
MXL862XX_CTP_PORT_CONFIG_EGRESS_METER = 0x00002000,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::b_bridging_bypass,
|
||||
\ref MXL862XX_CTP_port_config_t::n_dest_logical_port_id,
|
||||
\ref MXL862XX_CTP_port_config_t::b_pmapper_enable,
|
||||
\ref MXL862XX_CTP_port_config_t::n_dest_sub_if_id_group,
|
||||
\ref MXL862XX_CTP_port_config_t::e_pmapper_mapping_mode
|
||||
\ref mxl862xx_bridge_port_config_t::b_pmapper_id_valid and
|
||||
\ref MXL862XX_CTP_port_config_t::s_pmapper */
|
||||
MXL862XX_CTP_PORT_CONFIG_BRIDGING_BYPASS = 0x00004000,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::n_first_flow_entry_index and
|
||||
\ref MXL862XX_CTP_port_config_t::n_number_of_flow_entries */
|
||||
MXL862XX_CTP_PORT_CONFIG_FLOW_ENTRY = 0x00008000,
|
||||
/** Mask for \ref MXL862XX_CTP_port_config_t::b_ingress_loopback_enable,
|
||||
\ref MXL862XX_CTP_port_config_t::b_ingress_da_sa_swap_enable,
|
||||
\ref MXL862XX_CTP_port_config_t::b_egress_loopback_enable,
|
||||
\ref MXL862XX_CTP_port_config_t::b_egress_da_sa_swap_enable,
|
||||
\ref MXL862XX_CTP_port_config_t::b_ingress_mirror_enable and
|
||||
\ref MXL862XX_CTP_port_config_t::b_egress_mirror_enable */
|
||||
MXL862XX_CTP_PORT_CONFIG_LOOPBACK_AND_MIRROR = 0x00010000,
|
||||
|
||||
/** Enable all fields */
|
||||
MXL862XX_CTP_PORT_CONFIG_MASK_ALL = 0x7FFFFFFF,
|
||||
/** Bypass any check for debug purpose */
|
||||
MXL862XX_CTP_PORT_CONFIG_MASK_FORCE = 0x80000000
|
||||
} mxl862xx_ctp_port_config_mask_t;
|
||||
|
||||
/** \brief CTP Port Assignment/association with logical port.
|
||||
Used by \ref MXL862XX_CTP_PORT_ASSIGNMENT_ALLOC, \ref MXL862XX_CTP_PORT_ASSIGNMENT_SET
|
||||
and \ref MXL862XX_CTP_PORT_ASSIGNMENT_GET. */
|
||||
typedef struct {
|
||||
/** Logical Port Id. The valid range is hardware dependent. */
|
||||
u8 logical_port_id;
|
||||
|
||||
/** First CTP Port ID mapped to above logical port ID.
|
||||
|
||||
\remarks
|
||||
For \ref MXL862XX_CTP_PORT_ASSIGNMENT_ALLOC, this is output when CTP
|
||||
allocation is successful. For other APIs, this is input. */
|
||||
u16 first_ctp_port_id;
|
||||
/** Total number of CTP Ports mapped above logical port ID. */
|
||||
u16 number_of_ctp_port;
|
||||
|
||||
/** Logical port mode to define sub interface ID format. */
|
||||
mxl862xx_logical_port_mode_t mode;
|
||||
|
||||
/** Bridge ID (FID)
|
||||
|
||||
\remarks
|
||||
For \ref MXL862XX_CTP_PORT_ASSIGNMENT_ALLOC, this is input. Each CTP allocated
|
||||
is mapped to Bridge Port given by this field. The Bridge Port will be
|
||||
configured to use first CTP
|
||||
(\ref MXL862XX_CTP_port_assignment_t::n_first_ctp_port_id) as egress CTP.
|
||||
For other APIs, this is ignored. */
|
||||
u16 bridge_port_id;
|
||||
} mxl862xx_ctp_port_assignment_t;
|
||||
|
||||
/** \brief CTP Port Configuration.
|
||||
Used by \ref MXL862XX_CTP_PORT_CONFIG_SET and \ref MXL862XX_CTP_PORT_CONFIG_GET. */
|
||||
typedef struct {
|
||||
/** Logical Port Id. The valid range is hardware dependent.
|
||||
If \ref MXL862XX_CTP_port_config_t::e_mask has
|
||||
\ref MXL862XX_Ctp_port_config_mask_t::MXL862XX_CTP_PORT_CONFIG_MASK_FORCE, this field
|
||||
is ignored. */
|
||||
u8 logical_port_id;
|
||||
|
||||
/** Sub interface ID group. The valid range is hardware/protocol dependent.
|
||||
|
||||
\remarks
|
||||
Sub interface ID group is defined for each of \ref MXL862XX_Logical_port_mode_t.
|
||||
For both \ref MXL862XX_LOGICAL_PORT_8BIT_WLAN and
|
||||
\ref MXL862XX_LOGICAL_PORT_9BIT_WLAN, this field is VAP.
|
||||
For \ref MXL862XX_LOGICAL_PORT_GPON, this field is GEM index.
|
||||
For \ref MXL862XX_LOGICAL_PORT_EPON, this field is stream index.
|
||||
For \ref MXL862XX_LOGICAL_PORT_GINT, this field is LLID.
|
||||
For others, this field is 0.
|
||||
If \ref MXL862XX_CTP_port_config_t::e_mask has
|
||||
\ref MXL862XX_Ctp_port_config_mask_t::MXL862XX_CTP_PORT_CONFIG_MASK_FORCE, this field
|
||||
is absolute index of CTP in hardware for debug purpose, bypassing
|
||||
any check. */
|
||||
u16 n_sub_if_id_group;
|
||||
|
||||
/** Mask for updating/retrieving fields. */
|
||||
mxl862xx_ctp_port_config_mask_t mask;
|
||||
|
||||
/** Ingress Bridge Port ID to which this CTP port is associated for ingress
|
||||
traffic. */
|
||||
u16 bridge_port_id;
|
||||
|
||||
/** Default traffic class can not be overridden by other rules (except
|
||||
traffic flow table and special tag) in processing stages. */
|
||||
bool forced_traffic_class;
|
||||
/** Default traffic class associated with all ingress traffic from this CTP
|
||||
Port. */
|
||||
u8 default_traffic_class;
|
||||
|
||||
/** Enable Extended VLAN processing for ingress non-IGMP traffic. */
|
||||
bool ingress_extended_vlan_enable;
|
||||
/** Extended VLAN block allocated for ingress non-IGMP traffic. It defines
|
||||
extended VLAN process for ingress non-IGMP traffic. Valid when
|
||||
b_ingress_extended_vlan_enable is TRUE. */
|
||||
u16 ingress_extended_vlan_block_id;
|
||||
/** Extended VLAN block size for ingress non-IGMP traffic. This is optional.
|
||||
If it is 0, the block size of n_ingress_extended_vlan_block_id will be used.
|
||||
Otherwise, this field will be used. */
|
||||
u16 ingress_extended_vlan_block_size;
|
||||
/** Enable extended VLAN processing for ingress IGMP traffic. */
|
||||
bool ingress_extended_vlan_igmp_enable;
|
||||
/** Extended VLAN block allocated for ingress IGMP traffic. It defines
|
||||
extended VLAN process for ingress IGMP traffic. Valid when
|
||||
b_ingress_extended_vlan_igmp_enable is TRUE. */
|
||||
u16 ingress_extended_vlan_block_id_igmp;
|
||||
/** Extended VLAN block size for ingress IGMP traffic. This is optional.
|
||||
If it is 0, the block size of n_ingress_extended_vlan_block_id_igmp will be
|
||||
used. Otherwise, this field will be used. */
|
||||
u16 ingress_extended_vlan_block_size_igmp;
|
||||
|
||||
/** Enable extended VLAN processing for egress non-IGMP traffic. */
|
||||
bool egress_extended_vlan_enable;
|
||||
/** Extended VLAN block allocated for egress non-IGMP traffic. It defines
|
||||
extended VLAN process for egress non-IGMP traffic. Valid when
|
||||
b_egress_extended_vlan_enable is TRUE. */
|
||||
u16 egress_extended_vlan_block_id;
|
||||
/** Extended VLAN block size for egress non-IGMP traffic. This is optional.
|
||||
If it is 0, the block size of n_egress_extended_vlan_block_id will be used.
|
||||
Otherwise, this field will be used. */
|
||||
u16 egress_extended_vlan_block_size;
|
||||
/** Enable extended VLAN processing for egress IGMP traffic. */
|
||||
bool egress_extended_vlan_igmp_enable;
|
||||
/** Extended VLAN block allocated for egress IGMP traffic. It defines
|
||||
extended VLAN process for egress IGMP traffic. Valid when
|
||||
b_egress_extended_vlan_igmp_enable is TRUE. */
|
||||
u16 egress_extended_vlan_block_id_igmp;
|
||||
/** Extended VLAN block size for egress IGMP traffic. This is optional.
|
||||
If it is 0, the block size of n_egress_extended_vlan_block_id_igmp will be
|
||||
used. Otherwise, this field will be used. */
|
||||
u16 egress_extended_vlan_block_size_igmp;
|
||||
|
||||
/** For WLAN type logical port, this should be FALSE. For other types, if
|
||||
enabled and ingress packet is VLAN tagged, outer VLAN ID is used for
|
||||
"n_sub_if_id" field in MAC table, otherwise, 0 is used for "n_sub_if_id". */
|
||||
bool ingress_nto1vlan_enable;
|
||||
/** For WLAN type logical port, this should be FALSE. For other types, if
|
||||
enabled and egress packet is known unicast, outer VLAN ID is from
|
||||
"n_sub_if_id" field in MAC table. */
|
||||
bool egress_nto1vlan_enable;
|
||||
|
||||
/** Ingress color marking mode for ingress traffic. */
|
||||
mxl862xx_color_marking_mode_t ingress_marking_mode;
|
||||
/** Egress color marking mode for ingress traffic at egress priority queue
|
||||
color marking stage */
|
||||
mxl862xx_color_marking_mode_t egress_marking_mode;
|
||||
/** Egress color marking mode override color marking mode from last stage. */
|
||||
bool egress_marking_override_enable;
|
||||
/** Egress color marking mode for egress traffic. Valid only when
|
||||
b_egress_marking_override is TRUE. */
|
||||
mxl862xx_color_marking_mode_t egress_marking_mode_override;
|
||||
|
||||
/** Color remarking for egress traffic. */
|
||||
mxl862xx_color_remarking_mode_t egress_remarking_mode;
|
||||
|
||||
/** Traffic metering on ingress traffic applies. */
|
||||
bool ingress_metering_enable;
|
||||
/** Meter for ingress CTP process.
|
||||
|
||||
\remarks
|
||||
Meter should be allocated with \ref MXL862XX_QOS_METER_ALLOC before CTP
|
||||
port configuration. If this CTP port is re-set, the last used meter
|
||||
should be released. */
|
||||
u16 ingress_traffic_meter_id;
|
||||
/** Traffic metering on egress traffic applies. */
|
||||
bool egress_metering_enable;
|
||||
/** Meter for egress CTP process.
|
||||
|
||||
\remarks
|
||||
Meter should be allocated with \ref MXL862XX_QOS_METER_ALLOC before CTP
|
||||
port configuration. If this CTP port is re-set, the last used meter
|
||||
should be released. */
|
||||
u16 egress_traffic_meter_id;
|
||||
|
||||
/** Ingress traffic bypass bridging/multicast processing. Following
|
||||
parameters are used to determine destination. Traffic flow table is not
|
||||
bypassed. */
|
||||
bool bridging_bypass;
|
||||
/** When b_bridging_bypass is TRUE, this field defines destination logical
|
||||
port. */
|
||||
u8 dest_logical_port_id;
|
||||
/** When b_bridging_bypass is TRUE, this field indicates whether to use
|
||||
\ref MXL862XX_CTP_port_config_t::n_dest_sub_if_id_group or
|
||||
\ref MXL862XX_CTP_port_config_t::e_pmapper_mapping_mode/
|
||||
\ref MXL862XX_CTP_port_config_t::s_pmapper. */
|
||||
bool pmapper_enable;
|
||||
/** When b_bridging_bypass is TRUE and b_pmapper_enable is FALSE, this field
|
||||
defines destination sub interface ID group. */
|
||||
u16 dest_sub_if_id_group;
|
||||
/** When b_bridging_bypass is TRUE and b_pmapper_enable is TRUE, this field
|
||||
selects either DSCP or PCP to derive sub interface ID. */
|
||||
mxl862xx_pmapper_mapping_mode_t pmapper_mapping_mode;
|
||||
/** When b_pmapper_enable is TRUE, P-mapper is used. This field determines
|
||||
whether s_pmapper.n_pmapper_id is valid. If this field is TRUE, the
|
||||
P-mapper is re-used and no allocation of new P-mapper or value
|
||||
change in the P-mapper. If this field is FALSE, allocation is
|
||||
taken care in the API implementation. */
|
||||
bool pmapper_id_valid;
|
||||
/** When b_bridging_bypass is TRUE and b_pmapper_enable is TRUE, P-mapper is
|
||||
used. If b_pmapper_id_valid is FALSE, API implementation need take care
|
||||
of P-mapper allocation, and maintain the reference counter of
|
||||
P-mapper used multiple times. If b_pmapper_id_valid is TRUE, only
|
||||
s_pmapper.n_pmapper_id is used to associate the P-mapper, and there is
|
||||
no allocation of new P-mapper or value change in the P-mapper. */
|
||||
mxl862xx_pmapper_t pmapper;
|
||||
|
||||
/** First traffic flow table entry is associated to this CTP port. Ingress
|
||||
traffic from this CTP port will go through traffic flow table search
|
||||
starting from n_first_flow_entry_index. Should be times of 4. */
|
||||
u16 first_flow_entry_index;
|
||||
/** Number of traffic flow table entries are associated to this CTP port.
|
||||
Ingress traffic from this CTP port will go through PCE rules search
|
||||
ending at (n_first_flow_entry_index+n_number_of_flow_entries)-1. Should
|
||||
be times of 4. */
|
||||
u16 number_of_flow_entries;
|
||||
|
||||
/** Ingress traffic from this CTP port will be redirected to ingress
|
||||
logical port of this CTP port with source sub interface ID used as
|
||||
destination sub interface ID. Following processing except traffic
|
||||
flow table search is bypassed if loopback enabled. */
|
||||
bool ingress_loopback_enable;
|
||||
/** Destination/Source MAC address of ingress traffic is swapped before
|
||||
transmitted (not swapped during PCE processing stages). If destination
|
||||
is multicast, there is no swap, but source MAC address is replaced
|
||||
with global configurable value. */
|
||||
bool ingress_da_sa_swap_enable;
|
||||
/** Egress traffic to this CTP port will be redirected to ingress logical
|
||||
port with same sub interface ID as ingress. */
|
||||
bool egress_loopback_enable;
|
||||
/** Destination/Source MAC address of egress traffic is swapped before
|
||||
transmitted. */
|
||||
bool egress_da_sa_swap_enable;
|
||||
|
||||
/** If enabled, ingress traffic is mirrored to the monitoring port.
|
||||
\remarks
|
||||
This should be used exclusive with b_ingress_loopback_enable. */
|
||||
bool ingress_mirror_enable;
|
||||
/** If enabled, egress traffic is mirrored to the monitoring port.
|
||||
\remarks
|
||||
This should be used exclusive with b_egress_loopback_enable. */
|
||||
bool egress_mirror_enable;
|
||||
} mxl862xx_ctp_port_config_t;
|
||||
|
||||
#pragma scalar_storage_order default
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif /*_MXL862XX_CTP_H */
|
||||
@@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* drivers/net/dsa/host_api/mxl862xx_flow.h - Header file for DSA Driver for MaxLinear Mxl862xx switch chips family
|
||||
*
|
||||
* Copyright (C) 2024 MaxLinear Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MXL862XX_FLOW_H_
|
||||
#define _MXL862XX_FLOW_H_
|
||||
|
||||
#include "mxl862xx_types.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
#pragma scalar_storage_order little-endian
|
||||
|
||||
#define MPCE_RULES_INDEX 0
|
||||
#define MPCE_RULES_INDEX_LAST (MPCE_RULES_INDEX + 7)
|
||||
#define EAPOL_PCE_RULE_INDEX 8
|
||||
#define BPDU_PCE_RULE_INDEX 9
|
||||
#define PFC_PCE_RULE_INDEX 10
|
||||
|
||||
/** \brief Register access parameter to directly modify internal registers.
|
||||
Used by \ref GSW_REGISTER_MOD. */
|
||||
typedef struct {
|
||||
/** Register Address Offset for modifiation. */
|
||||
u16 reg_addr;
|
||||
/** Value to write to 'reg_addr'. */
|
||||
u16 data;
|
||||
/** Mask of bits to be modified. 1 to modify, 0 to ignore. */
|
||||
u16 mask;
|
||||
} mxl862xx_register_mod_t;
|
||||
|
||||
#pragma scalar_storage_order default
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif /* _MXL862XX_FLOW_H_ */
|
||||
@@ -0,0 +1,514 @@
|
||||
// spdx-license-identifier: gpl-2.0
|
||||
/*
|
||||
* drivers/net/dsa/host_api/mxl862xx_host_api_impl.c - dsa driver for maxlinear mxl862xx switch chips family
|
||||
*
|
||||
* copyright (c) 2024 maxlinear inc.
|
||||
*
|
||||
* this program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the gnu general public license
|
||||
* as published by the free software foundation; either version 2
|
||||
* of the license, or (at your option) any later version.
|
||||
*
|
||||
* this program is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. see the
|
||||
* gnu general public license for more details.
|
||||
*
|
||||
* you should have received a copy of the gnu general public license
|
||||
* along with this program; if not, write to the free software
|
||||
* foundation, inc., 51 franklin street, fifth floor, boston, ma 02110-1301, usa.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mxl862xx_mmd_apis.h"
|
||||
|
||||
#define CTRL_BUSY_MASK BIT(15)
|
||||
#define CTRL_CMD_MASK (BIT(15) - 1)
|
||||
|
||||
#define MAX_BUSY_LOOP 1000 /* roughly 10ms */
|
||||
|
||||
#define THR_RST_DATA 5
|
||||
|
||||
#define ENABLE_GETSET_OPT 1
|
||||
|
||||
//#define C22_MDIO
|
||||
|
||||
#if defined(ENABLE_GETSET_OPT) && ENABLE_GETSET_OPT
|
||||
static struct {
|
||||
uint16_t ctrl;
|
||||
int16_t ret;
|
||||
mmd_api_data_t data;
|
||||
} shadow = { .ctrl = ~0, .ret = -1, .data = { { 0 } } };
|
||||
#endif
|
||||
|
||||
/* required for Clause 22 extended read/write access */
|
||||
#define MXL862XX_MMDDATA 0xE
|
||||
#define MXL862XX_MMDCTRL 0xD
|
||||
|
||||
#define MXL862XX_ACTYPE_ADDRESS (0 << 14)
|
||||
#define MXL862XX_ACTYPE_DATA (1 << 14)
|
||||
|
||||
#ifndef LINUX_VERSION_CODE
|
||||
#include <linux/version.h>
|
||||
#else
|
||||
#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0))
|
||||
#include <linux/delay.h>
|
||||
#endif
|
||||
|
||||
#ifdef C22_MDIO
|
||||
/**
|
||||
* write access to MMD register of PHYs via Clause 22 extended access
|
||||
*/
|
||||
static int __mxl862xx_c22_ext_mmd_write(const mxl862xx_device_t *dev, struct mii_bus *bus, int sw_addr, int mmd,
|
||||
int reg, u16 val)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* Set the DevID for Write Command */
|
||||
res = __mdiobus_write(bus, sw_addr, MXL862XX_MMDCTRL, mmd);
|
||||
if (res < 0)
|
||||
goto error;
|
||||
|
||||
/* Issue the write command */
|
||||
res = __mdiobus_write(bus, sw_addr, MXL862XX_MMDDATA, reg);
|
||||
if (res < 0)
|
||||
goto error;
|
||||
|
||||
/* Set the DevID for Write Command */
|
||||
res = __mdiobus_write(bus, sw_addr, MXL862XX_MMDCTRL, MXL862XX_ACTYPE_DATA | mmd);
|
||||
if (res < 0)
|
||||
goto error;
|
||||
|
||||
/* Issue the write command */
|
||||
res = __mdiobus_write(bus, sw_addr, MXL862XX_MMDDATA, val);
|
||||
if (res < 0)
|
||||
goto error;
|
||||
|
||||
error:
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* read access to MMD register of PHYs via Clause 22 extended access
|
||||
*/
|
||||
static int __mxl862xx_c22_ext_mmd_read(const mxl862xx_device_t *dev, struct mii_bus *bus, int sw_addr, int mmd, int reg)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* Set the DevID for Write Command */
|
||||
res = __mdiobus_write(bus, sw_addr, MXL862XX_MMDCTRL, mmd);
|
||||
if (res < 0)
|
||||
goto error;
|
||||
|
||||
/* Issue the write command */
|
||||
res = __mdiobus_write(bus, sw_addr, MXL862XX_MMDDATA, reg);
|
||||
if (res < 0)
|
||||
goto error;
|
||||
|
||||
/* Set the DevID for Write Command */
|
||||
res = __mdiobus_write(bus, sw_addr, MXL862XX_MMDCTRL, MXL862XX_ACTYPE_DATA | mmd);
|
||||
if (res < 0)
|
||||
goto error;
|
||||
|
||||
/* Read the data */
|
||||
res = __mdiobus_read(bus, sw_addr, MXL862XX_MMDDATA);
|
||||
if (res < 0)
|
||||
goto error;
|
||||
|
||||
error:
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
int mxl862xx_read(const mxl862xx_device_t *dev, uint32_t regaddr)
|
||||
{
|
||||
int mmd = MXL862XX_MMD_DEV;
|
||||
#ifdef C22_MDIO
|
||||
int ret = __mxl862xx_c22_ext_mmd_read(dev, dev->bus, dev->sw_addr, mmd, regaddr);
|
||||
#else
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0))
|
||||
u32 addr = MII_ADDR_C45 | (mmd << 16) | (regaddr & 0xffff);
|
||||
int ret = __mdiobus_read(dev->bus, dev->sw_addr, addr);
|
||||
#else
|
||||
int ret = __mdiobus_c45_read(dev->bus, dev->sw_addr, mmd, regaddr);
|
||||
#endif
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mxl862xx_write(const mxl862xx_device_t *dev, uint32_t regaddr, uint16_t data)
|
||||
{
|
||||
int mmd = MXL862XX_MMD_DEV;
|
||||
#ifdef C22_MDIO
|
||||
int ret = __mxl862xx_c22_ext_mmd_write(dev, dev->bus, dev->sw_addr, mmd, regaddr, data);
|
||||
#else
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0))
|
||||
u32 addr = MII_ADDR_C45 | (mmd << 16) | (regaddr & 0xffff);
|
||||
int ret = __mdiobus_write(dev->bus, dev->sw_addr, addr, data);
|
||||
#else
|
||||
int ret = __mdiobus_c45_write(dev->bus, dev->sw_addr, mmd, regaddr, data);
|
||||
#endif
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __wait_ctrl_busy(const mxl862xx_device_t *dev)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < MAX_BUSY_LOOP; i++) {
|
||||
ret = mxl862xx_read(dev, MXL862XX_MMD_REG_CTRL);
|
||||
if (ret < 0) {
|
||||
goto busy_check_exit;
|
||||
}
|
||||
|
||||
if (!(ret & CTRL_BUSY_MASK)) {
|
||||
ret = 0;
|
||||
goto busy_check_exit;
|
||||
}
|
||||
|
||||
usleep_range(10, 15);
|
||||
}
|
||||
ret = -ETIMEDOUT;
|
||||
busy_check_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __mxl862xx_rst_data(const mxl862xx_device_t *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mxl862xx_write(dev, MXL862XX_MMD_REG_LEN_RET, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = mxl862xx_write(dev, MXL862XX_MMD_REG_CTRL,
|
||||
MMD_API_RST_DATA | CTRL_BUSY_MASK);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return __wait_ctrl_busy(dev);
|
||||
}
|
||||
|
||||
static int __mxl862xx_set_data(const mxl862xx_device_t *dev, uint16_t words)
|
||||
{
|
||||
int ret;
|
||||
uint16_t cmd;
|
||||
|
||||
ret = mxl862xx_write(dev, MXL862XX_MMD_REG_LEN_RET,
|
||||
MXL862XX_MMD_REG_DATA_MAX_SIZE * sizeof(uint16_t));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
cmd = words / MXL862XX_MMD_REG_DATA_MAX_SIZE - 1;
|
||||
if (!(cmd < 2))
|
||||
return -EINVAL;
|
||||
|
||||
cmd += MMD_API_SET_DATA_0;
|
||||
ret = mxl862xx_write(dev, MXL862XX_MMD_REG_CTRL, cmd | CTRL_BUSY_MASK);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return __wait_ctrl_busy(dev);
|
||||
}
|
||||
|
||||
static int __mxl862xx_get_data(const mxl862xx_device_t *dev, uint16_t words)
|
||||
{
|
||||
int ret;
|
||||
uint16_t cmd;
|
||||
|
||||
ret = mxl862xx_write(dev, MXL862XX_MMD_REG_LEN_RET,
|
||||
MXL862XX_MMD_REG_DATA_MAX_SIZE * sizeof(uint16_t));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
cmd = words / MXL862XX_MMD_REG_DATA_MAX_SIZE;
|
||||
if (!(cmd > 0 && cmd < 3))
|
||||
return -EINVAL;
|
||||
cmd += MMD_API_GET_DATA_0;
|
||||
ret = mxl862xx_write(dev, MXL862XX_MMD_REG_CTRL, cmd | CTRL_BUSY_MASK);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return __wait_ctrl_busy(dev);
|
||||
}
|
||||
|
||||
static int __mxl862xx_send_cmd(const mxl862xx_device_t *dev, uint16_t cmd, uint16_t size,
|
||||
int16_t *presult)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mxl862xx_write(dev, MXL862XX_MMD_REG_LEN_RET, size);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mxl862xx_write(dev, MXL862XX_MMD_REG_CTRL, cmd | CTRL_BUSY_MASK);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __wait_ctrl_busy(dev);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mxl862xx_read(dev, MXL862XX_MMD_REG_LEN_RET);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*presult = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool __mxl862xx_cmd_r_valid(uint16_t cmd_r)
|
||||
{
|
||||
#if defined(ENABLE_GETSET_OPT) && ENABLE_GETSET_OPT
|
||||
return (shadow.ctrl == cmd_r && shadow.ret >= 0) ? true : false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This is usually used to implement CFG_SET command.
|
||||
* With previous CFG_GET command executed properly, the retrieved data
|
||||
* are shadowed in local structure. WSP FW has a set of shadow too,
|
||||
* so that only the difference to be sent over SMDIO.
|
||||
*/
|
||||
static int __mxl862xx_api_wrap_cmd_r(const mxl862xx_device_t *dev, uint16_t cmd,
|
||||
void *pdata, uint16_t size, uint16_t r_size)
|
||||
{
|
||||
#if defined(ENABLE_GETSET_OPT) && ENABLE_GETSET_OPT
|
||||
int ret;
|
||||
|
||||
uint16_t max, i;
|
||||
uint16_t *data;
|
||||
int16_t result = 0;
|
||||
|
||||
max = (size + 1) / 2;
|
||||
data = pdata;
|
||||
|
||||
ret = __wait_ctrl_busy(dev);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
uint16_t off = i % MXL862XX_MMD_REG_DATA_MAX_SIZE;
|
||||
|
||||
if (i && off == 0) {
|
||||
/* Send command to set data when every
|
||||
* MXL862XX_MMD_REG_DATA_MAX_SIZE of WORDs are written
|
||||
* and reload next batch of data from last CFG_GET.
|
||||
*/
|
||||
ret = __mxl862xx_set_data(dev, i);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (data[i] == shadow.data.data[i])
|
||||
continue;
|
||||
|
||||
mxl862xx_write(dev, MXL862XX_MMD_REG_DATA_FIRST + off,
|
||||
le16_to_cpu(data[i]));
|
||||
//sys_le16_to_cpu(data[i]));
|
||||
}
|
||||
|
||||
ret = __mxl862xx_send_cmd(dev, cmd, size, &result);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
max = (r_size + 1) / 2;
|
||||
for (i = 0; i < max; i++) {
|
||||
uint16_t off = i % MXL862XX_MMD_REG_DATA_MAX_SIZE;
|
||||
|
||||
if (i && off == 0) {
|
||||
/* Send command to fetch next batch of data
|
||||
* when every MXL862XX_MMD_REG_DATA_MAX_SIZE of WORDs
|
||||
* are read.
|
||||
*/
|
||||
ret = __mxl862xx_get_data(dev, i);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mxl862xx_read(dev, MXL862XX_MMD_REG_DATA_FIRST + off);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((i * 2 + 1) == r_size) {
|
||||
/* Special handling for last BYTE
|
||||
* if it's not WORD aligned.
|
||||
*/
|
||||
*(uint8_t *)&data[i] = ret & 0xFF;
|
||||
} else {
|
||||
data[i] = cpu_to_le16((uint16_t)ret);
|
||||
}
|
||||
}
|
||||
|
||||
shadow.data.data[max] = 0;
|
||||
memcpy(shadow.data.data, data, r_size);
|
||||
|
||||
return result;
|
||||
#else /* defined(ENABLE_GETSET_OPT) && ENABLE_GETSET_OPT */
|
||||
ARG_UNUSED(dev);
|
||||
ARG_UNUSED(cmd);
|
||||
ARG_UNUSED(pdata);
|
||||
ARG_UNUSED(size);
|
||||
return -ENOTSUP;
|
||||
#endif /* defined(ENABLE_GETSET_OPT) && ENABLE_GETSET_OPT */
|
||||
}
|
||||
|
||||
int mxl862xx_api_wrap(const mxl862xx_device_t *dev, uint16_t cmd, void *pdata,
|
||||
uint16_t size, uint16_t cmd_r, uint16_t r_size)
|
||||
{
|
||||
int ret;
|
||||
uint16_t max, i, cnt;
|
||||
uint16_t *data;
|
||||
int16_t result = 0;
|
||||
|
||||
if (!dev || (!pdata && size))
|
||||
return -EINVAL;
|
||||
|
||||
if (!(size <= sizeof(mmd_api_data_t)) || !(r_size <= size))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock_nested(&dev->bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
|
||||
if (__mxl862xx_cmd_r_valid(cmd_r)) {
|
||||
/* Special handling for GET and SET command pair. */
|
||||
ret = __mxl862xx_api_wrap_cmd_r(dev, cmd, pdata, size, r_size);
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
max = (size + 1) / 2;
|
||||
data = pdata;
|
||||
|
||||
/* Check whether it's worth to issue RST_DATA command. */
|
||||
for (i = cnt = 0; i < max && cnt < THR_RST_DATA; i++) {
|
||||
if (!data[i])
|
||||
cnt++;
|
||||
}
|
||||
|
||||
ret = __wait_ctrl_busy(dev);
|
||||
if (ret < 0)
|
||||
goto EXIT;
|
||||
|
||||
if (cnt >= THR_RST_DATA) {
|
||||
/* Issue RST_DATA commdand. */
|
||||
ret = __mxl862xx_rst_data(dev);
|
||||
if (ret < 0)
|
||||
goto EXIT;
|
||||
|
||||
for (i = 0, cnt = 0; i < max; i++) {
|
||||
uint16_t off = i % MXL862XX_MMD_REG_DATA_MAX_SIZE;
|
||||
|
||||
if (i && off == 0) {
|
||||
uint16_t cnt_old = cnt;
|
||||
|
||||
cnt = 0;
|
||||
|
||||
/* No actual data was written. */
|
||||
if (!cnt_old)
|
||||
continue;
|
||||
|
||||
/* Send command to set data when every
|
||||
* MXL862XX_MMD_REG_DATA_MAX_SIZE of WORDs are written
|
||||
* and clear the MMD register space.
|
||||
*/
|
||||
ret = __mxl862xx_set_data(dev, i);
|
||||
if (ret < 0)
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
/* Skip '0' data. */
|
||||
if (!data[i])
|
||||
continue;
|
||||
|
||||
mxl862xx_write(dev, MXL862XX_MMD_REG_DATA_FIRST + off,
|
||||
le16_to_cpu(data[i]));
|
||||
cnt++;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < max; i++) {
|
||||
uint16_t off = i % MXL862XX_MMD_REG_DATA_MAX_SIZE;
|
||||
|
||||
if (i && off == 0) {
|
||||
/* Send command to set data when every
|
||||
* MXL862XX_MMD_REG_DATA_MAX_SIZE of WORDs are written.
|
||||
*/
|
||||
ret = __mxl862xx_set_data(dev, i);
|
||||
if (ret < 0)
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
mxl862xx_write(dev, MXL862XX_MMD_REG_DATA_FIRST + off,
|
||||
le16_to_cpu(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
ret = __mxl862xx_send_cmd(dev, cmd, size, &result);
|
||||
if (ret < 0)
|
||||
goto EXIT;
|
||||
|
||||
if (result < 0) {
|
||||
ret = result;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
max = (r_size + 1) / 2;
|
||||
for (i = 0; i < max; i++) {
|
||||
uint16_t off = i % MXL862XX_MMD_REG_DATA_MAX_SIZE;
|
||||
|
||||
if (i && off == 0) {
|
||||
/* Send command to fetch next batch of data
|
||||
* when every MXL862XX_MMD_REG_DATA_MAX_SIZE of WORDs
|
||||
* are read.
|
||||
*/
|
||||
ret = __mxl862xx_get_data(dev, i);
|
||||
if (ret < 0)
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
ret = mxl862xx_read(dev, MXL862XX_MMD_REG_DATA_FIRST + off);
|
||||
if (ret < 0)
|
||||
goto EXIT;
|
||||
|
||||
if ((i * 2 + 1) == r_size) {
|
||||
/* Special handling for last BYTE
|
||||
* if it's not WORD aligned.
|
||||
*/
|
||||
*(uint8_t *)&data[i] = ret & 0xFF;
|
||||
} else {
|
||||
data[i] = cpu_to_le16((uint16_t)ret);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ENABLE_GETSET_OPT) && ENABLE_GETSET_OPT
|
||||
if ((cmd != 0x1801) && (cmd != 0x1802))
|
||||
shadow.data.data[max] = 0;
|
||||
memcpy(shadow.data.data, data, r_size);
|
||||
#endif
|
||||
|
||||
ret = result;
|
||||
|
||||
EXIT:
|
||||
#if defined(ENABLE_GETSET_OPT) && ENABLE_GETSET_OPT
|
||||
shadow.ctrl = cmd;
|
||||
shadow.ret = ret;
|
||||
#endif
|
||||
mutex_unlock(&dev->bus->mdio_lock);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// spdx-license-identifier: gpl-2.0
|
||||
/*
|
||||
* drivers/net/dsa/host_api/mxl862xx_host_api_impl.h - dsa driver for maxlinear mxl862xx switch chips family
|
||||
*
|
||||
* copyright (c) 2024 maxlinear inc.
|
||||
*
|
||||
* this program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the gnu general public license
|
||||
* as published by the free software foundation; either version 2
|
||||
* of the license, or (at your option) any later version.
|
||||
*
|
||||
* this program is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. see the
|
||||
* gnu general public license for more details.
|
||||
*
|
||||
* you should have received a copy of the gnu general public license
|
||||
* along with this program; if not, write to the free software
|
||||
* foundation, inc., 51 franklin street, fifth floor, boston, ma 02110-1301, usa.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MXL862XX_HOST_API_IMPL_H_
|
||||
#define _MXL862XX_HOST_API_IMPL_H_
|
||||
|
||||
#include "mxl862xx_types.h"
|
||||
|
||||
extern int mxl862xx_api_wrap(const mxl862xx_device_t *dev, uint16_t cmd, void *pdata,
|
||||
uint16_t size, uint16_t cmd_r, uint16_t r_size);
|
||||
|
||||
#endif /* _MXL862XX_HOST_API_IMPL_H_ */
|
||||
@@ -0,0 +1,61 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* drivers/net/dsa/host_api/mxl862xx_mdio_relay.c - dsa driver for Maxlinear mxl862xx switch chips family
|
||||
*
|
||||
* Copyright (C) 2024 MaxLinear Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mxl862xx_mdio_relay.h"
|
||||
#include "mxl862xx_host_api_impl.h"
|
||||
#include "mxl862xx_mmd_apis.h"
|
||||
|
||||
int int_gphy_read(const mxl862xx_device_t *dev, struct mdio_relay_data *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, INT_GPHY_READ, parm, sizeof(*parm), 0,
|
||||
sizeof(parm->data));
|
||||
}
|
||||
|
||||
int int_gphy_write(const mxl862xx_device_t *dev, struct mdio_relay_data *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, INT_GPHY_WRITE, parm, sizeof(*parm), 0, 0);
|
||||
}
|
||||
|
||||
int int_gphy_mod(const mxl862xx_device_t *dev, struct mdio_relay_mod_data *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, INT_GPHY_MOD, parm, sizeof(*parm), 0, 0);
|
||||
}
|
||||
|
||||
int ext_mdio_read(const mxl862xx_device_t *dev, struct mdio_relay_data *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, EXT_MDIO_READ, parm, sizeof(*parm), 0,
|
||||
sizeof(parm->data));
|
||||
}
|
||||
|
||||
int ext_mdio_write(const mxl862xx_device_t *dev, struct mdio_relay_data *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, EXT_MDIO_WRITE, parm, sizeof(*parm), 0, 0);
|
||||
}
|
||||
|
||||
int ext_mdio_mod(const mxl862xx_device_t *dev, struct mdio_relay_mod_data *parm)
|
||||
{
|
||||
return mxl862xx_api_wrap(dev, EXT_MDIO_MOD, parm, sizeof(*parm), 0, 0);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(int_gphy_write);
|
||||
EXPORT_SYMBOL(int_gphy_read);
|
||||
EXPORT_SYMBOL(int_gphy_mod);
|
||||
@@ -0,0 +1,86 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* drivers/net/dsa/host_api/mxl862xx_mdio_relay.h - Header file for DSA Driver for MaxLinear Mxl862xx switch chips family
|
||||
*
|
||||
* Copyright (C) 2024 MaxLinear Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MXL862XX_MDIO_RELAY_H_
|
||||
#define _MXL862XX_MDIO_RELAY_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include "mxl862xx_types.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
#pragma scalar_storage_order little-endian
|
||||
|
||||
struct mdio_relay_data {
|
||||
/* data to be read or written */
|
||||
uint16_t data;
|
||||
/* PHY index (0~7) for internal PHY
|
||||
* PHY address (0~31) for external PHY access via MDIO bus
|
||||
*/
|
||||
uint8_t phy;
|
||||
/* MMD device (0~31) */
|
||||
uint8_t mmd;
|
||||
/* Register Index
|
||||
* 0~31 if mmd is 0 (CL22)
|
||||
* 0~65535 otherwise (CL45)
|
||||
*/
|
||||
uint16_t reg;
|
||||
};
|
||||
|
||||
struct mdio_relay_mod_data {
|
||||
/* data to be written with mask */
|
||||
uint16_t data;
|
||||
/* PHY index (0~7) for internal PHY
|
||||
* PHY address (0~31) for external PHY access via MDIO bus
|
||||
*/
|
||||
uint8_t phy;
|
||||
/* MMD device (0~31) */
|
||||
uint8_t mmd;
|
||||
/* Register Index
|
||||
* 0~31 if mmd is 0 (CL22)
|
||||
* 0~65535 otherwise (CL45)
|
||||
*/
|
||||
uint16_t reg;
|
||||
/* mask of bit fields to be updated
|
||||
* 1 to write the bit
|
||||
* 0 to ignore
|
||||
*/
|
||||
uint16_t mask;
|
||||
};
|
||||
|
||||
#pragma scalar_storage_order default
|
||||
#pragma pack(pop)
|
||||
|
||||
/* read internal GPHY MDIO/MMD registers */
|
||||
int int_gphy_read(const mxl862xx_device_t *dev, struct mdio_relay_data *pdata);
|
||||
/* write internal GPHY MDIO/MMD registers */
|
||||
int int_gphy_write(const mxl862xx_device_t *dev, struct mdio_relay_data *pdata);
|
||||
/* modify internal GPHY MDIO/MMD registers */
|
||||
int int_gphy_mod(const mxl862xx_device_t *dev, struct mdio_relay_mod_data *pdata);
|
||||
|
||||
/* read external GPHY MDIO/MMD registers via MDIO bus */
|
||||
int ext_mdio_read(const mxl862xx_device_t *dev, struct mdio_relay_data *pdata);
|
||||
/* write external GPHY MDIO/MMD registers via MDIO bus */
|
||||
int ext_mdio_write(const mxl862xx_device_t *dev, struct mdio_relay_data *pdata);
|
||||
/* modify external GPHY MDIO/MMD registers via MDIO bus */
|
||||
int ext_mdio_mod(const mxl862xx_device_t *dev, struct mdio_relay_mod_data *pdata);
|
||||
|
||||
#endif /* _MXL862XX_MDIO_RELAY_H_ */
|
||||
@@ -0,0 +1,279 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* drivers/net/dsa/host_api/mxl862xx_mmd_apis.h - Header file for DSA Driver for MaxLinear Mxl862xx switch chips family
|
||||
*
|
||||
* Copyright (C) 2024 MaxLinear Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MXL862XX_MMD_APIS_H_
|
||||
#define _MXL862XX_MMD_APIS_H_
|
||||
|
||||
#include "mxl862xx_api.h"
|
||||
#include "mxl862xx_mdio_relay.h"
|
||||
|
||||
#define MXL862XX_MMD_DEV 30
|
||||
#define MXL862XX_MMD_REG_CTRL 0
|
||||
#define MXL862XX_MMD_REG_LEN_RET 1
|
||||
#define MXL862XX_MMD_REG_DATA_FIRST 2
|
||||
#define MXL862XX_MMD_REG_DATA_LAST 95
|
||||
#define MXL862XX_MMD_REG_DATA_MAX_SIZE \
|
||||
(MXL862XX_MMD_REG_DATA_LAST - MXL862XX_MMD_REG_DATA_FIRST + 1)
|
||||
|
||||
typedef union mmd_api_data {
|
||||
uint16_t data[MXL862XX_MMD_REG_DATA_MAX_SIZE * 3]; //Maximum data size is GSW_PCE_rule_t (508)
|
||||
mxl862xx_register_mod_t mxl862xx_register_mod_t_data;
|
||||
mxl862xx_cpu_port_cfg_t mxl862xx_cpu_port_cfg_t_data;
|
||||
mxl862xx_port_link_cfg_t mxl862xx_port_link_cfg_t_data;
|
||||
mxl862xx_port_cfg_t mxl862xx_port_cfg_t_data;
|
||||
mxl862xx_bridge_alloc_t mxl862xx_bridge_alloc_t_data;
|
||||
mxl862xx_bridge_port_config_t mxl862xx_bridge_port_config_t_data;
|
||||
mxl862xx_debug_rmon_port_cnt_t mxl862xx_debug_rmon_port_cnt_t_data;
|
||||
mxl862xx_mac_table_clear_cond_t mxl862xx_mac_table_clear_cond_t_data;
|
||||
mxl862xx_mac_table_read_t mxl862xx_mac_table_read_t_data;
|
||||
mxl862xx_mac_table_add_t mxl862xx_mac_table_add_t_data;
|
||||
mxl862xx_mac_table_remove_t mxl862xx_mac_table_remove_t_data;
|
||||
mxl862xx_stp_port_cfg_t mxl862xx_stp_port_cfg_t_data;
|
||||
mxl862xx_ss_sp_tag_t mxl862xx_ss_sp_tag_t_data;
|
||||
mxl862xx_monitor_port_cfg_t mxl862xx_monitor_port_cfg_t_data;
|
||||
mxl862xx_ctp_port_config_t mxl862xx_ctp_port_config_t_data;
|
||||
|
||||
struct mdio_relay_data mdio_relay_data;
|
||||
struct mdio_relay_mod_data mdio_relay_mod_data;
|
||||
struct sys_fw_image_version img_ver_data;
|
||||
#ifdef CONFIG_SENSOR_MXL
|
||||
struct sys_sensor_value pvt_sensor_data;
|
||||
#endif
|
||||
} mmd_api_data_t;
|
||||
|
||||
#define MXL862XX_COMMON_MAGIC 0x100
|
||||
#define MXL862XX_TFLOW_MAGIC 0x200
|
||||
#define MXL862XX_BRDG_MAGIC 0x300
|
||||
#define MXL862XX_BRDGPORT_MAGIC 0x400
|
||||
#define MXL862XX_CTP_MAGIC 0x500
|
||||
#define MXL862XX_QOS_MAGIC 0x600
|
||||
#define MXL862XX_RMON_MAGIC 0x700
|
||||
#define MXL862XX_DEBUG_MAGIC 0x800
|
||||
#define MXL862XX_PMAC_MAGIC 0x900
|
||||
#define MXL862XX_SWMAC_MAGIC 0xA00
|
||||
#define MXL862XX_EXTVLAN_MAGIC 0xB00
|
||||
#define MXL862XX_VLANFILTER_MAGIC 0xC00
|
||||
#define MXL862XX_MULTICAST_MAGIC 0xD00
|
||||
#define MXL862XX_TRUNKING_MAGIC 0xE00
|
||||
#define MXL862XX_STP_MAGIC 0xF00
|
||||
#define MXL862XX_PBB_MAGIC 0x1000
|
||||
#define MXL862XX_VLAN_RMON_MAGIC 0x1100
|
||||
#define MXL862XX_SS_MAGIC 0x1600
|
||||
|
||||
#define GPY_GPY2XX_MAGIC 0x1800
|
||||
|
||||
#define SYS_MISC_MAGIC 0x1900
|
||||
|
||||
#ifdef MMD_API_TEST
|
||||
#define MMD_API_SIMPLE_TEST (0x0 + 0x1)
|
||||
#endif
|
||||
#define MMD_API_SET_DATA_0 (0x0 + 0x2)
|
||||
#define MMD_API_SET_DATA_1 (0x0 + 0x3)
|
||||
#define MMD_API_SET_DATA_2 (0x0 + 0x4)
|
||||
#define MMD_API_GET_DATA_0 (0x0 + 0x5)
|
||||
#define MMD_API_GET_DATA_1 (0x0 + 0x6)
|
||||
#define MMD_API_GET_DATA_2 (0x0 + 0x7)
|
||||
#define MMD_API_RST_DATA (0x0 + 0x8)
|
||||
|
||||
#define MXL862XX_COMMON_REGISTERGET (MXL862XX_COMMON_MAGIC + 0x1)
|
||||
#define MXL862XX_COMMON_REGISTERSET (MXL862XX_COMMON_MAGIC + 0x2)
|
||||
#define MXL862XX_COMMON_CPU_PORTCFGGET (MXL862XX_COMMON_MAGIC + 0x3)
|
||||
#define MXL862XX_COMMON_CPU_PORTCFGSET (MXL862XX_COMMON_MAGIC + 0x4)
|
||||
#define MXL862XX_COMMON_PORTLINKCFGGET (MXL862XX_COMMON_MAGIC + 0x5)
|
||||
#define MXL862XX_COMMON_PORTLINKCFGSET (MXL862XX_COMMON_MAGIC + 0x6)
|
||||
#define MXL862XX_COMMON_PORTCFGGET (MXL862XX_COMMON_MAGIC + 0x7)
|
||||
#define MXL862XX_COMMON_PORTCFGSET (MXL862XX_COMMON_MAGIC + 0x8)
|
||||
#define MXL862XX_COMMON_CFGGET (MXL862XX_COMMON_MAGIC + 0x9)
|
||||
#define MXL862XX_COMMON_CFGSET (MXL862XX_COMMON_MAGIC + 0xA)
|
||||
#define MXL862XX_COMMON_MONITORPORTCFGGET (MXL862XX_COMMON_MAGIC + 0xD)
|
||||
#define MXL862XX_COMMON_MONITORPORTCFGSET (MXL862XX_COMMON_MAGIC + 0xE)
|
||||
#define MXL862XX_COMMON_FREEZE (MXL862XX_COMMON_MAGIC + 0xF)
|
||||
#define MXL862XX_COMMON_UNFREEZE (MXL862XX_COMMON_MAGIC + 0x10)
|
||||
#define MXL862XX_COMMON_REGISTERMOD (MXL862XX_COMMON_MAGIC + 0x11)
|
||||
|
||||
#define MXL862XX_TFLOW_PCERULEREAD (MXL862XX_TFLOW_MAGIC + 0x1)
|
||||
#define MXL862XX_TFLOW_PCERULEWRITE (MXL862XX_TFLOW_MAGIC + 0x2)
|
||||
#define MXL862XX_TFLOW_PCERULEDELETE (MXL862XX_TFLOW_MAGIC + 0x3)
|
||||
#define MXL862XX_TFLOW_PCERULEALLOC (MXL862XX_TFLOW_MAGIC + 0x4)
|
||||
#define MXL862XX_TFLOW_PCERULEFREE (MXL862XX_TFLOW_MAGIC + 0x5)
|
||||
#define MXL862XX_TFLOW_PCERULEENABLE (MXL862XX_TFLOW_MAGIC + 0x6)
|
||||
#define MXL862XX_TFLOW_PCERULEDISABLE (MXL862XX_TFLOW_MAGIC + 0x7)
|
||||
|
||||
#define MXL862XX_BRIDGE_ALLOC (MXL862XX_BRDG_MAGIC + 0x1)
|
||||
#define MXL862XX_BRIDGE_CONFIGSET (MXL862XX_BRDG_MAGIC + 0x2)
|
||||
#define MXL862XX_BRIDGE_CONFIGGET (MXL862XX_BRDG_MAGIC + 0x3)
|
||||
#define MXL862XX_BRIDGE_FREE (MXL862XX_BRDG_MAGIC + 0x4)
|
||||
|
||||
#define MXL862XX_BRIDGEPORT_ALLOC (MXL862XX_BRDGPORT_MAGIC + 0x1)
|
||||
#define MXL862XX_BRIDGEPORT_CONFIGSET (MXL862XX_BRDGPORT_MAGIC + 0x2)
|
||||
#define MXL862XX_BRIDGEPORT_CONFIGGET (MXL862XX_BRDGPORT_MAGIC + 0x3)
|
||||
#define MXL862XX_BRIDGEPORT_FREE (MXL862XX_BRDGPORT_MAGIC + 0x4)
|
||||
|
||||
#define MXL862XX_CTP_PORTASSIGNMENTALLOC (MXL862XX_CTP_MAGIC + 0x1)
|
||||
#define MXL862XX_CTP_PORTASSIGNMENTFREE (MXL862XX_CTP_MAGIC + 0x2)
|
||||
#define MXL862XX_CTP_PORTASSIGNMENTSET (MXL862XX_CTP_MAGIC + 0x3)
|
||||
#define MXL862XX_CTP_PORTASSIGNMENTGET (MXL862XX_CTP_MAGIC + 0x4)
|
||||
#define MXL862XX_CTP_PORTCONFIGSET (MXL862XX_CTP_MAGIC + 0x5)
|
||||
#define MXL862XX_CTP_PORTCONFIGGET (MXL862XX_CTP_MAGIC + 0x6)
|
||||
#define MXL862XX_CTP_PORTCONFIGRESET (MXL862XX_CTP_MAGIC + 0x7)
|
||||
|
||||
#define MXL862XX_QOS_METERCFGGET (MXL862XX_QOS_MAGIC + 0x1)
|
||||
#define MXL862XX_QOS_METERCFGSET (MXL862XX_QOS_MAGIC + 0x2)
|
||||
#define MXL862XX_QOS_DSCP_CLASSGET (MXL862XX_QOS_MAGIC + 0x4)
|
||||
#define MXL862XX_QOS_DSCP_CLASSSET (MXL862XX_QOS_MAGIC + 0x5)
|
||||
#define MXL862XX_QOS_DSCP_DROPPRECEDENCECFGGET (MXL862XX_QOS_MAGIC + 0x6)
|
||||
#define MXL862XX_QOS_DSCP_DROPPRECEDENCECFGSET (MXL862XX_QOS_MAGIC + 0x7)
|
||||
#define MXL862XX_QOS_PORTREMARKINGCFGGET (MXL862XX_QOS_MAGIC + 0x8)
|
||||
#define MXL862XX_QOS_PORTREMARKINGCFGSET (MXL862XX_QOS_MAGIC + 0x9)
|
||||
#define MXL862XX_QOS_PCP_CLASSGET (MXL862XX_QOS_MAGIC + 0xA)
|
||||
#define MXL862XX_QOS_PCP_CLASSSET (MXL862XX_QOS_MAGIC + 0xB)
|
||||
#define MXL862XX_QOS_PORTCFGGET (MXL862XX_QOS_MAGIC + 0xC)
|
||||
#define MXL862XX_QOS_PORTCFGSET (MXL862XX_QOS_MAGIC + 0xD)
|
||||
#define MXL862XX_QOS_QUEUEPORTGET (MXL862XX_QOS_MAGIC + 0xE)
|
||||
#define MXL862XX_QOS_QUEUEPORTSET (MXL862XX_QOS_MAGIC + 0xF)
|
||||
#define MXL862XX_QOS_SCHEDULERCFGGET (MXL862XX_QOS_MAGIC + 0x10)
|
||||
#define MXL862XX_QOS_SCHEDULERCFGSET (MXL862XX_QOS_MAGIC + 0x11)
|
||||
#define MXL862XX_QOS_SHAPERCFGGET (MXL862XX_QOS_MAGIC + 0x12)
|
||||
#define MXL862XX_QOS_SHAPERCFGSET (MXL862XX_QOS_MAGIC + 0x13)
|
||||
#define MXL862XX_QOS_SHAPERQUEUEASSIGN (MXL862XX_QOS_MAGIC + 0x14)
|
||||
#define MXL862XX_QOS_SHAPERQUEUEDEASSIGN (MXL862XX_QOS_MAGIC + 0x15)
|
||||
#define MXL862XX_QOS_SHAPERQUEUEGET (MXL862XX_QOS_MAGIC + 0x16)
|
||||
#define MXL862XX_QOS_STORMCFGSET (MXL862XX_QOS_MAGIC + 0x17)
|
||||
#define MXL862XX_QOS_STORMCFGGET (MXL862XX_QOS_MAGIC + 0x18)
|
||||
#define MXL862XX_QOS_WREDCFGGET (MXL862XX_QOS_MAGIC + 0x19)
|
||||
#define MXL862XX_QOS_WREDCFGSET (MXL862XX_QOS_MAGIC + 0x1A)
|
||||
#define MXL862XX_QOS_WREDQUEUECFGGET (MXL862XX_QOS_MAGIC + 0x1B)
|
||||
#define MXL862XX_QOS_WREDQUEUECFGSET (MXL862XX_QOS_MAGIC + 0x1C)
|
||||
#define MXL862XX_QOS_WREDPORTCFGGET (MXL862XX_QOS_MAGIC + 0x1D)
|
||||
#define MXL862XX_QOS_WREDPORTCFGSET (MXL862XX_QOS_MAGIC + 0x1E)
|
||||
#define MXL862XX_QOS_FLOWCTRLCFGGET (MXL862XX_QOS_MAGIC + 0x1F)
|
||||
#define MXL862XX_QOS_FLOWCTRLCFGSET (MXL862XX_QOS_MAGIC + 0x20)
|
||||
#define MXL862XX_QOS_FLOWCTRLPORTCFGGET (MXL862XX_QOS_MAGIC + 0x21)
|
||||
#define MXL862XX_QOS_FLOWCTRLPORTCFGSET (MXL862XX_QOS_MAGIC + 0x22)
|
||||
#define MXL862XX_QOS_QUEUEBUFFERRESERVECFGGET (MXL862XX_QOS_MAGIC + 0x23)
|
||||
#define MXL862XX_QOS_QUEUEBUFFERRESERVECFGSET (MXL862XX_QOS_MAGIC + 0x24)
|
||||
#define MXL862XX_QOS_COLORMARKINGTABLEGET (MXL862XX_QOS_MAGIC + 0x26)
|
||||
#define MXL862XX_QOS_COLORMARKINGTABLESET (MXL862XX_QOS_MAGIC + 0x27)
|
||||
#define MXL862XX_QOS_COLORREMARKINGTABLESET (MXL862XX_QOS_MAGIC + 0x28)
|
||||
#define MXL862XX_QOS_COLORREMARKINGTABLEGET (MXL862XX_QOS_MAGIC + 0x29)
|
||||
#define MXL862XX_QOS_METERALLOC (MXL862XX_QOS_MAGIC + 0x2A)
|
||||
#define MXL862XX_QOS_METERFREE (MXL862XX_QOS_MAGIC + 0x2B)
|
||||
#define MXL862XX_QOS_DSCP2PCPTABLESET (MXL862XX_QOS_MAGIC + 0x2C)
|
||||
#define MXL862XX_QOS_DSCP2PCPTABLEGET (MXL862XX_QOS_MAGIC + 0x2D)
|
||||
#define MXL862XX_QOS_PMAPPERTABLESET (MXL862XX_QOS_MAGIC + 0x2E)
|
||||
#define MXL862XX_QOS_PMAPPERTABLEGET (MXL862XX_QOS_MAGIC + 0x2F)
|
||||
#define MXL862XX_QOS_SVLAN_PCP_CLASSGET (MXL862XX_QOS_MAGIC + 0x30)
|
||||
#define MXL862XX_QOS_SVLAN_PCP_CLASSSET (MXL862XX_QOS_MAGIC + 0x31)
|
||||
|
||||
#define MXL862XX_RMON_PORT_GET (MXL862XX_RMON_MAGIC + 0x1)
|
||||
#define MXL862XX_RMON_MODE_SET (MXL862XX_RMON_MAGIC + 0x2)
|
||||
#define MXL862XX_RMON_METER_GET (MXL862XX_RMON_MAGIC + 0x3)
|
||||
#define MXL862XX_RMON_CLEAR (MXL862XX_RMON_MAGIC + 0x4)
|
||||
#define MXL862XX_RMON_TFLOWGET (MXL862XX_RMON_MAGIC + 0x5)
|
||||
#define MXL862XX_RMON_TFLOWCLEAR (MXL862XX_RMON_MAGIC + 0x6)
|
||||
#define MXL862XX_RMON_TFLOWCOUNTMODESET (MXL862XX_RMON_MAGIC + 0x7)
|
||||
#define MXL862XX_RMON_TFLOWCOUNTMODEGET (MXL862XX_RMON_MAGIC + 0x8)
|
||||
|
||||
#define MXL862XX_DEBUG_RMON_PORT_GET (MXL862XX_DEBUG_MAGIC + 0x1)
|
||||
|
||||
#define MXL862XX_PMAC_COUNTGET (MXL862XX_PMAC_MAGIC + 0x1)
|
||||
#define MXL862XX_PMAC_GBL_CFGSET (MXL862XX_PMAC_MAGIC + 0x2)
|
||||
#define MXL862XX_PMAC_GBL_CFGGET (MXL862XX_PMAC_MAGIC + 0x3)
|
||||
#define MXL862XX_PMAC_BM_CFGSET (MXL862XX_PMAC_MAGIC + 0x4)
|
||||
#define MXL862XX_PMAC_BM_CFGGET (MXL862XX_PMAC_MAGIC + 0x5)
|
||||
#define MXL862XX_PMAC_IG_CFGSET (MXL862XX_PMAC_MAGIC + 0x6)
|
||||
#define MXL862XX_PMAC_IG_CFGGET (MXL862XX_PMAC_MAGIC + 0x7)
|
||||
#define MXL862XX_PMAC_EG_CFGSET (MXL862XX_PMAC_MAGIC + 0x8)
|
||||
#define MXL862XX_PMAC_EG_CFGGET (MXL862XX_PMAC_MAGIC + 0x9)
|
||||
|
||||
#define MXL862XX_MAC_TABLECLEAR (MXL862XX_SWMAC_MAGIC + 0x1)
|
||||
#define MXL862XX_MAC_TABLEENTRYADD (MXL862XX_SWMAC_MAGIC + 0x2)
|
||||
#define MXL862XX_MAC_TABLEENTRYREAD (MXL862XX_SWMAC_MAGIC + 0x3)
|
||||
#define MXL862XX_MAC_TABLEENTRYQUERY (MXL862XX_SWMAC_MAGIC + 0x4)
|
||||
#define MXL862XX_MAC_TABLEENTRYREMOVE (MXL862XX_SWMAC_MAGIC + 0x5)
|
||||
#define MXL862XX_MAC_DEFAULTFILTERSET (MXL862XX_SWMAC_MAGIC + 0x6)
|
||||
#define MXL862XX_MAC_DEFAULTFILTERGET (MXL862XX_SWMAC_MAGIC + 0x7)
|
||||
#define MXL862XX_MAC_TABLECLEARCOND (MXL862XX_SWMAC_MAGIC + 0x8)
|
||||
|
||||
#define MXL862XX_EXTENDEDVLAN_ALLOC (MXL862XX_EXTVLAN_MAGIC + 0x1)
|
||||
#define MXL862XX_EXTENDEDVLAN_SET (MXL862XX_EXTVLAN_MAGIC + 0x2)
|
||||
#define MXL862XX_EXTENDEDVLAN_GET (MXL862XX_EXTVLAN_MAGIC + 0x3)
|
||||
#define MXL862XX_EXTENDEDVLAN_FREE (MXL862XX_EXTVLAN_MAGIC + 0x4)
|
||||
|
||||
#define MXL862XX_VLANFILTER_ALLOC (MXL862XX_VLANFILTER_MAGIC + 0x1)
|
||||
#define MXL862XX_VLANFILTER_SET (MXL862XX_VLANFILTER_MAGIC + 0x2)
|
||||
#define MXL862XX_VLANFILTER_GET (MXL862XX_VLANFILTER_MAGIC + 0x3)
|
||||
#define MXL862XX_VLANFILTER_FREE (MXL862XX_VLANFILTER_MAGIC + 0x4)
|
||||
|
||||
#define MXL862XX_VLAN_COUNTER_MAPPING_SET (MXL862XX_VLAN_RMON_MAGIC + 0x1)
|
||||
#define MXL862XX_VLAN_COUNTER_MAPPING_GET (MXL862XX_VLAN_RMON_MAGIC + 0x2)
|
||||
#define MXL862XX_VLAN_RMON_GET (MXL862XX_VLAN_RMON_MAGIC + 0x3)
|
||||
#define MXL862XX_VLAN_RMON_CLEAR (MXL862XX_VLAN_RMON_MAGIC + 0x4)
|
||||
#define MXL862XX_VLAN_RMON_CONTROL_SET (MXL862XX_VLAN_RMON_MAGIC + 0x5)
|
||||
#define MXL862XX_VLAN_RMON_CONTROL_GET (MXL862XX_VLAN_RMON_MAGIC + 0x6)
|
||||
|
||||
#define MXL862XX_MULTICAST_ROUTERPORTADD (MXL862XX_MULTICAST_MAGIC + 0x1)
|
||||
#define MXL862XX_MULTICAST_ROUTERPORTREAD (MXL862XX_MULTICAST_MAGIC + 0x2)
|
||||
#define MXL862XX_MULTICAST_ROUTERPORTREMOVE (MXL862XX_MULTICAST_MAGIC + 0x3)
|
||||
#define MXL862XX_MULTICAST_SNOOPCFGGET (MXL862XX_MULTICAST_MAGIC + 0x4)
|
||||
#define MXL862XX_MULTICAST_SNOOPCFGSET (MXL862XX_MULTICAST_MAGIC + 0x5)
|
||||
#define MXL862XX_MULTICAST_TABLEENTRYADD (MXL862XX_MULTICAST_MAGIC + 0x6)
|
||||
#define MXL862XX_MULTICAST_TABLEENTRYREAD (MXL862XX_MULTICAST_MAGIC + 0x7)
|
||||
#define MXL862XX_MULTICAST_TABLEENTRYREMOVE (MXL862XX_MULTICAST_MAGIC + 0x8)
|
||||
|
||||
#define MXL862XX_TRUNKING_CFGGET (MXL862XX_TRUNKING_MAGIC + 0x1)
|
||||
#define MXL862XX_TRUNKING_CFGSET (MXL862XX_TRUNKING_MAGIC + 0x2)
|
||||
#define MXL862XX_TRUNKING_PORTCFGGET (MXL862XX_TRUNKING_MAGIC + 0x3)
|
||||
#define MXL862XX_TRUNKING_PORTCFGSET (MXL862XX_TRUNKING_MAGIC + 0x4)
|
||||
|
||||
#define MXL862XX_STP_PORTCFGGET (MXL862XX_STP_MAGIC + 0x1)
|
||||
#define MXL862XX_STP_PORTCFGSET (MXL862XX_STP_MAGIC + 0x2)
|
||||
#define MXL862XX_STP_BPDU_RULEGET (MXL862XX_STP_MAGIC + 0x3)
|
||||
#define MXL862XX_STP_BPDU_RULESET (MXL862XX_STP_MAGIC + 0x4)
|
||||
|
||||
#define MXL862XX_PBB_TEMPLATEALLOC (MXL862XX_PBB_MAGIC + 0x1)
|
||||
#define MXL862XX_PBB_TEMPLATEFREE (MXL862XX_PBB_MAGIC + 0x2)
|
||||
#define MXL862XX_PBB_TEMPLATESET (MXL862XX_PBB_MAGIC + 0x3)
|
||||
#define MXL862XX_PBB_TEMPLATEGET (MXL862XX_PBB_MAGIC + 0x4)
|
||||
|
||||
#define MXL862XX_SS_SPTAG_GET (MXL862XX_SS_MAGIC + 0x01)
|
||||
#define MXL862XX_SS_SPTAG_SET (MXL862XX_SS_MAGIC + 0x02)
|
||||
|
||||
#define INT_GPHY_READ (GPY_GPY2XX_MAGIC + 0x01)
|
||||
#define INT_GPHY_WRITE (GPY_GPY2XX_MAGIC + 0x02)
|
||||
#define INT_GPHY_MOD (GPY_GPY2XX_MAGIC + 0x03)
|
||||
#define EXT_MDIO_READ (GPY_GPY2XX_MAGIC + 0x11)
|
||||
#define EXT_MDIO_WRITE (GPY_GPY2XX_MAGIC + 0x12)
|
||||
#define EXT_MDIO_MOD (GPY_GPY2XX_MAGIC + 0x13)
|
||||
|
||||
#define SYS_MISC_FW_UPDATE (SYS_MISC_MAGIC + 0x01)
|
||||
#define SYS_MISC_FW_VERSION (SYS_MISC_MAGIC + 0x02)
|
||||
#define SYS_MISC_PVT_TEMP (SYS_MISC_MAGIC + 0x03)
|
||||
#define SYS_MISC_PVT_VOLTAGE (SYS_MISC_MAGIC + 0x04)
|
||||
|
||||
#define MMD_API_MAXIMUM_ID 0x7FFF
|
||||
|
||||
int mxl862xx_read(const mxl862xx_device_t *dev, uint32_t regaddr);
|
||||
int mxl862xx_write(const mxl862xx_device_t *dev, uint32_t regaddr, uint16_t data);
|
||||
|
||||
|
||||
#endif /* _MXL862XX_MMD_APIS_H_ */
|
||||
@@ -0,0 +1,509 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* drivers/net/dsa/host_api/mxl862xx_rmon.h - dsa driver for Maxlinear mxl862xx switch chips family
|
||||
*
|
||||
* Copyright (C) 2024 MaxLinear Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MXL862XX_RMON_H_
|
||||
#define _MXL862XX_RMON_H_
|
||||
|
||||
#include "mxl862xx_types.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
#pragma scalar_storage_order little-endian
|
||||
|
||||
/** \brief Port Type - GSWIP-3.1 only.
|
||||
Used by \ref MXL862XX_port_cfg_t. */
|
||||
typedef enum {
|
||||
/** Logical Port */
|
||||
MXL862XX_LOGICAL_PORT = 0,
|
||||
/** Physical Port
|
||||
Applicable only for GSWIP-3.1/3.2 */
|
||||
MXL862XX_PHYSICAL_PORT = 1,
|
||||
/** Connectivity Termination Port (CTP)
|
||||
Applicable only for GSWIP-3.1/3.2 */
|
||||
MXL862XX_CTP_PORT = 2,
|
||||
/** Bridge Port
|
||||
Applicable only for GSWIP-3.1/3.2 */
|
||||
MXL862XX_BRIDGE_PORT = 3
|
||||
} mxl862xx_port_type_t;
|
||||
|
||||
/**Defined as per RMON counter table structure
|
||||
Applicable only for GSWIP 3.1*/
|
||||
typedef enum {
|
||||
MXL862XX_RMON_CTP_PORT_RX = 0,
|
||||
MXL862XX_RMON_CTP_PORT_TX = 1,
|
||||
MXL862XX_RMON_BRIDGE_PORT_RX = 2,
|
||||
MXL862XX_RMON_BRIDGE_PORT_TX = 3,
|
||||
MXL862XX_RMON_CTP_PORT_PCE_BYPASS = 4,
|
||||
MXL862XX_RMON_TFLOW_RX = 5,
|
||||
MXL862XX_RMON_TFLOW_TX = 6,
|
||||
MXL862XX_RMON_QMAP = 0x0E,
|
||||
MXL862XX_RMON_METER = 0x19,
|
||||
MXL862XX_RMON_PMAC = 0x1C,
|
||||
} mxl862xx_rmon_port_type_t;
|
||||
|
||||
/** Defined as per RMON counter table structure
|
||||
* Applicable only for GSWIP 3.0
|
||||
*/
|
||||
typedef enum {
|
||||
MXL862XX_RMON_REDIRECTION = 0X18,
|
||||
MXL862XX_RMON_IF = 0x1A,
|
||||
MXL862XX_RMON_ROUTE = 0x1B,
|
||||
MXL862XX_RMON_PMACIG = 0x1C,
|
||||
} mxl862xx_rmon_port_t;
|
||||
|
||||
typedef enum {
|
||||
/** Parser microcode table */
|
||||
PMAC_BPMAP_INDEX = 0x00,
|
||||
PMAC_IGCFG_INDEX = 0x01,
|
||||
PMAC_EGCFG_INDEX = 0x02,
|
||||
} pm_tbl_cmds_t;
|
||||
/** \brief RMON Counters Type enumeration.
|
||||
Used by \ref MXL862XX_RMON_clear_t and \ref MXL862XX_RMON_mode_t. */
|
||||
typedef enum {
|
||||
/** All RMON Types Counters */
|
||||
MXL862XX_RMON_ALL_TYPE = 0,
|
||||
/** All PMAC RMON Counters */
|
||||
MXL862XX_RMON_PMAC_TYPE = 1,
|
||||
/** Port based RMON Counters */
|
||||
MXL862XX_RMON_PORT_TYPE = 2,
|
||||
/** Meter based RMON Counters */
|
||||
MXL862XX_RMON_METER_TYPE = 3,
|
||||
/** Interface based RMON Counters */
|
||||
MXL862XX_RMON_IF_TYPE = 4,
|
||||
/** Route based RMON Counters */
|
||||
MXL862XX_RMON_ROUTE_TYPE = 5,
|
||||
/** Redirected Traffic based RMON Counters */
|
||||
MXL862XX_RMON_REDIRECT_TYPE = 6,
|
||||
/** Bridge Port based RMON Counters */
|
||||
MXL862XX_RMON_BRIDGE_TYPE = 7,
|
||||
/** CTP Port based RMON Counters */
|
||||
MXL862XX_RMON_CTP_TYPE = 8,
|
||||
} mxl862xx_rmon_type_t;
|
||||
|
||||
/** \brief RMON Counters Mode Enumeration.
|
||||
This enumeration defines Counters mode - Packets based or Bytes based counting.
|
||||
Metering and Routing Sessions RMON counting support either Byte based or packets based only. */
|
||||
typedef enum {
|
||||
/** Packet based RMON Counters */
|
||||
MXL862XX_RMON_COUNT_PKTS = 0,
|
||||
/** Bytes based RMON Counters */
|
||||
MXL862XX_RMON_COUNT_BYTES = 1,
|
||||
/** number of dropped frames, supported only for interface cunters */
|
||||
MXL862XX_RMON_DROP_COUNT = 2,
|
||||
} mxl862xx_rmon_count_mode_t;
|
||||
|
||||
/** \brief Used for getting metering RMON counters.
|
||||
Used by \ref MXL862XX_RMON_METER_GET */
|
||||
typedef enum {
|
||||
/* Resereved */
|
||||
MXL862XX_RMON_METER_COLOR_RES = 0,
|
||||
/* Green color */
|
||||
MXL862XX_RMON_METER_COLOR_GREEN = 1,
|
||||
/* Yellow color */
|
||||
MXL862XX_RMON_METER_COLOR_YELLOW = 2,
|
||||
/* Red color */
|
||||
MXL862XX_RMON_METER_COLOR_RED = 3,
|
||||
} mxl862xx_rmon_meter_color_t;
|
||||
|
||||
/* TFLOW counter type */
|
||||
typedef enum {
|
||||
/* Set all Rx/Tx/PCE-Bp-Tx registers to same value */
|
||||
MXL862XX_TFLOW_COUNTER_ALL = 0, //Default for 'set' function.
|
||||
/* SEt PCE Rx register config only */
|
||||
MXL862XX_TFLOW_COUNTER_PCE_Rx = 1, //Default for 'get' function.
|
||||
/* SEt PCE Tx register config only */
|
||||
MXL862XX_TFLOW_COUNTER_PCE_Tx = 2,
|
||||
/* SEt PCE-Bypass Tx register config only */
|
||||
MXL862XX_TFLOW_COUNTER_PCE_BP_Tx = 3,
|
||||
} mxl862xx_tflow_count_conf_type_t;
|
||||
|
||||
/* TFLOW counter mode type */
|
||||
typedef enum {
|
||||
/* Global mode */
|
||||
MXL862XX_TFLOW_CMODE_GLOBAL = 0,
|
||||
/* Logical mode */
|
||||
MXL862XX_TFLOW_CMODE_LOGICAL = 1,
|
||||
/* CTP port mode */
|
||||
MXL862XX_TFLOW_CMODE_CTP = 2,
|
||||
/* Bridge port mode */
|
||||
MXL862XX_TFLOW_CMODE_BRIDGE = 3,
|
||||
} mxl862xx_tflow_cmode_type_t;
|
||||
|
||||
/* TFLOW CTP counter LSB bits */
|
||||
typedef enum {
|
||||
/* Num of valid bits */
|
||||
MXL862XX_TCM_CTP_VAL_BITS_0 = 0,
|
||||
MXL862XX_TCM_CTP_VAL_BITS_1 = 1,
|
||||
MXL862XX_TCM_CTP_VAL_BITS_2 = 2,
|
||||
MXL862XX_TCM_CTP_VAL_BITS_3 = 3,
|
||||
MXL862XX_TCM_CTP_VAL_BITS_4 = 4,
|
||||
MXL862XX_TCM_CTP_VAL_BITS_5 = 5,
|
||||
MXL862XX_TCM_CTP_VAL_BITS_6 = 6,
|
||||
} mxl862xx_tflow_ctp_val_bits_t;
|
||||
|
||||
/* TFLOW bridge port counter LSB bits */
|
||||
typedef enum {
|
||||
/* Num of valid bits */
|
||||
MXL862XX_TCM_BRP_VAL_BITS_2 = 2,
|
||||
MXL862XX_TCM_BRP_VAL_BITS_3 = 3,
|
||||
MXL862XX_TCM_BRP_VAL_BITS_4 = 4,
|
||||
MXL862XX_TCM_BRP_VAL_BITS_5 = 5,
|
||||
MXL862XX_TCM_BRP_VAL_BITS_6 = 6,
|
||||
} mxl862xx_tflow_brp_val_bits_t;
|
||||
|
||||
/**
|
||||
\brief RMON Counters for individual Port.
|
||||
This structure contains the RMON counters of an Ethernet Switch Port.
|
||||
Used by \ref MXL862XX_RMON_PORT_GET. */
|
||||
typedef struct {
|
||||
/** Port Type. This gives information which type of port to get RMON.
|
||||
port_id should be based on this field.
|
||||
This is new in GSWIP-3.1. For GSWIP-2.1/2.2/3.0, this field is always
|
||||
ZERO (MXL862XX_LOGICAL_PORT). */
|
||||
mxl862xx_port_type_t port_type;
|
||||
/** Ethernet Port number (zero-based counting). The valid range is hardware
|
||||
dependent. An error code is delivered if the selected port is not
|
||||
available. This parameter specifies for which MAC port the RMON
|
||||
counter is read. It has to be set by the application before
|
||||
calling \ref MXL862XX_RMON_PORT_GET. */
|
||||
u16 port_id;
|
||||
/** Sub interface ID group. The valid range is hardware/protocol dependent.
|
||||
|
||||
\remarks
|
||||
This field is valid when \ref MXL862XX_RMON_Port_cnt_t::e_port_type is
|
||||
\ref MXL862XX_port_type_t::MXL862XX_CTP_PORT.
|
||||
Sub interface ID group is defined for each of \ref MXL862XX_Logical_port_mode_t.
|
||||
For both \ref MXL862XX_LOGICAL_PORT_8BIT_WLAN and
|
||||
\ref MXL862XX_LOGICAL_PORT_9BIT_WLAN, this field is VAP.
|
||||
For \ref MXL862XX_LOGICAL_PORT_GPON, this field is GEM index.
|
||||
For \ref MXL862XX_LOGICAL_PORT_EPON, this field is stream index.
|
||||
For \ref MXL862XX_LOGICAL_PORT_GINT, this field is LLID.
|
||||
For others, this field is 0. */
|
||||
u16 sub_if_id_group;
|
||||
/** Separate set of CTP Tx counters when PCE is bypassed. GSWIP-3.1 only.*/
|
||||
bool pce_bypass;
|
||||
/*Applicable only for GSWIP 3.1*/
|
||||
/** Discarded at Extended VLAN Operation Packet Count. GSWIP-3.1 only. */
|
||||
u32 rx_extended_vlan_discard_pkts;
|
||||
/** Discarded MTU Exceeded Packet Count. GSWIP-3.1 only. */
|
||||
u32 mtu_exceed_discard_pkts;
|
||||
/** Tx Undersize (<64) Packet Count. GSWIP-3.1 only. */
|
||||
u32 tx_under_size_good_pkts;
|
||||
/** Tx Oversize (>1518) Packet Count. GSWIP-3.1 only. */
|
||||
u32 tx_oversize_good_pkts;
|
||||
/** Receive Packet Count (only packets that are accepted and not discarded). */
|
||||
u32 rx_good_pkts;
|
||||
/** Receive Unicast Packet Count. */
|
||||
u32 rx_unicast_pkts;
|
||||
/** Receive Broadcast Packet Count. */
|
||||
u32 rx_broadcast_pkts;
|
||||
/** Receive Multicast Packet Count. */
|
||||
u32 rx_multicast_pkts;
|
||||
/** Receive FCS Error Packet Count. */
|
||||
u32 rx_fCSError_pkts;
|
||||
/** Receive Undersize Good Packet Count. */
|
||||
u32 rx_under_size_good_pkts;
|
||||
/** Receive Oversize Good Packet Count. */
|
||||
u32 rx_oversize_good_pkts;
|
||||
/** Receive Undersize Error Packet Count. */
|
||||
u32 rx_under_size_error_pkts;
|
||||
/** Receive Good Pause Packet Count. */
|
||||
u32 rx_good_pause_pkts;
|
||||
/** Receive Oversize Error Packet Count. */
|
||||
u32 rx_oversize_error_pkts;
|
||||
/** Receive Align Error Packet Count. */
|
||||
u32 rx_align_error_pkts;
|
||||
/** Filtered Packet Count. */
|
||||
u32 rx_filtered_pkts;
|
||||
/** Receive Size 64 Bytes Packet Count. */
|
||||
u32 rx64Byte_pkts;
|
||||
/** Receive Size 65-127 Bytes Packet Count. */
|
||||
u32 rx127Byte_pkts;
|
||||
/** Receive Size 128-255 Bytes Packet Count. */
|
||||
u32 rx255Byte_pkts;
|
||||
/** Receive Size 256-511 Bytes Packet Count. */
|
||||
u32 rx511Byte_pkts;
|
||||
/** Receive Size 512-1023 Bytes Packet Count. */
|
||||
u32 rx1023Byte_pkts;
|
||||
/** Receive Size 1024-1522 Bytes (or more, if configured) Packet Count. */
|
||||
u32 rx_max_byte_pkts;
|
||||
/** Overall Transmit Good Packets Count. */
|
||||
u32 tx_good_pkts;
|
||||
/** Transmit Unicast Packet Count. */
|
||||
u32 tx_unicast_pkts;
|
||||
/** Transmit Broadcast Packet Count. */
|
||||
u32 tx_broadcast_pkts;
|
||||
/** Transmit Multicast Packet Count. */
|
||||
u32 tx_multicast_pkts;
|
||||
/** Transmit Single Collision Count. */
|
||||
u32 tx_single_coll_count;
|
||||
/** Transmit Multiple Collision Count. */
|
||||
u32 tx_mult_coll_count;
|
||||
/** Transmit Late Collision Count. */
|
||||
u32 tx_late_coll_count;
|
||||
/** Transmit Excessive Collision Count. */
|
||||
u32 tx_excess_coll_count;
|
||||
/** Transmit Collision Count. */
|
||||
u32 tx_coll_count;
|
||||
/** Transmit Pause Packet Count. */
|
||||
u32 tx_pause_count;
|
||||
/** Transmit Size 64 Bytes Packet Count. */
|
||||
u32 tx64Byte_pkts;
|
||||
/** Transmit Size 65-127 Bytes Packet Count. */
|
||||
u32 tx127Byte_pkts;
|
||||
/** Transmit Size 128-255 Bytes Packet Count. */
|
||||
u32 tx255Byte_pkts;
|
||||
/** Transmit Size 256-511 Bytes Packet Count. */
|
||||
u32 tx511Byte_pkts;
|
||||
/** Transmit Size 512-1023 Bytes Packet Count. */
|
||||
u32 tx1023Byte_pkts;
|
||||
/** Transmit Size 1024-1522 Bytes (or more, if configured) Packet Count. */
|
||||
u32 tx_max_byte_pkts;
|
||||
/** Transmit Drop Packet Count. */
|
||||
u32 tx_dropped_pkts;
|
||||
/** Transmit Dropped Packet Count, based on Congestion Management. */
|
||||
u32 tx_acm_dropped_pkts;
|
||||
/** Receive Dropped Packet Count. */
|
||||
u32 rx_dropped_pkts;
|
||||
/** Receive Good Byte Count (64 bit). */
|
||||
u64 rx_good_bytes;
|
||||
/** Receive Bad Byte Count (64 bit). */
|
||||
u64 rx_bad_bytes;
|
||||
/** Transmit Good Byte Count (64 bit). */
|
||||
u64 tx_good_bytes;
|
||||
} mxl862xx_rmon_port_cnt_t;
|
||||
|
||||
/** \brief RMON Counters Mode for different Elements.
|
||||
This structure takes RMON Counter Element Name and mode config */
|
||||
typedef struct {
|
||||
/** RMON Counters Type */
|
||||
mxl862xx_rmon_type_t rmon_type;
|
||||
/** RMON Counters Mode */
|
||||
mxl862xx_rmon_count_mode_t count_mode;
|
||||
} mxl862xx_rmon_mode_t;
|
||||
|
||||
/**
|
||||
\brief RMON Counters for Meter - Type (GSWIP-3.0 only).
|
||||
This structure contains the RMON counters of one Meter Instance.
|
||||
Used by \ref MXL862XX_RMON_METER_GET. */
|
||||
typedef struct {
|
||||
/** Meter Instance number (zero-based counting). The valid range is hardware
|
||||
dependent. An error code is delivered if the selected meter is not
|
||||
available. This parameter specifies for which Meter Id the RMON-1
|
||||
counter is read. It has to be set by the application before
|
||||
calling \ref MXL862XX_RMON_METER_GET. */
|
||||
u8 meter_id;
|
||||
/** Metered Green colored packets or bytes (depending upon mode) count. */
|
||||
u32 green_count;
|
||||
/** Metered Yellow colored packets or bytes (depending upon mode) count. */
|
||||
u32 yellow_count;
|
||||
/** Metered Red colored packets or bytes (depending upon mode) count. */
|
||||
u32 red_count;
|
||||
/** Metered Reserved (Future Use) packets or bytes (depending upon mode) count. */
|
||||
u32 res_count;
|
||||
} mxl862xx_rmon_meter_cnt_t;
|
||||
|
||||
/** \brief RMON Counters Data Structure for clearance of values.
|
||||
Used by \ref MXL862XX_RMON_CLEAR. */
|
||||
typedef struct {
|
||||
/** RMON Counters Type */
|
||||
mxl862xx_rmon_type_t rmon_type;
|
||||
/** RMON Counters Identifier - Meter, Port, If, Route, etc. */
|
||||
u8 rmon_id;
|
||||
} mxl862xx_rmon_clear_t;
|
||||
|
||||
/**
|
||||
\brief Hardware platform TFLOW counter mode.
|
||||
Supported modes include, Global (default), Logical, CTP, Bridge port mode.
|
||||
The number of counters that can be assigned varies based these mode type.
|
||||
Used by \ref MXL862XX_TFLOW_COUNT_MODE_SET and MXL862XX_TFLOW_COUNT_MODE_GET. */
|
||||
typedef struct {
|
||||
//Counter type. PCE Rx/Tx/Bp-Tx.
|
||||
mxl862xx_tflow_count_conf_type_t count_type;
|
||||
//Counter mode. Global/Logical/CTP/br_p.
|
||||
mxl862xx_tflow_cmode_type_t count_mode;
|
||||
//The below params are valid only for CTP/br_p types.
|
||||
//A group of ports matching MS (9-n) bits. n is n_ctp_lsb or n_brp_lsb.
|
||||
u16 port_msb;
|
||||
//Number of valid bits in CTP port counter mode.
|
||||
mxl862xx_tflow_ctp_val_bits_t ctp_lsb;
|
||||
//Number of valid bits in bridge port counter mode.
|
||||
mxl862xx_tflow_brp_val_bits_t brp_lsb;
|
||||
} mxl862xx_tflow_cmode_conf_t;
|
||||
|
||||
/**
|
||||
\brief Hardware platform extended RMON Counters. GSWIP-3.1 only.
|
||||
This structure contains additional RMON counters. These counters can be
|
||||
used by the packet classification engine and can be freely assigned to
|
||||
dedicated packet rules and flows.
|
||||
Used by \ref MXL862XX_RMON_FLOW_GET. */
|
||||
typedef struct {
|
||||
/** If TRUE, use \ref MXL862XX_RMON_flow_get_t::n_index to access the Flow Counter,
|
||||
otherwise, use \ref MXL862XX_TFLOW_COUNT_MODE_GET to determine mode and use
|
||||
\ref MXL862XX_RMON_flow_get_t::port_id and \ref MXL862XX_RMON_flow_get_t::flow_id
|
||||
to calculate index of the Flow Counter. */
|
||||
bool use_index;
|
||||
/** Absolute index of Flow Counter. */
|
||||
u16 index;
|
||||
/** Port ID. This could be Logical Port, CTP or Bridge Port. It depends
|
||||
on the mode set by \ref MXL862XX_TFLOW_COUNT_MODE_SET. */
|
||||
u16 port_id;
|
||||
/** \ref MXL862XX_PCE_action_t::flow_id. The range depends on the mode set
|
||||
by \ref MXL862XX_TFLOW_COUNT_MODE_SET. */
|
||||
u16 flow_id;
|
||||
|
||||
/** Rx Packet Counter */
|
||||
u32 rx_pkts;
|
||||
/** Tx Packet Counter (non-PCE-Bypass) */
|
||||
u32 tx_pkts;
|
||||
/** Tx Packet Counter (PCE-Bypass) */
|
||||
u32 tx_pce_bypass_pkts;
|
||||
} mxl862xx_rmon_flow_get_t;
|
||||
|
||||
/** \brief For debugging Purpose only.
|
||||
Used for GSWIP 3.1. */
|
||||
|
||||
typedef struct {
|
||||
/** Ethernet Port number (zero-based counting). The valid range is hardware
|
||||
dependent. An error code is delivered if the selected port is not
|
||||
available. This parameter specifies for which MAC port the RMON
|
||||
counter is read. It has to be set by the application before
|
||||
calling \ref MXL862XX_RMON_PORT_GET. */
|
||||
u16 port_id;
|
||||
/**Table address selection based on port type
|
||||
Applicable only for GSWIP 3.1
|
||||
\ref MXL862XX_RMON_port_type_t**/
|
||||
mxl862xx_rmon_port_type_t port_type;
|
||||
/*Applicable only for GSWIP 3.1*/
|
||||
u32 rx_extended_vlan_discard_pkts;
|
||||
/*Applicable only for GSWIP 3.1*/
|
||||
u32 mtu_exceed_discard_pkts;
|
||||
/*Applicable only for GSWIP 3.1*/
|
||||
u32 tx_under_size_good_pkts;
|
||||
/*Applicable only for GSWIP 3.1*/
|
||||
u32 tx_oversize_good_pkts;
|
||||
/** Receive Packet Count (only packets that are accepted and not discarded). */
|
||||
u32 rx_good_pkts;
|
||||
/** Receive Unicast Packet Count. */
|
||||
u32 rx_unicast_pkts;
|
||||
/** Receive Broadcast Packet Count. */
|
||||
u32 rx_broadcast_pkts;
|
||||
/** Receive Multicast Packet Count. */
|
||||
u32 rx_multicast_pkts;
|
||||
/** Receive FCS Error Packet Count. */
|
||||
u32 rx_fcserror_pkts;
|
||||
/** Receive Undersize Good Packet Count. */
|
||||
u32 rx_under_size_good_pkts;
|
||||
/** Receive Oversize Good Packet Count. */
|
||||
u32 rx_oversize_good_pkts;
|
||||
/** Receive Undersize Error Packet Count. */
|
||||
u32 rx_under_size_error_pkts;
|
||||
/** Receive Good Pause Packet Count. */
|
||||
u32 rx_good_pause_pkts;
|
||||
/** Receive Oversize Error Packet Count. */
|
||||
u32 rx_oversize_error_pkts;
|
||||
/** Receive Align Error Packet Count. */
|
||||
u32 rx_align_error_pkts;
|
||||
/** Filtered Packet Count. */
|
||||
u32 rx_filtered_pkts;
|
||||
/** Receive Size 64 Bytes Packet Count. */
|
||||
u32 rx64byte_pkts;
|
||||
/** Receive Size 65-127 Bytes Packet Count. */
|
||||
u32 rx127byte_pkts;
|
||||
/** Receive Size 128-255 Bytes Packet Count. */
|
||||
u32 rx255byte_pkts;
|
||||
/** Receive Size 256-511 Bytes Packet Count. */
|
||||
u32 rx511byte_pkts;
|
||||
/** Receive Size 512-1023 Bytes Packet Count. */
|
||||
u32 rx1023byte_pkts;
|
||||
/** Receive Size 1024-1522 Bytes (or more, if configured) Packet Count. */
|
||||
u32 rx_max_byte_pkts;
|
||||
/** Overall Transmit Good Packets Count. */
|
||||
u32 tx_good_pkts;
|
||||
/** Transmit Unicast Packet Count. */
|
||||
u32 tx_unicast_pkts;
|
||||
/** Transmit Broadcast Packet Count. */
|
||||
u32 tx_broadcast_pkts;
|
||||
/** Transmit Multicast Packet Count. */
|
||||
u32 tx_multicast_pkts;
|
||||
/** Transmit Single Collision Count. */
|
||||
u32 tx_single_coll_count;
|
||||
/** Transmit Multiple Collision Count. */
|
||||
u32 tx_mult_coll_count;
|
||||
/** Transmit Late Collision Count. */
|
||||
u32 tx_late_coll_count;
|
||||
/** Transmit Excessive Collision Count. */
|
||||
u32 tx_excess_coll_count;
|
||||
/** Transmit Collision Count. */
|
||||
u32 tx_coll_count;
|
||||
/** Transmit Pause Packet Count. */
|
||||
u32 tx_pause_count;
|
||||
/** Transmit Size 64 Bytes Packet Count. */
|
||||
u32 tx64byte_pkts;
|
||||
/** Transmit Size 65-127 Bytes Packet Count. */
|
||||
u32 tx127byte_pkts;
|
||||
/** Transmit Size 128-255 Bytes Packet Count. */
|
||||
u32 tx255byte_pkts;
|
||||
/** Transmit Size 256-511 Bytes Packet Count. */
|
||||
u32 tx511byte_pkts;
|
||||
/** Transmit Size 512-1023 Bytes Packet Count. */
|
||||
u32 tx1023byte_pkts;
|
||||
/** Transmit Size 1024-1522 Bytes (or more, if configured) Packet Count. */
|
||||
u32 tx_max_byte_pkts;
|
||||
/** Transmit Drop Packet Count. */
|
||||
u32 tx_dropped_pkts;
|
||||
/** Transmit Dropped Packet Count, based on Congestion Management. */
|
||||
u32 tx_acm_dropped_pkts;
|
||||
/** Receive Dropped Packet Count. */
|
||||
u32 rx_dropped_pkts;
|
||||
/** Receive Good Byte Count (64 bit). */
|
||||
u64 rx_good_bytes;
|
||||
/** Receive Bad Byte Count (64 bit). */
|
||||
u64 rx_bad_bytes;
|
||||
/** Transmit Good Byte Count (64 bit). */
|
||||
u64 tx_good_bytes;
|
||||
/**For GSWIP V32 only **/
|
||||
/** Receive Unicast Packet Count for Yellow & Red packet. */
|
||||
u32 rx_unicast_pkts_yellow_red;
|
||||
/** Receive Broadcast Packet Count for Yellow & Red packet. */
|
||||
u32 rx_broadcast_pkts_yellow_red;
|
||||
/** Receive Multicast Packet Count for Yellow & Red packet. */
|
||||
u32 rx_multicast_pkts_yellow_red;
|
||||
/** Receive Good Byte Count (64 bit) for Yellow & Red packet. */
|
||||
u64 rx_good_bytes_yellow_red;
|
||||
/** Receive Packet Count for Yellow & Red packet. */
|
||||
u32 rx_good_pkts_yellow_red;
|
||||
/** Transmit Unicast Packet Count for Yellow & Red packet. */
|
||||
u32 tx_unicast_pkts_yellow_red;
|
||||
/** Transmit Broadcast Packet Count for Yellow & Red packet. */
|
||||
u32 tx_broadcast_pkts_yellow_red;
|
||||
/** Transmit Multicast Packet Count for Yellow & Red packet. */
|
||||
u32 tx_multicast_pkts_yellow_red;
|
||||
/** Transmit Good Byte Count (64 bit) for Yellow & Red packet. */
|
||||
u64 tx_good_bytes_yellow_red;
|
||||
/** Transmit Packet Count for Yellow & Red packet. */
|
||||
u32 tx_good_pkts_yellow_red;
|
||||
} mxl862xx_debug_rmon_port_cnt_t;
|
||||
|
||||
#pragma scalar_storage_order default
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif /* _MXL862XX_RMON_H_ */
|
||||
@@ -0,0 +1,76 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* drivers/net/dsa/host_api/mxl862xx_types.h - DSA Driver for MaxLinear Mxl862xx switch chips family
|
||||
*
|
||||
* Copyright (C) 2024 MaxLinear Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MXL862XX_TYPES_H_
|
||||
#define _MXL862XX_TYPES_H_
|
||||
|
||||
#include <linux/phy.h>
|
||||
|
||||
/** \brief This is the unsigned 64-bit datatype. */
|
||||
typedef uint64_t u64;
|
||||
/** \brief This is the unsigned 32-bit datatype. */
|
||||
typedef uint32_t u32;
|
||||
/** \brief This is the unsigned 16-bit datatype. */
|
||||
typedef uint16_t u16;
|
||||
/** \brief This is the unsigned 8-bit datatype. */
|
||||
typedef uint8_t u8;
|
||||
/** \brief This is the signed 64-bit datatype. */
|
||||
typedef int64_t i64;
|
||||
/** \brief This is the signed 32-bit datatype. */
|
||||
typedef int32_t i32;
|
||||
/** \brief This is the signed 16-bit datatype. */
|
||||
typedef int16_t i16;
|
||||
/** \brief This is the signed 8-bit datatype. */
|
||||
typedef int8_t i8;
|
||||
/** \brief This is the signed 8-bit datatype. */
|
||||
typedef int32_t s32;
|
||||
/** \brief This is the signed 8-bit datatype. */
|
||||
typedef int8_t s8;
|
||||
|
||||
|
||||
/** \brief This is a union to describe the IPv4 and IPv6 Address in numeric representation. Used by multiple Structures and APIs. The member selection would be based upon \ref GSW_IP_Select_t */
|
||||
typedef union {
|
||||
/** Describe the IPv4 address.
|
||||
Only used if the IPv4 address should be read or configured.
|
||||
Cannot be used together with the IPv6 address fields. */
|
||||
u32 nIPv4;
|
||||
/** Describe the IPv6 address.
|
||||
Only used if the IPv6 address should be read or configured.
|
||||
Cannot be used together with the IPv4 address fields. */
|
||||
u16 nIPv6[8];
|
||||
} mxl862xx_ip_t;
|
||||
|
||||
/** \brief Selection to use IPv4 or IPv6.
|
||||
Used along with \ref GSW_IP_t to denote which union member to be accessed.
|
||||
*/
|
||||
typedef enum {
|
||||
/** IPv4 Type */
|
||||
MXL862XX_IP_SELECT_IPV4 = 0,
|
||||
/** IPv6 Type */
|
||||
MXL862XX_IP_SELECT_IPV6 = 1
|
||||
} mxl862xx_ip_select_t;
|
||||
|
||||
typedef struct {
|
||||
int sw_addr;
|
||||
struct mii_bus *bus;
|
||||
} mxl862xx_device_t;
|
||||
#endif /* _MXL862XX_TYPES_H_ */
|
||||
4587
feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/mxl862xx/mxl862xx.c
Executable file
4587
feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/mxl862xx/mxl862xx.c
Executable file
File diff suppressed because it is too large
Load Diff
@@ -4,5 +4,5 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o
|
||||
mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o
|
||||
mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o mtk_eth_ptp.o
|
||||
obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtk_hnat/
|
||||
|
||||
1401
feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
Executable file → Normal file
1401
feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
@@ -30,6 +30,24 @@
|
||||
#define MTK_FE_GDM1_FSM 0x228
|
||||
#define MTK_FE_GDM2_FSM 0x22C
|
||||
#define MTK_FE_GDM3_FSM 0x23C
|
||||
#define MTK_FE_CDM1_DBG1 0x200
|
||||
#define MTK_FE_CDM1_DBG2 0x204
|
||||
#define MTK_FE_CDM2_DBG1 0x208
|
||||
#define MTK_FE_CDM2_DBG2 0x20C
|
||||
#define MTK_FE_CDM3_DBG1 0x230
|
||||
#define MTK_FE_CDM3_DBG2 0x234
|
||||
#define MTK_FE_CDM4_DBG1 0x290
|
||||
#define MTK_FE_CDM4_DBG2 0x294
|
||||
#define MTK_FE_CDM5_DBG1 0x310
|
||||
#define MTK_FE_CDM5_DBG2 0x314
|
||||
#define MTK_FE_CDM6_DBG1 0x320
|
||||
#define MTK_FE_CDM6_DBG2 0x324
|
||||
#define MTK_FE_CDM7_DBG1 0x330
|
||||
#define MTK_FE_CDM7_DBG2 0x334
|
||||
#define MTK_FE_GDM1_DBG1 0x210
|
||||
#define MTK_FE_GDM1_DBG2 0x214
|
||||
#define MTK_FE_GDM2_DBG1 0x218
|
||||
#define MTK_FE_GDM2_DBG2 0x21C
|
||||
#define MTK_FE_PSE_FREE 0x240
|
||||
#define MTK_FE_DROP_FQ 0x244
|
||||
#define MTK_FE_DROP_FC 0x248
|
||||
@@ -42,6 +60,24 @@
|
||||
#define MTK_FE_GDM_FSM(x) (((x) == 2) ? MTK_FE_GDM3_FSM : \
|
||||
((x) == 1) ? MTK_FE_GDM2_FSM : MTK_FE_GDM1_FSM)
|
||||
|
||||
#define MTK_FE_CDM_FSM(x) (((x) == 0) ? MTK_FE_CDM3_FSM : \
|
||||
((x) == 1) ? MTK_FE_CDM4_FSM : MTK_FE_CDM5_FSM)
|
||||
|
||||
#define MTK_FE_WDMA_OQ(x) \
|
||||
(((x) == 0) ? (mtk_r32(eth, MTK_PSE_OQ_STA(4)) & 0x00000FFF) : \
|
||||
(((x) == 1) ? (mtk_r32(eth, MTK_PSE_OQ_STA(4)) & 0x0FFF0000) : \
|
||||
(mtk_r32(eth, MTK_PSE_OQ_STA(6)) & 0x0FFF0000)))
|
||||
|
||||
#define MTK_FE_GDM_IQ(x) \
|
||||
(((x) == 2) ? mtk_r32(eth, MTK_PSE_IQ_STA(7)) & 0x0fff0000 : \
|
||||
((x) == 1) ? mtk_r32(eth, MTK_PSE_IQ_STA(1)) & 0x00000fff : \
|
||||
mtk_r32(eth, MTK_PSE_IQ_STA(0)) & 0x0fff0000)
|
||||
|
||||
#define MTK_FE_GDM_OQ(x) \
|
||||
(((x) == 2) ? mtk_r32(eth, MTK_PSE_OQ_STA(7)) & 0x0fff0000 : \
|
||||
((x) == 1) ? mtk_r32(eth, MTK_PSE_OQ_STA(1)) & 0x00000fff : \
|
||||
mtk_r32(eth, MTK_PSE_OQ_STA(0)) & 0x0fff0000)
|
||||
|
||||
#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
#define MTK_PSE_IQ_STA(x) (0x180 + (x) * 0x4)
|
||||
#define MTK_PSE_OQ_STA(x) (0x1A0 + (x) * 0x4)
|
||||
@@ -59,6 +95,7 @@
|
||||
#define REG_ESW_MAX 0xFC
|
||||
|
||||
#define PROCREG_ESW_CNT "esw_cnt"
|
||||
#define PROCREG_MAC_CNT "mac_cnt"
|
||||
#define PROCREG_XFI_CNT "xfi_cnt"
|
||||
#define PROCREG_TXRING "tx_ring"
|
||||
#define PROCREG_HWTXRING "hwtx_ring"
|
||||
@@ -70,6 +107,40 @@
|
||||
#define PROCREG_HW_LRO_AUTO_TLB "hw_lro_auto_tlb"
|
||||
#define PROCREG_RESET_EVENT "reset_event"
|
||||
|
||||
#define MAX_SWITCH_PORT_NUM (6)
|
||||
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
#define MAX_PPPQ_QUEUE_NUM (2 * MAX_SWITCH_PORT_NUM + 2)
|
||||
#else
|
||||
#define MAX_PPPQ_QUEUE_NUM (2 * MAX_SWITCH_PORT_NUM)
|
||||
#endif
|
||||
|
||||
/* GMAC MIB Register */
|
||||
#define MTK_MAC_MIB_BASE(x) (0x10400 + (x * 0x60))
|
||||
#define MTK_MAC_RX_UC_PKT_CNT_L 0x00
|
||||
#define MTK_MAC_RX_UC_PKT_CNT_H 0x04
|
||||
#define MTK_MAC_RX_UC_BYTE_CNT_L 0x08
|
||||
#define MTK_MAC_RX_UC_BYTE_CNT_H 0x0C
|
||||
#define MTK_MAC_RX_MC_PKT_CNT_L 0x10
|
||||
#define MTK_MAC_RX_MC_PKT_CNT_H 0x14
|
||||
#define MTK_MAC_RX_MC_BYTE_CNT_L 0x18
|
||||
#define MTK_MAC_RX_MC_BYTE_CNT_H 0x1C
|
||||
#define MTK_MAC_RX_BC_PKT_CNT_L 0x20
|
||||
#define MTK_MAC_RX_BC_PKT_CNT_H 0x24
|
||||
#define MTK_MAC_RX_BC_BYTE_CNT_L 0x28
|
||||
#define MTK_MAC_RX_BC_BYTE_CNT_H 0x2C
|
||||
#define MTK_MAC_TX_UC_PKT_CNT_L 0x30
|
||||
#define MTK_MAC_TX_UC_PKT_CNT_H 0x34
|
||||
#define MTK_MAC_TX_UC_BYTE_CNT_L 0x38
|
||||
#define MTK_MAC_TX_UC_BYTE_CNT_H 0x3C
|
||||
#define MTK_MAC_TX_MC_PKT_CNT_L 0x40
|
||||
#define MTK_MAC_TX_MC_PKT_CNT_H 0x44
|
||||
#define MTK_MAC_TX_MC_BYTE_CNT_L 0x48
|
||||
#define MTK_MAC_TX_MC_BYTE_CNT_H 0x4C
|
||||
#define MTK_MAC_TX_BC_PKT_CNT_L 0x50
|
||||
#define MTK_MAC_TX_BC_PKT_CNT_H 0x54
|
||||
#define MTK_MAC_TX_BC_BYTE_CNT_L 0x58
|
||||
#define MTK_MAC_TX_BC_BYTE_CNT_H 0x5C
|
||||
|
||||
/* XFI MAC MIB Register */
|
||||
#define MTK_XFI_MIB_BASE(x) (MTK_XMAC_MCR(x))
|
||||
#define MTK_XFI_CNT_CTRL 0x100
|
||||
@@ -100,6 +171,18 @@
|
||||
#define MTK_XFI_RX_MC_DROP_CNT 0x208
|
||||
#define MTK_XFI_RX_ALL_DROP_CNT 0x20C
|
||||
|
||||
#define MTK_MT753X_PMCR_P(x) (0x3000 + (x) * 100)
|
||||
|
||||
#define PRINT_FORMATTED_MAC_MIB64(seq, reg) \
|
||||
{ \
|
||||
seq_printf(seq, "| MAC%d_%s : %010llu |\n", \
|
||||
gdm_id, #reg, \
|
||||
mtk_r32(eth, MTK_MAC_MIB_BASE(gdm_id) + \
|
||||
MTK_MAC_##reg##_L) + \
|
||||
((u64)mtk_r32(eth, MTK_MAC_MIB_BASE(gdm_id) +\
|
||||
MTK_MAC_##reg##_H) << 32)); \
|
||||
}
|
||||
|
||||
#define PRINT_FORMATTED_XFI_MIB(seq, reg, mask) \
|
||||
{ \
|
||||
seq_printf(seq, "| XFI%d_%s : %010lu |\n", \
|
||||
@@ -126,55 +209,176 @@
|
||||
#define MTK_HW_LRO_TIMESTAMP_FLUSH (4)
|
||||
#define MTK_HW_LRO_NON_RULE_FLUSH (5)
|
||||
|
||||
#define SET_PDMA_RXRING_MAX_AGG_CNT(eth, x, y) \
|
||||
{ \
|
||||
u32 reg_val1 = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \
|
||||
u32 reg_val2 = mtk_r32(eth, MTK_LRO_CTRL_DW3_CFG(x)); \
|
||||
reg_val1 &= ~MTK_LRO_RING_AGG_CNT_L_MASK; \
|
||||
reg_val2 &= ~MTK_LRO_RING_AGG_CNT_H_MASK; \
|
||||
reg_val1 |= ((y) & 0x3f) << MTK_LRO_RING_AGG_CNT_L_OFFSET; \
|
||||
reg_val2 |= (((y) >> 6) & 0x03) << \
|
||||
MTK_LRO_RING_AGG_CNT_H_OFFSET; \
|
||||
mtk_w32(eth, reg_val1, MTK_LRO_CTRL_DW2_CFG(x)); \
|
||||
mtk_w32(eth, reg_val2, MTK_LRO_CTRL_DW3_CFG(x)); \
|
||||
#define SET_PDMA_RXRING_MAX_AGG_CNT(eth, x, y) \
|
||||
{ \
|
||||
const struct mtk_reg_map *reg_map = eth->soc->reg_map; \
|
||||
u32 reg_val1, reg_val2; \
|
||||
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_GLO_MEM_ACCESS)) { \
|
||||
reg_val1 = mtk_r32(eth, reg_map->pdma.lro_rx_ctrl_dw0 + \
|
||||
0x8 + (x * 0x40)); \
|
||||
reg_val2 = mtk_r32(eth, reg_map->pdma.lro_rx_ctrl_dw0 + \
|
||||
0xc + (x * 0x40)); \
|
||||
reg_val1 &= ~MTK_LRO_RING_AGG_CNT_L_MASK; \
|
||||
reg_val2 &= ~MTK_LRO_RING_AGG_CNT_H_MASK; \
|
||||
reg_val1 |= ((y) & 0x3f) << MTK_LRO_RING_AGG_CNT_L_OFFSET; \
|
||||
reg_val2 |= (((y) >> 6) & 0x03) << \
|
||||
MTK_LRO_RING_AGG_CNT_H_OFFSET; \
|
||||
mtk_w32(eth, reg_val1, reg_map->pdma.lro_rx_ctrl_dw0 + \
|
||||
0x8 + (x * 0x40)); \
|
||||
mtk_w32(eth, reg_val2, reg_map->pdma.lro_rx_ctrl_dw0 + \
|
||||
0xc + (x * 0x40)); \
|
||||
} else { \
|
||||
reg_val1 = FIELD_PREP(MTK_GLO_MEM_IDX, MTK_LRO_MEM_IDX); \
|
||||
reg_val1 |= FIELD_PREP(MTK_GLO_MEM_ADDR, MTK_LRO_MEM_CFG_BASE + x); \
|
||||
reg_val1 |= FIELD_PREP(MTK_GLO_MEM_CMD, MTK_GLO_MEM_READ); \
|
||||
mtk_w32(eth, reg_val1, MTK_GLO_MEM_CTRL); \
|
||||
reg_val1 = mtk_r32(eth, MTK_GLO_MEM_DATA(1)); \
|
||||
reg_val1 &= ~MTK_RING_MAX_AGG_CNT; \
|
||||
reg_val1 |= FIELD_PREP(MTK_RING_MAX_AGG_CNT, y); \
|
||||
mtk_w32(eth, reg_val1, MTK_GLO_MEM_DATA(1)); \
|
||||
reg_val1 = FIELD_PREP(MTK_GLO_MEM_IDX, MTK_LRO_MEM_IDX); \
|
||||
reg_val1 |= FIELD_PREP(MTK_GLO_MEM_ADDR, MTK_LRO_MEM_CFG_BASE + x); \
|
||||
reg_val1 |= FIELD_PREP(MTK_GLO_MEM_CMD, MTK_GLO_MEM_WRITE); \
|
||||
mtk_w32(eth, reg_val1, MTK_GLO_MEM_CTRL); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SET_PDMA_RXRING_AGG_TIME(eth, x, y) \
|
||||
{ \
|
||||
u32 reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \
|
||||
reg_val &= ~MTK_LRO_RING_AGG_TIME_MASK; \
|
||||
reg_val |= ((y) & 0xffff) << MTK_LRO_RING_AGG_TIME_OFFSET; \
|
||||
mtk_w32(eth, reg_val, MTK_LRO_CTRL_DW2_CFG(x)); \
|
||||
#define SET_PDMA_RXRING_AGG_TIME(eth, x, y) \
|
||||
{ \
|
||||
const struct mtk_reg_map *reg_map = eth->soc->reg_map; \
|
||||
u32 reg_val; \
|
||||
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_GLO_MEM_ACCESS)) { \
|
||||
reg_val = mtk_r32(eth, reg_map->pdma.lro_rx_ctrl_dw0 + \
|
||||
0x8 + (x * 0x40)); \
|
||||
reg_val &= ~MTK_LRO_RING_AGG_TIME_MASK; \
|
||||
reg_val |= ((y) & 0xffff) << MTK_LRO_RING_AGG_TIME_OFFSET; \
|
||||
mtk_w32(eth, reg_val, reg_map->pdma.lro_rx_ctrl_dw0 + \
|
||||
0x8 + (x * 0x40)); \
|
||||
} else { \
|
||||
reg_val = FIELD_PREP(MTK_GLO_MEM_IDX, MTK_LRO_MEM_IDX); \
|
||||
reg_val |= FIELD_PREP(MTK_GLO_MEM_ADDR, MTK_LRO_MEM_CFG_BASE + x); \
|
||||
reg_val |= FIELD_PREP(MTK_GLO_MEM_CMD, MTK_GLO_MEM_READ); \
|
||||
mtk_w32(eth, reg_val, MTK_GLO_MEM_CTRL); \
|
||||
reg_val = mtk_r32(eth, MTK_GLO_MEM_DATA(0)); \
|
||||
reg_val &= ~MTK_RING_MAX_AGG_TIME_V2; \
|
||||
reg_val |= FIELD_PREP(MTK_RING_MAX_AGG_TIME_V2, y); \
|
||||
mtk_w32(eth, reg_val, MTK_GLO_MEM_DATA(0)); \
|
||||
reg_val = FIELD_PREP(MTK_GLO_MEM_IDX, MTK_LRO_MEM_IDX); \
|
||||
reg_val |= FIELD_PREP(MTK_GLO_MEM_ADDR, MTK_LRO_MEM_CFG_BASE + x); \
|
||||
reg_val |= FIELD_PREP(MTK_GLO_MEM_CMD, MTK_GLO_MEM_WRITE); \
|
||||
mtk_w32(eth, reg_val, MTK_GLO_MEM_CTRL); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SET_PDMA_RXRING_AGE_TIME(eth, x, y) \
|
||||
{ \
|
||||
u32 reg_val1 = mtk_r32(eth, MTK_LRO_CTRL_DW1_CFG(x)); \
|
||||
u32 reg_val2 = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \
|
||||
reg_val1 &= ~MTK_LRO_RING_AGE_TIME_L_MASK; \
|
||||
reg_val2 &= ~MTK_LRO_RING_AGE_TIME_H_MASK; \
|
||||
reg_val1 |= ((y) & 0x3ff) << MTK_LRO_RING_AGE_TIME_L_OFFSET; \
|
||||
reg_val2 |= (((y) >> 10) & 0x03f) << \
|
||||
MTK_LRO_RING_AGE_TIME_H_OFFSET; \
|
||||
mtk_w32(eth, reg_val1, MTK_LRO_CTRL_DW1_CFG(x)); \
|
||||
mtk_w32(eth, reg_val2, MTK_LRO_CTRL_DW2_CFG(x)); \
|
||||
#define SET_PDMA_RXRING_AGE_TIME(eth, x, y) \
|
||||
{ \
|
||||
const struct mtk_reg_map *reg_map = eth->soc->reg_map; \
|
||||
u32 reg_val1, reg_val2; \
|
||||
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_GLO_MEM_ACCESS)) { \
|
||||
reg_val1 = mtk_r32(eth, reg_map->pdma.lro_rx_ctrl_dw0 + \
|
||||
0x4 + (x * 0x40)); \
|
||||
reg_val2 = mtk_r32(eth, reg_map->pdma.lro_rx_ctrl_dw0 + \
|
||||
0x8 + (x * 0x40)); \
|
||||
reg_val1 &= ~MTK_LRO_RING_AGE_TIME_L_MASK; \
|
||||
reg_val2 &= ~MTK_LRO_RING_AGE_TIME_H_MASK; \
|
||||
reg_val1 |= ((y) & 0x3ff) << MTK_LRO_RING_AGE_TIME_L_OFFSET; \
|
||||
reg_val2 |= (((y) >> 10) & 0x03f) << \
|
||||
MTK_LRO_RING_AGE_TIME_H_OFFSET; \
|
||||
mtk_w32(eth, reg_val1, reg_map->pdma.lro_rx_ctrl_dw0 + \
|
||||
0x4 + (x * 0x40)); \
|
||||
mtk_w32(eth, reg_val2, reg_map->pdma.lro_rx_ctrl_dw0 + \
|
||||
0x8 + (x * 0x40)); \
|
||||
} else { \
|
||||
reg_val1 = FIELD_PREP(MTK_GLO_MEM_IDX, MTK_LRO_MEM_IDX); \
|
||||
reg_val1 |= FIELD_PREP(MTK_GLO_MEM_ADDR, MTK_LRO_MEM_CFG_BASE + x); \
|
||||
reg_val1 |= FIELD_PREP(MTK_GLO_MEM_CMD, MTK_GLO_MEM_READ); \
|
||||
mtk_w32(eth, reg_val1, MTK_GLO_MEM_CTRL); \
|
||||
reg_val1 = mtk_r32(eth, MTK_GLO_MEM_DATA(0)); \
|
||||
reg_val1 &= ~MTK_RING_AGE_TIME; \
|
||||
reg_val1 |= FIELD_PREP(MTK_RING_AGE_TIME, y); \
|
||||
mtk_w32(eth, reg_val1, MTK_GLO_MEM_DATA(0)); \
|
||||
reg_val1 = FIELD_PREP(MTK_GLO_MEM_IDX, MTK_LRO_MEM_IDX); \
|
||||
reg_val1 |= FIELD_PREP(MTK_GLO_MEM_ADDR, MTK_LRO_MEM_CFG_BASE + x); \
|
||||
reg_val1 |= FIELD_PREP(MTK_GLO_MEM_CMD, MTK_GLO_MEM_WRITE); \
|
||||
mtk_w32(eth, reg_val1, MTK_GLO_MEM_CTRL); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SET_PDMA_LRO_BW_THRESHOLD(eth, x) \
|
||||
{ \
|
||||
u32 reg_val = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW2); \
|
||||
const struct mtk_reg_map *reg_map = eth->soc->reg_map; \
|
||||
u32 reg_val = mtk_r32(eth, reg_map->pdma.lro_ctrl_dw0 + 0x8); \
|
||||
reg_val = (x); \
|
||||
mtk_w32(eth, reg_val, MTK_PDMA_LRO_CTRL_DW2); \
|
||||
mtk_w32(eth, reg_val, reg_map->pdma.lro_ctrl_dw0 + 0x8); \
|
||||
}
|
||||
|
||||
#define SET_PDMA_RXRING_VALID(eth, x, y) \
|
||||
{ \
|
||||
u32 reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \
|
||||
reg_val &= ~(0x1 << MTK_RX_PORT_VALID_OFFSET); \
|
||||
reg_val |= ((y) & 0x1) << MTK_RX_PORT_VALID_OFFSET; \
|
||||
mtk_w32(eth, reg_val, MTK_LRO_CTRL_DW2_CFG(x)); \
|
||||
#define SET_PDMA_RXRING_VALID(eth, x, y) \
|
||||
{ \
|
||||
const struct mtk_reg_map *reg_map = eth->soc->reg_map; \
|
||||
u32 reg_val; \
|
||||
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_GLO_MEM_ACCESS)) { \
|
||||
reg_val = mtk_r32(eth, reg_map->pdma.lro_rx_ctrl_dw0 + \
|
||||
0x8 + (x * 0x40)); \
|
||||
reg_val &= ~(0x1 << MTK_RX_PORT_VALID_OFFSET); \
|
||||
reg_val |= ((y) & 0x1) << MTK_RX_PORT_VALID_OFFSET; \
|
||||
mtk_w32(eth, reg_val, reg_map->pdma.lro_rx_ctrl_dw0 + \
|
||||
0x8 + (x * 0x40)); \
|
||||
} else { \
|
||||
reg_val = FIELD_PREP(MTK_GLO_MEM_IDX, MTK_LRO_MEM_IDX); \
|
||||
reg_val |= FIELD_PREP(MTK_GLO_MEM_ADDR, MTK_LRO_MEM_CFG_BASE + x); \
|
||||
reg_val |= FIELD_PREP(MTK_GLO_MEM_CMD, MTK_GLO_MEM_READ); \
|
||||
mtk_w32(eth, reg_val, MTK_GLO_MEM_CTRL); \
|
||||
reg_val = mtk_r32(eth, MTK_GLO_MEM_DATA(1)); \
|
||||
reg_val &= ~MTK_RING_OPMODE; \
|
||||
reg_val |= FIELD_PREP(MTK_RING_OPMODE, y); \
|
||||
mtk_w32(eth, reg_val, MTK_GLO_MEM_DATA(1)); \
|
||||
reg_val = FIELD_PREP(MTK_GLO_MEM_IDX, MTK_LRO_MEM_IDX); \
|
||||
reg_val |= FIELD_PREP(MTK_GLO_MEM_ADDR, MTK_LRO_MEM_CFG_BASE + x); \
|
||||
reg_val |= FIELD_PREP(MTK_GLO_MEM_CMD, MTK_GLO_MEM_WRITE); \
|
||||
mtk_w32(eth, reg_val, MTK_GLO_MEM_CTRL); \
|
||||
} \
|
||||
}
|
||||
|
||||
struct mtk_pse_fs_lgc_info_v2 {
|
||||
u32 rev3 : 14;
|
||||
u32 ppe_crsn: 5;
|
||||
u32 sport : 4;
|
||||
u32 is_l4f: 1;
|
||||
u32 is_l4vld: 1;
|
||||
u32 is_tack : 1;
|
||||
u32 is_ip4f : 1;
|
||||
u32 is_ip4 : 1;
|
||||
u32 is_ip6 : 1;
|
||||
u32 dr_idx : 2;
|
||||
u32 rev2 : 4;
|
||||
u32 l3_pidx : 2;
|
||||
u32 rev : 2;
|
||||
u32 fport : 4;
|
||||
u32 l2_len : 7;
|
||||
u32 l3_len : 14;
|
||||
} __packed;
|
||||
|
||||
struct mtk_pse_fs_lgc_info_v3 {
|
||||
u32 is_snap : 1;
|
||||
u32 vofst : 3;
|
||||
u32 l3_pidx : 2;
|
||||
u32 pse_sport : 4;
|
||||
u32 fport : 4;
|
||||
u32 ppe_crsn: 5;
|
||||
u32 sport : 4;
|
||||
u32 is_l4f: 1;
|
||||
u32 is_l4vld: 1;
|
||||
u32 is_tack : 1;
|
||||
u32 is_ip4f : 1;
|
||||
u32 is_ip4 : 1;
|
||||
u32 is_ip6 : 1;
|
||||
u32 is_err_pkt : 1;
|
||||
u32 err_pkt_action : 2;
|
||||
u32 pl_end : 11;
|
||||
u32 l2_len : 7;
|
||||
u32 l3_len : 14;
|
||||
} __packed;
|
||||
|
||||
struct mtk_lro_alt_v1_info0 {
|
||||
u32 dtp : 16;
|
||||
u32 stp : 16;
|
||||
@@ -313,23 +517,13 @@ struct mtk_mii_ioctl_data {
|
||||
unsigned int val_out;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_DSA_MT7530) || defined(CONFIG_MT753X_GSW)
|
||||
static inline bool mt7530_exist(struct mtk_eth *eth)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static inline bool mt7530_exist(struct mtk_eth *eth)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern u32 _mtk_mdio_read(struct mtk_eth *eth, int phy_addr, int phy_reg);
|
||||
extern u32 _mtk_mdio_write(struct mtk_eth *eth, int phy_addr,
|
||||
int phy_reg, u16 write_data);
|
||||
|
||||
extern atomic_t force;
|
||||
extern atomic_t reset_lock;
|
||||
extern int eth_debug_level;
|
||||
|
||||
int debug_proc_init(struct mtk_eth *eth);
|
||||
void debug_proc_exit(void);
|
||||
@@ -339,5 +533,6 @@ void mtketh_debugfs_exit(struct mtk_eth *eth);
|
||||
int mtk_do_priv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
|
||||
void hw_lro_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd);
|
||||
void hw_lro_flush_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd);
|
||||
void mt753x_set_port_link_state(bool up);
|
||||
|
||||
#endif /* MTK_ETH_DBG_H */
|
||||
|
||||
@@ -31,8 +31,8 @@ static const char *mtk_eth_path_name(u64 path)
|
||||
return "gmac2_rgmii";
|
||||
case MTK_ETH_PATH_GMAC2_SGMII:
|
||||
return "gmac2_sgmii";
|
||||
case MTK_ETH_PATH_GMAC2_XGMII:
|
||||
return "gmac2_xgmii";
|
||||
case MTK_ETH_PATH_GMAC2_2P5GPHY:
|
||||
return "gmac2_2p5gphy";
|
||||
case MTK_ETH_PATH_GMAC2_GEPHY:
|
||||
return "gmac2_gephy";
|
||||
case MTK_ETH_PATH_GMAC3_SGMII:
|
||||
@@ -104,13 +104,14 @@ static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, u64 path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
|
||||
static int set_mux_u3_gmac23_to_qphy(struct mtk_eth *eth, u64 path)
|
||||
{
|
||||
unsigned int val = 0,mask=0,reg=0;
|
||||
bool updated = true;
|
||||
|
||||
switch (path) {
|
||||
case MTK_ETH_PATH_GMAC2_SGMII:
|
||||
case MTK_ETH_PATH_GMAC3_SGMII:
|
||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_U3_COPHY_V2)) {
|
||||
reg = USB_PHY_SWITCH_REG;
|
||||
val = SGMII_QPHY_SEL;
|
||||
@@ -135,7 +136,7 @@ static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_mux_gmac2_to_xgmii(struct mtk_eth *eth, u64 path)
|
||||
static int set_mux_gmac2_to_2p5gphy(struct mtk_eth *eth, u64 path)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
bool updated = true;
|
||||
@@ -149,7 +150,7 @@ static int set_mux_gmac2_to_xgmii(struct mtk_eth *eth, u64 path)
|
||||
regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
|
||||
|
||||
switch (path) {
|
||||
case MTK_ETH_PATH_GMAC2_XGMII:
|
||||
case MTK_ETH_PATH_GMAC2_2P5GPHY:
|
||||
val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
|
||||
mac_id = MTK_GMAC2_ID;
|
||||
break;
|
||||
@@ -311,13 +312,13 @@ static const struct mtk_eth_muxc mtk_eth_muxc[] = {
|
||||
.cap_bit = MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
|
||||
.set_path = set_mux_gmac2_gmac0_to_gephy,
|
||||
}, {
|
||||
.name = "mux_u3_gmac2_to_qphy",
|
||||
.cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
|
||||
.set_path = set_mux_u3_gmac2_to_qphy,
|
||||
.name = "mux_u3_gmac23_to_qphy",
|
||||
.cap_bit = MTK_ETH_MUX_U3_GMAC23_TO_QPHY,
|
||||
.set_path = set_mux_u3_gmac23_to_qphy,
|
||||
}, {
|
||||
.name = "mux_gmac2_to_xgmii",
|
||||
.cap_bit = MTK_ETH_MUX_GMAC2_TO_XGMII,
|
||||
.set_path = set_mux_gmac2_to_xgmii,
|
||||
.name = "mux_gmac2_to_2p5gphy",
|
||||
.cap_bit = MTK_ETH_MUX_GMAC2_TO_2P5GPHY,
|
||||
.set_path = set_mux_gmac2_to_2p5gphy,
|
||||
}, {
|
||||
.name = "mux_gmac1_gmac2_to_sgmii_rgmii",
|
||||
.cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
|
||||
@@ -403,13 +404,13 @@ int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_gmac_xgmii_path_setup(struct mtk_eth *eth, int mac_id)
|
||||
int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id)
|
||||
{
|
||||
int err;
|
||||
u64 path = 0;
|
||||
|
||||
if (mac_id == 1)
|
||||
path = MTK_ETH_PATH_GMAC2_XGMII;
|
||||
if (mac_id == MTK_GMAC2_ID)
|
||||
path = MTK_ETH_PATH_GMAC2_2P5GPHY;
|
||||
|
||||
if (!path)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -0,0 +1,497 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* IEEE1588v2 PTP support for MediaTek ETH device.
|
||||
*
|
||||
* Copyright (c) 2024 MediaTek Inc.
|
||||
* Authors: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/ptp_classify.h>
|
||||
|
||||
#include "mtk_eth_soc.h"
|
||||
|
||||
/* Values for the messageType field */
|
||||
#define SYNC 0x0
|
||||
#define DELAY_REQ 0x1
|
||||
#define PDELAY_REQ 0x2
|
||||
#define PDELAY_RESP 0x3
|
||||
#define FOLLOW_UP 0x8
|
||||
#define DELAY_RESP 0x9
|
||||
#define PDELAY_RESP_FOLLOW_UP 0xA
|
||||
#define ANNOUNCE 0xB
|
||||
|
||||
static int mtk_ptp_hwtstamp_enable(struct net_device *dev, int hwtstamp)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
|
||||
mtk_m32(eth, CSR_HW_TS_EN(mac->id),
|
||||
hwtstamp ? CSR_HW_TS_EN(mac->id) : 0, MAC_TS_MAC_CFG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_ptp_hwtstamp_get_t1(struct mtk_mac *mac, u16 seqid, struct timespec64 *ts)
|
||||
{
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
u32 sid[2], dw[4];
|
||||
int i;
|
||||
|
||||
sid[0] = mtk_r32(eth, MAC_TS_T1_SID1(mac->id));
|
||||
for (i = 0; i < 4; i++)
|
||||
dw[i] = mtk_r32(eth, MAC_TS_T1_DW(mac->id) + i * 4);
|
||||
sid[1] = mtk_r32(eth, MAC_TS_T1_SID2(mac->id));
|
||||
|
||||
if (seqid != sid[0] || sid[0] != sid[1]) {
|
||||
dev_warn(eth->dev, "invalid t1 hwtstamp(%d, %d, %d)!\n",
|
||||
seqid, sid[0], sid[1]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ts->tv_sec = dw[2] | ((u64)dw[3] << 32);
|
||||
ts->tv_nsec = dw[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_ptp_hwtstamp_get_t2(struct mtk_mac *mac, u16 seqid, struct timespec64 *ts)
|
||||
{
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
u32 sid[2], dw[4];
|
||||
int i;
|
||||
|
||||
sid[0] = mtk_r32(eth, MAC_TS_T2_SID1(mac->id));
|
||||
for (i = 0; i < 4; i++)
|
||||
dw[i] = mtk_r32(eth, MAC_TS_T2_DW(mac->id) + i * 4);
|
||||
sid[1] = mtk_r32(eth, MAC_TS_T2_SID2(mac->id));
|
||||
|
||||
if (seqid != sid[0] || sid[0] != sid[1]) {
|
||||
dev_warn(eth->dev, "invalid t2 hwtstamp(%d, %d, %d)!\n",
|
||||
seqid, sid[0], sid[1]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ts->tv_sec = dw[2] | ((u64)dw[3] << 32);
|
||||
ts->tv_nsec = dw[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_ptp_hwtstamp_get_t3(struct mtk_mac *mac, u16 seqid, struct timespec64 *ts)
|
||||
{
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
u32 sid[2], dw[4];
|
||||
int i;
|
||||
|
||||
sid[0] = mtk_r32(eth, MAC_TS_T3_SID1(mac->id));
|
||||
for (i = 0; i < 4; i++)
|
||||
dw[i] = mtk_r32(eth, MAC_TS_T3_DW(mac->id) + i * 4);
|
||||
sid[1] = mtk_r32(eth, MAC_TS_T3_SID2(mac->id));
|
||||
|
||||
if (seqid != sid[0] || sid[0] != sid[1]) {
|
||||
dev_warn(eth->dev, "invalid t3 hwtstamp(%d, %d, %d)!\n",
|
||||
seqid, sid[0], sid[1]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ts->tv_sec = dw[2] | ((u64)dw[3] << 32);
|
||||
ts->tv_nsec = dw[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_ptp_hwtstamp_get_t4(struct mtk_mac *mac, u16 seqid, struct timespec64 *ts)
|
||||
{
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
u32 sid[2], dw[4];
|
||||
int i;
|
||||
|
||||
sid[0] = mtk_r32(eth, MAC_TS_T4_SID1(mac->id));
|
||||
for (i = 0; i < 4; i++)
|
||||
dw[i] = mtk_r32(eth, MAC_TS_T4_DW(mac->id) + i * 4);
|
||||
sid[1] = mtk_r32(eth, MAC_TS_T4_SID2(mac->id));
|
||||
|
||||
if (seqid != sid[0] || sid[0] != sid[1]) {
|
||||
dev_warn(eth->dev, "invalid t4 hwtstamp(%d, %d, %d)!\n",
|
||||
seqid, sid[0], sid[1]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ts->tv_sec = dw[2] | ((u64)dw[3] << 32);
|
||||
ts->tv_nsec = dw[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_ptp_hwtstamp_tx_work(struct work_struct *work)
|
||||
{
|
||||
struct mtk_mac *mac = container_of(work, struct mtk_mac, ptp_tx_work);
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
struct sk_buff *skb = mac->ptp_tx_skb;
|
||||
struct skb_shared_hwtstamps shhwtstamps;
|
||||
struct timespec64 ts;
|
||||
unsigned int ptp_class, offset = 0;
|
||||
u8 *data, msgtype;
|
||||
u16 seqid;
|
||||
int ret;
|
||||
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
ptp_class = mac->ptp_tx_class;
|
||||
if (ptp_class & PTP_CLASS_VLAN)
|
||||
offset += VLAN_HLEN;
|
||||
|
||||
if ((ptp_class & PTP_CLASS_PMASK) == PTP_CLASS_L2)
|
||||
offset += ETH_HLEN;
|
||||
|
||||
data = skb_mac_header(skb);
|
||||
seqid = get_unaligned_be16(data + offset + OFF_PTP_SEQUENCE_ID);
|
||||
msgtype = data[offset] & 0x0f;
|
||||
switch (msgtype) {
|
||||
case SYNC:
|
||||
case PDELAY_REQ:
|
||||
ret = mtk_ptp_hwtstamp_get_t1(mac, seqid, &ts);
|
||||
break;
|
||||
case DELAY_REQ:
|
||||
case PDELAY_RESP:
|
||||
ret = mtk_ptp_hwtstamp_get_t3(mac, seqid, &ts);
|
||||
break;
|
||||
default:
|
||||
dev_warn(eth->dev, "unrecognized hwtstamp msgtype (%d)!", msgtype);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
if (time_is_before_jiffies(mac->ptp_tx_start +
|
||||
msecs_to_jiffies(500))) {
|
||||
dev_warn(eth->dev, "detect %s hwtstamp timeout!",
|
||||
(msgtype == SYNC || msgtype == PDELAY_REQ) ? "t1" : "t3");
|
||||
goto out;
|
||||
} else {
|
||||
schedule_work(&mac->ptp_tx_work);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
||||
|
||||
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
|
||||
shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
|
||||
skb_tstamp_tx(skb, &shhwtstamps);
|
||||
|
||||
out:
|
||||
dev_kfree_skb_any(skb);
|
||||
mac->ptp_tx_skb = NULL;
|
||||
mac->ptp_tx_class = 0;
|
||||
mac->ptp_tx_start = 0;
|
||||
}
|
||||
|
||||
int mtk_ptp_hwtstamp_process_tx(struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
unsigned int ptp_class, offset = 0;
|
||||
|
||||
ptp_class = ptp_classify_raw(skb);
|
||||
if (ptp_class == PTP_CLASS_NONE)
|
||||
return 0;
|
||||
|
||||
if (ptp_class & PTP_CLASS_VLAN)
|
||||
offset += VLAN_HLEN;
|
||||
|
||||
if ((ptp_class & PTP_CLASS_PMASK) == PTP_CLASS_L2)
|
||||
offset += ETH_HLEN;
|
||||
else
|
||||
return 0;
|
||||
|
||||
mac->ptp_tx_skb = skb_get(skb);
|
||||
mac->ptp_tx_class = ptp_class;
|
||||
mac->ptp_tx_start = jiffies;
|
||||
schedule_work(&mac->ptp_tx_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_ptp_hwtstamp_process_rx(struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
|
||||
struct timespec64 ts;
|
||||
unsigned int ptp_class, offset = 0;
|
||||
int ret;
|
||||
u8 *data, msgtype;
|
||||
u16 seqid;
|
||||
|
||||
ptp_class = ptp_classify_raw(skb);
|
||||
if (ptp_class == PTP_CLASS_NONE)
|
||||
return 0;
|
||||
|
||||
if (ptp_class & PTP_CLASS_VLAN)
|
||||
offset += VLAN_HLEN;
|
||||
|
||||
if ((ptp_class & PTP_CLASS_PMASK) == PTP_CLASS_L2)
|
||||
offset += ETH_HLEN;
|
||||
else
|
||||
return 0;
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
data = skb_mac_header(skb);
|
||||
seqid = get_unaligned_be16(data + offset + OFF_PTP_SEQUENCE_ID);
|
||||
msgtype = data[offset] & 0x0f;
|
||||
switch (msgtype) {
|
||||
case SYNC:
|
||||
case PDELAY_REQ:
|
||||
ret = mtk_ptp_hwtstamp_get_t2(mac, seqid, &ts);
|
||||
break;
|
||||
case DELAY_REQ:
|
||||
case PDELAY_RESP:
|
||||
ret = mtk_ptp_hwtstamp_get_t4(mac, seqid, &ts);
|
||||
break;
|
||||
default:
|
||||
dev_warn(eth->dev, "unrecognized hwtstamp msgtype (%d)!", msgtype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(shhwtstamps, 0, sizeof(*shhwtstamps));
|
||||
shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_ptp_hwtstamp_set_config(struct net_device *dev, struct ifreq *ifr)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
struct hwtstamp_config cfg;
|
||||
|
||||
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_HWTSTAMP))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
|
||||
return -EFAULT;
|
||||
|
||||
/* reserved for future extensions */
|
||||
if (cfg.flags)
|
||||
return -EINVAL;
|
||||
|
||||
if (cfg.tx_type != HWTSTAMP_TX_OFF && cfg.tx_type != HWTSTAMP_TX_ON &&
|
||||
cfg.tx_type != HWTSTAMP_TX_ONESTEP_SYNC)
|
||||
return -ERANGE;
|
||||
|
||||
switch (cfg.rx_filter) {
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
eth->rx_ts_enabled = 0;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
|
||||
eth->rx_ts_enabled = HWTSTAMP_FILTER_PTP_V2_EVENT;
|
||||
cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
|
||||
break;
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
eth->tx_ts_enabled = cfg.tx_type;
|
||||
|
||||
mtk_ptp_hwtstamp_enable(dev, eth->tx_ts_enabled);
|
||||
|
||||
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
int mtk_ptp_hwtstamp_get_config(struct net_device *dev, struct ifreq *ifr)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
struct hwtstamp_config cfg;
|
||||
|
||||
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_HWTSTAMP))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
cfg.flags = 0;
|
||||
cfg.tx_type = eth->tx_ts_enabled;
|
||||
cfg.rx_filter = eth->rx_ts_enabled;
|
||||
|
||||
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
static int mtk_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
|
||||
{
|
||||
struct mtk_eth *eth = container_of(ptp, struct mtk_eth, ptp_info);
|
||||
u64 base, adj;
|
||||
u16 data16;
|
||||
bool negative;
|
||||
|
||||
if (scaled_ppm) {
|
||||
base = 0x4 << 16;
|
||||
negative = diff_by_scaled_ppm(base, scaled_ppm, &adj);
|
||||
data16 = (u16)adj;
|
||||
|
||||
if (negative)
|
||||
mtk_w32(eth,
|
||||
FIELD_PREP(CSR_TICK_NANOSECOND, 0x3) |
|
||||
FIELD_PREP(CSR_TICK_SUB_NANOSECOND, 0xFFFF - data16),
|
||||
MAC_TS_TICK_SUBSECOND);
|
||||
else
|
||||
mtk_w32(eth,
|
||||
FIELD_PREP(CSR_TICK_NANOSECOND, 0x4) |
|
||||
FIELD_PREP(CSR_TICK_SUB_NANOSECOND, data16),
|
||||
MAC_TS_TICK_SUBSECOND);
|
||||
|
||||
// update tick configuration
|
||||
mtk_m32(eth, CSR_TICK_UPDATE, CSR_TICK_UPDATE, MAC_TS_TICK_CTRL);
|
||||
mtk_m32(eth, CSR_TICK_UPDATE, 0, MAC_TS_TICK_CTRL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
|
||||
{
|
||||
struct mtk_eth *eth = container_of(ptp, struct mtk_eth, ptp_info);
|
||||
struct timespec64 ts = ns_to_timespec64(delta);
|
||||
|
||||
mtk_w32(eth, (ts.tv_nsec >> 0) & 0xFFFFFFFF, MAC_TS_SUBSECOND_FIELD1);
|
||||
mtk_w32(eth, (ts.tv_sec >> 0) & 0xFFFFFFFF, MAC_TS_SECOND_FIELD0);
|
||||
mtk_w32(eth, (ts.tv_sec >> 32) & 0x0000FFFF, MAC_TS_SECOND_FIELD1);
|
||||
|
||||
// adjust timestamp
|
||||
mtk_m32(eth, CSR_TS_ADJUST, CSR_TS_ADJUST, MAC_TS_TIMESTAMP_CTRL);
|
||||
mtk_m32(eth, CSR_TS_ADJUST, 0, MAC_TS_TIMESTAMP_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_ptp_gettime64(struct ptp_clock_info *ptp,
|
||||
struct timespec64 *ts)
|
||||
{
|
||||
struct mtk_eth *eth = container_of(ptp, struct mtk_eth, ptp_info);
|
||||
unsigned long t_start = jiffies;
|
||||
u32 val[4];
|
||||
int i;
|
||||
|
||||
mtk_w32(eth, CPU_TRIG, MAC_TS_CPU_TRIG);
|
||||
|
||||
while (1) {
|
||||
if (!(mtk_r32(eth, MAC_TS_CPU_TRIG) & CPU_TS_VALID))
|
||||
break;
|
||||
if (time_after(jiffies, t_start + jiffies_to_msecs(1000))) {
|
||||
pr_warn("cpu trigger timeout!");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
val[i] = mtk_r32(eth, MAC_TS_CPU_TS_DW(i));
|
||||
|
||||
ts->tv_sec = val[2] | ((u64)val[3] << 32);
|
||||
ts->tv_nsec = val[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_ptp_settime64(struct ptp_clock_info *ptp,
|
||||
const struct timespec64 *ts)
|
||||
{
|
||||
struct mtk_eth *eth = container_of(ptp, struct mtk_eth, ptp_info);
|
||||
|
||||
mtk_w32(eth, (ts->tv_nsec >> 0) & 0xFFFFFFFF, MAC_TS_SUBSECOND_FIELD1);
|
||||
mtk_w32(eth, (ts->tv_sec >> 0) & 0xFFFFFFFF, MAC_TS_SECOND_FIELD0);
|
||||
mtk_w32(eth, (ts->tv_sec >> 32) & 0x0000FFFF, MAC_TS_SECOND_FIELD1);
|
||||
|
||||
// update timestamp
|
||||
mtk_m32(eth, CSR_TS_UPDATE, CSR_TS_UPDATE, MAC_TS_TIMESTAMP_CTRL);
|
||||
mtk_m32(eth, CSR_TS_UPDATE, 0, MAC_TS_TIMESTAMP_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_ptp_enable(struct ptp_clock_info *ptp,
|
||||
struct ptp_clock_request *request, int on)
|
||||
{
|
||||
struct mtk_eth *eth = container_of(ptp, struct mtk_eth, ptp_info);
|
||||
|
||||
// enable rx T1/T3 timestamp mask
|
||||
mtk_w32(eth, 0x00000077, MAC_TS_RSV);
|
||||
// update tick configuration
|
||||
mtk_m32(eth, CSR_TICK_UPDATE, CSR_TICK_UPDATE, MAC_TS_TICK_CTRL);
|
||||
mtk_m32(eth, CSR_TICK_UPDATE, 0, MAC_TS_TICK_CTRL);
|
||||
// enable tick
|
||||
mtk_m32(eth, CSR_TICK_RUN, on, MAC_TS_TICK_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ptp_clock_info mtk_ptp_caps = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "mtk_ptp",
|
||||
.max_adj = 24999999,
|
||||
.n_alarm = 0,
|
||||
.n_ext_ts = 0,
|
||||
.n_per_out = 1,
|
||||
.n_pins = 0,
|
||||
.pps = 0,
|
||||
.adjfine = mtk_ptp_adjfine,
|
||||
.adjtime = mtk_ptp_adjtime,
|
||||
.gettime64 = mtk_ptp_gettime64,
|
||||
.settime64 = mtk_ptp_settime64,
|
||||
.enable = mtk_ptp_enable,
|
||||
};
|
||||
|
||||
int mtk_ptp_clock_init(struct mtk_eth *eth)
|
||||
{
|
||||
struct mtk_mac *mac;
|
||||
int i;
|
||||
|
||||
eth->ptp_info = mtk_ptp_caps;
|
||||
eth->ptp_clock = ptp_clock_register(ð->ptp_info,
|
||||
eth->dev);
|
||||
if (IS_ERR(eth->ptp_clock)) {
|
||||
eth->ptp_clock = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < MTK_MAX_DEVS; i++) {
|
||||
mac = eth->mac[i];
|
||||
if (!mac)
|
||||
continue;
|
||||
|
||||
INIT_WORK(&mac->ptp_tx_work, mtk_ptp_hwtstamp_tx_work);
|
||||
}
|
||||
|
||||
mtk_ptp_enable(ð->ptp_info, NULL, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_ptp_clock_deinit(struct mtk_eth *eth)
|
||||
{
|
||||
struct mtk_mac *mac;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MTK_MAX_DEVS; i++) {
|
||||
mac = eth->mac[i];
|
||||
if (!mac)
|
||||
continue;
|
||||
|
||||
cancel_work_sync(&mac->ptp_tx_work);
|
||||
dev_kfree_skb_any(mac->ptp_tx_skb);
|
||||
mac->ptp_tx_skb = NULL;
|
||||
mac->ptp_tx_class = 0;
|
||||
mac->ptp_tx_start = 0;
|
||||
}
|
||||
|
||||
mtk_ptp_enable(ð->ptp_info, NULL, 0);
|
||||
|
||||
ptp_clock_unregister(eth->ptp_clock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,18 +7,23 @@
|
||||
#ifndef MTK_ETH_RESET_H
|
||||
#define MTK_ETH_RESET_H
|
||||
|
||||
#define MTK_ETH_RESET_VERSION "v1.1.0"
|
||||
|
||||
/* Frame Engine Reset FSM */
|
||||
#define MTK_FE_START_RESET 0x2000
|
||||
#define MTK_FE_RESET_DONE 0x2001
|
||||
#define MTK_WIFI_RESET_DONE 0x2002
|
||||
#define MTK_WIFI_CHIP_ONLINE 0x2003
|
||||
#define MTK_WIFI_CHIP_OFFLINE 0x2004
|
||||
#define MTK_TOPS_DUMP_DONE 0x3001
|
||||
#define MTK_FE_RESET_NAT_DONE 0x4001
|
||||
|
||||
#define MTK_FE_STOP_TRAFFIC (0x2005)
|
||||
#define MTK_FE_STOP_TRAFFIC_DONE (0x2006)
|
||||
#define MTK_FE_START_TRAFFIC (0x2007)
|
||||
#define MTK_FE_STOP_TRAFFIC_DONE_FAIL (0x2008)
|
||||
#define MTK_FE_START_RESET_INIT (0x2009)
|
||||
#define MTK_WIFI_L1SER_DONE (0x200a)
|
||||
|
||||
/*FE GDM Counter */
|
||||
#define MTK_GDM_RX_FC (0x24)
|
||||
@@ -42,12 +47,10 @@
|
||||
#define MTK_PPE_BUSY BIT(31)
|
||||
|
||||
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
#define MTK_WDMA_CNT (0x3)
|
||||
#define MTK_GDM_RX_BASE (0x8)
|
||||
#define MTK_GDM_CNT_OFFSET (0x80)
|
||||
#define MTK_GDM_TX_BASE (0x48)
|
||||
#else
|
||||
#define MTK_WDMA_CNT (0x2)
|
||||
#define MTK_GDM_RX_BASE (0x8)
|
||||
#define MTK_GDM_CNT_OFFSET (0x40)
|
||||
#define MTK_GDM_TX_BASE (0x38)
|
||||
@@ -71,12 +74,14 @@ enum mtk_reset_event_id {
|
||||
MTK_EVENT_RFIFO_UF = 19,
|
||||
};
|
||||
|
||||
extern struct notifier_block mtk_eth_netdevice_nb __read_mostly;
|
||||
int mtk_eth_netdevice_event(struct notifier_block *n, unsigned long event, void *ptr);
|
||||
extern struct completion wait_ser_done;
|
||||
extern struct completion wait_ack_done;
|
||||
extern struct completion wait_tops_done;
|
||||
extern char* mtk_reset_event_name[32];
|
||||
extern atomic_t reset_lock;
|
||||
extern struct completion wait_nat_done;
|
||||
extern u32 mtk_reset_flag;
|
||||
extern int mtk_wifi_num;
|
||||
extern bool mtk_stop_fail;
|
||||
|
||||
irqreturn_t mtk_handle_fe_irq(int irq, void *_eth);
|
||||
@@ -85,8 +90,11 @@ int mtk_eth_cold_reset(struct mtk_eth *eth);
|
||||
int mtk_eth_warm_reset(struct mtk_eth *eth);
|
||||
void mtk_reset_event_update(struct mtk_eth *eth, u32 id);
|
||||
void mtk_dump_netsys_info(void *_eth);
|
||||
void mtk_dma_monitor(struct timer_list *t);
|
||||
void mtk_prepare_reset_fe(struct mtk_eth *eth);
|
||||
void mtk_dump_netsys_info_brief(void *_eth);
|
||||
void mtk_hw_reset_monitor(struct mtk_eth *eth);
|
||||
void mtk_save_qdma_cfg(struct mtk_eth *eth);
|
||||
void mtk_restore_qdma_cfg(struct mtk_eth *eth);
|
||||
void mtk_prepare_reset_ppe(struct mtk_eth *eth, u32 ppe_id);
|
||||
|
||||
void mtk_pse_set_port_link(struct mtk_eth *eth, u32 port, bool enable);
|
||||
#endif /* MTK_ETH_RESET_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -10,12 +10,16 @@
|
||||
* Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com>
|
||||
* Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org>
|
||||
*/
|
||||
#ifndef NF_HNAT_H
|
||||
#define NF_HNAT_H
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <net/dsa.h>
|
||||
#include <net/netevent.h>
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include "hnat_mcast.h"
|
||||
#include "nf_hnat_mtk.h"
|
||||
@@ -76,8 +80,8 @@
|
||||
#define PPE_MCAST_H_E 0xE0
|
||||
#define PPE_MCAST_L_F 0x100
|
||||
#define PPE_MCAST_H_F 0x104
|
||||
#define PPE_MCAST_L_10 0xC00
|
||||
#define PPE_MCAST_H_10 0xC04
|
||||
#define PPE_MCAST_L_10 (-0x200)
|
||||
#define PPE_MCAST_H_10 (-0x200 + 0x4)
|
||||
#define PPE_MTU_DRP 0x108
|
||||
#define PPE_MTU_VLYR_0 0x10C
|
||||
#define PPE_MTU_VLYR_1 0x110
|
||||
@@ -103,32 +107,14 @@
|
||||
#define PPE_MIB_CAH_RDATA 0X160
|
||||
#define PPE_SB_FIFO_DBG 0x170
|
||||
#define PPE_SBW_CTRL 0x174
|
||||
#define PPE_SB_WED0_CNT 0x18C
|
||||
#define PPE_CAH_DBG 0x190
|
||||
#define PPE_FLOW_CHK_STATUS 0x1B0
|
||||
|
||||
#define GDMA1_FWD_CFG 0x500
|
||||
#define GDMA2_FWD_CFG 0x1500
|
||||
#define GDMA3_FWD_CFG 0x540
|
||||
|
||||
/* QDMA Tx queue configuration */
|
||||
#define QTX_CFG(x) (QDMA_BASE + ((x) * 0x10))
|
||||
#define QTX_CFG_HW_RESV_CNT_OFFSET (8)
|
||||
#define QTX_CFG_SW_RESV_CNT_OFFSET (0)
|
||||
|
||||
#define QTX_SCH(x) (QDMA_BASE + 0x4 + ((x) * 0x10))
|
||||
#define QTX_SCH_MIN_RATE_EN BIT(27)
|
||||
#define QTX_SCH_MAX_RATE_EN BIT(11)
|
||||
#define QTX_SCH_MIN_RATE_MAN_OFFSET (20)
|
||||
#define QTX_SCH_MIN_RATE_EXP_OFFSET (16)
|
||||
#define QTX_SCH_MAX_RATE_WGHT_OFFSET (12)
|
||||
#define QTX_SCH_MAX_RATE_MAN_OFFSET (4)
|
||||
#define QTX_SCH_MAX_RATE_EXP_OFFSET (0)
|
||||
|
||||
/* QDMA Tx scheduler configuration */
|
||||
#define QDMA_PAGE (QDMA_BASE + 0x1f0)
|
||||
#define QDMA_TX_2SCH_BASE (QDMA_BASE + 0x214)
|
||||
#define QTX_MIB_IF (QDMA_BASE + 0x2bc)
|
||||
#define QDMA_TX_4SCH_BASE(x) (QDMA_BASE + 0x398 + (((x) >> 1) * 0x4))
|
||||
#define QDMA_TX_SCH_WFQ_EN BIT(15)
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Register Mask*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -145,13 +131,29 @@
|
||||
#define HASH_MODE (0x3 << 14) /* RW */
|
||||
#define SCAN_MODE (0x3 << 16) /* RW */
|
||||
#define XMODE (0x3 << 18) /* RW */
|
||||
#define HASH_DBG (0x3 << 21) /* RW */
|
||||
#define TICK_SEL (0x1 << 24) /* RW */
|
||||
#define DSCP_TRFC_ECN_EN (0x1 << 25) /* RW */
|
||||
|
||||
|
||||
/*PPE_CAH_CTRL mask*/
|
||||
#define CAH_EN (0x1 << 0) /* RW */
|
||||
#define CAH_REQ (0x1 << 8) /* RW */
|
||||
#define CAH_X_MODE (0x1 << 9) /* RW */
|
||||
#define CAH_CMD (0x3 << 12) /* RW */
|
||||
#define CAH_DATA_SEL (0x3 << 18) /* RW */
|
||||
|
||||
/*PPE_CAH_LINE_RW mask*/
|
||||
#define LINE_RW (0xffff << 0) /* RW */
|
||||
#define OFFSET_RW (0xff << 16) /* RW */
|
||||
|
||||
/*PPE_CAH_TAG_SRH mask*/
|
||||
#define TAG_SRH (0xffff << 0) /* RW */
|
||||
#define SRH_LNUM (0x7fff << 16) /* RW */
|
||||
#define SRH_HIT (0x1 << 31) /* RW */
|
||||
|
||||
/*PPE_MIB_SER_CR mask*/
|
||||
#define BIT_MIB_BUSY (1 << 16) /* RW */
|
||||
|
||||
/*PPE_UNB_AGE mask*/
|
||||
#define UNB_DLTA (0xff << 0) /* RW */
|
||||
@@ -188,8 +190,10 @@
|
||||
#define TTL0_DRP (0x1 << 4) /* RW */
|
||||
#define MCAST_TB_EN (0x1 << 7) /* RW */
|
||||
#define MCAST_HASH (0x3 << 12) /* RW */
|
||||
#define NEW_IPV4_ID_INC_EN (0x1 << 20) /* RW */
|
||||
#define SP_CMP_EN (0x1 << 25) /* RW */
|
||||
|
||||
#define MC_P4_PPSE (0xf << 16) /* RW */
|
||||
#define MC_P3_PPSE (0xf << 12) /* RW */
|
||||
#define MC_P2_PPSE (0xf << 8) /* RW */
|
||||
#define MC_P1_PPSE (0xf << 4) /* RW */
|
||||
@@ -207,16 +211,12 @@
|
||||
#define GDM_ALL_FRC_MASK \
|
||||
(GDM_UFRC_MASK | GDM_BFRC_MASK | GDM_MFRC_MASK | GDM_OFRC_MASK)
|
||||
|
||||
/*QDMA_PAGE mask*/
|
||||
#define QTX_CFG_PAGE (0xf << 0) /* RW */
|
||||
|
||||
/*QTX_MIB_IF mask*/
|
||||
#define MIB_ON_QTX_CFG (0x1 << 31) /* RW */
|
||||
#define VQTX_MIB_EN (0x1 << 28) /* RW */
|
||||
|
||||
/* PPE Side Band FIFO Debug Mask */
|
||||
#define SB_MED_FULL_DRP_EN (0x1 << 11)
|
||||
|
||||
/* PPE Cache Debug status Mask */
|
||||
#define CAH_DBG_BUSY (0xf << 0)
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Descriptor Structure */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -359,6 +359,48 @@ struct hnat_info_blk2_whnat {
|
||||
u32 dscp : 8; /* DSCP value */
|
||||
} __packed;
|
||||
|
||||
struct hnat_l2_bridge {
|
||||
union {
|
||||
struct hnat_bind_info_blk bfib1;
|
||||
struct hnat_unbind_info_blk udib1;
|
||||
u32 info_blk1;
|
||||
};
|
||||
u32 dmac_hi;
|
||||
u16 smac_lo;
|
||||
u16 dmac_lo;
|
||||
u32 smac_hi;
|
||||
u16 etype;
|
||||
u16 hph; /* hash placeholder */
|
||||
u16 vlan1;
|
||||
u16 vlan2;
|
||||
u32 resv1;
|
||||
u32 resv2;
|
||||
union {
|
||||
struct hnat_info_blk2 iblk2;
|
||||
struct hnat_info_blk2_whnat iblk2w;
|
||||
u32 info_blk2;
|
||||
};
|
||||
u32 resv3;
|
||||
u32 resv4 : 24;
|
||||
u32 act_dp : 8; /* UDF */
|
||||
u16 new_vlan1;
|
||||
u16 sp_tag;
|
||||
u32 new_dmac_hi;
|
||||
u16 new_vlan2;
|
||||
u16 new_dmac_lo;
|
||||
u32 new_smac_hi;
|
||||
u16 resv5;
|
||||
u16 new_smac_lo;
|
||||
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
u32 resv6;
|
||||
struct hnat_winfo winfo;
|
||||
struct hnat_winfo_pao winfo_pao;
|
||||
#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
|
||||
u16 minfo;
|
||||
struct hnat_winfo winfo;
|
||||
#endif
|
||||
} __packed;
|
||||
|
||||
struct hnat_ipv4_hnapt {
|
||||
union {
|
||||
struct hnat_bind_info_blk bfib1;
|
||||
@@ -385,13 +427,13 @@ struct hnat_ipv4_hnapt {
|
||||
u32 resv3_1 : 9;
|
||||
u32 eg_keep_ecn : 1;
|
||||
u32 eg_keep_dscp : 1;
|
||||
u32 resv3_2:13;
|
||||
u32 resv3_2 : 13;
|
||||
#else
|
||||
u32 resv3:24;
|
||||
u32 resv3 : 24;
|
||||
#endif
|
||||
u32 act_dp : 8; /* UDF */
|
||||
u16 vlan1;
|
||||
u16 etype;
|
||||
u16 sp_tag;
|
||||
u32 dmac_hi;
|
||||
union {
|
||||
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
@@ -444,12 +486,12 @@ struct hnat_ipv4_dslite {
|
||||
u8 priority; /* in order to consist with Linux kernel (should be 8bits) */
|
||||
u32 hop_limit : 8;
|
||||
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
u32 resv2_1 : 1;
|
||||
u32 eg_keep_ecn : 1;
|
||||
u32 eg_keep_cls : 1;
|
||||
u32 resv2_2 : 13;
|
||||
u32 resv2_1 : 1;
|
||||
u32 eg_keep_ecn : 1;
|
||||
u32 eg_keep_cls : 1;
|
||||
u32 resv2_2 : 13;
|
||||
#else
|
||||
u32 resv2 : 16;
|
||||
u32 resv2 : 16;
|
||||
#endif
|
||||
u32 act_dp : 8; /* UDF */
|
||||
|
||||
@@ -460,7 +502,7 @@ struct hnat_ipv4_dslite {
|
||||
};
|
||||
|
||||
u16 vlan1;
|
||||
u16 etype;
|
||||
u16 sp_tag;
|
||||
u32 dmac_hi;
|
||||
union {
|
||||
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
@@ -529,7 +571,7 @@ struct hnat_ipv4_mape {
|
||||
};
|
||||
|
||||
u16 vlan1;
|
||||
u16 etype;
|
||||
u16 sp_tag;
|
||||
u32 dmac_hi;
|
||||
union {
|
||||
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
@@ -601,7 +643,7 @@ struct hnat_ipv6_3t_route {
|
||||
u32 info_blk2;
|
||||
};
|
||||
u16 vlan1;
|
||||
u16 etype;
|
||||
u16 sp_tag;
|
||||
u32 dmac_hi;
|
||||
union {
|
||||
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
@@ -666,7 +708,7 @@ struct hnat_ipv6_5t_route {
|
||||
};
|
||||
|
||||
u16 vlan1;
|
||||
u16 etype;
|
||||
u16 sp_tag;
|
||||
u32 dmac_hi;
|
||||
union {
|
||||
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
@@ -739,7 +781,7 @@ struct hnat_ipv6_6rd {
|
||||
};
|
||||
|
||||
u16 vlan1;
|
||||
u16 etype;
|
||||
u16 sp_tag;
|
||||
u32 dmac_hi;
|
||||
union {
|
||||
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
@@ -801,7 +843,7 @@ struct hnat_ipv6_hnapt {
|
||||
};
|
||||
|
||||
u16 vlan1;
|
||||
u16 etype;
|
||||
u16 sp_tag;
|
||||
u32 dmac_hi;
|
||||
u16 vlan2;
|
||||
u16 dmac_lo;
|
||||
@@ -837,6 +879,7 @@ struct foe_entry {
|
||||
union {
|
||||
struct hnat_unbind_info_blk udib1;
|
||||
struct hnat_bind_info_blk bfib1;
|
||||
struct hnat_l2_bridge l2_bridge;
|
||||
struct hnat_ipv4_hnapt ipv4_hnapt;
|
||||
struct hnat_ipv4_dslite ipv4_dslite;
|
||||
struct hnat_ipv4_mape ipv4_mape;
|
||||
@@ -868,6 +911,12 @@ struct foe_entry {
|
||||
#endif
|
||||
#define CFG_PPE_NUM (hnat_priv->ppe_num)
|
||||
|
||||
#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
#define MAX_PPE_CACHE_NUM (128)
|
||||
#else
|
||||
#define MAX_PPE_CACHE_NUM (32)
|
||||
#endif
|
||||
|
||||
/* If the user wants to set skb->mark to prevent hardware acceleration
|
||||
* for the packet flow.
|
||||
*/
|
||||
@@ -885,6 +934,8 @@ struct mib_entry {
|
||||
struct hnat_accounting {
|
||||
u64 bytes;
|
||||
u64 packets;
|
||||
struct nf_conntrack_zone zone;
|
||||
u8 dir;
|
||||
};
|
||||
|
||||
enum mtk_hnat_version {
|
||||
@@ -957,7 +1008,19 @@ struct mtk_hnat {
|
||||
struct timer_list hnat_mcast_check_timer;
|
||||
bool nf_stat_en;
|
||||
struct xlat_conf xlat;
|
||||
spinlock_t cah_lock;
|
||||
spinlock_t entry_lock;
|
||||
spinlock_t flow_entry_lock;
|
||||
struct hlist_head *foe_flow[MAX_PPE_NUM];
|
||||
int fe_irq2;
|
||||
};
|
||||
|
||||
struct hnat_flow_entry {
|
||||
struct hlist_node list;
|
||||
struct foe_entry data;
|
||||
unsigned long last_update;
|
||||
u16 ppe_index;
|
||||
u16 hash;
|
||||
};
|
||||
|
||||
struct extdev_entry {
|
||||
@@ -970,11 +1033,28 @@ struct tcpudphdr {
|
||||
__be16 dst;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
struct ppe_flow_chk_status {
|
||||
u32 entry : 15;
|
||||
u32 sta : 1;
|
||||
u32 state : 2;
|
||||
u32 sp : 4;
|
||||
u32 fp : 4;
|
||||
u32 cah : 1;
|
||||
u32 rmt : 1;
|
||||
u32 psn : 1;
|
||||
u32 dram : 1;
|
||||
u32 resv : 1;
|
||||
u32 valid : 1;
|
||||
};
|
||||
#endif
|
||||
|
||||
enum FoeEntryState { INVALID = 0, UNBIND = 1, BIND = 2, FIN = 3 };
|
||||
|
||||
enum FoeIpAct {
|
||||
IPV4_HNAPT = 0,
|
||||
IPV4_HNAT = 1,
|
||||
L2_BRIDGE = 2,
|
||||
IPV4_DSLITE = 3,
|
||||
IPV6_3T_ROUTE = 4,
|
||||
IPV6_5T_ROUTE = 5,
|
||||
@@ -1012,9 +1092,11 @@ enum FoeIpAct {
|
||||
#define HASH_MODE_3 3
|
||||
|
||||
/*PPE_FLOW_CFG*/
|
||||
#define BIT_FUC_FOE BIT(2)
|
||||
#define BIT_FMC_FOE BIT(1)
|
||||
#define BIT_FBC_FOE BIT(0)
|
||||
#define BIT_ALERT_TCP_FIN_RST_SYN BIT(0)
|
||||
#define BIT_MD_TOAP_BYP_CRSN0 BIT(1)
|
||||
#define BIT_MD_TOAP_BYP_CRSN1 BIT(2)
|
||||
#define BIT_MD_TOAP_BYP_CRSN2 BIT(3)
|
||||
#define BIT_TCP_IP4F_NAT_EN BIT(6) /*Enable IPv4 fragment + TCP packet NAT*/
|
||||
#define BIT_UDP_IP4F_NAT_EN BIT(7) /*Enable IPv4 fragment + UDP packet NAT*/
|
||||
#define BIT_IPV6_3T_ROUTE_EN BIT(8)
|
||||
#define BIT_IPV6_5T_ROUTE_EN BIT(9)
|
||||
@@ -1023,7 +1105,8 @@ enum FoeIpAct {
|
||||
#define BIT_IPV4_NAT_EN BIT(12)
|
||||
#define BIT_IPV4_NAPT_EN BIT(13)
|
||||
#define BIT_IPV4_DSL_EN BIT(14)
|
||||
#define BIT_MIB_BUSY BIT(16)
|
||||
#define BIT_L2_BRG_EN BIT(15)
|
||||
#define BIT_IP_PROT_CHK_BLIST BIT(16)
|
||||
#define BIT_IPV4_NAT_FRAG_EN BIT(17)
|
||||
#define BIT_IPV4_HASH_GREK BIT(19)
|
||||
#define BIT_IPV6_HASH_GREK BIT(20)
|
||||
@@ -1032,6 +1115,9 @@ enum FoeIpAct {
|
||||
#define BIT_IPV6_NAT_EN BIT(23)
|
||||
#define BIT_IPV6_NAPT_EN BIT(24)
|
||||
#define BIT_CS0_RM_ALL_IP6_IP_EN BIT(25)
|
||||
#define BIT_L2_HASH_ETH BIT(29)
|
||||
#define BIT_L2_HASH_VID BIT(30)
|
||||
#define BIT_L2_LRN_EN BIT(31)
|
||||
|
||||
/*GDMA_FWD_CFG value*/
|
||||
#define BITS_GDM_UFRC_P_PPE (NR_PPE0_PORT << 12)
|
||||
@@ -1058,6 +1144,14 @@ enum FoeIpAct {
|
||||
(BITS_GDM_UFRC_P_PPE2 | BITS_GDM_BFRC_P_PPE2 | \
|
||||
BITS_GDM_MFRC_P_PPE2 | BITS_GDM_OFRC_P_PPE2)
|
||||
|
||||
#define BITS_GDM_UFRC_P_TDMA (NR_TDMA_PORT << 12)
|
||||
#define BITS_GDM_BFRC_P_TDMA (NR_TDMA_PORT << 8)
|
||||
#define BITS_GDM_MFRC_P_TDMA (NR_TDMA_PORT << 4)
|
||||
#define BITS_GDM_OFRC_P_TDMA (NR_TDMA_PORT << 0)
|
||||
#define BITS_GDM_ALL_FRC_P_TDMA \
|
||||
(BITS_GDM_UFRC_P_TDMA | BITS_GDM_BFRC_P_TDMA | \
|
||||
BITS_GDM_MFRC_P_TDMA | BITS_GDM_OFRC_P_TDMA)
|
||||
|
||||
#define BITS_GDM_UFRC_P_CPU_PDMA (NR_PDMA_PORT << 12)
|
||||
#define BITS_GDM_BFRC_P_CPU_PDMA (NR_PDMA_PORT << 8)
|
||||
#define BITS_GDM_MFRC_P_CPU_PDMA (NR_PDMA_PORT << 4)
|
||||
@@ -1144,22 +1238,36 @@ enum FoeIpAct {
|
||||
#define NR_DISCARD 7
|
||||
#define NR_WDMA0_PORT 8
|
||||
#define NR_WDMA1_PORT 9
|
||||
#define NR_TDMA_PORT 10
|
||||
#define NR_WDMA2_PORT 13
|
||||
#define NR_GMAC3_PORT 15
|
||||
#define NR_QDMA_TPORT 1
|
||||
#define NR_EIP197_TPORT 2
|
||||
#define NR_EIP197_QDMA_TPORT 3
|
||||
#define NR_TDMA_TPORT 4
|
||||
#define NR_TDMA_QDMA_TPORT 5
|
||||
#define NR_TDMA_EIP197_TPORT 8
|
||||
#define NR_TDMA_EIP197_QDMA_TPORT 9
|
||||
#define WAN_DEV_NAME hnat_priv->wan
|
||||
#define LAN_DEV_NAME hnat_priv->lan
|
||||
#define LAN2_DEV_NAME hnat_priv->lan2
|
||||
#define IS_WAN(dev) \
|
||||
(!strncmp((dev)->name, hnat_priv->wan, strlen(hnat_priv->wan)))
|
||||
#define IS_ETH_GRP(dev) (IS_LAN_GRP(dev) || IS_WAN(dev))
|
||||
#define IS_WAN(dev) (!strncmp((dev)->name, WAN_DEV_NAME, strlen(WAN_DEV_NAME)))
|
||||
#define IS_LAN_GRP(dev) (IS_LAN(dev) | IS_LAN2(dev))
|
||||
#define IS_LAN(dev) (!strncmp(dev->name, LAN_DEV_NAME, strlen(LAN_DEV_NAME)))
|
||||
#define IS_LAN2(dev) (!strncmp(dev->name, LAN2_DEV_NAME, \
|
||||
strlen(LAN2_DEV_NAME)))
|
||||
#define IS_LAN(dev) \
|
||||
(!strncmp(dev->name, LAN_DEV_NAME, strlen(LAN_DEV_NAME)) || \
|
||||
IS_BOND(dev))
|
||||
#define IS_LAN2(dev) \
|
||||
(!strncmp(dev->name, LAN2_DEV_NAME, strlen(LAN2_DEV_NAME)) || \
|
||||
IS_BOND(dev))
|
||||
#define IS_BR(dev) (!strncmp(dev->name, "br", 2))
|
||||
#define IS_BOND(dev) (!strncmp(dev->name, "bond", 4))
|
||||
#define IS_WHNAT(dev) \
|
||||
((hnat_priv->data->whnat && \
|
||||
(get_wifi_hook_if_index_from_dev(dev) != 0)) ? 1 : 0)
|
||||
#define IS_EXT(dev) ((get_index_from_dev(dev) != 0) ? 1 : 0)
|
||||
#define IS_PPD(dev) (!strcmp(dev->name, hnat_priv->ppd))
|
||||
#define IS_L2_BRIDGE(x) (((x)->bfib1.pkt_type == L2_BRIDGE) ? 1 : 0)
|
||||
#define IS_IPV4_HNAPT(x) (((x)->bfib1.pkt_type == IPV4_HNAPT) ? 1 : 0)
|
||||
#define IS_IPV4_HNAT(x) (((x)->bfib1.pkt_type == IPV4_HNAT) ? 1 : 0)
|
||||
#define IS_IPV4_GRP(x) (IS_IPV4_HNAPT(x) | IS_IPV4_HNAT(x))
|
||||
@@ -1175,16 +1283,25 @@ enum FoeIpAct {
|
||||
(IS_IPV6_3T_ROUTE(x) | IS_IPV6_5T_ROUTE(x) | IS_IPV6_6RD(x) | \
|
||||
IS_IPV4_DSLITE(x) | IS_IPV4_MAPE(x) | IS_IPV4_MAPT(x) | \
|
||||
IS_IPV6_HNAPT(x) | IS_IPV6_HNAT(x))
|
||||
#define IS_BOND_MODE (!strncmp(LAN_DEV_NAME, "bond", 4))
|
||||
#define IS_GMAC1_MODE ((hnat_priv->gmac_num == 1) ? 1 : 0)
|
||||
#define IS_HQOS_MODE (qos_toggle == 1)
|
||||
#define IS_PPPQ_MODE (qos_toggle == 2) /* Per Port Per Queue */
|
||||
#define IS_PPPQ_PATH(dev, skb) \
|
||||
((IS_DSA_1G_LAN(dev) || IS_DSA_WAN(dev)) || \
|
||||
(FROM_WED(skb) && IS_DSA_LAN(dev)))
|
||||
#define IS_HQOS_DL_MODE (IS_HQOS_MODE && qos_dl_toggle)
|
||||
#define IS_HQOS_UL_MODE (IS_HQOS_MODE && qos_ul_toggle)
|
||||
#define MAX_PPPQ_PORT_NUM 6
|
||||
#define MAX_SWITCH_PORT_NUM (6)
|
||||
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
#define MAX_PPPQ_QUEUE_NUM (2 * MAX_SWITCH_PORT_NUM + 2)
|
||||
#define IS_PPPQ_PATH(dev, skb) \
|
||||
((IS_DSA_1G_LAN(dev) || IS_DSA_WAN(dev)) || \
|
||||
(IS_ETH_GRP(dev) && is_eth_dev_speed_under(dev, SPEED_1000)) ||\
|
||||
(FROM_WED(skb) && (IS_DSA_LAN(dev) || \
|
||||
is_eth_dev_speed_under(dev, SPEED_2500))))
|
||||
#else
|
||||
#define MAX_PPPQ_QUEUE_NUM (2 * MAX_SWITCH_PORT_NUM)
|
||||
#define IS_PPPQ_PATH(dev, skb) \
|
||||
((IS_DSA_1G_LAN(dev) || IS_DSA_WAN(dev)) || \
|
||||
(FROM_WED(skb) && IS_DSA_LAN(dev)))
|
||||
#endif
|
||||
|
||||
#define es(entry) (entry_state[entry->bfib1.state])
|
||||
#define ei(entry, end) (hnat_priv->foe_etry_num - (int)(end - entry))
|
||||
@@ -1212,68 +1329,51 @@ enum FoeIpAct {
|
||||
#define IS_DSA_1G_LAN(dev) (!strncmp(dev->name, "lan", 3) && \
|
||||
strcmp(dev->name, "lan5"))
|
||||
#define IS_DSA_WAN(dev) (!strncmp(dev->name, "wan", 3))
|
||||
#define IS_DSA_TAG_PROTO_MXL862_8021Q(dp) \
|
||||
(dp->cpu_dp->tag_ops->proto == DSA_TAG_PROTO_MXL862_8021Q)
|
||||
#define NONE_DSA_PORT 0xff
|
||||
#define MAX_CRSN_NUM 32
|
||||
#define IPV6_HDR_LEN 40
|
||||
#define IPV6_SNAT 0
|
||||
#define IPV6_DNAT 1
|
||||
|
||||
/*QDMA_PAGE value*/
|
||||
#define NUM_OF_Q_PER_PAGE 16
|
||||
|
||||
/*IPv6 Header*/
|
||||
#ifndef NEXTHDR_IPIP
|
||||
#define NEXTHDR_IPIP 4
|
||||
#endif
|
||||
|
||||
#define UDF_PINGPONG_IFIDX GENMASK(6, 0)
|
||||
#define UDF_HNAT_PRE_FILLED BIT(7)
|
||||
|
||||
#define HQOS_FLAG(dev, skb, qid) \
|
||||
((IS_HQOS_UL_MODE && IS_WAN(dev)) || \
|
||||
(IS_HQOS_DL_MODE && IS_LAN_GRP(dev)) || \
|
||||
(IS_PPPQ_MODE && (IS_PPPQ_PATH(dev, skb) || \
|
||||
qid >= MAX_PPPQ_PORT_NUM)))
|
||||
#define HQOS_FLAG(dev, skb, qid) \
|
||||
((IS_HQOS_UL_MODE && IS_WAN(dev)) || \
|
||||
(IS_HQOS_DL_MODE && IS_LAN_GRP(dev)) || \
|
||||
(IS_PPPQ_MODE && (IS_PPPQ_PATH(dev, skb) || \
|
||||
qid >= MAX_PPPQ_QUEUE_NUM)))
|
||||
|
||||
#define HNAT_GMAC_FP(mac_id) \
|
||||
((IS_GMAC1_MODE || mac_id == MTK_GMAC1_ID) ? NR_GMAC1_PORT : \
|
||||
(mac_id == MTK_GMAC2_ID) ? NR_GMAC2_PORT : \
|
||||
(mac_id == MTK_GMAC3_ID) ? NR_GMAC3_PORT : \
|
||||
-EINVAL)
|
||||
|
||||
extern const struct of_device_id of_hnat_match[];
|
||||
extern struct mtk_hnat *hnat_priv;
|
||||
|
||||
static inline int is_hnat_pre_filled(struct foe_entry *entry)
|
||||
{
|
||||
u32 udf = 0;
|
||||
|
||||
if (IS_IPV4_GRP(entry))
|
||||
udf = entry->ipv4_hnapt.act_dp;
|
||||
else
|
||||
udf = entry->ipv6_5t_route.act_dp;
|
||||
|
||||
return !!(udf & UDF_HNAT_PRE_FILLED);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_DSA_MT7530)
|
||||
u32 hnat_dsa_fill_stag(const struct net_device *netdev,
|
||||
int hnat_dsa_fill_stag(const struct net_device *netdev,
|
||||
struct foe_entry *entry,
|
||||
struct flow_offload_hw_path *hw_path,
|
||||
u16 eth_proto, int mape);
|
||||
|
||||
int hnat_dsa_get_port(struct net_device **dev);
|
||||
static inline bool hnat_dsa_is_enable(struct mtk_hnat *priv)
|
||||
{
|
||||
#if defined(CONFIG_NET_DSA)
|
||||
return (priv->wan_dsa_port != NONE_DSA_PORT);
|
||||
}
|
||||
#else
|
||||
static inline u32 hnat_dsa_fill_stag(const struct net_device *netdev,
|
||||
struct foe_entry *entry,
|
||||
struct flow_offload_hw_path *hw_path,
|
||||
u16 eth_proto, int mape)
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool hnat_dsa_is_enable(struct mtk_hnat *priv)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
struct foe_entry *hnat_get_foe_entry(u32 ppe_id, u32 index);
|
||||
|
||||
void hnat_deinit_debugfs(struct mtk_hnat *h);
|
||||
int hnat_init_debugfs(struct mtk_hnat *h);
|
||||
@@ -1282,8 +1382,14 @@ void hnat_unregister_nf_hooks(void);
|
||||
int whnat_adjust_nf_hooks(void);
|
||||
int mtk_hqos_ptype_cb(struct sk_buff *skb, struct net_device *dev,
|
||||
struct packet_type *pt, struct net_device *unused);
|
||||
int hnat_search_cache_line(u32 ppe_id, u32 tag);
|
||||
int hnat_write_cache_line(u32 ppe_id, int line, u32 tag, u32 state, u32 *data);
|
||||
int hnat_dump_cache_entry(u32 ppe_id, int hash);
|
||||
int hnat_dump_ppe_entry(u32 ppe_id, u32 hash);
|
||||
bool is_eth_dev_speed_under(const struct net_device *dev, u32 speed);
|
||||
extern int dbg_cpu_reason;
|
||||
extern int debug_level;
|
||||
extern int mcast_mode;
|
||||
extern int xlat_toggle;
|
||||
extern struct hnat_desc headroom[DEF_ETRY_NUM];
|
||||
extern int qos_dl_toggle;
|
||||
@@ -1291,9 +1397,21 @@ extern int qos_ul_toggle;
|
||||
extern int hook_toggle;
|
||||
extern int mape_toggle;
|
||||
extern int qos_toggle;
|
||||
|
||||
extern int l2br_toggle;
|
||||
extern int l4s_toggle;
|
||||
extern int tnl_toggle;
|
||||
extern int (*mtk_tnl_encap_offload)(struct sk_buff *skb, struct ethhdr *eth);
|
||||
extern int (*mtk_tnl_decap_offload)(struct sk_buff *skb);
|
||||
extern bool (*mtk_tnl_decap_offloadable)(struct sk_buff *skb);
|
||||
extern bool (*mtk_crypto_offloadable)(struct sk_buff *skb);
|
||||
extern int hnat_bind_crypto_entry(struct sk_buff *skb,
|
||||
const struct net_device *dev,
|
||||
int fill_inner_info);
|
||||
extern void foe_clear_crypto_entry(struct xfrm_selector sel);
|
||||
int ext_if_add(struct extdev_entry *ext_entry);
|
||||
int ext_if_del(struct extdev_entry *ext_entry);
|
||||
void cr_set_bits(void __iomem *reg, u32 bs);
|
||||
void cr_clr_bits(void __iomem *reg, u32 bs);
|
||||
void cr_set_field(void __iomem *reg, u32 field, u32 val);
|
||||
int mtk_sw_nat_hook_tx(struct sk_buff *skb, int gmac_no);
|
||||
int mtk_sw_nat_hook_rx(struct sk_buff *skb);
|
||||
@@ -1309,21 +1427,41 @@ uint32_t hnat_cpu_reason_cnt(struct sk_buff *skb);
|
||||
int hnat_enable_hook(void);
|
||||
int hnat_disable_hook(void);
|
||||
void hnat_cache_ebl(int enable);
|
||||
void __hnat_cache_ebl(u32 ppe_id, int enable);
|
||||
void hnat_cache_clr(u32 ppe_id);
|
||||
void __hnat_cache_clr(u32 ppe_id);
|
||||
void hnat_qos_shaper_ebl(u32 id, u32 enable);
|
||||
void exclude_boundary_entry(struct foe_entry *foe_table_cpu);
|
||||
void set_gmac_ppe_fwd(int gmac_no, int enable);
|
||||
int entry_detail(u32 ppe_id, int index);
|
||||
int entry_delete_by_mac(u8 *mac);
|
||||
int entry_delete_by_ip(bool is_ipv4, void *addr);
|
||||
int entry_delete(u32 ppe_id, int index);
|
||||
void __entry_delete(struct foe_entry *entry);
|
||||
int hnat_warm_init(void);
|
||||
u32 hnat_get_ppe_hash(struct foe_entry *entry);
|
||||
int mtk_ppe_get_xlat_v4_by_v6(struct in6_addr *ipv6, u32 *ipv4);
|
||||
int mtk_ppe_get_xlat_v6_by_v4(u32 *ipv4, struct in6_addr *ipv6,
|
||||
struct in6_addr *prefix);
|
||||
bool hnat_flow_entry_match(struct foe_entry *entry, struct foe_entry *data);
|
||||
void hnat_flow_entry_delete(struct hnat_flow_entry *flow_entry);
|
||||
|
||||
struct hnat_accounting *hnat_get_count(struct mtk_hnat *h, u32 ppe_id,
|
||||
u32 index, struct hnat_accounting *diff);
|
||||
|
||||
static inline u16 foe_timestamp(struct mtk_hnat *h)
|
||||
int mtk_hnat_skb_headroom_copy(struct sk_buff *new, struct sk_buff *old);
|
||||
static inline u16 foe_timestamp(struct mtk_hnat *h, bool mcast)
|
||||
{
|
||||
return (readl(hnat_priv->fe_base + 0x0010)) & 0xffff;
|
||||
u16 time_stamp;
|
||||
|
||||
if (mcast)
|
||||
time_stamp = (readl(h->fe_base + 0x0010)) & 0xffff;
|
||||
else if (h->data->version == MTK_HNAT_V2 || h->data->version == MTK_HNAT_V3)
|
||||
time_stamp = readl(h->fe_base + 0x0010) & (0xFF);
|
||||
else
|
||||
time_stamp = readl(h->fe_base + 0x0010) & (0x7FFF);
|
||||
|
||||
return time_stamp;
|
||||
}
|
||||
|
||||
#endif /* NF_HNAT_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,8 @@
|
||||
*
|
||||
* Copyright (C) 2014-2016 Zhiqiang Yang <zhiqiang.yang@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <net/netfilter/nf_flow_table.h>
|
||||
#include <net/sock.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
@@ -19,20 +21,21 @@
|
||||
* mcast_entry_get - Returns the index of an unused entry
|
||||
* or an already existed entry in mtbl
|
||||
*/
|
||||
static int mcast_entry_get(u16 vlan_id, u32 dst_mac)
|
||||
static int mcast_entry_get(u16 vlan_id, u8 *dmac)
|
||||
{
|
||||
int index = -1;
|
||||
u8 i;
|
||||
struct ppe_mcast_group *p = hnat_priv->pmcast->mtbl;
|
||||
int index = -1;
|
||||
u8 max = hnat_priv->pmcast->max_entry;
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
if ((index == -1) && (!p->valid)) {
|
||||
if (p->valid) {
|
||||
if ((p->vid == vlan_id) && !memcmp(p->dmac, dmac, ETH_ALEN)) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
} else if (index == -1) {
|
||||
index = i; /*get the first unused entry index*/
|
||||
continue;
|
||||
}
|
||||
if ((p->vid == vlan_id) && (p->mac_hi == dst_mac)) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
@@ -43,21 +46,37 @@ static int mcast_entry_get(u16 vlan_id, u32 dst_mac)
|
||||
return index;
|
||||
}
|
||||
|
||||
static void get_mac_from_mdb_entry(struct br_mdb_entry *entry,
|
||||
u32 *mac_hi, u16 *mac_lo)
|
||||
static int get_mac_from_mdb_entry(struct br_mdb_entry *entry, u8 *mac)
|
||||
{
|
||||
u32 ip;
|
||||
|
||||
switch (ntohs(entry->addr.proto)) {
|
||||
case ETH_P_IP:
|
||||
*mac_lo = 0x0100;
|
||||
*mac_hi = swab32((entry->addr.u.ip4 & 0xfffffe00) + 0x5e);
|
||||
ip = be32_to_cpu(entry->addr.u.ip4);
|
||||
mac[0] = 0x01;
|
||||
mac[1] = 0x00;
|
||||
mac[2] = 0x5e;
|
||||
mac[3] = (ip >> 16) & 0x7F;
|
||||
mac[4] = (ip >> 8) & 0xFF;
|
||||
mac[5] = ip & 0xFF;
|
||||
break;
|
||||
case ETH_P_IPV6:
|
||||
*mac_lo = 0x3333;
|
||||
*mac_hi = swab32(entry->addr.u.ip6.s6_addr32[3]);
|
||||
ip = be32_to_cpu(entry->addr.u.ip6.s6_addr32[3]);
|
||||
mac[0] = 0x33;
|
||||
mac[1] = 0x33;
|
||||
mac[2] = (ip >> 24) & 0xFF;
|
||||
mac[3] = (ip >> 16) & 0xFF;
|
||||
mac[4] = (ip >> 8) & 0xFF;
|
||||
mac[5] = ip & 0xFF;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
trace_printk("%s:group mac_h=0x%08x, mac_l=0x%04x\n",
|
||||
__func__, *mac_hi, *mac_lo);
|
||||
|
||||
if (debug_level >= 7)
|
||||
pr_info("%s:group mac=%pM\n", __func__, mac);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*set_hnat_mtbl - set ppe multicast register*/
|
||||
@@ -65,8 +84,8 @@ static int set_hnat_mtbl(struct ppe_mcast_group *group, u32 ppe_id, int index)
|
||||
{
|
||||
struct ppe_mcast_h mcast_h;
|
||||
struct ppe_mcast_l mcast_l;
|
||||
u16 mac_lo = group->mac_lo;
|
||||
u32 mac_hi = group->mac_hi;
|
||||
u16 mac_hi = DMAC_TO_HI16(group->dmac);
|
||||
u32 mac_lo = DMAC_TO_LO32(group->dmac);
|
||||
u8 mc_port = group->mc_port;
|
||||
void __iomem *reg;
|
||||
|
||||
@@ -75,16 +94,20 @@ static int set_hnat_mtbl(struct ppe_mcast_group *group, u32 ppe_id, int index)
|
||||
|
||||
mcast_h.u.value = 0;
|
||||
mcast_l.addr = 0;
|
||||
if (mac_lo == 0x0100)
|
||||
if (mac_hi == 0x0100)
|
||||
mcast_h.u.info.mc_mpre_sel = 0;
|
||||
else if (mac_lo == 0x3333)
|
||||
else if (mac_hi == 0x3333)
|
||||
mcast_h.u.info.mc_mpre_sel = 1;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
mcast_h.u.info.mc_px_en = mc_port;
|
||||
mcast_l.addr = mac_hi;
|
||||
mcast_h.u.info.valid = group->valid;
|
||||
trace_printk("%s:index=%d,group info=0x%x,addr=0x%x\n",
|
||||
__func__, index, mcast_h.u.value, mcast_l.addr);
|
||||
mcast_l.addr = mac_lo;
|
||||
|
||||
if (debug_level >= 7)
|
||||
trace_printk("%s:index=%d,group info=0x%x,addr=0x%x\n",
|
||||
__func__, index, mcast_h.u.value, mcast_l.addr);
|
||||
|
||||
if (index < 0x10) {
|
||||
reg = hnat_priv->ppe_base[ppe_id] + PPE_MCAST_H_0 + ((index) * 8);
|
||||
writel(mcast_h.u.value, reg);
|
||||
@@ -92,31 +115,55 @@ static int set_hnat_mtbl(struct ppe_mcast_group *group, u32 ppe_id, int index)
|
||||
writel(mcast_l.addr, reg);
|
||||
} else {
|
||||
index = index - 0x10;
|
||||
reg = hnat_priv->fe_base + PPE_MCAST_H_10 + ((index) * 8);
|
||||
writel(mcast_h.u.value, reg);
|
||||
reg = hnat_priv->fe_base + PPE_MCAST_L_10 + ((index) * 8);
|
||||
reg = hnat_priv->ppe_base[ppe_id] + PPE_MCAST_H_10 + ((index) * 8);
|
||||
writel(mcast_h.u.value, reg);
|
||||
reg = hnat_priv->ppe_base[ppe_id] + PPE_MCAST_L_10 + ((index) * 8);
|
||||
writel(mcast_l.addr, reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*clr_hnat_mtbl - clear ppe multicast register*/
|
||||
static void clr_hnat_mtbl(struct ppe_mcast_group *group, u32 ppe_id, int index)
|
||||
{
|
||||
void __iomem *reg;
|
||||
|
||||
if (ppe_id >= CFG_PPE_NUM)
|
||||
return;
|
||||
|
||||
if (index < 0x10) {
|
||||
reg = hnat_priv->ppe_base[ppe_id] + PPE_MCAST_H_0 + ((index) * 8);
|
||||
writel(0, reg);
|
||||
reg = hnat_priv->ppe_base[ppe_id] + PPE_MCAST_L_0 + ((index) * 8);
|
||||
writel(0, reg);
|
||||
} else {
|
||||
index = index - 0x10;
|
||||
reg = hnat_priv->ppe_base[ppe_id] + PPE_MCAST_H_10 + ((index) * 8);
|
||||
writel(0, reg);
|
||||
reg = hnat_priv->ppe_base[ppe_id] + PPE_MCAST_L_10 + ((index) * 8);
|
||||
writel(0, reg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* hnat_mcast_table_update -
|
||||
* 1.get a valid group entry
|
||||
* 2.update group info
|
||||
* a.update eif&oif count
|
||||
* b.eif ==0 & oif == 0,delete it from group table
|
||||
* c.oif != 0,set mc forward port to cpu,else do not forward to cpu
|
||||
* a.update if_num count
|
||||
* b.if_num[i] port refer to ppe_mcast_port in hnat_mcash.h
|
||||
* c.if_num[i] = 0 for i, delete it from group table
|
||||
* 3.set the group info to ppe register
|
||||
*/
|
||||
static int hnat_mcast_table_update(int type, struct br_mdb_entry *entry)
|
||||
{
|
||||
struct net_device *dev;
|
||||
u32 mac_hi = 0;
|
||||
u16 mac_lo = 0;
|
||||
int i, index;
|
||||
struct flow_offload_hw_path hw_path = { 0 };
|
||||
struct ppe_mcast_group *group;
|
||||
struct net_device *dev;
|
||||
struct mtk_mac *mac;
|
||||
int i, index, port;
|
||||
int ret;
|
||||
u8 dmac[ETH_ALEN];
|
||||
|
||||
rcu_read_lock();
|
||||
dev = dev_get_by_index_rcu(&init_net, entry->ifindex);
|
||||
@@ -126,55 +173,242 @@ static int hnat_mcast_table_update(int type, struct br_mdb_entry *entry)
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
get_mac_from_mdb_entry(entry, &mac_hi, &mac_lo);
|
||||
index = mcast_entry_get(entry->vid, mac_hi);
|
||||
ret = get_mac_from_mdb_entry(entry, dmac);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
index = mcast_entry_get(entry->vid, dmac);
|
||||
if (index == -1)
|
||||
return -1;
|
||||
|
||||
group = &hnat_priv->pmcast->mtbl[index];
|
||||
group->mac_hi = mac_hi;
|
||||
group->mac_lo = mac_lo;
|
||||
memcpy(group->dmac, dmac, ETH_ALEN);
|
||||
|
||||
if (IS_ETH_GRP(dev) && !IS_DSA_LAN(dev)) {
|
||||
if (dev->netdev_ops->ndo_flow_offload_check) {
|
||||
hw_path.dev = dev;
|
||||
hw_path.virt_dev = dev;
|
||||
dev->netdev_ops->ndo_flow_offload_check(&hw_path);
|
||||
dev = hw_path.dev;
|
||||
}
|
||||
mac = netdev_priv(dev);
|
||||
port = (mac->id == MTK_GMAC1_ID) ? MCAST_TO_GDMA1 :
|
||||
(mac->id == MTK_GMAC2_ID) ? MCAST_TO_GDMA2 :
|
||||
(mac->id == MTK_GMAC3_ID) ? MCAST_TO_GDMA3 :
|
||||
-EINVAL;
|
||||
if (port < 0)
|
||||
return -1;
|
||||
} else {
|
||||
port = MCAST_TO_PDMA; /* to PDMA */
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case RTM_NEWMDB:
|
||||
if (IS_LAN(dev) || IS_WAN(dev))
|
||||
group->eif++;
|
||||
else
|
||||
group->oif++;
|
||||
group->if_num[port]++;
|
||||
group->vid = entry->vid;
|
||||
group->valid = true;
|
||||
break;
|
||||
case RTM_DELMDB:
|
||||
if (group->valid) {
|
||||
if (IS_LAN(dev) || IS_WAN(dev))
|
||||
group->eif--;
|
||||
else
|
||||
group->oif--;
|
||||
}
|
||||
if (group->valid)
|
||||
group->if_num[port]--;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
trace_printk("%s:devname=%s,eif=%d,oif=%d\n", __func__,
|
||||
dev->name, group->eif, group->oif);
|
||||
if (group->valid) {
|
||||
if (group->oif && group->eif)
|
||||
/*eth&wifi both in group,forward to cpu&GDMA1*/
|
||||
group->mc_port = (MCAST_TO_PDMA || MCAST_TO_GDMA1);
|
||||
else if (group->oif)
|
||||
/*only wifi in group,forward to cpu only*/
|
||||
group->mc_port = MCAST_TO_PDMA;
|
||||
else
|
||||
/*only eth in group,forward to GDMA1 only*/
|
||||
group->mc_port = MCAST_TO_GDMA1;
|
||||
if (!group->oif && !group->eif)
|
||||
/*nobody in this group,clear the entry*/
|
||||
memset(group, 0, sizeof(struct ppe_mcast_group));
|
||||
if (debug_level >= 7)
|
||||
trace_printk("%s:devname=%s,if_num=%d|%d|%d|%d|%d\n", __func__,
|
||||
dev->name, group->if_num[4], group->if_num[3],
|
||||
group->if_num[2], group->if_num[1], group->if_num[0]);
|
||||
|
||||
for (i = 0; i < CFG_PPE_NUM; i++)
|
||||
set_hnat_mtbl(group, i, index);
|
||||
if (group->valid) {
|
||||
group->mc_port = 0;
|
||||
for (i = 0; i < MAX_MCAST_PORT; i++) {
|
||||
if (group->if_num[i] > 0)
|
||||
group->mc_port |= (0x1 << i);
|
||||
}
|
||||
|
||||
if (group->mc_port == 0) {
|
||||
for (i = 0; i < CFG_PPE_NUM; i++)
|
||||
clr_hnat_mtbl(group, i, index);
|
||||
/* nobody in this group, clear the entry */
|
||||
memset(group, 0, sizeof(struct ppe_mcast_group));
|
||||
} else {
|
||||
for (i = 0; i < CFG_PPE_NUM; i++)
|
||||
set_hnat_mtbl(group, i, index);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get mc_port value for read-only access */
|
||||
static bool hnat_mcast_get_mc_port(u8 *dmac, u16 vlan_id, u8 *mc_port)
|
||||
{
|
||||
struct ppe_mcast_list *entry;
|
||||
struct list_head *head;
|
||||
bool found = false;
|
||||
|
||||
if (!hnat_priv->pmcast)
|
||||
return false;
|
||||
|
||||
head = &hnat_priv->pmcast->mlist;
|
||||
|
||||
read_lock(&hnat_priv->pmcast->mcast_lock);
|
||||
list_for_each_entry(entry, head, list) {
|
||||
if (!memcmp(entry->dmac, dmac, ETH_ALEN) && (entry->vid == vlan_id)) {
|
||||
*mc_port = entry->mc_port;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
read_unlock(&hnat_priv->pmcast->mcast_lock);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/* Find node for update access - must be called with mcast_lock held */
|
||||
static struct ppe_mcast_list *hnat_mcast_list_find(u8 *dmac, u16 vlan_id)
|
||||
{
|
||||
struct ppe_mcast_list *entry;
|
||||
struct list_head *head;
|
||||
|
||||
if (!hnat_priv->pmcast)
|
||||
return NULL;
|
||||
|
||||
head = &hnat_priv->pmcast->mlist;
|
||||
|
||||
/* Regular list traversal since we hold the lock */
|
||||
list_for_each_entry(entry, head, list) {
|
||||
if (!memcmp(entry->dmac, dmac, ETH_ALEN) && (entry->vid == vlan_id))
|
||||
return entry;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void hnat_mcast_list_del_all(void)
|
||||
{
|
||||
struct ppe_mcast_list *entry, *tmp;
|
||||
struct list_head *head;
|
||||
|
||||
if (!hnat_priv->pmcast)
|
||||
return;
|
||||
|
||||
head = &hnat_priv->pmcast->mlist;
|
||||
|
||||
write_lock(&hnat_priv->pmcast->mcast_lock);
|
||||
list_for_each_entry_safe(entry, tmp, head, list) {
|
||||
list_del(&entry->list);
|
||||
kfree(entry);
|
||||
}
|
||||
write_unlock(&hnat_priv->pmcast->mcast_lock);
|
||||
}
|
||||
|
||||
bool hnat_is_mcast_uni(struct sk_buff *skb)
|
||||
{
|
||||
u8 mc_port;
|
||||
u16 vid;
|
||||
|
||||
if (!skb)
|
||||
return false;
|
||||
|
||||
vid = skb_vlan_tagged(skb) ? skb->vlan_tci & VLAN_VID_MASK : 0;
|
||||
|
||||
if (!hnat_mcast_get_mc_port(eth_hdr(skb)->h_dest, vid, &mc_port))
|
||||
return false;
|
||||
|
||||
/* only allows packets destined to single GDMA ports */
|
||||
return IS_MCAST_PORT_GDM(mc_port);
|
||||
}
|
||||
|
||||
static int hnat_mcast_list_update(int type, struct br_mdb_entry *entry)
|
||||
{
|
||||
struct flow_offload_hw_path hw_path = { 0 };
|
||||
struct ppe_mcast_list *pmcast_list;
|
||||
struct net_device *dev;
|
||||
struct mtk_mac *mac;
|
||||
int port, ret;
|
||||
u8 dmac[ETH_ALEN];
|
||||
|
||||
rcu_read_lock();
|
||||
dev = dev_get_by_index_rcu(&init_net, entry->ifindex);
|
||||
if (!dev) {
|
||||
rcu_read_unlock();
|
||||
return -ENODEV;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
ret = get_mac_from_mdb_entry(entry, dmac);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (IS_ETH_GRP(dev) && !IS_DSA_LAN(dev)) {
|
||||
if (dev->netdev_ops->ndo_flow_offload_check) {
|
||||
hw_path.dev = dev;
|
||||
hw_path.virt_dev = dev;
|
||||
dev->netdev_ops->ndo_flow_offload_check(&hw_path);
|
||||
dev = hw_path.dev;
|
||||
}
|
||||
mac = netdev_priv(dev);
|
||||
port = (mac->id == MTK_GMAC1_ID) ? MCAST_TO_GDMA1 :
|
||||
(mac->id == MTK_GMAC2_ID) ? MCAST_TO_GDMA2 :
|
||||
(mac->id == MTK_GMAC3_ID) ? MCAST_TO_GDMA3 :
|
||||
-EINVAL;
|
||||
if (port < 0)
|
||||
return -1;
|
||||
} else {
|
||||
port = MCAST_TO_PDMA; /* to PDMA */
|
||||
}
|
||||
|
||||
write_lock(&hnat_priv->pmcast->mcast_lock);
|
||||
|
||||
pmcast_list = hnat_mcast_list_find(dmac, entry->vid);
|
||||
|
||||
switch (type) {
|
||||
case RTM_NEWMDB:
|
||||
if (!pmcast_list) {
|
||||
pmcast_list = kmalloc(sizeof(struct ppe_mcast_list), GFP_KERNEL);
|
||||
if (!pmcast_list) {
|
||||
write_unlock(&hnat_priv->pmcast->mcast_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
INIT_LIST_HEAD(&pmcast_list->list);
|
||||
memcpy(pmcast_list->dmac, dmac, ETH_ALEN);
|
||||
pmcast_list->vid = entry->vid;
|
||||
pmcast_list->mc_port = (1 << port);
|
||||
list_add_tail(&pmcast_list->list, &hnat_priv->pmcast->mlist);
|
||||
} else {
|
||||
pmcast_list->mc_port |= (1 << port);
|
||||
}
|
||||
break;
|
||||
case RTM_DELMDB:
|
||||
if (pmcast_list) {
|
||||
pmcast_list->mc_port &= ~(1 << port);
|
||||
if (pmcast_list->mc_port == 0) {
|
||||
list_del(&pmcast_list->list);
|
||||
kfree(pmcast_list);
|
||||
pmcast_list = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
write_unlock(&hnat_priv->pmcast->mcast_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
write_unlock(&hnat_priv->pmcast->mcast_lock);
|
||||
|
||||
entry_delete_by_mac(dmac);
|
||||
|
||||
if (debug_level >= 7)
|
||||
pr_info("%s_%s:devname=%s,mcast_port=%x, mac:%pM\n",
|
||||
__func__,
|
||||
(type == RTM_NEWMDB) ? "NEW" : "DEL", dev->name,
|
||||
(pmcast_list) ? pmcast_list->mc_port : 0, dmac);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hnat_mcast_nlmsg_handler(struct work_struct *work)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
@@ -209,13 +443,19 @@ static void hnat_mcast_nlmsg_handler(struct work_struct *work)
|
||||
}
|
||||
|
||||
entry = (struct br_mdb_entry *)nla_data(info);
|
||||
trace_printk("%s:cmd=0x%2x,ifindex=0x%x,state=0x%x",
|
||||
__func__, nlh->nlmsg_type,
|
||||
entry->ifindex, entry->state);
|
||||
trace_printk("vid=0x%x,ip=0x%x,proto=0x%x\n",
|
||||
entry->vid, entry->addr.u.ip4,
|
||||
entry->addr.proto);
|
||||
hnat_mcast_table_update(nlh->nlmsg_type, entry);
|
||||
if (debug_level >= 7) {
|
||||
trace_printk("%s:cmd=0x%2x,ifindex=0x%x,state=0x%x",
|
||||
__func__, nlh->nlmsg_type,
|
||||
entry->ifindex, entry->state);
|
||||
trace_printk("vid=0x%x,ip=0x%x,proto=0x%x\n",
|
||||
entry->vid, entry->addr.u.ip4,
|
||||
entry->addr.proto);
|
||||
}
|
||||
|
||||
if (IS_MCAST_MULTI_MODE)
|
||||
hnat_mcast_table_update(nlh->nlmsg_type, entry);
|
||||
|
||||
hnat_mcast_list_update(nlh->nlmsg_type, entry);
|
||||
}
|
||||
kfree_skb(skb);
|
||||
}
|
||||
@@ -267,7 +507,7 @@ static void hnat_mcast_check_timestamp(struct timer_list *t)
|
||||
entry = hnat_priv->foe_table_cpu[i] + hash_index;
|
||||
if (entry->bfib1.sta == 1) {
|
||||
e_ts = (entry->ipv4_hnapt.m_timestamp) & 0xffff;
|
||||
foe_ts = foe_timestamp(hnat_priv);
|
||||
foe_ts = foe_timestamp(hnat_priv, true);
|
||||
if ((foe_ts - e_ts) > 0x3000)
|
||||
foe_ts = (~(foe_ts)) & 0xffff;
|
||||
if (abs(foe_ts - e_ts) > 20)
|
||||
@@ -285,44 +525,54 @@ int hnat_mcast_enable(u32 ppe_id)
|
||||
if (ppe_id >= CFG_PPE_NUM)
|
||||
return -EINVAL;
|
||||
|
||||
pmcast = kzalloc(sizeof(*pmcast), GFP_KERNEL);
|
||||
if (!pmcast)
|
||||
return -1;
|
||||
if (!hnat_priv->pmcast) {
|
||||
pmcast = kzalloc(sizeof(*pmcast), GFP_KERNEL);
|
||||
if (!pmcast)
|
||||
return -1;
|
||||
|
||||
if (hnat_priv->data->version == MTK_HNAT_V1_1)
|
||||
pmcast->max_entry = 0x10;
|
||||
else
|
||||
pmcast->max_entry = MAX_MCAST_ENTRY;
|
||||
memset(pmcast->mtbl, 0, sizeof(struct ppe_mcast_group) * MAX_MCAST_ENTRY);
|
||||
|
||||
INIT_WORK(&pmcast->work, hnat_mcast_nlmsg_handler);
|
||||
pmcast->queue = create_singlethread_workqueue("ppe_mcast");
|
||||
if (!pmcast->queue)
|
||||
goto err1;
|
||||
/* Initialize multicast list for unicast mode */
|
||||
INIT_LIST_HEAD(&pmcast->mlist);
|
||||
rwlock_init(&pmcast->mcast_lock);
|
||||
|
||||
pmcast->msock = hnat_mcast_netlink_open(&init_net);
|
||||
if (!pmcast->msock)
|
||||
goto err2;
|
||||
if (hnat_priv->data->version == MTK_HNAT_V1_1)
|
||||
pmcast->max_entry = 0x10;
|
||||
else
|
||||
pmcast->max_entry = MAX_MCAST_ENTRY;
|
||||
|
||||
hnat_priv->pmcast = pmcast;
|
||||
INIT_WORK(&pmcast->work, hnat_mcast_nlmsg_handler);
|
||||
pmcast->queue = create_singlethread_workqueue("ppe_mcast");
|
||||
if (!pmcast->queue)
|
||||
goto err1;
|
||||
|
||||
/* mt7629 should checkout mcast entry life time manualy */
|
||||
if (hnat_priv->data->version == MTK_HNAT_V1_3) {
|
||||
timer_setup(&hnat_priv->hnat_mcast_check_timer,
|
||||
hnat_mcast_check_timestamp, 0);
|
||||
hnat_priv->hnat_mcast_check_timer.expires = jiffies;
|
||||
add_timer(&hnat_priv->hnat_mcast_check_timer);
|
||||
pmcast->msock = hnat_mcast_netlink_open(&init_net);
|
||||
if (!pmcast->msock)
|
||||
goto err2;
|
||||
|
||||
hnat_priv->pmcast = pmcast;
|
||||
|
||||
/* mt7629 should checkout mcast entry life time manualy */
|
||||
if (hnat_priv->data->version == MTK_HNAT_V1_3) {
|
||||
timer_setup(&hnat_priv->hnat_mcast_check_timer,
|
||||
hnat_mcast_check_timestamp, 0);
|
||||
hnat_priv->hnat_mcast_check_timer.expires = jiffies;
|
||||
add_timer(&hnat_priv->hnat_mcast_check_timer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable multicast table lookup */
|
||||
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_GLO_CFG, MCAST_TB_EN, 1);
|
||||
/* multicast port0 map to PDMA */
|
||||
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P0_PPSE, 0);
|
||||
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P0_PPSE, NR_PDMA_PORT);
|
||||
/* multicast port1 map to GMAC1 */
|
||||
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P1_PPSE, 1);
|
||||
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P1_PPSE, NR_GMAC1_PORT);
|
||||
/* multicast port2 map to GMAC2 */
|
||||
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P2_PPSE, 2);
|
||||
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P2_PPSE, NR_GMAC2_PORT);
|
||||
/* multicast port3 map to QDMA */
|
||||
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P3_PPSE, 5);
|
||||
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P3_PPSE, NR_QDMA_PORT);
|
||||
/* multicast port4 map to GMAC3 */
|
||||
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P4_PPSE, NR_GMAC3_PORT);
|
||||
|
||||
return 0;
|
||||
err2:
|
||||
@@ -337,6 +587,7 @@ err1:
|
||||
int hnat_mcast_disable(void)
|
||||
{
|
||||
struct ppe_mcast_table *pmcast = hnat_priv->pmcast;
|
||||
int i;
|
||||
|
||||
if (!pmcast)
|
||||
return -EINVAL;
|
||||
@@ -344,10 +595,16 @@ int hnat_mcast_disable(void)
|
||||
if (hnat_priv->data->version == MTK_HNAT_V1_3)
|
||||
del_timer_sync(&hnat_priv->hnat_mcast_check_timer);
|
||||
|
||||
/* Disable multicast table lookup */
|
||||
for (i = 0; i < CFG_PPE_NUM; i++)
|
||||
cr_set_field(hnat_priv->ppe_base[i] + PPE_GLO_CFG, MCAST_TB_EN, 0);
|
||||
|
||||
flush_work(&pmcast->work);
|
||||
destroy_workqueue(pmcast->queue);
|
||||
sock_release(pmcast->msock);
|
||||
hnat_mcast_list_del_all();
|
||||
kfree(pmcast);
|
||||
hnat_priv->pmcast = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -17,18 +17,20 @@
|
||||
#define RTMGRP_MDB 0x2000000
|
||||
|
||||
#define MAX_MCAST_ENTRY 64
|
||||
#define MAX_MCAST_PORT 5
|
||||
|
||||
#define MCAST_TO_PDMA (0x1 << 0)
|
||||
#define MCAST_TO_GDMA1 (0x1 << 1)
|
||||
#define MCAST_TO_GDMA2 (0x1 << 2)
|
||||
struct ppe_mcast_list {
|
||||
struct list_head list; /* Protected by rwlock */
|
||||
u16 vid; /* vlan id */
|
||||
u8 dmac[ETH_ALEN]; /* multicast mac addr */
|
||||
u8 mc_port; /* multicast port */
|
||||
};
|
||||
|
||||
struct ppe_mcast_group {
|
||||
u32 mac_hi; /*multicast mac addr*/
|
||||
u16 mac_lo; /*multicast mac addr*/
|
||||
u16 vid;
|
||||
u8 mc_port; /*1:forward to cpu,2:forward to GDMA1,4:forward to GDMA2*/
|
||||
u8 eif; /*num of eth if added to multi group. */
|
||||
u8 oif; /* num of other if added to multi group ,ex wifi.*/
|
||||
u8 dmac[ETH_ALEN]; /* multicast mac addr */
|
||||
u8 if_num[MAX_MCAST_PORT]; /* num of if added to multi group. */
|
||||
u8 mc_port; /* 1:forward to cpu,2:forward to GDMA1,3:forward to GDMA2 */
|
||||
bool valid;
|
||||
};
|
||||
|
||||
@@ -37,24 +39,22 @@ struct ppe_mcast_table {
|
||||
struct work_struct work;
|
||||
struct socket *msock;
|
||||
struct ppe_mcast_group mtbl[MAX_MCAST_ENTRY];
|
||||
struct list_head mlist;
|
||||
u8 max_entry;
|
||||
rwlock_t mcast_lock; /* Protect list and mc_port field */
|
||||
};
|
||||
|
||||
struct ppe_mcast_h {
|
||||
union {
|
||||
u32 value;
|
||||
struct {
|
||||
u32 mc_vid:12;
|
||||
u32 mc_qos_qid54:2; /* mt7622 only */
|
||||
u32 valid:1;
|
||||
u32 rev1:1;
|
||||
/*0:forward to cpu,1:forward to GDMA1*/
|
||||
u32 mc_px_en:4;
|
||||
u32 mc_mpre_sel:2; /* 0=01:00, 2=33:33 */
|
||||
u32 mc_vid_cmp:1;
|
||||
u32 rev2:1;
|
||||
u32 mc_px_qos_en:4;
|
||||
u32 mc_qos_qid:4;
|
||||
u32 mc_vid : 12;
|
||||
u32 mc_qos_qid64 : 3;
|
||||
u32 mc_px_en : 5;
|
||||
u32 mc_mpre_sel : 2; /* 0=01:00, 1=33:33 */
|
||||
u32 mc_vid_cmp: 1;
|
||||
u32 mc_px_qos_en : 5;
|
||||
u32 mc_qos_qid : 4;
|
||||
} info;
|
||||
} u;
|
||||
};
|
||||
@@ -63,7 +63,29 @@ struct ppe_mcast_l {
|
||||
u32 addr;
|
||||
};
|
||||
|
||||
enum ppe_mcast_port {
|
||||
MCAST_TO_GDMA3,
|
||||
MCAST_TO_PDMA,
|
||||
MCAST_TO_GDMA1,
|
||||
MCAST_TO_GDMA2,
|
||||
MCAST_TO_QDMA,
|
||||
};
|
||||
|
||||
enum hnat_mcast_mode {
|
||||
HNAT_MCAST_MODE_MULTI = 0,
|
||||
HNAT_MCAST_MODE_UNI,
|
||||
};
|
||||
|
||||
#define IS_MCAST_MULTI_MODE (hnat_priv->data->mcast && mcast_mode == HNAT_MCAST_MODE_MULTI)
|
||||
#define IS_MCAST_UNI_MODE (hnat_priv->data->mcast && mcast_mode == HNAT_MCAST_MODE_UNI)
|
||||
#define IS_MCAST_PORT_GDM(port) \
|
||||
(port == (1 << MCAST_TO_GDMA1) || port == (1 << MCAST_TO_GDMA2) || \
|
||||
port == (1 << MCAST_TO_GDMA3))
|
||||
#define DMAC_TO_HI16(dmac) ((dmac[0] << 8) | dmac[1])
|
||||
#define DMAC_TO_LO32(dmac) ((dmac[2] << 24) | (dmac[3] << 16) | (dmac[4] << 8) | dmac[5])
|
||||
|
||||
int hnat_mcast_enable(u32 ppe_id);
|
||||
int hnat_mcast_disable(void);
|
||||
bool hnat_is_mcast_uni(struct sk_buff *skb);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,58 +6,110 @@
|
||||
|
||||
#include <linux/of_device.h>
|
||||
#include <net/netfilter/nf_flow_table.h>
|
||||
|
||||
#include "hnat.h"
|
||||
|
||||
u32 hnat_dsa_fill_stag(const struct net_device *netdev,
|
||||
int hnat_dsa_get_port(struct net_device **dev)
|
||||
{
|
||||
#if defined(CONFIG_NET_DSA)
|
||||
struct dsa_port *dp;
|
||||
|
||||
dp = dsa_port_from_netdev(*dev);
|
||||
if (IS_ERR(dp))
|
||||
return -ENODEV;
|
||||
|
||||
*dev = dp->cpu_dp->master;
|
||||
|
||||
return dp->index;
|
||||
#else
|
||||
return -ENODEV;
|
||||
#endif
|
||||
}
|
||||
|
||||
int hnat_dsa_fill_stag(const struct net_device *netdev,
|
||||
struct foe_entry *entry,
|
||||
struct flow_offload_hw_path *hw_path,
|
||||
u16 eth_proto,
|
||||
int mape)
|
||||
{
|
||||
const struct net_device *ndev;
|
||||
#if defined(CONFIG_NET_DSA)
|
||||
const unsigned int *port_reg;
|
||||
const struct dsa_port *dp;
|
||||
struct net_device *ndev;
|
||||
int port_index;
|
||||
u16 sp_tag;
|
||||
u16 dsa_tag;
|
||||
|
||||
if (hw_path->flags & FLOW_OFFLOAD_PATH_VLAN)
|
||||
if (hw_path->flags & BIT(DEV_PATH_VLAN))
|
||||
ndev = hw_path->dev;
|
||||
else
|
||||
ndev = netdev;
|
||||
ndev = (struct net_device *)netdev;
|
||||
|
||||
port_reg = of_get_property(ndev->dev.of_node, "reg", NULL);
|
||||
if (unlikely(!port_reg))
|
||||
return -EINVAL;
|
||||
|
||||
port_index = be32_to_cpup(port_reg);
|
||||
sp_tag = BIT(port_index);
|
||||
|
||||
if (!entry->bfib1.vlan_layer)
|
||||
entry->bfib1.vlan_layer = 1;
|
||||
else
|
||||
/* VLAN existence indicator */
|
||||
sp_tag |= BIT(8);
|
||||
entry->bfib1.vpm = 0;
|
||||
/* In the case MAPE LAN --> WAN, binding entry is to CPU.
|
||||
* Do not add special tag.
|
||||
*/
|
||||
if (IS_WAN(ndev) && mape)
|
||||
return port_index;
|
||||
|
||||
switch (eth_proto) {
|
||||
case ETH_P_IP:
|
||||
if (entry->ipv4_hnapt.bfib1.pkt_type == IPV4_DSLITE
|
||||
|| (entry->ipv4_hnapt.bfib1.pkt_type == IPV4_MAP_E))
|
||||
entry->ipv4_dslite.etype = sp_tag;
|
||||
dp = dsa_port_from_netdev(ndev);
|
||||
if (IS_ERR(dp))
|
||||
return -ENODEV;
|
||||
|
||||
if (IS_DSA_TAG_PROTO_MXL862_8021Q(dp)) {
|
||||
dsa_tag = port_index + BIT(11);
|
||||
|
||||
if (IS_IPV4_GRP(entry)) {
|
||||
/* PPE can only be filled up to 2 VLAN layers,
|
||||
* outer VLAN(vlan1) is preserved for stag.
|
||||
*/
|
||||
if (unlikely(entry->ipv4_hnapt.vlan2))
|
||||
return -EINVAL;
|
||||
else if (entry->ipv4_hnapt.vlan1)
|
||||
/* Move to inner VLAN if it's already set */
|
||||
entry->ipv4_hnapt.vlan2 = entry->ipv4_hnapt.vlan1;
|
||||
entry->ipv4_hnapt.vlan1 = dsa_tag;
|
||||
|
||||
entry->bfib1.vlan_layer = (entry->ipv4_hnapt.vlan1 != 0) +
|
||||
(entry->ipv4_hnapt.vlan2 != 0);
|
||||
} else {
|
||||
if (unlikely(entry->ipv6_5t_route.vlan2))
|
||||
return -EINVAL;
|
||||
else if (entry->ipv6_5t_route.vlan1)
|
||||
/* Move to inner VLAN if it's already set */
|
||||
entry->ipv6_5t_route.vlan2 = entry->ipv6_5t_route.vlan1;
|
||||
entry->ipv6_5t_route.vlan1 = dsa_tag;
|
||||
|
||||
entry->bfib1.vlan_layer = (entry->ipv6_5t_route.vlan1 != 0) +
|
||||
(entry->ipv6_5t_route.vlan2 != 0);
|
||||
}
|
||||
|
||||
entry->bfib1.vpm = 1;
|
||||
} else {
|
||||
dsa_tag = BIT(port_index);
|
||||
|
||||
if (!entry->bfib1.vlan_layer)
|
||||
entry->bfib1.vlan_layer = 1;
|
||||
else
|
||||
entry->ipv4_hnapt.etype = sp_tag;
|
||||
break;
|
||||
case ETH_P_IPV6:
|
||||
/* In the case MAPE LAN --> WAN, binding entry is to CPU.
|
||||
* Do not add special tag.
|
||||
*/
|
||||
if (!mape)
|
||||
/* etype offset of ipv6 entries are the same. */
|
||||
entry->ipv6_5t_route.etype = sp_tag;
|
||||
/* VLAN existence indicator */
|
||||
dsa_tag |= BIT(8);
|
||||
|
||||
break;
|
||||
default:
|
||||
pr_info("DSA + HNAT unsupport protocol\n");
|
||||
if (IS_IPV4_GRP(entry))
|
||||
entry->ipv4_hnapt.sp_tag = dsa_tag;
|
||||
else if (IS_IPV6_GRP(entry))
|
||||
entry->ipv6_5t_route.sp_tag = dsa_tag;
|
||||
else if (IS_L2_BRIDGE(entry))
|
||||
entry->l2_bridge.sp_tag = dsa_tag;
|
||||
|
||||
entry->bfib1.vpm = 0;
|
||||
}
|
||||
|
||||
return port_index;
|
||||
#else
|
||||
return -EINVAL;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -44,7 +44,11 @@ struct hnat_desc {
|
||||
u32 is_sp : 1;
|
||||
u32 hf : 1;
|
||||
u32 amsdu : 1;
|
||||
u32 resv3 : 19;
|
||||
u32 tops : 6;
|
||||
u32 is_decap : 1;
|
||||
u32 cdrt : 8;
|
||||
u32 is_decrypt : 1;
|
||||
u32 resv3 : 3;
|
||||
u32 magic_tag_protect : 16;
|
||||
} __packed;
|
||||
#elif defined(CONFIG_MEDIATEK_NETSYS_RX_V2)
|
||||
@@ -85,12 +89,36 @@ struct hnat_desc {
|
||||
#define HAS_HQOS_MAGIC_TAG(skb) (qos_toggle && skb->protocol == HQOS_MAGIC_TAG)
|
||||
|
||||
#define HNAT_MAGIC_TAG 0x6789
|
||||
#define HNAT_INFO_FILLED 0x7
|
||||
#define WIFI_INFO_LEN 6
|
||||
#define FOE_INFO_LEN (10 + WIFI_INFO_LEN)
|
||||
#define IS_SPACE_AVAILABLE_HEAD(skb) \
|
||||
((((skb_headroom(skb) >= FOE_INFO_LEN) ? 1 : 0)))
|
||||
|
||||
#define skb_hnat_info(skb) ((struct hnat_desc *)(skb->head))
|
||||
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
|
||||
#define skb_hnat_tops(skb) (((struct hnat_desc *)((skb)->head))->tops)
|
||||
#define skb_hnat_is_decap(skb) (((struct hnat_desc *)((skb)->head))->is_decap)
|
||||
#define skb_hnat_is_encap(skb) (!skb_hnat_is_decap(skb))
|
||||
#define skb_hnat_set_tops(skb, tops) ((skb_hnat_tops(skb)) = (tops))
|
||||
#define skb_hnat_set_is_decap(skb, is_decap) ((skb_hnat_is_decap(skb)) = (is_decap))
|
||||
#define skb_hnat_cdrt(skb) (((struct hnat_desc *)((skb)->head))->cdrt)
|
||||
#define skb_hnat_is_decrypt(skb) (((struct hnat_desc *)((skb)->head))->is_decrypt)
|
||||
#define skb_hnat_is_encrypt(skb) (!skb_hnat_is_decrypt(skb))
|
||||
#define skb_hnat_set_cdrt(skb, cdrt) ((skb_hnat_cdrt(skb)) = (cdrt))
|
||||
#define skb_hnat_set_is_decrypt(skb, is_dec) ((skb_hnat_is_decrypt(skb)) = is_dec)
|
||||
#else /* !defined(CONFIG_MEDIATEK_NETSYS_V3) */
|
||||
#define skb_hnat_tops(skb) (0)
|
||||
#define skb_hnat_is_decap(skb) (0)
|
||||
#define skb_hnat_is_encap(skb) (0)
|
||||
#define skb_hnat_set_tops(skb, tops)
|
||||
#define skb_hnat_set_is_decap(skb, is_decap)
|
||||
#define skb_hnat_cdrt(skb) (0)
|
||||
#define skb_hnat_is_decrypt(skb) (0)
|
||||
#define skb_hnat_is_encrypt(skb) (0)
|
||||
#define skb_hnat_set_cdrt(skb, cdrt)
|
||||
#define skb_hnat_set_is_decrypt(skb, is_dec)
|
||||
#endif /* defined(CONFIG_MEDIATEK_NETSYS_V3) */
|
||||
#define skb_hnat_magic(skb) (((struct hnat_desc *)(skb->head))->magic)
|
||||
#define skb_hnat_reason(skb) (((struct hnat_desc *)(skb->head))->crsn)
|
||||
#define skb_hnat_entry(skb) (((struct hnat_desc *)(skb->head))->entry)
|
||||
@@ -134,6 +162,7 @@ struct hnat_desc {
|
||||
#define set_to_ppe(skb) (HNAT_SKB_CB2(skb)->magic = 0x78681415)
|
||||
#define is_from_extge(skb) (HNAT_SKB_CB2(skb)->magic == 0x78786688)
|
||||
#define is_magic_tag_valid(skb) (skb_hnat_magic_tag(skb) == HNAT_MAGIC_TAG)
|
||||
#define is_hnat_info_filled(skb) (skb_hnat_filled(skb) == HNAT_INFO_FILLED)
|
||||
#define set_from_mape(skb) (HNAT_SKB_CB2(skb)->magic = 0x78787788)
|
||||
#define is_from_mape(skb) (HNAT_SKB_CB2(skb)->magic == 0x78787788)
|
||||
#define is_unreserved_port(hdr) \
|
||||
@@ -164,6 +193,8 @@ struct hnat_desc {
|
||||
#define HIT_PRE_BIND 0x1A
|
||||
#define HIT_BIND_PACKET_SAMPLING 0x1B
|
||||
#define HIT_BIND_EXCEED_MTU 0x1C
|
||||
#define IPVERSION_V4 0x04
|
||||
#define IPVERSION_V6 0x06
|
||||
|
||||
#define TPORT_ID(x) ((x) & GENMASK(3, 0))
|
||||
#define TOPS_ENTRY(x) ((x) & GENMASK(5, 0))
|
||||
|
||||
@@ -45,7 +45,7 @@ static int mtk_sgmii_xfi_pll_init(struct mtk_sgmii *ss, struct device_node *r)
|
||||
|
||||
np = of_parse_phandle(r, "mediatek,xfi_pll", 0);
|
||||
if (!np)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
ss->pll = syscon_node_to_regmap(np);
|
||||
if (IS_ERR(ss->pll))
|
||||
@@ -77,96 +77,142 @@ int mtk_sgmii_link_status(struct mtk_sgmii_pcs *mpcs)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
mutex_lock(&mpcs->reset_lock);
|
||||
|
||||
regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
|
||||
|
||||
mutex_unlock(&mpcs->reset_lock);
|
||||
|
||||
return FIELD_GET(SGMII_LINK_STATYS, val);
|
||||
}
|
||||
|
||||
void mtk_sgmii_reset(struct mtk_eth *eth, int id)
|
||||
static void mtk_sgmii_get_state(struct mtk_sgmii_pcs *mpcs)
|
||||
{
|
||||
struct phylink_link_state *state = &mpcs->state;
|
||||
unsigned int bm, adv, rgc3, sgm_mode;
|
||||
|
||||
mutex_lock(&mpcs->reset_lock);
|
||||
|
||||
state->interface = mpcs->interface;
|
||||
|
||||
regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm);
|
||||
if (bm & SGMII_AN_ENABLE) {
|
||||
regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv);
|
||||
|
||||
phylink_mii_c22_pcs_decode_state(state,
|
||||
FIELD_GET(SGMII_BMSR, bm),
|
||||
FIELD_GET(SGMII_LPA, adv));
|
||||
} else {
|
||||
state->link = !!(bm & SGMII_LINK_STATYS);
|
||||
|
||||
regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &sgm_mode);
|
||||
|
||||
switch (sgm_mode & SGMII_SPEED_MASK) {
|
||||
case SGMII_SPEED_10:
|
||||
state->speed = SPEED_10;
|
||||
break;
|
||||
case SGMII_SPEED_100:
|
||||
state->speed = SPEED_100;
|
||||
break;
|
||||
case SGMII_SPEED_1000:
|
||||
regmap_read(mpcs->regmap, mpcs->ana_rgc3, &rgc3);
|
||||
rgc3 = FIELD_GET(RG_PHY_SPEED_3_125G, rgc3);
|
||||
state->speed = rgc3 ? SPEED_2500 : SPEED_1000;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sgm_mode & SGMII_DUPLEX_HALF)
|
||||
state->duplex = DUPLEX_HALF;
|
||||
else
|
||||
state->duplex = DUPLEX_FULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&mpcs->reset_lock);
|
||||
}
|
||||
|
||||
void mtk_sgmii_reset(struct mtk_sgmii_pcs *mpcs)
|
||||
{
|
||||
struct mtk_eth *eth = mpcs->eth;
|
||||
int id = mpcs->id;
|
||||
u32 val = 0;
|
||||
|
||||
if (!eth->toprgu)
|
||||
if (id >= MTK_MAX_DEVS || !eth->toprgu)
|
||||
return;
|
||||
|
||||
mutex_lock(&mpcs->reset_lock);
|
||||
|
||||
switch (id) {
|
||||
case 0:
|
||||
/* Enable software reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
|
||||
val |= SWSYSRST_XFI_PEXPT0_GRST |
|
||||
SWSYSRST_SGMII0_GRST;
|
||||
val |= SWSYSRST_SGMII0_GRST;
|
||||
if (mpcs->regmap_pextp)
|
||||
val |= SWSYSRST_XFI_PEXPT0_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
|
||||
|
||||
/* Assert SGMII reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
|
||||
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
|
||||
SWSYSRST_XFI_PEXPT0_GRST |
|
||||
SWSYSRST_SGMII0_GRST;
|
||||
if (mpcs->regmap_pextp)
|
||||
val |= SWSYSRST_XFI_PEXPT0_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
|
||||
|
||||
udelay(100);
|
||||
usleep_range(100, 500);
|
||||
|
||||
/* De-assert SGMII reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
|
||||
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
|
||||
val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
|
||||
SWSYSRST_SGMII0_GRST);
|
||||
val &= ~SWSYSRST_SGMII0_GRST;
|
||||
if (mpcs->regmap_pextp)
|
||||
val &= ~SWSYSRST_XFI_PEXPT0_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
|
||||
|
||||
/* Disable software reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
|
||||
val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
|
||||
SWSYSRST_SGMII0_GRST);
|
||||
val &= ~SWSYSRST_SGMII0_GRST;
|
||||
if (mpcs->regmap_pextp)
|
||||
val &= ~SWSYSRST_XFI_PEXPT0_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
|
||||
break;
|
||||
case 1:
|
||||
/* Enable software reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
|
||||
val |= SWSYSRST_XFI_PEXPT1_GRST |
|
||||
SWSYSRST_SGMII1_GRST;
|
||||
val |= SWSYSRST_SGMII1_GRST;
|
||||
if (mpcs->regmap_pextp)
|
||||
val |= SWSYSRST_XFI_PEXPT1_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
|
||||
|
||||
/* Assert SGMII reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
|
||||
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
|
||||
SWSYSRST_XFI_PEXPT1_GRST |
|
||||
SWSYSRST_SGMII1_GRST;
|
||||
if (mpcs->regmap_pextp)
|
||||
val |= SWSYSRST_XFI_PEXPT1_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
|
||||
|
||||
udelay(100);
|
||||
usleep_range(100, 500);
|
||||
|
||||
/* De-assert SGMII reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
|
||||
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
|
||||
val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
|
||||
SWSYSRST_SGMII1_GRST);
|
||||
val &= ~SWSYSRST_SGMII1_GRST;
|
||||
if (mpcs->regmap_pextp)
|
||||
val &= ~SWSYSRST_XFI_PEXPT1_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
|
||||
|
||||
/* Disable software reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
|
||||
val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
|
||||
SWSYSRST_SGMII1_GRST);
|
||||
val &= ~SWSYSRST_SGMII1_GRST;
|
||||
if (mpcs->regmap_pextp)
|
||||
val &= ~SWSYSRST_XFI_PEXPT1_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
|
||||
break;
|
||||
}
|
||||
|
||||
mdelay(1);
|
||||
}
|
||||
mutex_unlock(&mpcs->reset_lock);
|
||||
|
||||
int mtk_sgmii_need_powerdown(struct mtk_sgmii_pcs *mpcs, unsigned int bmcr)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* need to power down sgmii if link down */
|
||||
regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
|
||||
if (!(val & SGMII_LINK_STATYS))
|
||||
return true;
|
||||
|
||||
/* need to power down sgmii if autoneg change */
|
||||
if ((val & SGMII_AN_ENABLE) != bmcr)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
usleep_range(10000, 11000);
|
||||
}
|
||||
|
||||
void mtk_sgmii_setup_phya_gen1(struct mtk_sgmii_pcs *mpcs)
|
||||
@@ -226,7 +272,7 @@ void mtk_sgmii_setup_phya_gen1(struct mtk_sgmii_pcs *mpcs)
|
||||
/* Force AEQ on */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x02002800);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
|
||||
0x20000000);
|
||||
/* Setup DA default value */
|
||||
@@ -257,28 +303,28 @@ void mtk_sgmii_setup_phya_gen1(struct mtk_sgmii_pcs *mpcs)
|
||||
/* Release reset */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200E800);
|
||||
udelay(150);
|
||||
usleep_range(150, 500);
|
||||
/* Switch to P0 */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200C111);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200C101);
|
||||
udelay(15);
|
||||
usleep_range(15, 50);
|
||||
/* Switch to Gen2 */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0201C111);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0201C101);
|
||||
udelay(100);
|
||||
usleep_range(100, 500);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
|
||||
0x00000030);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
|
||||
0x80201F01);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
|
||||
0x30000000);
|
||||
udelay(400);
|
||||
usleep_range(400, 1000);
|
||||
}
|
||||
|
||||
void mtk_sgmii_setup_phya_gen2(struct mtk_sgmii_pcs *mpcs)
|
||||
@@ -338,7 +384,7 @@ void mtk_sgmii_setup_phya_gen2(struct mtk_sgmii_pcs *mpcs)
|
||||
/* Force AEQ on */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x02002800);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
|
||||
0x20000000);
|
||||
/* Setup DA default value */
|
||||
@@ -367,28 +413,28 @@ void mtk_sgmii_setup_phya_gen2(struct mtk_sgmii_pcs *mpcs)
|
||||
/* Release reset */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200E800);
|
||||
udelay(150);
|
||||
usleep_range(150, 500);
|
||||
/* Switch to P0 */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200C111);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200C101);
|
||||
udelay(15);
|
||||
usleep_range(15, 50);
|
||||
/* Switch to Gen2 */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0201C111);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0201C101);
|
||||
udelay(100);
|
||||
usleep_range(100, 500);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
|
||||
0x00000030);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
|
||||
0x80201F01);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
|
||||
0x30000000);
|
||||
udelay(400);
|
||||
usleep_range(400, 1000);
|
||||
}
|
||||
|
||||
static int mtk_sgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
|
||||
@@ -407,8 +453,6 @@ static int mtk_sgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
|
||||
if (advertise < 0)
|
||||
return advertise;
|
||||
|
||||
spin_lock(&mpcs->regmap_lock);
|
||||
|
||||
/* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and
|
||||
* we assume that fixes it's speed at bitrate = line rate (in
|
||||
* other words, 1000Mbps or 2500Mbps).
|
||||
@@ -432,55 +476,63 @@ static int mtk_sgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
|
||||
speed = SGMII_SPEED_1000;
|
||||
}
|
||||
|
||||
if (mpcs->interface != interface ||
|
||||
mtk_sgmii_need_powerdown(mpcs, bmcr)) {
|
||||
link_timer = phylink_get_link_timer_ns(interface);
|
||||
if (link_timer < 0) {
|
||||
spin_unlock(&mpcs->regmap_lock);
|
||||
return link_timer;
|
||||
}
|
||||
link_timer = phylink_get_link_timer_ns(interface);
|
||||
if (link_timer < 0)
|
||||
return link_timer;
|
||||
|
||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
|
||||
mtk_sgmii_xfi_pll_enable(eth->sgmii);
|
||||
mtk_sgmii_reset(eth, mpcs->id);
|
||||
}
|
||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
|
||||
mtk_sgmii_xfi_pll_enable(eth->sgmii);
|
||||
mtk_sgmii_reset(mpcs);
|
||||
}
|
||||
|
||||
/* PHYA power down */
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
|
||||
SGMII_PHYA_PWD, SGMII_PHYA_PWD);
|
||||
|
||||
/* Reset SGMII PCS state */
|
||||
regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0,
|
||||
SGMII_SW_RESET, SGMII_SW_RESET);
|
||||
|
||||
/* Configure the interface polarity */
|
||||
if (MTK_HAS_FLAGS(mpcs->flags, MTK_SGMII_PN_SWAP))
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL,
|
||||
SGMII_PN_SWAP_MASK,
|
||||
SGMII_PN_SWAP_TX_RX);
|
||||
|
||||
if (interface == PHY_INTERFACE_MODE_2500BASEX)
|
||||
rgc3 = RG_PHY_SPEED_3_125G;
|
||||
else
|
||||
rgc3 = 0;
|
||||
|
||||
/* Configure the underlying interface speed */
|
||||
regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
|
||||
RG_PHY_SPEED_3_125G, rgc3);
|
||||
|
||||
/* Setup the link timer */
|
||||
regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
|
||||
link_timer / 2 / 8);
|
||||
mutex_lock(&mpcs->regmap_lock);
|
||||
|
||||
if (mode <= MLO_AN_INBAND && mpcs->interface != interface) {
|
||||
mpcs->interface = interface;
|
||||
mpcs->mode = mode;
|
||||
linkmode_copy(mpcs->advertising, advertising);
|
||||
mode_changed = true;
|
||||
}
|
||||
|
||||
/* PHYA power down */
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
|
||||
SGMII_PHYA_PWD, SGMII_PHYA_PWD);
|
||||
|
||||
/* Reset SGMII PCS state */
|
||||
regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0,
|
||||
SGMII_SW_RESET, SGMII_SW_RESET);
|
||||
|
||||
/* Configure the interface polarity */
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL,
|
||||
SGMII_PN_SWAP_MASK, mpcs->polarity);
|
||||
|
||||
if (interface == PHY_INTERFACE_MODE_2500BASEX)
|
||||
rgc3 = RG_PHY_SPEED_3_125G;
|
||||
else
|
||||
rgc3 = 0;
|
||||
|
||||
/* Configure the underlying interface speed */
|
||||
regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
|
||||
RG_PHY_SPEED_3_125G, rgc3);
|
||||
|
||||
/* Setup the link timer */
|
||||
regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
|
||||
link_timer / 2 / 8);
|
||||
|
||||
/* Update the advertisement, noting whether it has changed */
|
||||
regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
|
||||
SGMII_ADVERTISE, advertise, &changed);
|
||||
|
||||
if (eth->soc->caps == MT7987_CAPS) {
|
||||
/* Change the sgmsys clock source from PHYA */
|
||||
bmcr |= SGMII_PCS_REF_CK_SEL;
|
||||
|
||||
/* Change the sgmsys tx/rx buffer threshold */
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
|
||||
SGMII_TRX_BUF_THR_MASK,
|
||||
FIELD_PREP(SGMII_TRX_BUF_THR_MASK, 0x2111));
|
||||
}
|
||||
|
||||
/* Update the sgmsys mode register */
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
|
||||
SGMII_REMOTE_FAULT_DIS | SGMII_DUPLEX_HALF |
|
||||
@@ -489,74 +541,94 @@ static int mtk_sgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
|
||||
|
||||
/* Update the BMCR */
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
|
||||
SGMII_AN_ENABLE, bmcr);
|
||||
SGMII_AN_ENABLE | SGMII_PCS_REF_CK_SEL, bmcr);
|
||||
|
||||
/* Release PHYA power down state */
|
||||
usleep_range(50, 100);
|
||||
regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
|
||||
|
||||
if (mode_changed) {
|
||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
|
||||
if (interface == PHY_INTERFACE_MODE_2500BASEX)
|
||||
mtk_sgmii_setup_phya_gen2(mpcs);
|
||||
else
|
||||
mtk_sgmii_setup_phya_gen1(mpcs);
|
||||
}
|
||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
|
||||
if (interface == PHY_INTERFACE_MODE_2500BASEX)
|
||||
mtk_sgmii_setup_phya_gen2(mpcs);
|
||||
else
|
||||
mtk_sgmii_setup_phya_gen1(mpcs);
|
||||
}
|
||||
|
||||
spin_unlock(&mpcs->regmap_lock);
|
||||
mutex_unlock(&mpcs->regmap_lock);
|
||||
|
||||
return changed || mode_changed;
|
||||
}
|
||||
|
||||
static void mtk_sgmii_pcs_link_poll(struct work_struct *work)
|
||||
{
|
||||
struct mtk_sgmii_pcs *mpcs = container_of(work, struct mtk_sgmii_pcs,
|
||||
link_poll.work);
|
||||
|
||||
if ((mpcs->interface != PHY_INTERFACE_MODE_SGMII &&
|
||||
mpcs->interface != PHY_INTERFACE_MODE_1000BASEX &&
|
||||
mpcs->interface != PHY_INTERFACE_MODE_2500BASEX) ||
|
||||
(mpcs->link_poll_enable == false))
|
||||
goto exit;
|
||||
|
||||
if (!mtk_sgmii_link_status(mpcs))
|
||||
mtk_sgmii_pcs_config(&mpcs->pcs, UINT_MAX, mpcs->interface,
|
||||
mpcs->advertising, false);
|
||||
|
||||
exit:
|
||||
if (mpcs->mode == MLO_AN_INBAND)
|
||||
mtk_sgmii_get_state(mpcs);
|
||||
else if (!delayed_work_pending(&mpcs->link_poll))
|
||||
schedule_delayed_work(&mpcs->link_poll, msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
static int mtk_sgmii_pcs_enable(struct phylink_pcs *pcs)
|
||||
{
|
||||
struct mtk_sgmii_pcs *mpcs = pcs_to_mtk_sgmii_pcs(pcs);
|
||||
|
||||
if (!delayed_work_pending(&mpcs->link_poll))
|
||||
schedule_delayed_work(&mpcs->link_poll, msecs_to_jiffies(1000));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_sgmii_pcs_disable(struct phylink_pcs *pcs)
|
||||
{
|
||||
struct mtk_sgmii_pcs *mpcs = pcs_to_mtk_sgmii_pcs(pcs);
|
||||
|
||||
cancel_delayed_work_sync(&mpcs->link_poll);
|
||||
|
||||
if (mpcs->mode == MLO_AN_INBAND)
|
||||
mtk_sgmii_get_state(mpcs);
|
||||
}
|
||||
|
||||
static void mtk_sgmii_pcs_get_state(struct phylink_pcs *pcs,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
struct mtk_sgmii_pcs *mpcs = pcs_to_mtk_sgmii_pcs(pcs);
|
||||
unsigned int bm, adv, rgc3, sgm_mode;
|
||||
static unsigned long t_start;
|
||||
|
||||
state->interface = mpcs->interface;
|
||||
/* Passing the advertising and lp_advertising parameters to
|
||||
* phylink_mii_c22_pcs_decode_state()in mtk_sgmii_get_state().
|
||||
*/
|
||||
linkmode_copy(mpcs->state.advertising, state->advertising);
|
||||
linkmode_copy(mpcs->state.lp_advertising, state->lp_advertising);
|
||||
|
||||
regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm);
|
||||
if (bm & SGMII_AN_ENABLE) {
|
||||
regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv);
|
||||
|
||||
phylink_mii_c22_pcs_decode_state(state,
|
||||
FIELD_GET(SGMII_BMSR, bm),
|
||||
FIELD_GET(SGMII_LPA, adv));
|
||||
} else {
|
||||
state->link = !!(bm & SGMII_LINK_STATYS);
|
||||
|
||||
regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &sgm_mode);
|
||||
|
||||
switch (sgm_mode & SGMII_SPEED_MASK) {
|
||||
case SGMII_SPEED_10:
|
||||
state->speed = SPEED_10;
|
||||
break;
|
||||
case SGMII_SPEED_100:
|
||||
state->speed = SPEED_100;
|
||||
break;
|
||||
case SGMII_SPEED_1000:
|
||||
regmap_read(mpcs->regmap, mpcs->ana_rgc3, &rgc3);
|
||||
rgc3 = FIELD_GET(RG_PHY_SPEED_3_125G, rgc3);
|
||||
state->speed = rgc3 ? SPEED_2500 : SPEED_1000;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sgm_mode & SGMII_DUPLEX_HALF)
|
||||
state->duplex = DUPLEX_HALF;
|
||||
else
|
||||
state->duplex = DUPLEX_FULL;
|
||||
}
|
||||
/* When the interface of the mpcs is not initialized,
|
||||
* we should avoid overriding the state interface.
|
||||
*/
|
||||
if (mpcs->state.interface != PHY_INTERFACE_MODE_NA)
|
||||
state->interface = mpcs->state.interface;
|
||||
state->speed = mpcs->state.speed;
|
||||
state->duplex = mpcs->state.duplex;
|
||||
state->link = mpcs->state.link;
|
||||
|
||||
/* Reconfiguring SGMII every second to ensure that PCS can
|
||||
* link up with the Link Partner when a module is inserted.
|
||||
*/
|
||||
if (state->link == 0 && time_after(jiffies, t_start + HZ)) {
|
||||
t_start = jiffies;
|
||||
mtk_sgmii_pcs_config(pcs, MLO_AN_INBAND,
|
||||
state->interface, mpcs->advertising, false);
|
||||
if (time_after(jiffies, mpcs->link_poll_expire) &&
|
||||
!delayed_work_pending(&mpcs->link_poll)) {
|
||||
mpcs->link_poll_expire = jiffies + HZ;
|
||||
mpcs->state.an_enabled = state->an_enabled;
|
||||
schedule_delayed_work(&mpcs->link_poll, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,21 +650,20 @@ static void mtk_sgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
|
||||
int speed, int duplex)
|
||||
{
|
||||
struct mtk_sgmii_pcs *mpcs = pcs_to_mtk_sgmii_pcs(pcs);
|
||||
struct device *dev = mpcs->eth->dev;
|
||||
unsigned int sgm_mode, val;
|
||||
unsigned long t_start = jiffies;
|
||||
|
||||
do {
|
||||
msleep(1000);
|
||||
msleep(100);
|
||||
|
||||
if (mtk_sgmii_link_status(mpcs))
|
||||
goto exit;
|
||||
|
||||
if (mode != MLO_AN_INBAND)
|
||||
mtk_sgmii_pcs_config(&mpcs->pcs, mode,
|
||||
interface, mpcs->advertising, false);
|
||||
} while (time_before(jiffies, t_start + msecs_to_jiffies(3000)));
|
||||
|
||||
pr_warn("%s wait link up timeout!\n", __func__);
|
||||
dev_warn(dev, "sgmii%d: wait link up timeout!\n", mpcs->id);
|
||||
return;
|
||||
|
||||
exit:
|
||||
/* If autoneg is enabled, the force speed and duplex
|
||||
@@ -620,6 +691,8 @@ exit:
|
||||
|
||||
static const struct phylink_pcs_ops mtk_sgmii_pcs_ops = {
|
||||
.pcs_config = mtk_sgmii_pcs_config,
|
||||
.pcs_enable = mtk_sgmii_pcs_enable,
|
||||
.pcs_disable = mtk_sgmii_pcs_disable,
|
||||
.pcs_get_state = mtk_sgmii_pcs_get_state,
|
||||
.pcs_an_restart = mtk_sgmii_pcs_restart_an,
|
||||
.pcs_link_up = mtk_sgmii_pcs_link_up,
|
||||
@@ -644,15 +717,27 @@ int mtk_sgmii_init(struct mtk_eth *eth, struct device_node *r, u32 ana_rgc3)
|
||||
if (IS_ERR(ss->pcs[i].regmap))
|
||||
return PTR_ERR(ss->pcs[i].regmap);
|
||||
|
||||
ss->pcs[i].flags &= ~(MTK_SGMII_PN_SWAP);
|
||||
ss->pcs[i].polarity = 0;
|
||||
if (of_property_read_bool(np, "pn_swap"))
|
||||
ss->pcs[i].flags |= MTK_SGMII_PN_SWAP;
|
||||
ss->pcs[i].polarity |= SGMII_PN_SWAP_TX | SGMII_PN_SWAP_RX;
|
||||
else if (of_property_read_bool(np, "pn_swap_tx"))
|
||||
ss->pcs[i].polarity |= SGMII_PN_SWAP_TX;
|
||||
else if (of_property_read_bool(np, "pn_swap_rx"))
|
||||
ss->pcs[i].polarity |= SGMII_PN_SWAP_RX;
|
||||
|
||||
ss->pcs[i].pcs.ops = &mtk_sgmii_pcs_ops;
|
||||
ss->pcs[i].pcs.poll = true;
|
||||
ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
|
||||
|
||||
spin_lock_init(&ss->pcs[i].regmap_lock);
|
||||
ss->pcs[i].state.link = 0;
|
||||
ss->pcs[i].state.duplex = DUPLEX_FULL;
|
||||
ss->pcs[i].state.speed = SPEED_1000;
|
||||
|
||||
ss->pcs[i].link_poll_enable = true;
|
||||
INIT_DELAYED_WORK(&ss->pcs[i].link_poll, mtk_sgmii_pcs_link_poll);
|
||||
|
||||
mutex_init(&ss->pcs[i].regmap_lock);
|
||||
mutex_init(&ss->pcs[i].reset_lock);
|
||||
|
||||
of_node_put(np);
|
||||
}
|
||||
@@ -670,9 +755,9 @@ int mtk_sgmii_init(struct mtk_eth *eth, struct device_node *r, u32 ana_rgc3)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id)
|
||||
struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, unsigned int id)
|
||||
{
|
||||
if (!ss->pcs[id].regmap)
|
||||
if (id >= MTK_MAX_DEVS || !ss->pcs[id].regmap)
|
||||
return NULL;
|
||||
|
||||
return &ss->pcs[id].pcs;
|
||||
|
||||
@@ -41,7 +41,7 @@ int mtk_usxgmii_xfi_pll_init(struct mtk_usxgmii *ss, struct device_node *r)
|
||||
|
||||
np = of_parse_phandle(r, "mediatek,xfi_pll", 0);
|
||||
if (!np)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < MTK_MAX_DEVS; i++) {
|
||||
ss->pll = syscon_node_to_regmap(np);
|
||||
@@ -60,7 +60,7 @@ int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r)
|
||||
|
||||
np = of_parse_phandle(r, "mediatek,toprgu", 0);
|
||||
if (!np)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
eth->toprgu = syscon_node_to_regmap(np);
|
||||
if (IS_ERR(eth->toprgu))
|
||||
@@ -91,17 +91,32 @@ int mtk_mac2xgmii_id(struct mtk_eth *eth, int mac_id)
|
||||
u32 xgmii_id = mac_id;
|
||||
|
||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
|
||||
switch (mac_id) {
|
||||
case MTK_GMAC1_ID:
|
||||
case MTK_GMAC2_ID:
|
||||
xgmii_id = 1;
|
||||
break;
|
||||
case MTK_GMAC3_ID:
|
||||
xgmii_id = 0;
|
||||
break;
|
||||
default:
|
||||
pr_info("[%s] Warning: get illegal mac_id=%d !=!!!\n",
|
||||
__func__, mac_id);
|
||||
if (eth->soc->caps == MT7988_CAPS) {
|
||||
switch (mac_id) {
|
||||
case MTK_GMAC1_ID:
|
||||
case MTK_GMAC2_ID:
|
||||
xgmii_id = 1;
|
||||
break;
|
||||
case MTK_GMAC3_ID:
|
||||
xgmii_id = 0;
|
||||
break;
|
||||
default:
|
||||
pr_info("[%s] Warning: get illegal mac_id=%d !=!!!\n",
|
||||
__func__, mac_id);
|
||||
}
|
||||
} else {
|
||||
switch (mac_id) {
|
||||
case MTK_GMAC1_ID:
|
||||
xgmii_id = 0;
|
||||
break;
|
||||
case MTK_GMAC2_ID:
|
||||
case MTK_GMAC3_ID:
|
||||
xgmii_id = 1;
|
||||
break;
|
||||
default:
|
||||
pr_info("[%s] Warning: get illegal mac_id=%d !=!!!\n",
|
||||
__func__, mac_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,16 +128,30 @@ int mtk_xgmii2mac_id(struct mtk_eth *eth, int xgmii_id)
|
||||
u32 mac_id = xgmii_id;
|
||||
|
||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
|
||||
switch (xgmii_id) {
|
||||
case 0:
|
||||
mac_id = 2;
|
||||
break;
|
||||
case 1:
|
||||
mac_id = 1;
|
||||
break;
|
||||
default:
|
||||
pr_info("[%s] Warning: get illegal xgmii_id=%d !=!!!\n",
|
||||
__func__, xgmii_id);
|
||||
if (eth->soc->caps == MT7988_CAPS) {
|
||||
switch (xgmii_id) {
|
||||
case 0:
|
||||
mac_id = 2;
|
||||
break;
|
||||
case 1:
|
||||
mac_id = 1;
|
||||
break;
|
||||
default:
|
||||
pr_info("[%s] Warning: get illegal xgmii_id=%d !=!!!\n",
|
||||
__func__, xgmii_id);
|
||||
}
|
||||
} else {
|
||||
switch (xgmii_id) {
|
||||
case 0:
|
||||
mac_id = 0;
|
||||
break;
|
||||
case 1:
|
||||
mac_id = 2;
|
||||
break;
|
||||
default:
|
||||
pr_info("[%s] Warning: get illegal xgmii_id=%d !=!!!\n",
|
||||
__func__, xgmii_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +215,7 @@ void mtk_usxgmii_setup_phya_usxgmii(struct mtk_usxgmii_pcs *mpcs)
|
||||
/* Force AEQ on */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x02002800);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
|
||||
0x20000000);
|
||||
/* Setup DA default value */
|
||||
@@ -219,28 +248,28 @@ void mtk_usxgmii_setup_phya_usxgmii(struct mtk_usxgmii_pcs *mpcs)
|
||||
/* Release reset */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200E800);
|
||||
udelay(150);
|
||||
usleep_range(150, 500);
|
||||
/* Switch to P0 */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200C111);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200C101);
|
||||
udelay(15);
|
||||
usleep_range(15, 50);
|
||||
/* Switch to Gen3 */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0202C111);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0202C101);
|
||||
udelay(100);
|
||||
usleep_range(100, 500);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
|
||||
0x00000030);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
|
||||
0x80201F00);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
|
||||
0x30000000);
|
||||
udelay(400);
|
||||
usleep_range(400, 1000);
|
||||
}
|
||||
|
||||
void mtk_usxgmii_setup_phya_5gbaser(struct mtk_usxgmii_pcs *mpcs)
|
||||
@@ -300,7 +329,7 @@ void mtk_usxgmii_setup_phya_5gbaser(struct mtk_usxgmii_pcs *mpcs)
|
||||
/* Force AEQ on */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x02002800);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
|
||||
0x20000000);
|
||||
/* Setup DA default value */
|
||||
@@ -333,28 +362,28 @@ void mtk_usxgmii_setup_phya_5gbaser(struct mtk_usxgmii_pcs *mpcs)
|
||||
/* Release reset */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200E800);
|
||||
udelay(150);
|
||||
usleep_range(150, 500);
|
||||
/* Switch to P0 */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200C111);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200C101);
|
||||
udelay(15);
|
||||
usleep_range(15, 50);
|
||||
/* Switch to Gen3 */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0202C111);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0202C101);
|
||||
udelay(100);
|
||||
usleep_range(100, 500);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
|
||||
0x00000030);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
|
||||
0x80201F00);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
|
||||
0x30000000);
|
||||
udelay(400);
|
||||
usleep_range(400, 1000);
|
||||
}
|
||||
|
||||
void mtk_usxgmii_setup_phya_10gbaser(struct mtk_usxgmii_pcs *mpcs)
|
||||
@@ -414,7 +443,7 @@ void mtk_usxgmii_setup_phya_10gbaser(struct mtk_usxgmii_pcs *mpcs)
|
||||
/* Force AEQ on */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x02002800);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
|
||||
0x20000000);
|
||||
/* Setup DA default value */
|
||||
@@ -450,34 +479,36 @@ void mtk_usxgmii_setup_phya_10gbaser(struct mtk_usxgmii_pcs *mpcs)
|
||||
/* Release reset */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200E800);
|
||||
udelay(150);
|
||||
usleep_range(150, 500);
|
||||
/* Switch to P0 */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200C111);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0200C101);
|
||||
udelay(15);
|
||||
usleep_range(15, 50);
|
||||
/* Switch to Gen3 */
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0202C111);
|
||||
ndelay(1020);
|
||||
usleep_range(1, 5);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
|
||||
0x0202C101);
|
||||
udelay(100);
|
||||
usleep_range(100, 500);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
|
||||
0x00000030);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
|
||||
0x80201F00);
|
||||
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
|
||||
0x30000000);
|
||||
udelay(400);
|
||||
usleep_range(400, 1000);
|
||||
}
|
||||
|
||||
int mtk_usxgmii_link_status(struct mtk_usxgmii_pcs *mpcs)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
mutex_lock(&mpcs->reset_lock);
|
||||
|
||||
/* Refresh USXGMII link status by toggling RG_PCS_RX_STATUS_UPDATE */
|
||||
regmap_read(mpcs->regmap, RG_PCS_RX_STATUS0, &val);
|
||||
val |= RG_PCS_RX_STATUS_UPDATE;
|
||||
@@ -490,196 +521,39 @@ int mtk_usxgmii_link_status(struct mtk_usxgmii_pcs *mpcs)
|
||||
/* Read USXGMII link status */
|
||||
regmap_read(mpcs->regmap, RG_PCS_RX_STATUS0, &val);
|
||||
|
||||
mutex_unlock(&mpcs->reset_lock);
|
||||
|
||||
return FIELD_GET(RG_PCS_RX_LINK_STATUS, val);
|
||||
}
|
||||
|
||||
void mtk_usxgmii_reset(struct mtk_eth *eth, int id)
|
||||
bool mtk_usxgmii_is_valid_ctle(struct mtk_usxgmii_pcs *mpcs)
|
||||
{
|
||||
u32 val = 0;
|
||||
unsigned int val, ctle;
|
||||
|
||||
if (id >= MTK_MAX_DEVS || !eth->toprgu)
|
||||
return;
|
||||
mutex_lock(&mpcs->reset_lock);
|
||||
|
||||
switch (id) {
|
||||
case 0:
|
||||
/* Enable software reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
|
||||
val |= SWSYSRST_XFI_PEXPT0_GRST |
|
||||
SWSYSRST_XFI0_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
|
||||
regmap_write(mpcs->regmap_pextp, 0x00, 0x00000404);
|
||||
regmap_write(mpcs->regmap_pextp, 0x10, 0x00d600d5);
|
||||
regmap_read(mpcs->regmap_pextp, 0xd0, &val);
|
||||
|
||||
/* Assert USXGMII reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
|
||||
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
|
||||
SWSYSRST_XFI_PEXPT0_GRST |
|
||||
SWSYSRST_XFI0_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
|
||||
mutex_unlock(&mpcs->reset_lock);
|
||||
|
||||
udelay(100);
|
||||
ctle = FIELD_GET(GENMASK(12, 8), val);
|
||||
if (ctle > 10)
|
||||
return false;
|
||||
|
||||
/* De-assert USXGMII reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
|
||||
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
|
||||
val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
|
||||
SWSYSRST_XFI0_GRST);
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
|
||||
|
||||
/* Disable software reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
|
||||
val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
|
||||
SWSYSRST_XFI0_GRST);
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
|
||||
break;
|
||||
case 1:
|
||||
/* Enable software reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
|
||||
val |= SWSYSRST_XFI_PEXPT1_GRST |
|
||||
SWSYSRST_XFI1_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
|
||||
|
||||
/* Assert USXGMII reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
|
||||
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
|
||||
SWSYSRST_XFI_PEXPT1_GRST |
|
||||
SWSYSRST_XFI1_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
|
||||
|
||||
udelay(100);
|
||||
|
||||
/* De-assert USXGMII reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
|
||||
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
|
||||
val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
|
||||
SWSYSRST_XFI1_GRST);
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
|
||||
|
||||
/* Disable software reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
|
||||
val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
|
||||
SWSYSRST_XFI1_GRST);
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
|
||||
break;
|
||||
}
|
||||
|
||||
mdelay(10);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int mtk_usxgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
|
||||
phy_interface_t interface,
|
||||
const unsigned long *advertising,
|
||||
bool permit_pause_to_mac)
|
||||
static void mtk_usxgmii_get_state(struct mtk_usxgmii_pcs *mpcs)
|
||||
{
|
||||
struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
|
||||
struct mtk_eth *eth = mpcs->eth;
|
||||
unsigned int an_ctrl = 0, link_timer = 0, xfi_mode = 0, adapt_mode = 0;
|
||||
bool mode_changed = false;
|
||||
|
||||
spin_lock(&mpcs->regmap_lock);
|
||||
|
||||
if (interface == PHY_INTERFACE_MODE_USXGMII) {
|
||||
an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF) |
|
||||
USXGMII_AN_ENABLE;
|
||||
link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) |
|
||||
FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) |
|
||||
FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B);
|
||||
xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_10G) |
|
||||
FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_10G);
|
||||
} else if (interface == PHY_INTERFACE_MODE_10GKR) {
|
||||
an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF);
|
||||
link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) |
|
||||
FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) |
|
||||
FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B);
|
||||
xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_10G) |
|
||||
FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_10G);
|
||||
adapt_mode = USXGMII_RATE_UPDATE_MODE;
|
||||
} else if (interface == PHY_INTERFACE_MODE_5GBASER) {
|
||||
an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0xFF);
|
||||
link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x3D) |
|
||||
FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x3D) |
|
||||
FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x3D);
|
||||
xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_5G) |
|
||||
FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_5G);
|
||||
adapt_mode = USXGMII_RATE_UPDATE_MODE;
|
||||
} else {
|
||||
spin_unlock(&mpcs->regmap_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
adapt_mode |= FIELD_PREP(USXGMII_RATE_ADAPT_MODE, USXGMII_RATE_ADAPT_MODE_X1);
|
||||
|
||||
if (mpcs->interface != interface) {
|
||||
mpcs->interface = interface;
|
||||
mpcs->mode = mode;
|
||||
mode_changed = true;
|
||||
}
|
||||
|
||||
mtk_usxgmii_xfi_pll_enable(eth->usxgmii);
|
||||
mtk_usxgmii_reset(eth, mpcs->id);
|
||||
|
||||
/* Setup USXGMII AN ctrl */
|
||||
regmap_update_bits(mpcs->regmap, RG_PCS_AN_CTRL0,
|
||||
USXGMII_AN_SYNC_CNT | USXGMII_AN_ENABLE,
|
||||
an_ctrl);
|
||||
|
||||
regmap_update_bits(mpcs->regmap, RG_PCS_AN_CTRL2,
|
||||
USXGMII_LINK_TIMER_IDLE_DETECT |
|
||||
USXGMII_LINK_TIMER_COMP_ACK_DETECT |
|
||||
USXGMII_LINK_TIMER_AN_RESTART,
|
||||
link_timer);
|
||||
|
||||
/* Gated MAC CK */
|
||||
regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
|
||||
USXGMII_MAC_CK_GATED, USXGMII_MAC_CK_GATED);
|
||||
|
||||
/* Enable interface force mode */
|
||||
regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
|
||||
USXGMII_IF_FORCE_EN, USXGMII_IF_FORCE_EN);
|
||||
|
||||
/* Setup USXGMII adapt mode */
|
||||
regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
|
||||
USXGMII_RATE_UPDATE_MODE | USXGMII_RATE_ADAPT_MODE,
|
||||
adapt_mode);
|
||||
|
||||
/* Setup USXGMII speed */
|
||||
regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
|
||||
USXGMII_XFI_RX_MODE | USXGMII_XFI_TX_MODE,
|
||||
xfi_mode);
|
||||
|
||||
udelay(1);
|
||||
|
||||
/* Un-gated MAC CK */
|
||||
regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
|
||||
USXGMII_MAC_CK_GATED, 0);
|
||||
|
||||
udelay(1);
|
||||
|
||||
/* Disable interface force mode for the AN mode */
|
||||
if (an_ctrl & USXGMII_AN_ENABLE)
|
||||
regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
|
||||
USXGMII_IF_FORCE_EN, 0);
|
||||
|
||||
/* Setup USXGMIISYS with the determined property */
|
||||
if (interface == PHY_INTERFACE_MODE_USXGMII)
|
||||
mtk_usxgmii_setup_phya_usxgmii(mpcs);
|
||||
else if (interface == PHY_INTERFACE_MODE_10GKR)
|
||||
mtk_usxgmii_setup_phya_10gbaser(mpcs);
|
||||
else if (interface == PHY_INTERFACE_MODE_5GBASER)
|
||||
mtk_usxgmii_setup_phya_5gbaser(mpcs);
|
||||
|
||||
spin_unlock(&mpcs->regmap_lock);
|
||||
|
||||
return mode_changed;
|
||||
}
|
||||
|
||||
static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
|
||||
struct phylink_link_state *state = &mpcs->state;
|
||||
struct mtk_eth *eth = mpcs->eth;
|
||||
struct mtk_mac *mac = eth->mac[mtk_xgmii2mac_id(eth, mpcs->id)];
|
||||
static unsigned long t_start;
|
||||
u32 val = 0;
|
||||
|
||||
mutex_lock(&mpcs->reset_lock);
|
||||
|
||||
regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
|
||||
if (FIELD_GET(USXGMII_AN_ENABLE, val)) {
|
||||
/* Refresh LPA by inverting LPA_LATCH */
|
||||
@@ -740,13 +614,257 @@ static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs,
|
||||
state->duplex = DUPLEX_FULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&mpcs->reset_lock);
|
||||
}
|
||||
|
||||
void mtk_usxgmii_reset(struct mtk_usxgmii_pcs *mpcs)
|
||||
{
|
||||
struct mtk_eth *eth = mpcs->eth;
|
||||
int id = mpcs->id;
|
||||
u32 val = 0;
|
||||
|
||||
if (id >= MTK_MAX_DEVS || !eth->toprgu)
|
||||
return;
|
||||
|
||||
mutex_lock(&mpcs->reset_lock);
|
||||
|
||||
switch (id) {
|
||||
case 0:
|
||||
/* Enable software reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
|
||||
val |= SWSYSRST_XFI_PEXPT0_GRST |
|
||||
SWSYSRST_XFI0_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
|
||||
|
||||
/* Assert USXGMII reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
|
||||
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
|
||||
SWSYSRST_XFI_PEXPT0_GRST |
|
||||
SWSYSRST_XFI0_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
|
||||
|
||||
usleep_range(100, 500);
|
||||
|
||||
/* De-assert USXGMII reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
|
||||
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
|
||||
val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
|
||||
SWSYSRST_XFI0_GRST);
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
|
||||
|
||||
/* Disable software reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
|
||||
val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
|
||||
SWSYSRST_XFI0_GRST);
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
|
||||
break;
|
||||
case 1:
|
||||
/* Enable software reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
|
||||
val |= SWSYSRST_XFI_PEXPT1_GRST |
|
||||
SWSYSRST_XFI1_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
|
||||
|
||||
/* Assert USXGMII reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
|
||||
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
|
||||
SWSYSRST_XFI_PEXPT1_GRST |
|
||||
SWSYSRST_XFI1_GRST;
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
|
||||
|
||||
usleep_range(100, 500);
|
||||
|
||||
/* De-assert USXGMII reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
|
||||
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
|
||||
val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
|
||||
SWSYSRST_XFI1_GRST);
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
|
||||
|
||||
/* Disable software reset */
|
||||
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
|
||||
val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
|
||||
SWSYSRST_XFI1_GRST);
|
||||
regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&mpcs->reset_lock);
|
||||
|
||||
usleep_range(10000, 11000);
|
||||
}
|
||||
|
||||
static int mtk_usxgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
|
||||
phy_interface_t interface,
|
||||
const unsigned long *advertising,
|
||||
bool permit_pause_to_mac)
|
||||
{
|
||||
struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
|
||||
struct mtk_eth *eth = mpcs->eth;
|
||||
unsigned int an_ctrl = 0, link_timer = 0, xfi_mode = 0, adapt_mode = 0;
|
||||
bool mode_changed = false;
|
||||
|
||||
if (interface == PHY_INTERFACE_MODE_USXGMII) {
|
||||
an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF) |
|
||||
USXGMII_AN_ENABLE;
|
||||
link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) |
|
||||
FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) |
|
||||
FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B);
|
||||
xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_10G) |
|
||||
FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_10G);
|
||||
} else if (interface == PHY_INTERFACE_MODE_10GKR) {
|
||||
an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF);
|
||||
link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) |
|
||||
FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) |
|
||||
FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B);
|
||||
xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_10G) |
|
||||
FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_10G);
|
||||
adapt_mode = USXGMII_RATE_UPDATE_MODE;
|
||||
} else if (interface == PHY_INTERFACE_MODE_5GBASER) {
|
||||
an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0xFF);
|
||||
link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x3D) |
|
||||
FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x3D) |
|
||||
FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x3D);
|
||||
xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_5G) |
|
||||
FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_5G);
|
||||
adapt_mode = USXGMII_RATE_UPDATE_MODE;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
adapt_mode |= FIELD_PREP(USXGMII_RATE_ADAPT_MODE, USXGMII_RATE_ADAPT_MODE_X1);
|
||||
|
||||
mtk_usxgmii_xfi_pll_enable(eth->usxgmii);
|
||||
mtk_usxgmii_reset(mpcs);
|
||||
|
||||
mutex_lock(&mpcs->regmap_lock);
|
||||
|
||||
if (mode <= MLO_AN_INBAND && mpcs->interface != interface) {
|
||||
mpcs->interface = interface;
|
||||
mpcs->mode = mode;
|
||||
mode_changed = true;
|
||||
}
|
||||
|
||||
/* Configure the interface polarity */
|
||||
regmap_update_bits(mpcs->regmap, RG_PHY_TOP_CTRL0,
|
||||
USXGMII_PN_SWAP_MASK, mpcs->polarity);
|
||||
|
||||
/* Setup USXGMII AN ctrl */
|
||||
regmap_update_bits(mpcs->regmap, RG_PCS_AN_CTRL0,
|
||||
USXGMII_AN_SYNC_CNT | USXGMII_AN_ENABLE,
|
||||
an_ctrl);
|
||||
|
||||
regmap_update_bits(mpcs->regmap, RG_PCS_AN_CTRL2,
|
||||
USXGMII_LINK_TIMER_IDLE_DETECT |
|
||||
USXGMII_LINK_TIMER_COMP_ACK_DETECT |
|
||||
USXGMII_LINK_TIMER_AN_RESTART,
|
||||
link_timer);
|
||||
|
||||
/* Gated MAC CK */
|
||||
regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
|
||||
USXGMII_MAC_CK_GATED, USXGMII_MAC_CK_GATED);
|
||||
|
||||
/* Enable interface force mode */
|
||||
regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
|
||||
USXGMII_IF_FORCE_EN, USXGMII_IF_FORCE_EN);
|
||||
|
||||
/* Setup USXGMII adapt mode */
|
||||
regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
|
||||
USXGMII_RATE_UPDATE_MODE | USXGMII_RATE_ADAPT_MODE,
|
||||
adapt_mode);
|
||||
|
||||
/* Setup USXGMII speed */
|
||||
regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
|
||||
USXGMII_XFI_RX_MODE | USXGMII_XFI_TX_MODE,
|
||||
xfi_mode);
|
||||
|
||||
usleep_range(1, 5);
|
||||
|
||||
/* Un-gated MAC CK */
|
||||
regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
|
||||
USXGMII_MAC_CK_GATED, 0);
|
||||
|
||||
usleep_range(1, 5);
|
||||
|
||||
/* Disable interface force mode for the AN mode */
|
||||
if (an_ctrl & USXGMII_AN_ENABLE)
|
||||
regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
|
||||
USXGMII_IF_FORCE_EN, 0);
|
||||
|
||||
/* Setup USXGMIISYS with the determined property */
|
||||
if (interface == PHY_INTERFACE_MODE_USXGMII)
|
||||
mtk_usxgmii_setup_phya_usxgmii(mpcs);
|
||||
else if (interface == PHY_INTERFACE_MODE_10GKR)
|
||||
mtk_usxgmii_setup_phya_10gbaser(mpcs);
|
||||
else if (interface == PHY_INTERFACE_MODE_5GBASER)
|
||||
mtk_usxgmii_setup_phya_5gbaser(mpcs);
|
||||
|
||||
mutex_unlock(&mpcs->regmap_lock);
|
||||
|
||||
return mode_changed;
|
||||
}
|
||||
|
||||
static void mtk_usxgmii_pcs_link_poll(struct work_struct *work)
|
||||
{
|
||||
struct mtk_usxgmii_pcs *mpcs = container_of(work, struct mtk_usxgmii_pcs,
|
||||
link_poll.work);
|
||||
|
||||
if ((mpcs->interface != PHY_INTERFACE_MODE_5GBASER &&
|
||||
mpcs->interface != PHY_INTERFACE_MODE_10GKR &&
|
||||
mpcs->interface != PHY_INTERFACE_MODE_USXGMII) ||
|
||||
(mpcs->link_poll_enable == false))
|
||||
goto exit;
|
||||
|
||||
if (!mtk_usxgmii_link_status(mpcs) || !mtk_usxgmii_is_valid_ctle(mpcs))
|
||||
mtk_usxgmii_pcs_config(&mpcs->pcs, UINT_MAX,
|
||||
mpcs->interface, NULL, false);
|
||||
|
||||
exit:
|
||||
if (mpcs->mode == MLO_AN_INBAND)
|
||||
mtk_usxgmii_get_state(mpcs);
|
||||
else if (!delayed_work_pending(&mpcs->link_poll))
|
||||
schedule_delayed_work(&mpcs->link_poll, msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
static int mtk_usxgmii_pcs_enable(struct phylink_pcs *pcs)
|
||||
{
|
||||
struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
|
||||
|
||||
if (!delayed_work_pending(&mpcs->link_poll))
|
||||
schedule_delayed_work(&mpcs->link_poll, msecs_to_jiffies(1000));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_usxgmii_pcs_disable(struct phylink_pcs *pcs)
|
||||
{
|
||||
struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
|
||||
|
||||
cancel_delayed_work_sync(&mpcs->link_poll);
|
||||
|
||||
if (mpcs->mode == MLO_AN_INBAND)
|
||||
mtk_usxgmii_get_state(mpcs);
|
||||
}
|
||||
|
||||
static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
|
||||
|
||||
if (mpcs->state.interface != PHY_INTERFACE_MODE_NA)
|
||||
state->interface = mpcs->state.interface;
|
||||
state->speed = mpcs->state.speed;
|
||||
state->duplex = mpcs->state.duplex;
|
||||
state->link = mpcs->state.link;
|
||||
|
||||
/* Reconfiguring USXGMII every second to ensure that PCS can
|
||||
* link up with the Link Partner when a module is inserted.
|
||||
*/
|
||||
if (state->link == 0 && time_after(jiffies, t_start + HZ)) {
|
||||
t_start = jiffies;
|
||||
mtk_usxgmii_pcs_config(pcs, MLO_AN_INBAND,
|
||||
state->interface, NULL, false);
|
||||
if (time_after(jiffies, mpcs->link_poll_expire) &&
|
||||
!delayed_work_pending(&mpcs->link_poll)) {
|
||||
mpcs->link_poll_expire = jiffies + HZ;
|
||||
mpcs->state.an_enabled = state->an_enabled;
|
||||
schedule_delayed_work(&mpcs->link_poll, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -768,35 +886,24 @@ static void mtk_usxgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
|
||||
int speed, int duplex)
|
||||
{
|
||||
struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
|
||||
struct device *dev = mpcs->eth->dev;
|
||||
unsigned long t_start = jiffies;
|
||||
unsigned int mpcs_mode;
|
||||
|
||||
/* Reconfiguring USXGMII to ensure the quality of the RX signal
|
||||
* after the line side link up.
|
||||
*/
|
||||
mtk_usxgmii_pcs_config(pcs, mode,
|
||||
interface, NULL, false);
|
||||
|
||||
do {
|
||||
msleep(1000);
|
||||
msleep(100);
|
||||
|
||||
if (mtk_usxgmii_link_status(mpcs))
|
||||
return;
|
||||
|
||||
spin_lock(&mpcs->regmap_lock);
|
||||
mpcs_mode = mpcs->mode;
|
||||
spin_unlock(&mpcs->regmap_lock);
|
||||
|
||||
if (mpcs_mode != MLO_AN_INBAND)
|
||||
mtk_usxgmii_pcs_config(&mpcs->pcs, mode,
|
||||
interface, NULL, false);
|
||||
} while (time_before(jiffies, t_start + msecs_to_jiffies(3000)));
|
||||
|
||||
pr_warn("%s wait link up timeout!\n", __func__);
|
||||
dev_warn(dev, "usxgmii%d: wait link up timeout!\n", mpcs->id);
|
||||
}
|
||||
|
||||
static const struct phylink_pcs_ops mtk_usxgmii_pcs_ops = {
|
||||
.pcs_config = mtk_usxgmii_pcs_config,
|
||||
.pcs_enable = mtk_usxgmii_pcs_enable,
|
||||
.pcs_disable = mtk_usxgmii_pcs_disable,
|
||||
.pcs_get_state = mtk_usxgmii_pcs_get_state,
|
||||
.pcs_an_restart = mtk_usxgmii_pcs_restart_an,
|
||||
.pcs_link_up = mtk_usxgmii_pcs_link_up,
|
||||
@@ -820,11 +927,27 @@ int mtk_usxgmii_init(struct mtk_eth *eth, struct device_node *r)
|
||||
if (IS_ERR(ss->pcs[i].regmap))
|
||||
return PTR_ERR(ss->pcs[i].regmap);
|
||||
|
||||
ss->pcs[i].polarity = 0;
|
||||
if (of_property_read_bool(np, "pn_swap"))
|
||||
ss->pcs[i].polarity |= USXGMII_PN_SWAP_TX | USXGMII_PN_SWAP_RX;
|
||||
else if (of_property_read_bool(np, "pn_swap_tx"))
|
||||
ss->pcs[i].polarity |= USXGMII_PN_SWAP_TX;
|
||||
else if (of_property_read_bool(np, "pn_swap_rx"))
|
||||
ss->pcs[i].polarity |= USXGMII_PN_SWAP_RX;
|
||||
|
||||
ss->pcs[i].pcs.ops = &mtk_usxgmii_pcs_ops;
|
||||
ss->pcs[i].pcs.poll = true;
|
||||
ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
|
||||
|
||||
spin_lock_init(&ss->pcs[i].regmap_lock);
|
||||
ss->pcs[i].state.link = 0;
|
||||
ss->pcs[i].state.duplex = DUPLEX_FULL;
|
||||
ss->pcs[i].state.speed = SPEED_10000;
|
||||
|
||||
ss->pcs[i].link_poll_enable = true;
|
||||
INIT_DELAYED_WORK(&ss->pcs[i].link_poll, mtk_usxgmii_pcs_link_poll);
|
||||
|
||||
mutex_init(&ss->pcs[i].regmap_lock);
|
||||
mutex_init(&ss->pcs[i].reset_lock);
|
||||
|
||||
of_node_put(np);
|
||||
}
|
||||
@@ -840,9 +963,9 @@ int mtk_usxgmii_init(struct mtk_eth *eth, struct device_node *r)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_usxgmii *ss, int id)
|
||||
struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_usxgmii *ss, unsigned int id)
|
||||
{
|
||||
if (!ss->pcs[id].regmap)
|
||||
if (id >= MTK_MAX_DEVS || !ss->pcs[id].regmap)
|
||||
return NULL;
|
||||
|
||||
return &ss->pcs[id].pcs;
|
||||
|
||||
@@ -12,11 +12,13 @@
|
||||
|
||||
#define EN8811H_MD32_DM "EthMD32.dm.bin"
|
||||
#define EN8811H_MD32_DSP "EthMD32.DSP.bin"
|
||||
#define EN8811H_IVY "ivypram.bin"
|
||||
|
||||
#define EN8811H_PHY_ID1 0x03a2
|
||||
#define EN8811H_PHY_ID2 0xa411
|
||||
#define EN8811H_PHY_ID ((EN8811H_PHY_ID1 << 16) | EN8811H_PHY_ID2)
|
||||
#define EN8811H_PHY_READY 0x02
|
||||
#define EN8811H_PHY_IVY_READY 0xABC
|
||||
#define MAX_RETRY 25
|
||||
|
||||
#define EN8811H_TX_POL_NORMAL 0x1
|
||||
@@ -46,7 +48,7 @@
|
||||
#define MII_MMD_ADDR_DATA_REG 0x0e
|
||||
#define MMD_OP_MODE_DATA BIT(14)
|
||||
|
||||
#define EN8811H_DRIVER_VERSION "v1.2.5"
|
||||
#define EN8811H_DRIVER_VERSION "v1.3.0"
|
||||
|
||||
#define LED_ON_CTRL(i) (0x024 + ((i)*2))
|
||||
#define LED_ON_EN (1 << 15)
|
||||
@@ -86,20 +88,64 @@
|
||||
#define LED_BLK_DUR (0x023)
|
||||
#define LED_BLK_DUR_MASK (0xffff)
|
||||
|
||||
#define UNIT_LED_BLINK_DURATION 1024
|
||||
#define UNIT_LED_BLINK_DURATION 780
|
||||
|
||||
#define GET_BIT(val, bit) ((val & BIT(bit)) >> bit)
|
||||
|
||||
#define INVALID_DATA 0xffff
|
||||
#define PBUS_INVALID_DATA 0xffffffff
|
||||
|
||||
/* MII Registers */
|
||||
#define AIR_AUX_CTRL_STATUS 0x1d
|
||||
#define AIR_AUX_CTRL_STATUS_SPEED_MASK GENMASK(4, 2)
|
||||
#define AIR_AUX_CTRL_STATUS_SPEED_100 0x4
|
||||
#define AIR_AUX_CTRL_STATUS_SPEED_1000 0x8
|
||||
#define AIR_AUX_CTRL_STATUS_SPEED_2500 0xc
|
||||
|
||||
/* Registers on BUCKPBUS */
|
||||
#define EN8811H_2P5G_LPA 0x3b30
|
||||
#define EN8811H_2P5G_LPA_2P5G BIT(0)
|
||||
|
||||
#define EN8811H_FW_CTRL_1 0x0f0018
|
||||
#define EN8811H_FW_CTRL_1_START 0x0
|
||||
#define EN8811H_FW_CTRL_1_FINISH 0x1
|
||||
#define EN8811H_FW_CTRL_2 0x800000
|
||||
#define EN8811H_FW_CTRL_2_LOADING BIT(11)
|
||||
#define EN8811H_LOOP 0x800
|
||||
|
||||
#define NUM_ASI_REGS 5
|
||||
struct air_cable_test_rsl {
|
||||
int status[4];
|
||||
unsigned int length[4];
|
||||
};
|
||||
|
||||
struct en8811h_priv {
|
||||
struct dentry *debugfs_root;
|
||||
unsigned int dm_crc32;
|
||||
unsigned int dsp_crc32;
|
||||
char buf[512];
|
||||
unsigned int ivy_crc32;
|
||||
int pol;
|
||||
int surge;
|
||||
int cko;
|
||||
struct kobject *cable_kobj;
|
||||
int running_status;
|
||||
int pair[4];
|
||||
int an;
|
||||
int link;
|
||||
int speed;
|
||||
int duplex;
|
||||
int pause;
|
||||
int asym_pause;
|
||||
u16 on_crtl[3];
|
||||
u16 blk_crtl[3];
|
||||
u32 firmware_version;
|
||||
bool mcu_needs_restart;
|
||||
bool mcu_load;
|
||||
int debug;
|
||||
int phy_handle;
|
||||
int init_stage;
|
||||
int need_an;
|
||||
int count;
|
||||
};
|
||||
|
||||
struct air_base_t_led_cfg {
|
||||
@@ -109,6 +155,18 @@ struct air_base_t_led_cfg {
|
||||
u16 on_cfg;
|
||||
u16 blk_cfg;
|
||||
};
|
||||
|
||||
enum air_init_stage {
|
||||
AIR_INIT_START,
|
||||
AIR_INIT_CONFIG,
|
||||
AIR_INIT_FW_LOADING,
|
||||
AIR_INIT_FW_READY,
|
||||
AIR_INIT_SUCESS,
|
||||
AIR_INIT_FW_FAIL,
|
||||
AIR_INIT_FAIL,
|
||||
AIR_INIT_LAST
|
||||
};
|
||||
|
||||
enum air_led_gpio {
|
||||
AIR_LED2_GPIO3 = 3,
|
||||
AIR_LED1_GPIO4,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,10 +15,12 @@
|
||||
#define phydev_mdio_bus(_dev) (_dev->bus)
|
||||
#define phydev_addr(_dev) (_dev->addr)
|
||||
#define phydev_dev(_dev) (&_dev->dev)
|
||||
#define phydev_kobj(_dev) (&_dev->dev.kobj)
|
||||
#else
|
||||
#define phydev_mdio_bus(_dev) (_dev->mdio.bus)
|
||||
#define phydev_addr(_dev) (_dev->mdio.addr)
|
||||
#define phydev_dev(_dev) (&_dev->mdio.dev)
|
||||
#define phydev_kobj(_dev) (&_dev->mdio.dev.kobj)
|
||||
#endif
|
||||
|
||||
#define DEBUGFS_COUNTER "counter"
|
||||
@@ -31,8 +33,42 @@
|
||||
#define DEBUGFS_DBG_REG_SHOW "dbg_regs_show"
|
||||
#define DEBUGFS_TEMPERATURE "temp"
|
||||
#define DEBUGFS_LP_SPEED "lp_speed"
|
||||
#define DEBUGFS_MII_CL22_OP "cl22_op"
|
||||
#define DEBUGFS_MII_CL45_OP "cl45_op"
|
||||
#define DEBUGFS_MII_CL22_OP "cl22_op"
|
||||
#define DEBUGFS_MII_CL45_OP "cl45_op"
|
||||
#define DEBUGFS_CABLE_DIAG "cable_diag"
|
||||
#define DEBUGFS_LED_MODE "led_mode"
|
||||
#define DEBUGFS_TX_COMP "tx_comp"
|
||||
|
||||
#define CMD_MAX_LENGTH 128
|
||||
|
||||
/* bits range: for example AIR_BITS_RANGE(16, 4) = 0x0F0000 */
|
||||
#ifndef AIR_BITS_RANGE
|
||||
#define AIR_BITS_RANGE(offset, range) GENMASK((offset) + (range) - 1U, (offset))
|
||||
#endif /* End of AIR_BITS_RANGE */
|
||||
|
||||
/* bits offset right: for example AIR_BITS_OFF_R(0x1234, 8, 4) = 0x2 */
|
||||
#ifndef AIR_BITS_OFF_R
|
||||
#define AIR_BITS_OFF_R(val, offset, range) (((val) >> (offset)) & GENMASK((range) - 1U, 0))
|
||||
#endif /* End of AIR_BITS_OFF_R */
|
||||
|
||||
/* bits offset left: for example AIR_BITS_OFF_L(0x1234, 8, 4) = 0x400 */
|
||||
#ifndef AIR_BITS_OFF_L
|
||||
#define AIR_BITS_OFF_L(val, offset, range) (((val) & GENMASK((range) - 1U, 0)) << (offset))
|
||||
#endif /* End of AIR_BITS_OFF_L */
|
||||
|
||||
#define AIR_EN8811H_SET_VALUE(__out__, __val__, __offset__, __length__) \
|
||||
{ \
|
||||
(__out__) &= ~AIR_BITS_RANGE((__offset__), (__length__)); \
|
||||
(__out__) |= AIR_BITS_OFF_L((__val__), (__offset__), (__length__)); \
|
||||
}
|
||||
|
||||
#define CTL1000_PORT_TYPE (0x0400)
|
||||
#define CTL1000_TEST_NORMAL (0x0000)
|
||||
#define CTL1000_TEST_TM1 (0x2000)
|
||||
#define CTL1000_TEST_TM2 (0x4000)
|
||||
#define CTL1000_TEST_TM3 (0x6000)
|
||||
#define CTL1000_TEST_TM4 (0x8000)
|
||||
#define MMD_DEV_VSPEC1 (0x1e)
|
||||
|
||||
enum air_port_mode {
|
||||
AIR_PORT_MODE_FORCE_100,
|
||||
@@ -64,6 +100,104 @@ enum air_link_mode_bit {
|
||||
AIR_LINK_MODE_2500baseT_Full_BIT = 5,
|
||||
};
|
||||
|
||||
enum air_led_force {
|
||||
AIR_LED_NORMAL = 0,
|
||||
AIR_LED_FORCE_OFF,
|
||||
AIR_LED_FORCE_ON,
|
||||
AIR_LED_FORCE_LAST = 0xff,
|
||||
};
|
||||
|
||||
enum air_para {
|
||||
AIR_PARA_PRIV,
|
||||
AIR_PARA_PHYDEV,
|
||||
AIR_PARA_LAST = 0xff
|
||||
};
|
||||
|
||||
enum air_port_cable_status {
|
||||
AIR_PORT_CABLE_STATUS_ERROR,
|
||||
AIR_PORT_CABLE_STATUS_OPEN,
|
||||
AIR_PORT_CABLE_STATUS_SHORT,
|
||||
AIR_PORT_CABLE_STATUS_NORMAL,
|
||||
AIR_PORT_CABLE_STATUS_LAST = 0xff
|
||||
};
|
||||
|
||||
enum air_surge {
|
||||
AIR_SURGE_0R,
|
||||
AIR_SURGE_5R,
|
||||
AIR_SURGE_LAST = 0xff
|
||||
};
|
||||
|
||||
enum air_port_cable_test_pair {
|
||||
AIR_PORT_CABLE_TEST_PAIR_A,
|
||||
AIR_PORT_CABLE_TEST_PAIR_B,
|
||||
AIR_PORT_CABLE_TEST_PAIR_C,
|
||||
AIR_PORT_CABLE_TEST_PAIR_D,
|
||||
AIR_PORT_CABLE_TEST_PAIR_ALL,
|
||||
AIR_PORT_CABLE_TEST_PAIR_LAST
|
||||
};
|
||||
|
||||
enum air_cko {
|
||||
AIR_CKO_DIS,
|
||||
AIR_CKO_EN,
|
||||
AIR_CKO_LAST = 0xff
|
||||
};
|
||||
|
||||
enum air_tx_comp_mode {
|
||||
AIR_TX_COMP_MODE_100M_PAIR_A,
|
||||
AIR_TX_COMP_MODE_100M_PAIR_B,
|
||||
AIR_TX_COMP_MODE_100M_PAIR_A_DISCRETE,
|
||||
AIR_TX_COMP_MODE_100M_PAIR_B_DISCRETE,
|
||||
AIR_TX_COMP_MODE_1000M_TM1,
|
||||
AIR_TX_COMP_MODE_1000M_TM2,
|
||||
AIR_TX_COMP_MODE_1000M_TM3,
|
||||
AIR_TX_COMP_MODE_1000M_TM4_TD,
|
||||
AIR_TX_COMP_MODE_1000M_TM4_CM_PAIR_A,
|
||||
AIR_TX_COMP_MODE_1000M_TM4_CM_PAIR_B,
|
||||
AIR_TX_COMP_MODE_1000M_TM4_CM_PAIR_C,
|
||||
AIR_TX_COMP_MODE_1000M_TM4_CM_PAIR_D,
|
||||
AIR_TX_COMP_MODE_2500M_TM1,
|
||||
AIR_TX_COMP_MODE_2500M_TM2,
|
||||
AIR_TX_COMP_MODE_2500M_TM3,
|
||||
AIR_TX_COMP_MODE_2500M_TM4_TONE_1,
|
||||
AIR_TX_COMP_MODE_2500M_TM4_TONE_2,
|
||||
AIR_TX_COMP_MODE_2500M_TM4_TONE_3,
|
||||
AIR_TX_COMP_MODE_2500M_TM4_TONE_4,
|
||||
AIR_TX_COMP_MODE_2500M_TM4_TONE_5,
|
||||
AIR_TX_COMP_MODE_2500M_TM5,
|
||||
AIR_TX_COMP_MODE_2500M_TM6,
|
||||
AIR_TX_COMP_MODE_LAST = 0xFF,
|
||||
};
|
||||
|
||||
struct trrg_param_s {
|
||||
unsigned int TrRG_LSB :5;
|
||||
unsigned int Reserved_21 :3;
|
||||
unsigned int TrRG_MSB :5;
|
||||
unsigned int Reserved_29 :3;
|
||||
unsigned int Reserved_0 :1;
|
||||
unsigned int DATA_ADDR :6;
|
||||
unsigned int NODE_ADDR :4;
|
||||
unsigned int CH_ADDR :2;
|
||||
unsigned int WR_RD_CTRL :1;
|
||||
unsigned int Reserved_14 :1;
|
||||
unsigned int PKT_XMT_STA :1;
|
||||
};
|
||||
|
||||
union trrgdesc_s {
|
||||
struct trrg_param_s param;
|
||||
unsigned short Raw[2];
|
||||
unsigned int DescVal;
|
||||
};
|
||||
|
||||
struct trrg_s {
|
||||
union trrgdesc_s TrRGDesc;
|
||||
unsigned int RgMask;
|
||||
};
|
||||
|
||||
struct hal_tr_data_s {
|
||||
unsigned short data_lo;
|
||||
unsigned char data_hi;
|
||||
};
|
||||
|
||||
#ifndef unlikely
|
||||
# define unlikely(x) (x)
|
||||
#endif
|
||||
@@ -84,7 +218,10 @@ unsigned int air_buckpbus_reg_read(struct phy_device *phydev,
|
||||
int air_buckpbus_reg_write(struct phy_device *phydev,
|
||||
unsigned int pbus_address, unsigned int pbus_data);
|
||||
int en8811h_of_init(struct phy_device *phydev);
|
||||
int air_surge_5ohm_config(struct phy_device *phydev);
|
||||
int air_surge_protect_cfg(struct phy_device *phydev);
|
||||
int air_ref_clk_speed(struct phy_device *phydev, int para);
|
||||
int air_cko_cfg(struct phy_device *phydev);
|
||||
int airoha_control_flag(struct phy_device *phydev, int mask, int val);
|
||||
#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
|
||||
int airphy_debugfs_init(struct phy_device *phydev);
|
||||
void airphy_debugfs_remove(struct phy_device *phydev);
|
||||
|
||||
@@ -35,7 +35,11 @@ MODULE_LICENSE("GPL");
|
||||
* GPIO3 <-> BASE_T_LED2,
|
||||
**************************/
|
||||
/* User-defined.B */
|
||||
/*#define AIR_MD32_FW_CHECK*/
|
||||
/* #define AIR_MD32_FW_CHECK */
|
||||
/* #define AIR_IVY_LOAD */
|
||||
#ifdef AIR_IVY_LOAD
|
||||
/* #define AIR_IVY_CHECK */
|
||||
#endif
|
||||
#define AIR_LED_SUPPORT
|
||||
#ifdef AIR_LED_SUPPORT
|
||||
static const struct air_base_t_led_cfg led_cfg[3] = {
|
||||
@@ -53,17 +57,20 @@ static const u16 led_dur = UNIT_LED_BLINK_DURATION << AIR_LED_BLK_DUR_64M;
|
||||
/***********************************************************
|
||||
* F U N C T I O N S
|
||||
***********************************************************/
|
||||
#ifdef AIR_MD32_FW_CHECK
|
||||
static void air_mdio_read_buf(struct phy_device *phydev, unsigned long address,
|
||||
const struct firmware *fw, unsigned int *crc32)
|
||||
{
|
||||
unsigned int write_data, offset;
|
||||
int ret = 0, len = 0;
|
||||
unsigned int offset;
|
||||
int ret = 0;
|
||||
unsigned int pbus_data_low, pbus_data_high;
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
struct mii_bus *mbus = phydev_mdio_bus(phydev);
|
||||
int addr = phydev_addr(phydev);
|
||||
char *buf = kmalloc(fw->size, GFP_KERNEL);
|
||||
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
memset(buf, '\0', fw->size);
|
||||
/* page 4 */
|
||||
ret |= air_mii_cl22_write(mbus, addr, 0x1F, 4);
|
||||
@@ -90,7 +97,7 @@ static void air_mdio_read_buf(struct phy_device *phydev, unsigned long address,
|
||||
__func__, address, ret);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
static int air_mdio_write_buf(struct phy_device *phydev,
|
||||
unsigned long address, const struct firmware *fw)
|
||||
{
|
||||
@@ -144,7 +151,113 @@ static int air_mdio_write_buf(struct phy_device *phydev,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#ifdef AIR_IVY_LOAD
|
||||
static int modify_reg_bits(struct phy_device *phydev,
|
||||
unsigned int reg, unsigned int mask, unsigned int set)
|
||||
{
|
||||
unsigned int write_data;
|
||||
int ret;
|
||||
|
||||
write_data = air_buckpbus_reg_read(phydev, reg);
|
||||
write_data &= ~mask;
|
||||
write_data |= set;
|
||||
ret = air_buckpbus_reg_write(phydev, reg, write_data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int air_mdio_load_ivy(struct phy_device *phydev,
|
||||
unsigned long address, const struct firmware *fw)
|
||||
{
|
||||
unsigned int write_data = 0, offset, read_data;
|
||||
int ret = 0, retry;
|
||||
#ifdef AIR_IVY_CHECK
|
||||
int error = 0;
|
||||
#endif
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
|
||||
ret = air_buckpbus_reg_write(phydev,
|
||||
0xcf924, 0x12);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
write_data = air_buckpbus_reg_read(phydev, 0xcfa28);
|
||||
write_data |= BIT(0);
|
||||
ret = air_buckpbus_reg_write(phydev,
|
||||
0xcfa28, write_data);
|
||||
write_data = air_buckpbus_reg_read(phydev, 0xcfa28);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
msleep(100);
|
||||
for (offset = 0; offset < fw->size; offset += 4) {
|
||||
write_data = (fw->data[offset + 3] << 24) | (fw->data[offset + 2] << 16);
|
||||
write_data |= ((fw->data[offset + 1] << 8) | fw->data[offset]);
|
||||
ret = air_buckpbus_reg_write(phydev,
|
||||
address, write_data);
|
||||
#ifdef AIR_IVY_CHECK
|
||||
read_data = air_buckpbus_reg_read(phydev, address);
|
||||
if (write_data != read_data) {
|
||||
dev_info(dev, "%x: write_data(0x%x) != read_data(0x%x)\n",
|
||||
address, write_data, read_data);
|
||||
error++;
|
||||
}
|
||||
#endif
|
||||
address += 1;
|
||||
}
|
||||
#ifdef AIR_IVY_CHECK
|
||||
if (error)
|
||||
dev_err(dev, "Check ivy Fail(%d)\n", error);
|
||||
else
|
||||
dev_err(dev, "Check ivy Pass\n");
|
||||
#endif
|
||||
ret = modify_reg_bits(phydev, 0xCFA28, BIT(0), 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = modify_reg_bits(phydev, 0xCFA28, 0, BIT(16));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret |= air_buckpbus_reg_write(phydev,
|
||||
0xDC065, 0x80);
|
||||
ret |= air_buckpbus_reg_write(phydev,
|
||||
0xDC064, 0x0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
retry = 5;
|
||||
do {
|
||||
msleep(300);
|
||||
ret = air_buckpbus_reg_write(phydev,
|
||||
0xDC064, 0x0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
write_data = air_buckpbus_reg_read(phydev, 0xDC065);
|
||||
if (write_data == 0x80)
|
||||
break;
|
||||
if (!retry)
|
||||
dev_err(dev, "0xDC065 is not ready.(0x%x)\n", write_data);
|
||||
} while (retry--);
|
||||
|
||||
ret = modify_reg_bits(phydev, 0xCFA28, BIT(16), 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = modify_reg_bits(phydev, 0xCFA28, 0, BIT(24));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
retry = 10;
|
||||
do {
|
||||
msleep(300);
|
||||
write_data = air_buckpbus_reg_read(phydev, 0xCFA38);
|
||||
if (write_data == EN8811H_PHY_IVY_READY) {
|
||||
dev_info(dev, "IVY ready!\n");
|
||||
break;
|
||||
}
|
||||
if (!retry)
|
||||
dev_err(dev, "IVY is not ready.(0x%x)\n", write_data);
|
||||
} while (retry--);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
static int en8811h_load_firmware(struct phy_device *phydev)
|
||||
{
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
@@ -158,6 +271,27 @@ static int en8811h_load_firmware(struct phy_device *phydev)
|
||||
#endif
|
||||
struct en8811h_priv *priv = phydev->priv;
|
||||
|
||||
priv->init_stage = AIR_INIT_FW_LOADING;
|
||||
#ifdef AIR_IVY_LOAD
|
||||
firmware = EN8811H_IVY;
|
||||
ret = request_firmware_direct(&fw, firmware, dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"failed to load firmware %s, ret: %d\n", firmware, ret);
|
||||
return ret;
|
||||
}
|
||||
priv->ivy_crc32 = ~crc32(~0, fw->data, fw->size);
|
||||
dev_info(dev, "%s: crc32=0x%x\n",
|
||||
firmware, ~crc32(~0, fw->data, fw->size));
|
||||
/* Download ivy */
|
||||
ret = air_mdio_load_ivy(phydev, 0xd4000, fw);
|
||||
release_firmware(fw);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"air_mdio_write_buf 0xd4000 fail, ret: %d\n", ret);
|
||||
goto release;
|
||||
}
|
||||
#endif
|
||||
ret = air_buckpbus_reg_write(phydev,
|
||||
0x0f0018, 0x0);
|
||||
if (ret < 0)
|
||||
@@ -228,13 +362,13 @@ static int en8811h_load_firmware(struct phy_device *phydev)
|
||||
return ret;
|
||||
msleep(100);
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0x0f0018);
|
||||
retry--;
|
||||
if (retry == 0) {
|
||||
dev_err(dev,
|
||||
"Release Software Reset fail , ret: %d\n",
|
||||
pbus_value);
|
||||
break;
|
||||
goto release;
|
||||
}
|
||||
retry--;
|
||||
} while (pbus_value != 0x1);
|
||||
dev_info(dev,
|
||||
"Release Software Reset successful.\n");
|
||||
@@ -250,6 +384,41 @@ release:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int en8811h_init_up(struct phy_device *phydev)
|
||||
{
|
||||
int ret = 0, retry, reg_value;
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
unsigned int pbus_value;
|
||||
struct en8811h_priv *priv = phydev->priv;
|
||||
|
||||
dev_info(dev, "%s start\n", __func__);
|
||||
ret = en8811h_load_firmware(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "EN8811H load firmware fail.\n");
|
||||
return ret;
|
||||
}
|
||||
retry = MAX_RETRY;
|
||||
do {
|
||||
mdelay(300);
|
||||
reg_value = air_mii_cl45_read(phydev, 0x1e, 0x8009);
|
||||
if (reg_value == EN8811H_PHY_READY) {
|
||||
dev_info(dev, "EN8811H PHY ready!\n");
|
||||
priv->init_stage = AIR_INIT_FW_READY;
|
||||
break;
|
||||
}
|
||||
if (retry == 0) {
|
||||
dev_err(dev, "MD32 FW is not ready.(Status 0x%x)\n", reg_value);
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
|
||||
dev_err(dev,
|
||||
"Check MD32 FW Version(0x3b3c) : %08x\n", pbus_value);
|
||||
dev_err(dev,
|
||||
"%s fail!\n", __func__);
|
||||
priv->init_stage = AIR_INIT_FW_FAIL;
|
||||
}
|
||||
} while (retry--);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef AIR_LED_SUPPORT
|
||||
static int airoha_led_set_usr_def(struct phy_device *phydev, u8 entity,
|
||||
int polar, u16 on_evt, u16 blk_evt)
|
||||
@@ -322,6 +491,7 @@ static int en8811h_led_init(struct phy_device *phydev)
|
||||
u16 cl45_data = led_dur;
|
||||
int ret = 0, id;
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
struct en8811h_priv *priv = phydev->priv;
|
||||
|
||||
ret = air_mii_cl45_write(phydev, 0x1f, LED_BLK_DUR, cl45_data);
|
||||
if (ret < 0)
|
||||
@@ -357,6 +527,10 @@ static int en8811h_led_init(struct phy_device *phydev)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
priv->on_crtl[id] = air_mii_cl45_read(phydev, 0x1f,
|
||||
LED_ON_CTRL(id));
|
||||
priv->blk_crtl[id] = air_mii_cl45_read(phydev, 0x1f,
|
||||
LED_BLK_CTRL(id));
|
||||
}
|
||||
reg_value = air_buckpbus_reg_read(phydev, 0xcf8b8) | led_gpio;
|
||||
ret = air_buckpbus_reg_write(phydev, 0xcf8b8, reg_value);
|
||||
@@ -366,6 +540,7 @@ static int en8811h_led_init(struct phy_device *phydev)
|
||||
return 0;
|
||||
}
|
||||
#endif /* AIR_LED_SUPPORT */
|
||||
|
||||
#if (KERNEL_VERSION(4, 5, 0) < LINUX_VERSION_CODE)
|
||||
static int en8811h_get_features(struct phy_device *phydev)
|
||||
{
|
||||
@@ -386,11 +561,13 @@ static int en8811h_get_features(struct phy_device *phydev)
|
||||
phydev->supported);
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
|
||||
phydev->supported);
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
|
||||
phydev->supported);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
|
||||
phydev->supported);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||
phydev->supported);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
phydev->supported);
|
||||
return 0;
|
||||
}
|
||||
@@ -399,12 +576,11 @@ static int en8811h_get_features(struct phy_device *phydev)
|
||||
static int en8811h_probe(struct phy_device *phydev)
|
||||
{
|
||||
int ret = 0;
|
||||
int reg_value, pid1 = 0, pid2 = 0;
|
||||
u32 retry, pbus_value = 0;
|
||||
int pid1 = 0, pid2 = 0;
|
||||
u32 pbus_value = 0;
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
struct mii_bus *mbus = phydev_mdio_bus(phydev);
|
||||
int addr = phydev_addr(phydev);
|
||||
|
||||
struct en8811h_priv *priv;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
@@ -414,23 +590,30 @@ static int en8811h_probe(struct phy_device *phydev)
|
||||
ret = air_pbus_reg_write(phydev, 0xcf928, 0x0);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
pid1 = air_mii_cl22_read(mbus, addr, MII_PHYSID1);
|
||||
pid2 = air_mii_cl22_read(mbus, addr, MII_PHYSID2);
|
||||
dev_info(dev, "PHY = %x - %x\n", pid1, pid2);
|
||||
if ((pid1 != EN8811H_PHY_ID1) || (pid2 != EN8811H_PHY_ID2)) {
|
||||
dev_err(dev, "EN8811H dose not exist!!\n");
|
||||
kfree(priv);
|
||||
return -ENODEV;
|
||||
goto priv_free;
|
||||
}
|
||||
|
||||
priv->init_stage = AIR_INIT_START;
|
||||
ret = air_buckpbus_reg_write(phydev, 0x1e00d0, 0xf);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x1e0228, 0xf0);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
priv->mcu_needs_restart = false;
|
||||
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xcf914);
|
||||
dev_info(dev, "Bootmode: %s\n",
|
||||
(GET_BIT(pbus_value, 24) ? "Flash" : "Download Code"));
|
||||
|
||||
ret = en8811h_load_firmware(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "EN8811H load firmware fail.\n");
|
||||
ret = en8811h_of_init(phydev);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
|
||||
ret = airphy_debugfs_init(phydev);
|
||||
if (ret < 0) {
|
||||
@@ -439,69 +622,68 @@ static int en8811h_probe(struct phy_device *phydev)
|
||||
goto priv_free;
|
||||
}
|
||||
#endif /* CONFIG_AIROHA_EN8811H_PHY_DEBUGFS */
|
||||
retry = MAX_RETRY;
|
||||
do {
|
||||
mdelay(300);
|
||||
reg_value = air_mii_cl45_read(phydev, 0x1e, 0x8009);
|
||||
if (reg_value == EN8811H_PHY_READY) {
|
||||
dev_info(dev, "EN8811H PHY ready!\n");
|
||||
break;
|
||||
}
|
||||
retry--;
|
||||
} while (retry);
|
||||
if (retry == 0) {
|
||||
dev_err(dev, "MD32 FW is not ready.(Status 0x%x)\n", reg_value);
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
|
||||
dev_err(dev,
|
||||
"Check MD32 FW Version(0x3b3c) : %08x\n", pbus_value);
|
||||
dev_err(dev,
|
||||
"EN8811H initialize fail!\n");
|
||||
goto priv_free;
|
||||
}
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
/* Serdes polarity */
|
||||
ret = en8811h_of_init(phydev);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
|
||||
pbus_value &= ~0x3;
|
||||
#if defined(CONFIG_OF)
|
||||
pbus_value |= priv->pol;
|
||||
#else
|
||||
pbus_value |= (EN8811H_RX_POL_NORMAL | EN8811H_TX_POL_NORMAL);
|
||||
#endif
|
||||
ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_value);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
|
||||
dev_info(dev, "Tx, Rx Polarity : %08x\n", pbus_value);
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
|
||||
dev_info(dev, "MD32 FW Version : %08x\n", pbus_value);
|
||||
if (priv->surge) {
|
||||
ret = air_surge_5ohm_config(phydev);
|
||||
|
||||
if (priv->phy_handle) {
|
||||
dev_info(dev, "EN8811H Probe OK! (%s)\n", EN8811H_DRIVER_VERSION);
|
||||
} else {
|
||||
ret = en8811h_init_up(phydev);
|
||||
if (ret < 0)
|
||||
dev_err(dev,
|
||||
"air_surge_5ohm_config fail. (ret=%d)\n", ret);
|
||||
} else
|
||||
dev_info(dev, "Surge Protection Mode - 0R\n");
|
||||
#if defined(AIR_LED_SUPPORT)
|
||||
ret = en8811h_led_init(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "en8811h_led_init fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
}
|
||||
goto priv_free;
|
||||
|
||||
priv->init_stage = AIR_INIT_CONFIG;
|
||||
ret = air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
|
||||
pbus_value &= ~0x3;
|
||||
#if defined(CONFIG_OF)
|
||||
pbus_value |= priv->pol;
|
||||
#else
|
||||
pbus_value |= (EN8811H_RX_POL_NORMAL | EN8811H_TX_POL_NORMAL);
|
||||
#endif
|
||||
dev_info(dev, "EN8811H initialize OK! (%s)\n", EN8811H_DRIVER_VERSION);
|
||||
ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_value);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
|
||||
dev_info(dev, "Tx, Rx Polarity : %08x\n", pbus_value);
|
||||
priv->firmware_version = air_buckpbus_reg_read(phydev, 0x3b3c);
|
||||
dev_info(dev, "MD32 FW Version : %08x\n", priv->firmware_version);
|
||||
ret = air_surge_protect_cfg(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"air_surge_protect_cfg fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
}
|
||||
|
||||
ret = air_cko_cfg(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"air_cko_cfg fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
}
|
||||
|
||||
#if defined(AIR_LED_SUPPORT)
|
||||
ret = en8811h_led_init(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "en8811h_led_init fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
}
|
||||
#endif
|
||||
|
||||
priv->init_stage = AIR_INIT_SUCESS;
|
||||
dev_info(dev, "EN8811H initialize OK! (%s)\n", EN8811H_DRIVER_VERSION);
|
||||
}
|
||||
return 0;
|
||||
priv_free:
|
||||
kfree(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void en8811h_remove(struct phy_device *phydev)
|
||||
{
|
||||
|
||||
@@ -518,6 +700,229 @@ void en8811h_remove(struct phy_device *phydev)
|
||||
}
|
||||
}
|
||||
|
||||
static int en8811h_restart_up(struct phy_device *phydev)
|
||||
{
|
||||
int ret, retry, reg_value;
|
||||
u32 pbus_value;
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
struct en8811h_priv *priv = phydev->priv;
|
||||
|
||||
dev_info(dev, "%s start\n", __func__);
|
||||
ret = air_mii_cl45_write(phydev, 0x1e, 0x8009, 0x0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
|
||||
EN8811H_FW_CTRL_1_START);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
|
||||
EN8811H_FW_CTRL_1_FINISH);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
retry = MAX_RETRY;
|
||||
do {
|
||||
mdelay(300);
|
||||
reg_value = air_mii_cl45_read(phydev, 0x1e, 0x8009);
|
||||
if (reg_value == EN8811H_PHY_READY) {
|
||||
priv->init_stage = AIR_INIT_FW_READY;
|
||||
dev_info(dev, "EN8811H PHY ready!\n");
|
||||
break;
|
||||
}
|
||||
if (retry == 0) {
|
||||
dev_err(dev, "MD32 FW is not ready.(Status 0x%x)\n", reg_value);
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
|
||||
dev_err(dev,
|
||||
"Check MD32 FW Version(0x3b3c) : %08x\n", pbus_value);
|
||||
dev_err(dev,
|
||||
"%s fail!\n", __func__);
|
||||
priv->init_stage = AIR_INIT_FW_FAIL;
|
||||
}
|
||||
} while (retry--);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int en8811h_config_init(struct phy_device *phydev)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 pbus_value = 0;
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
struct en8811h_priv *priv = phydev->priv;
|
||||
|
||||
ret = air_buckpbus_reg_write(phydev, 0x1e00d0, 0xf);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x1e0228, 0xf0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* If restart happened in .probe(), no need to restart now */
|
||||
if (priv->mcu_needs_restart) {
|
||||
ret = en8811h_restart_up(phydev);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
} else {
|
||||
ret = en8811h_init_up(phydev);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
/* Next calls to .config_init() mcu needs to restart */
|
||||
priv->mcu_needs_restart = true;
|
||||
}
|
||||
|
||||
priv->init_stage = AIR_INIT_CONFIG;
|
||||
ret = air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
/* Serdes polarity */
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
|
||||
pbus_value &= ~0x3;
|
||||
#if defined(CONFIG_OF)
|
||||
pbus_value |= priv->pol;
|
||||
#else
|
||||
pbus_value |= (EN8811H_RX_POL_NORMAL | EN8811H_TX_POL_NORMAL);
|
||||
#endif
|
||||
|
||||
ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_value);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
|
||||
dev_info(dev, "Tx, Rx Polarity : %08x\n", pbus_value);
|
||||
priv->firmware_version = air_buckpbus_reg_read(phydev, 0x3b3c);
|
||||
dev_info(dev, "MD32 FW Version : %08x\n", priv->firmware_version);
|
||||
|
||||
ret = air_surge_protect_cfg(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"air_surge_protect_cfg fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
}
|
||||
|
||||
ret = air_cko_cfg(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"air_cko_cfg fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
}
|
||||
|
||||
#if defined(AIR_LED_SUPPORT)
|
||||
ret = en8811h_led_init(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "en8811h_led_init fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
}
|
||||
#endif
|
||||
|
||||
priv->init_stage = AIR_INIT_SUCESS;
|
||||
dev_info(dev, "EN8811H initialize OK! (%s)\n", EN8811H_DRIVER_VERSION);
|
||||
return 0;
|
||||
|
||||
priv_free:
|
||||
kfree(priv);
|
||||
return ret;
|
||||
}
|
||||
static int en8811h_get_rate_matching(struct phy_device *phydev,
|
||||
phy_interface_t iface)
|
||||
{
|
||||
return RATE_MATCH_PAUSE;
|
||||
}
|
||||
|
||||
static int en8811h_config_aneg(struct phy_device *phydev)
|
||||
{
|
||||
bool changed = false;
|
||||
int err, val;
|
||||
|
||||
val = 0;
|
||||
if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
phydev->advertising))
|
||||
val |= MDIO_AN_10GBT_CTRL_ADV2_5G;
|
||||
err = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
|
||||
MDIO_AN_10GBT_CTRL_ADV2_5G, val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (err > 0)
|
||||
changed = true;
|
||||
|
||||
return __genphy_config_aneg(phydev, changed);
|
||||
}
|
||||
|
||||
static int en8811h_update_link(struct phy_device *phydev)
|
||||
{
|
||||
int status = 0, bmcr;
|
||||
struct mii_bus *mbus = phydev_mdio_bus(phydev);
|
||||
int addr = phydev_addr(phydev);
|
||||
|
||||
bmcr = air_mii_cl22_read(mbus, addr, MII_BMCR);
|
||||
if (bmcr < 0)
|
||||
return bmcr;
|
||||
/* Autoneg is being started, therefore disregard BMSR value and
|
||||
* report link as down.
|
||||
*/
|
||||
if (bmcr & BMCR_ANRESTART)
|
||||
goto done;
|
||||
status = air_mii_cl22_read(mbus, addr, MII_BMSR);
|
||||
if (status < 0)
|
||||
return status;
|
||||
done:
|
||||
phydev->link = status & BMSR_LSTATUS ? 1 : 0;
|
||||
phydev->autoneg_complete = status & BMSR_ANEGCOMPLETE ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int en8811h_read_status(struct phy_device *phydev)
|
||||
{
|
||||
struct en8811h_priv *priv = phydev->priv;
|
||||
u32 pbus_value;
|
||||
int old_link = phydev->link, ret;
|
||||
|
||||
ret = en8811h_update_link(phydev);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* why bother the PHY if nothing can have changed */
|
||||
if (old_link && phydev->link)
|
||||
return 0;
|
||||
phydev->speed = SPEED_UNKNOWN;
|
||||
phydev->duplex = DUPLEX_UNKNOWN;
|
||||
phydev->pause = 0;
|
||||
phydev->asym_pause = 0;
|
||||
phydev->rate_matching = RATE_MATCH_PAUSE;
|
||||
|
||||
ret = genphy_read_lpa(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Get link partner 2.5GBASE-T ability from vendor register */
|
||||
pbus_value = air_buckpbus_reg_read(phydev, EN8811H_2P5G_LPA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
phydev->lp_advertising,
|
||||
pbus_value & EN8811H_2P5G_LPA_2P5G);
|
||||
|
||||
phydev->duplex = DUPLEX_FULL;
|
||||
if (phydev->autoneg_complete)
|
||||
phy_resolve_aneg_pause(phydev);
|
||||
|
||||
if (!phydev->link)
|
||||
return 0;
|
||||
|
||||
ret = air_ref_clk_speed(phydev, AIR_PARA_PHYDEV);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Firmware before version 24011202 has no vendor register 2P5G_LPA.
|
||||
* Assume link partner advertised it if connected at 2500Mbps.
|
||||
*/
|
||||
if (priv->firmware_version < 0x24011202) {
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
phydev->lp_advertising,
|
||||
phydev->speed == SPEED_2500);
|
||||
}
|
||||
if (phydev->speed <= SPEED_1000)
|
||||
phydev->pause = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct phy_driver en8811h_driver[] = {
|
||||
{
|
||||
.phy_id = EN8811H_PHY_ID,
|
||||
@@ -530,6 +935,12 @@ static struct phy_driver en8811h_driver[] = {
|
||||
.read_mmd = __air_mii_cl45_read,
|
||||
.write_mmd = __air_mii_cl45_write,
|
||||
#endif
|
||||
.config_init = en8811h_config_init,
|
||||
.read_status = en8811h_read_status,
|
||||
.get_rate_matching = en8811h_get_rate_matching,
|
||||
.config_aneg = en8811h_config_aneg,
|
||||
.resume = genphy_resume,
|
||||
.suspend = genphy_suspend,
|
||||
} };
|
||||
|
||||
int __init en8811h_phy_driver_register(void)
|
||||
|
||||
@@ -18,6 +18,16 @@
|
||||
/* AN8855 registers */
|
||||
#define SCU_BASE 0x10000000
|
||||
#define RG_RGMII_TXCK_C (SCU_BASE + 0x1d0)
|
||||
#define RG_GPIO_LED_MODE (SCU_BASE + 0x0054)
|
||||
#define RG_GPIO_LED_SEL(i) (SCU_BASE + (0x0058 + ((i) * 4)))
|
||||
#define RG_INTB_MODE (SCU_BASE + 0x0080)
|
||||
#define RG_GDMP_RAM (SCU_BASE + 0x10000)
|
||||
|
||||
#define RG_GPIO_L_INV (SCU_BASE + 0x0010)
|
||||
#define RG_GPIO_CTRL (SCU_BASE + 0xa300)
|
||||
#define RG_GPIO_DATA (SCU_BASE + 0xa304)
|
||||
#define RG_GPIO_OE (SCU_BASE + 0xa314)
|
||||
|
||||
|
||||
#define HSGMII_AN_CSR_BASE 0x10220000
|
||||
#define SGMII_REG_AN0 (HSGMII_AN_CSR_BASE + 0x000)
|
||||
@@ -61,6 +71,8 @@
|
||||
#define SS_LCPLL_TDC_PCW_1 (QP_PMA_TOP_BASE + 0x248)
|
||||
#define INTF_CTRL_8 (QP_PMA_TOP_BASE + 0x320)
|
||||
#define INTF_CTRL_9 (QP_PMA_TOP_BASE + 0x324)
|
||||
#define INTF_CTRL_10 (QP_PMA_TOP_BASE + 0x328)
|
||||
#define INTF_CTRL_11 (QP_PMA_TOP_BASE + 0x32c)
|
||||
#define PLL_CTRL_0 (QP_PMA_TOP_BASE + 0x400)
|
||||
#define PLL_CTRL_2 (QP_PMA_TOP_BASE + 0x408)
|
||||
#define PLL_CTRL_3 (QP_PMA_TOP_BASE + 0x40c)
|
||||
@@ -78,6 +90,7 @@
|
||||
#define QP_ANA_CSR_BASE 0x1022f000
|
||||
#define RG_QP_RX_DAC_EN (QP_ANA_CSR_BASE + 0x00)
|
||||
#define RG_QP_RXAFE_RESERVE (QP_ANA_CSR_BASE + 0x04)
|
||||
#define RG_QP_CDR_LPF_BOT_LIM (QP_ANA_CSR_BASE + 0x08)
|
||||
#define RG_QP_CDR_LPF_MJV_LIM (QP_ANA_CSR_BASE + 0x0c)
|
||||
#define RG_QP_CDR_LPF_SETVALUE (QP_ANA_CSR_BASE + 0x14)
|
||||
#define RG_QP_CDR_PR_CKREF_DIV1 (QP_ANA_CSR_BASE + 0x18)
|
||||
@@ -106,9 +119,72 @@
|
||||
/* Fields of PHY_EXT_REG_14 */
|
||||
#define PHY_EN_DOWN_SHFIT BIT(4)
|
||||
|
||||
/* PHY dev address 0x1E */
|
||||
#define PHY_DEV1E 0x1e
|
||||
|
||||
/* PHY TX PAIR DELAY SELECT Register */
|
||||
#define PHY_TX_PAIR_DLY_SEL_GBE 0x013
|
||||
/* PHY ADC Register */
|
||||
#define PHY_RXADC_CTRL 0x0d8
|
||||
#define PHY_RXADC_REV_0 0x0d9
|
||||
#define PHY_RXADC_REV_1 0x0da
|
||||
|
||||
/* PHY LED Register bitmap of define */
|
||||
#define PHY_LED_CTRL_SELECT 0x3e8
|
||||
#define PHY_SINGLE_LED_ON_CTRL(i) (0x3e0 + ((i) * 2))
|
||||
#define PHY_SINGLE_LED_BLK_CTRL(i) (0x3e1 + ((i) * 2))
|
||||
#define PHY_SINGLE_LED_ON_DUR(i) (0x3e9 + ((i) * 2))
|
||||
#define PHY_SINGLE_LED_BLK_DUR(i) (0x3ea + ((i) * 2))
|
||||
|
||||
#define PHY_PMA_CTRL (0x340)
|
||||
|
||||
/* PHY dev address 0x1F */
|
||||
#define PHY_DEV1F 0x1f
|
||||
#define PHY_LED_ON_CTRL(i) (0x24 + ((i) * 2))
|
||||
#define LED_ON_EN (1 << 15)
|
||||
#define LED_ON_POL (1 << 14)
|
||||
#define LED_ON_EVT_MASK (0x7f)
|
||||
/* LED ON Event */
|
||||
#define LED_ON_EVT_FORCE (1 << 6)
|
||||
#define LED_ON_EVT_LINK_HD (1 << 5)
|
||||
#define LED_ON_EVT_LINK_FD (1 << 4)
|
||||
#define LED_ON_EVT_LINK_DOWN (1 << 3)
|
||||
#define LED_ON_EVT_LINK_10M (1 << 2)
|
||||
#define LED_ON_EVT_LINK_100M (1 << 1)
|
||||
#define LED_ON_EVT_LINK_1000M (1 << 0)
|
||||
|
||||
#define PHY_LED_BLK_CTRL(i) (0x25 + ((i) * 2))
|
||||
#define LED_BLK_EVT_MASK (0x3ff)
|
||||
/* LED Blinking Event */
|
||||
#define LED_BLK_EVT_FORCE (1 << 9)
|
||||
#define LED_BLK_EVT_10M_RX_ACT (1 << 5)
|
||||
#define LED_BLK_EVT_10M_TX_ACT (1 << 4)
|
||||
#define LED_BLK_EVT_100M_RX_ACT (1 << 3)
|
||||
#define LED_BLK_EVT_100M_TX_ACT (1 << 2)
|
||||
#define LED_BLK_EVT_1000M_RX_ACT (1 << 1)
|
||||
#define LED_BLK_EVT_1000M_TX_ACT (1 << 0)
|
||||
|
||||
#define PHY_LED_BCR (0x21)
|
||||
#define LED_BCR_EXT_CTRL (1 << 15)
|
||||
#define LED_BCR_CLK_EN (1 << 3)
|
||||
#define LED_BCR_TIME_TEST (1 << 2)
|
||||
#define LED_BCR_MODE_MASK (3)
|
||||
#define LED_BCR_MODE_DISABLE (0)
|
||||
|
||||
#define PHY_LED_ON_DUR (0x22)
|
||||
#define LED_ON_DUR_MASK (0xffff)
|
||||
|
||||
#define PHY_LED_BLK_DUR (0x23)
|
||||
#define LED_BLK_DUR_MASK (0xffff)
|
||||
|
||||
#define PHY_LED_BLINK_DUR_CTRL (0x720)
|
||||
|
||||
/* Unique fields of PMCR for AN8855 */
|
||||
#define FORCE_TX_FC BIT(4)
|
||||
#define FORCE_RX_FC BIT(5)
|
||||
#define FORCE_EEE100 BIT(6)
|
||||
#define FORCE_EEE1G BIT(7)
|
||||
#define FORCE_EEE2P5G BIT(8)
|
||||
#define FORCE_DPX BIT(25)
|
||||
#define FORCE_SPD BITS(28, 30)
|
||||
#define FORCE_LNK BIT(24)
|
||||
@@ -117,10 +193,114 @@
|
||||
#define CHIP_ID 0x10005000
|
||||
#define CHIP_REV 0x10005004
|
||||
|
||||
#define AN8855_EFUSE_DATA0 0x1000a500
|
||||
|
||||
const u8 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 u8 shift_check(u8 base)
|
||||
{
|
||||
u8 i;
|
||||
u32 sz = sizeof(r50ohm_table)/sizeof(u8);
|
||||
|
||||
for (i = 0; i < sz; ++i)
|
||||
if (r50ohm_table[i] == base)
|
||||
break;
|
||||
|
||||
if (i < 8 || i >= sz)
|
||||
return 25; /* index of 94 */
|
||||
|
||||
return (i - 8);
|
||||
}
|
||||
|
||||
static u8 get_shift_val(u8 idx)
|
||||
{
|
||||
return r50ohm_table[idx];
|
||||
}
|
||||
|
||||
/* T830 AN8855 Reference Board */
|
||||
static const struct an8855_led_cfg led_cfg[] = {
|
||||
/*************************************************************************
|
||||
* Enable, LED idx, LED Polarity, LED ON event, LED Blink event LED Freq
|
||||
*************************************************************************
|
||||
*/
|
||||
/* GPIO0 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO1 */
|
||||
{1, P0_LED1, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO2 */
|
||||
{1, P1_LED1, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO3 */
|
||||
{1, P2_LED1, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO4 */
|
||||
{1, P3_LED1, LED_LOW, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO5 */
|
||||
{1, P4_LED1, LED_LOW, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO6 */
|
||||
{0, PHY_LED_MAX, LED_LOW, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO7 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO8 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO9 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO10 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO11 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO12 */
|
||||
{0, PHY_LED_MAX, LED_LOW, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO13 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO14 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO15 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO16 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO17 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO18 */
|
||||
{0, PHY_LED_MAX, LED_HIGH, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO19 */
|
||||
{0, PHY_LED_MAX, LED_LOW, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
/* GPIO20 */
|
||||
{0, PHY_LED_MAX, LED_LOW, LED_ON_EVENT, LED_BLK_EVENT, LED_FREQ},
|
||||
};
|
||||
|
||||
static int an8855_set_hsgmii_mode(struct gsw_an8855 *gsw)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
/* TX FIR - improve TX EYE */
|
||||
val = an8855_reg_read(gsw, INTF_CTRL_10);
|
||||
val &= ~(0x3f << 16);
|
||||
val |= BIT(21);
|
||||
val &= ~(0x1f << 24);
|
||||
val |= (0x4 << 24);
|
||||
val |= BIT(29);
|
||||
an8855_reg_write(gsw, INTF_CTRL_10, val);
|
||||
|
||||
val = an8855_reg_read(gsw, INTF_CTRL_11);
|
||||
val &= ~(0x3f);
|
||||
val |= BIT(6);
|
||||
an8855_reg_write(gsw, INTF_CTRL_11, val);
|
||||
|
||||
/* RX CDR - improve RX Jitter Tolerance */
|
||||
val = an8855_reg_read(gsw, RG_QP_CDR_LPF_BOT_LIM);
|
||||
val &= ~(0x7 << 24);
|
||||
val |= (0x5 << 24);
|
||||
val &= ~(0x7 << 20);
|
||||
val |= (0x5 << 20);
|
||||
an8855_reg_write(gsw, RG_QP_CDR_LPF_BOT_LIM, val);
|
||||
|
||||
/* PLL */
|
||||
val = an8855_reg_read(gsw, QP_DIG_MODE_CTRL_1);
|
||||
val &= ~(0x3 << 2);
|
||||
@@ -250,7 +430,7 @@ static int an8855_set_hsgmii_mode(struct gsw_an8855 *gsw)
|
||||
val &= ~(0xf << 25);
|
||||
val |= (0x1 << 25);
|
||||
val &= ~(0x7 << 29);
|
||||
val |= (0x3 << 29);
|
||||
val |= (0x6 << 29);
|
||||
an8855_reg_write(gsw, RG_QP_CDR_LPF_SETVALUE, val);
|
||||
|
||||
val = an8855_reg_read(gsw, RG_QP_CDR_PR_CKREF_DIV1);
|
||||
@@ -281,12 +461,10 @@ static int an8855_set_hsgmii_mode(struct gsw_an8855 *gsw)
|
||||
val |= (0x4 << 24);
|
||||
an8855_reg_write(gsw, RG_QP_CDR_PR_CKREF_DIV1, val);
|
||||
|
||||
val = an8855_reg_read(gsw, PLL_CTRL_0);
|
||||
val |= BIT(0);
|
||||
an8855_reg_write(gsw, PLL_CTRL_0, val);
|
||||
|
||||
/* PMA (For HW Mode) */
|
||||
val = an8855_reg_read(gsw, RX_CTRL_26);
|
||||
val &= ~BIT(23);
|
||||
val |= BIT(23);
|
||||
val &= ~BIT(24);
|
||||
val |= BIT(26);
|
||||
an8855_reg_write(gsw, RX_CTRL_26, val);
|
||||
|
||||
@@ -314,8 +492,8 @@ static int an8855_set_hsgmii_mode(struct gsw_an8855 *gsw)
|
||||
val = an8855_reg_read(gsw, RX_CTRL_8);
|
||||
val &= ~(0xfff << 16);
|
||||
val |= (0x200 << 16);
|
||||
val &= ~(0x7fff << 14);
|
||||
val |= (0xfff << 14);
|
||||
val &= ~(0x7fff << 0);
|
||||
val |= (0xfff << 0);
|
||||
an8855_reg_write(gsw, RX_CTRL_8, val);
|
||||
|
||||
/* Frequency memter */
|
||||
@@ -334,6 +512,10 @@ static int an8855_set_hsgmii_mode(struct gsw_an8855 *gsw)
|
||||
val |= (0x2710 << 0);
|
||||
an8855_reg_write(gsw, RX_CTRL_7, val);
|
||||
|
||||
val = an8855_reg_read(gsw, PLL_CTRL_0);
|
||||
val |= BIT(0);
|
||||
an8855_reg_write(gsw, PLL_CTRL_0, val);
|
||||
|
||||
/* PCS Init */
|
||||
val = an8855_reg_read(gsw, RG_HSGMII_PCS_CTROL_1);
|
||||
val &= ~BIT(30);
|
||||
@@ -372,6 +554,28 @@ static int an8855_sgmii_setup(struct gsw_an8855 *gsw, int mode)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
/* TX FIR - improve TX EYE */
|
||||
val = an8855_reg_read(gsw, INTF_CTRL_10);
|
||||
val &= ~(0x3f << 16);
|
||||
val |= BIT(21);
|
||||
val &= ~(0x1f << 24);
|
||||
val |= BIT(29);
|
||||
an8855_reg_write(gsw, INTF_CTRL_10, val);
|
||||
|
||||
val = an8855_reg_read(gsw, INTF_CTRL_11);
|
||||
val &= ~(0x3f);
|
||||
val |= (0xd << 0);
|
||||
val |= BIT(6);
|
||||
an8855_reg_write(gsw, INTF_CTRL_11, val);
|
||||
|
||||
/* RX CDR - improve RX Jitter Tolerance */
|
||||
val = an8855_reg_read(gsw, RG_QP_CDR_LPF_BOT_LIM);
|
||||
val &= ~(0x7 << 24);
|
||||
val |= (0x6 << 24);
|
||||
val &= ~(0x7 << 20);
|
||||
val |= (0x6 << 20);
|
||||
an8855_reg_write(gsw, RG_QP_CDR_LPF_BOT_LIM, val);
|
||||
|
||||
/* PMA Init */
|
||||
/* PLL */
|
||||
val = an8855_reg_read(gsw, QP_DIG_MODE_CTRL_1);
|
||||
@@ -531,13 +735,10 @@ static int an8855_sgmii_setup(struct gsw_an8855 *gsw, int mode)
|
||||
val |= (0x4 << 24);
|
||||
an8855_reg_write(gsw, RG_QP_CDR_PR_CKREF_DIV1, val);
|
||||
|
||||
val = an8855_reg_read(gsw, PLL_CTRL_0);
|
||||
val |= BIT(0);
|
||||
an8855_reg_write(gsw, PLL_CTRL_0, val);
|
||||
|
||||
/* PMA (For HW Mode) */
|
||||
val = an8855_reg_read(gsw, RX_CTRL_26);
|
||||
val &= ~BIT(23);
|
||||
if (mode == SGMII_MODE_AN)
|
||||
val |= BIT(23);
|
||||
val &= ~BIT(24);
|
||||
val |= BIT(26);
|
||||
|
||||
an8855_reg_write(gsw, RX_CTRL_26, val);
|
||||
@@ -586,6 +787,10 @@ static int an8855_sgmii_setup(struct gsw_an8855 *gsw, int mode)
|
||||
val |= (0x2710 << 0);
|
||||
an8855_reg_write(gsw, RX_CTRL_7, val);
|
||||
|
||||
val = an8855_reg_read(gsw, PLL_CTRL_0);
|
||||
val |= BIT(0);
|
||||
an8855_reg_write(gsw, PLL_CTRL_0, val);
|
||||
|
||||
if (mode == SGMII_MODE_FORCE) {
|
||||
/* PCS Init */
|
||||
val = an8855_reg_read(gsw, QP_DIG_MODE_CTRL_0);
|
||||
@@ -670,7 +875,6 @@ static int an8855_sgmii_setup(struct gsw_an8855 *gsw, int mode)
|
||||
/* Restart AN */
|
||||
val = an8855_reg_read(gsw, SGMII_REG_AN0);
|
||||
val |= BIT(9);
|
||||
val |= BIT(15);
|
||||
an8855_reg_write(gsw, SGMII_REG_AN0, val);
|
||||
}
|
||||
|
||||
@@ -745,6 +949,9 @@ static int an8855_mac_port_setup(struct gsw_an8855 *gsw, u32 port,
|
||||
phy_modes(port_cfg->phy_mode), port);
|
||||
}
|
||||
|
||||
/* disable eee on cpu port */
|
||||
pmcr &= ~(FORCE_EEE100 | FORCE_EEE1G | FORCE_EEE2P5G);
|
||||
|
||||
if (port_cfg->force_link)
|
||||
an8855_reg_write(gsw, PMCR(port), pmcr);
|
||||
}
|
||||
@@ -772,7 +979,10 @@ static int an8855_sw_detect(struct gsw_an8855 *gsw, struct chip_rev *crev)
|
||||
|
||||
static void an8855_phy_setting(struct gsw_an8855 *gsw)
|
||||
{
|
||||
int i;
|
||||
int i, j;
|
||||
u8 shift_sel = 0, rsel_tx_a = 0, rsel_tx_b = 0;
|
||||
u8 rsel_tx_c = 0, rsel_tx_d = 0;
|
||||
u16 cl45_data = 0;
|
||||
u32 val;
|
||||
|
||||
/* Release power down */
|
||||
@@ -791,40 +1001,44 @@ static void an8855_phy_setting(struct gsw_an8855 *gsw)
|
||||
val |= ADVERTISE_PAUSE_ASYM;
|
||||
gsw->mii_write(gsw, i, MII_ADVERTISE, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void an8855_low_power_setting(struct gsw_an8855 *gsw)
|
||||
{
|
||||
int port, addr;
|
||||
if (gsw->extSurge) {
|
||||
for (i = 0; i < AN8855_NUM_PHYS; i++) {
|
||||
/* Read data */
|
||||
for (j = 0; j < AN8855_WORD_SIZE; j++) {
|
||||
val = an8855_reg_read(gsw, AN8855_EFUSE_DATA0 +
|
||||
(AN8855_WORD_SIZE * (3 + j + (4 * i))));
|
||||
|
||||
for (port = 0; port < AN8855_NUM_PHYS; port++) {
|
||||
gsw->mmd_write(gsw, port, 0x1e, 0x11, 0x0f00);
|
||||
gsw->mmd_write(gsw, port, 0x1e, 0x3c, 0x0000);
|
||||
gsw->mmd_write(gsw, port, 0x1e, 0x3d, 0x0000);
|
||||
gsw->mmd_write(gsw, port, 0x1e, 0x3e, 0x0000);
|
||||
gsw->mmd_write(gsw, port, 0x1e, 0xc6, 0x53aa);
|
||||
shift_sel = shift_check((val & 0x7f000000) >> 24);
|
||||
switch (j) {
|
||||
case 0:
|
||||
rsel_tx_a = get_shift_val(shift_sel);
|
||||
break;
|
||||
case 1:
|
||||
rsel_tx_b = get_shift_val(shift_sel);
|
||||
break;
|
||||
case 2:
|
||||
rsel_tx_c = get_shift_val(shift_sel);
|
||||
break;
|
||||
case 3:
|
||||
rsel_tx_d = get_shift_val(shift_sel);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
cl45_data = gsw->mmd_read(gsw, i, PHY_DEV1E, 0x174);
|
||||
cl45_data &= ~(0x7f7f);
|
||||
cl45_data |= (rsel_tx_a << 8);
|
||||
cl45_data |= rsel_tx_b;
|
||||
gsw->mmd_write(gsw, i, PHY_DEV1E, 0x174, cl45_data);
|
||||
cl45_data = gsw->mmd_read(gsw, i, PHY_DEV1E, 0x175);
|
||||
cl45_data &= ~(0x7f7f);
|
||||
cl45_data |= (rsel_tx_c << 8);
|
||||
cl45_data |= rsel_tx_d;
|
||||
gsw->mmd_write(gsw, i, PHY_DEV1E, 0x175, cl45_data);
|
||||
}
|
||||
}
|
||||
|
||||
gsw->mmd_write(gsw, 0, 0x1f, 0x268, 0x07f1);
|
||||
gsw->mmd_write(gsw, 0, 0x1f, 0x269, 0x2111);
|
||||
gsw->mmd_write(gsw, 0, 0x1f, 0x26a, 0x0000);
|
||||
gsw->mmd_write(gsw, 0, 0x1f, 0x26b, 0x0074);
|
||||
gsw->mmd_write(gsw, 0, 0x1f, 0x26e, 0x00f6);
|
||||
gsw->mmd_write(gsw, 0, 0x1f, 0x26f, 0x6666);
|
||||
gsw->mmd_write(gsw, 0, 0x1f, 0x271, 0x2c02);
|
||||
gsw->mmd_write(gsw, 0, 0x1f, 0x272, 0x0c22);
|
||||
gsw->mmd_write(gsw, 0, 0x1f, 0x700, 0x0001);
|
||||
gsw->mmd_write(gsw, 0, 0x1f, 0x701, 0x0803);
|
||||
gsw->mmd_write(gsw, 0, 0x1f, 0x702, 0x01b6);
|
||||
gsw->mmd_write(gsw, 0, 0x1f, 0x703, 0x2111);
|
||||
|
||||
gsw->mmd_write(gsw, 1, 0x1f, 0x700, 0x0001);
|
||||
|
||||
for (addr = 0x200; addr <= 0x230; addr += 2)
|
||||
gsw->mmd_write(gsw, 0, 0x1f, addr, 0x2020);
|
||||
|
||||
for (addr = 0x201; addr <= 0x231; addr += 2)
|
||||
gsw->mmd_write(gsw, 0, 0x1f, addr, 0x0020);
|
||||
}
|
||||
|
||||
static void an8855_eee_setting(struct gsw_an8855 *gsw, u32 port)
|
||||
@@ -833,10 +1047,216 @@ static void an8855_eee_setting(struct gsw_an8855 *gsw, u32 port)
|
||||
gsw->mmd_write(gsw, port, PHY_DEV07, PHY_DEV07_REG_03C, 0);
|
||||
}
|
||||
|
||||
static int an8855_led_set_usr_def(struct gsw_an8855 *gsw, u8 entity,
|
||||
int polar, u16 on_evt, u16 blk_evt, u8 led_freq)
|
||||
{
|
||||
u32 cl45_data = 0;
|
||||
|
||||
if (polar == LED_HIGH)
|
||||
on_evt |= LED_ON_POL;
|
||||
else
|
||||
on_evt &= ~LED_ON_POL;
|
||||
|
||||
/* LED on event */
|
||||
gsw->mmd_write(gsw, (entity / 4), PHY_DEV1E,
|
||||
PHY_SINGLE_LED_ON_CTRL(entity % 4), on_evt | LED_ON_EN);
|
||||
|
||||
/* LED blink event */
|
||||
gsw->mmd_write(gsw, (entity / 4), PHY_DEV1E,
|
||||
PHY_SINGLE_LED_BLK_CTRL(entity % 4), blk_evt);
|
||||
|
||||
/* LED freq */
|
||||
switch (led_freq) {
|
||||
case AIR_LED_BLK_DUR_32M:
|
||||
cl45_data = 0x30e;
|
||||
break;
|
||||
case AIR_LED_BLK_DUR_64M:
|
||||
cl45_data = 0x61a;
|
||||
break;
|
||||
case AIR_LED_BLK_DUR_128M:
|
||||
cl45_data = 0xc35;
|
||||
break;
|
||||
case AIR_LED_BLK_DUR_256M:
|
||||
cl45_data = 0x186a;
|
||||
break;
|
||||
case AIR_LED_BLK_DUR_512M:
|
||||
cl45_data = 0x30d4;
|
||||
break;
|
||||
case AIR_LED_BLK_DUR_1024M:
|
||||
cl45_data = 0x61a8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
gsw->mmd_write(gsw, (entity / 4), PHY_DEV1E,
|
||||
PHY_SINGLE_LED_BLK_DUR(entity % 4), cl45_data);
|
||||
|
||||
gsw->mmd_write(gsw, (entity / 4), PHY_DEV1E,
|
||||
PHY_SINGLE_LED_ON_DUR(entity % 4), (cl45_data >> 1));
|
||||
|
||||
/* Disable DATA & BAD_SSD for port LED blink behavior */
|
||||
cl45_data = gsw->mmd_read(gsw, (entity / 4), PHY_DEV1E,
|
||||
PHY_PMA_CTRL);
|
||||
cl45_data &= ~BIT(0);
|
||||
cl45_data &= ~BIT(15);
|
||||
gsw->mmd_write(gsw, (entity / 4), PHY_DEV1E,
|
||||
PHY_PMA_CTRL, cl45_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_led_set_mode(struct gsw_an8855 *gsw, u8 mode)
|
||||
{
|
||||
u16 cl45_data;
|
||||
|
||||
cl45_data = gsw->mmd_read(gsw, 0, PHY_DEV1F, PHY_LED_BCR);
|
||||
switch (mode) {
|
||||
case AN8855_LED_MODE_DISABLE:
|
||||
cl45_data &= ~LED_BCR_EXT_CTRL;
|
||||
cl45_data &= ~LED_BCR_MODE_MASK;
|
||||
cl45_data |= LED_BCR_MODE_DISABLE;
|
||||
break;
|
||||
case AN8855_LED_MODE_USER_DEFINE:
|
||||
cl45_data |= LED_BCR_EXT_CTRL;
|
||||
cl45_data |= LED_BCR_CLK_EN;
|
||||
break;
|
||||
default:
|
||||
dev_info(gsw->dev, "LED mode%d is not supported!\n", mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_LED_BCR, cl45_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_led_set_state(struct gsw_an8855 *gsw, u8 entity, u8 state)
|
||||
{
|
||||
u16 cl45_data = 0;
|
||||
|
||||
/* Change to per port contorl */
|
||||
cl45_data = gsw->mmd_read(gsw, (entity / 4), PHY_DEV1E,
|
||||
PHY_LED_CTRL_SELECT);
|
||||
|
||||
if (state == 1)
|
||||
cl45_data |= (1 << (entity % 4));
|
||||
else
|
||||
cl45_data &= ~(1 << (entity % 4));
|
||||
gsw->mmd_write(gsw, (entity / 4), PHY_DEV1E,
|
||||
PHY_LED_CTRL_SELECT, cl45_data);
|
||||
|
||||
/* LED enable setting */
|
||||
cl45_data = gsw->mmd_read(gsw, (entity / 4),
|
||||
PHY_DEV1E, PHY_SINGLE_LED_ON_CTRL(entity % 4));
|
||||
|
||||
if (state == 1)
|
||||
cl45_data |= LED_ON_EN;
|
||||
else
|
||||
cl45_data &= ~LED_ON_EN;
|
||||
|
||||
gsw->mmd_write(gsw, (entity / 4), PHY_DEV1E,
|
||||
PHY_SINGLE_LED_ON_CTRL(entity % 4), cl45_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_led_init(struct gsw_an8855 *gsw)
|
||||
{
|
||||
u32 val, led_count = ARRAY_SIZE(led_cfg);
|
||||
int ret = 0, id;
|
||||
u32 tmp_val = 0;
|
||||
u32 tmp_id = 0;
|
||||
|
||||
ret = an8855_led_set_mode(gsw, AN8855_LED_MODE_USER_DEFINE);
|
||||
if (ret != 0) {
|
||||
dev_info(gsw->dev, "led_set_mode fail(ret:%d)!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (id = 0; id < led_count; id++) {
|
||||
ret = an8855_led_set_state(gsw,
|
||||
led_cfg[id].phy_led_idx, led_cfg[id].en);
|
||||
if (ret != 0) {
|
||||
dev_info(gsw->dev, "led_set_state fail(ret:%d)!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (led_cfg[id].en == 1) {
|
||||
ret = an8855_led_set_usr_def(gsw,
|
||||
led_cfg[id].phy_led_idx,
|
||||
led_cfg[id].pol, led_cfg[id].on_cfg,
|
||||
led_cfg[id].blk_cfg,
|
||||
led_cfg[id].led_freq);
|
||||
if (ret != 0) {
|
||||
dev_info(gsw->dev, "led_set_usr_def fail!\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Setting for System LED & Loop LED */
|
||||
an8855_reg_write(gsw, RG_GPIO_OE, 0x0);
|
||||
an8855_reg_write(gsw, RG_GPIO_CTRL, 0x0);
|
||||
val = 0;
|
||||
an8855_reg_write(gsw, RG_GPIO_L_INV, val);
|
||||
|
||||
val = 0x1001;
|
||||
an8855_reg_write(gsw, RG_GPIO_CTRL, val);
|
||||
val = an8855_reg_read(gsw, RG_GPIO_DATA);
|
||||
val |= BITS(1, 3);
|
||||
val &= ~(BIT(0));
|
||||
val &= ~(BIT(6));
|
||||
|
||||
an8855_reg_write(gsw, RG_GPIO_DATA, val);
|
||||
val = an8855_reg_read(gsw, RG_GPIO_OE);
|
||||
val |= 0x41;
|
||||
an8855_reg_write(gsw, RG_GPIO_OE, val);
|
||||
|
||||
/* Mapping between GPIO & LED */
|
||||
val = 0;
|
||||
for (id = 0; id < led_count; id++) {
|
||||
/* Skip GPIO6, due to GPIO6 does not support PORT LED */
|
||||
if (id == 6)
|
||||
continue;
|
||||
|
||||
if (led_cfg[id].en == 1) {
|
||||
if (id < 7)
|
||||
val |= led_cfg[id].phy_led_idx << ((id % 4) * 8);
|
||||
else
|
||||
val |= led_cfg[id].phy_led_idx << (((id - 1) % 4) * 8);
|
||||
}
|
||||
|
||||
if (id < 7)
|
||||
tmp_id = id;
|
||||
else
|
||||
tmp_id = id - 1;
|
||||
|
||||
if ((tmp_id % 4) == 0x3) {
|
||||
an8855_reg_write(gsw, RG_GPIO_LED_SEL(tmp_id / 4), val);
|
||||
tmp_val = an8855_reg_read(gsw, RG_GPIO_LED_SEL(tmp_id / 4));
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Turn on LAN LED mode */
|
||||
val = 0;
|
||||
for (id = 0; id < led_count; id++) {
|
||||
if (led_cfg[id].en == 1)
|
||||
val |= 0x1 << id;
|
||||
}
|
||||
an8855_reg_write(gsw, RG_GPIO_LED_MODE, val);
|
||||
|
||||
/* Force clear blink pulse for per port LED */
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_LED_BLINK_DUR_CTRL, 0x1f);
|
||||
usleep_range(1000, 5000);
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_LED_BLINK_DUR_CTRL, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_sw_init(struct gsw_an8855 *gsw)
|
||||
{
|
||||
int i;
|
||||
u32 val;
|
||||
int i, ret = 0;
|
||||
u32 val, led_count = ARRAY_SIZE(led_cfg);
|
||||
int id;
|
||||
|
||||
gsw->phy_base = gsw->smi_addr & AN8855_SMI_ADDR_MASK;
|
||||
|
||||
@@ -852,7 +1272,7 @@ static int an8855_sw_init(struct gsw_an8855 *gsw)
|
||||
an8855_reg_write(gsw, SYS_CTRL, SW_SYS_RST);
|
||||
usleep_range(100000, 110000);
|
||||
|
||||
/* change gphy smi address */
|
||||
/* Change gphy smi address */
|
||||
if (gsw->new_smi_addr != gsw->smi_addr) {
|
||||
an8855_reg_write(gsw, RG_GPHY_SMI_ADDR, gsw->new_smi_addr);
|
||||
gsw->smi_addr = gsw->new_smi_addr;
|
||||
@@ -865,6 +1285,59 @@ static int an8855_sw_init(struct gsw_an8855 *gsw)
|
||||
gsw->mii_write(gsw, i, MII_BMCR, val);
|
||||
}
|
||||
|
||||
/* AN8855H need to setup before switch init */
|
||||
val = an8855_reg_read(gsw, PKG_SEL);
|
||||
if ((val & 0x7) == PAG_SEL_AN8855H) {
|
||||
|
||||
/* Invert for LED activity change */
|
||||
val = an8855_reg_read(gsw, RG_GPIO_L_INV);
|
||||
for (id = 0; id < led_count; id++) {
|
||||
if ((led_cfg[id].pol == LED_HIGH) &&
|
||||
(led_cfg[id].en == 1))
|
||||
val |= 0x1 << id;
|
||||
}
|
||||
an8855_reg_write(gsw, RG_GPIO_L_INV, (val | 0x1));
|
||||
|
||||
/* MCU NOP CMD */
|
||||
an8855_reg_write(gsw, RG_GDMP_RAM, 0x846);
|
||||
an8855_reg_write(gsw, RG_GDMP_RAM + 4, 0x4a);
|
||||
|
||||
/* Enable MCU */
|
||||
val = an8855_reg_read(gsw, RG_CLK_CPU_ICG);
|
||||
an8855_reg_write(gsw, RG_CLK_CPU_ICG, val | MCU_ENABLE);
|
||||
usleep_range(1000, 5000);
|
||||
|
||||
/* Disable MCU watchdog */
|
||||
val = an8855_reg_read(gsw, RG_TIMER_CTL);
|
||||
an8855_reg_write(gsw, RG_TIMER_CTL, (val & (~WDOG_ENABLE)));
|
||||
|
||||
/* Configure interrupt */
|
||||
an8855_reg_write(gsw, RG_INTB_MODE, (0x1 << gsw->intr_pin));
|
||||
|
||||
/* LED settings for T830 reference board */
|
||||
ret = an8855_led_init(gsw);
|
||||
if (ret < 0) {
|
||||
dev_info(gsw->dev, "an8855_led_init fail. (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust to reduce noise */
|
||||
for (i = 0; i < AN8855_NUM_PHYS; i++) {
|
||||
gsw->mmd_write(gsw, i, PHY_DEV1E,
|
||||
PHY_TX_PAIR_DLY_SEL_GBE, 0x4040);
|
||||
|
||||
gsw->mmd_write(gsw, i, PHY_DEV1E,
|
||||
PHY_RXADC_CTRL, 0x1010);
|
||||
|
||||
gsw->mmd_write(gsw, i, PHY_DEV1E,
|
||||
PHY_RXADC_REV_0, 0x100);
|
||||
|
||||
gsw->mmd_write(gsw, i, PHY_DEV1E,
|
||||
PHY_RXADC_REV_1, 0x100);
|
||||
}
|
||||
|
||||
/* Setup SERDES port 5 */
|
||||
an8855_mac_port_setup(gsw, 5, &gsw->port5_cfg);
|
||||
|
||||
/* Global mac control settings */
|
||||
@@ -875,6 +1348,7 @@ static int an8855_sw_init(struct gsw_an8855 *gsw)
|
||||
val = an8855_reg_read(gsw, CKGCR);
|
||||
val &= ~(CKG_LNKDN_GLB_STOP | CKG_LNKDN_PORT_STOP);
|
||||
an8855_reg_write(gsw, CKGCR, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,24 @@
|
||||
|
||||
#define AN8855_DFL_CPU_PORT 5
|
||||
#define AN8855_NUM_PHYS 5
|
||||
#define AN8855_WORD_SIZE 4
|
||||
#define AN8855_DFL_SMI_ADDR 0x1
|
||||
#define AN8855_SMI_ADDR_MASK 0x1f
|
||||
#define AN8855_DFL_INTR_ID 0xd
|
||||
#define AN8855_DFL_EXT_SURGE 0x0
|
||||
|
||||
#define LED_ON_EVENT (LED_ON_EVT_LINK_1000M | \
|
||||
LED_ON_EVT_LINK_100M | LED_ON_EVT_LINK_10M |\
|
||||
LED_ON_EVT_LINK_HD | LED_ON_EVT_LINK_FD)
|
||||
|
||||
#define LED_BLK_EVENT (LED_BLK_EVT_1000M_TX_ACT | \
|
||||
LED_BLK_EVT_1000M_RX_ACT | \
|
||||
LED_BLK_EVT_100M_TX_ACT | \
|
||||
LED_BLK_EVT_100M_RX_ACT | \
|
||||
LED_BLK_EVT_10M_TX_ACT | \
|
||||
LED_BLK_EVT_10M_RX_ACT)
|
||||
|
||||
#define LED_FREQ AIR_LED_BLK_DUR_64M
|
||||
|
||||
struct gsw_an8855;
|
||||
|
||||
@@ -37,6 +53,60 @@ enum sgmii_mode {
|
||||
SGMII_MODE_FORCE,
|
||||
};
|
||||
|
||||
enum phy_led_idx {
|
||||
P0_LED0,
|
||||
P0_LED1,
|
||||
P0_LED2,
|
||||
P0_LED3,
|
||||
P1_LED0,
|
||||
P1_LED1,
|
||||
P1_LED2,
|
||||
P1_LED3,
|
||||
P2_LED0,
|
||||
P2_LED1,
|
||||
P2_LED2,
|
||||
P2_LED3,
|
||||
P3_LED0,
|
||||
P3_LED1,
|
||||
P3_LED2,
|
||||
P3_LED3,
|
||||
P4_LED0,
|
||||
P4_LED1,
|
||||
P4_LED2,
|
||||
P4_LED3,
|
||||
PHY_LED_MAX
|
||||
};
|
||||
|
||||
/* TBD */
|
||||
enum an8855_led_blk_dur {
|
||||
AIR_LED_BLK_DUR_32M,
|
||||
AIR_LED_BLK_DUR_64M,
|
||||
AIR_LED_BLK_DUR_128M,
|
||||
AIR_LED_BLK_DUR_256M,
|
||||
AIR_LED_BLK_DUR_512M,
|
||||
AIR_LED_BLK_DUR_1024M,
|
||||
AIR_LED_BLK_DUR_LAST
|
||||
};
|
||||
|
||||
enum an8855_led_polarity {
|
||||
LED_LOW,
|
||||
LED_HIGH,
|
||||
};
|
||||
enum an8855_led_mode {
|
||||
AN8855_LED_MODE_DISABLE,
|
||||
AN8855_LED_MODE_USER_DEFINE,
|
||||
AN8855_LED_MODE_LAST
|
||||
};
|
||||
|
||||
struct an8855_led_cfg {
|
||||
u16 en;
|
||||
u8 phy_led_idx;
|
||||
u16 pol;
|
||||
u16 on_cfg;
|
||||
u16 blk_cfg;
|
||||
u8 led_freq;
|
||||
};
|
||||
|
||||
struct an8855_port_cfg {
|
||||
struct device_node *np;
|
||||
phy_interface_t phy_mode;
|
||||
@@ -55,6 +125,8 @@ struct gsw_an8855 {
|
||||
u32 smi_addr;
|
||||
u32 new_smi_addr;
|
||||
u32 phy_base;
|
||||
u32 intr_pin;
|
||||
u32 extSurge;
|
||||
|
||||
enum an8855_model model;
|
||||
const char *name;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifian8855_gsw_ider: GPL-2.0
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023 Airoha Inc.
|
||||
* Author: Min Yao <min.yao@airoha.com>
|
||||
@@ -18,6 +18,9 @@
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
#include "an8855.h"
|
||||
#include "an8855_swconfig.h"
|
||||
@@ -25,11 +28,15 @@
|
||||
#include "an8855_nl.h"
|
||||
|
||||
/* AN8855 driver version */
|
||||
#define ARHT_AN8855_SWCFG_DRIVER_VER "1.0.1-L5.4"
|
||||
#define ARHT_AN8855_SWCFG_DRIVER_VER "1.0.6"
|
||||
#define ARHT_CHIP_NAME "an8855"
|
||||
#define ARHT_PROC_DIR "air_sw"
|
||||
#define ARHT_PROC_NODE_DEVICE "device"
|
||||
|
||||
static u32 an8855_gsw_id;
|
||||
struct list_head an8855_devs;
|
||||
static DEFINE_MUTEX(an8855_devs_lock);
|
||||
struct proc_dir_entry *proc_an8855_gsw_dir;
|
||||
|
||||
static struct an8855_sw_id *an8855_sw_ids[] = {
|
||||
&an8855_id,
|
||||
@@ -53,7 +60,6 @@ u32 an8855_reg_read(struct gsw_an8855 *gsw, u32 reg)
|
||||
high = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, 0x17);
|
||||
|
||||
gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x0);
|
||||
gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0);
|
||||
|
||||
mutex_unlock(&gsw->host_bus->mdio_lock);
|
||||
|
||||
@@ -78,7 +84,6 @@ void an8855_reg_write(struct gsw_an8855 *gsw, u32 reg, u32 val)
|
||||
(val & 0xFFFF));
|
||||
|
||||
gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x0);
|
||||
gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0);
|
||||
|
||||
mutex_unlock(&gsw->host_bus->mdio_lock);
|
||||
}
|
||||
@@ -110,13 +115,17 @@ void an8855_mii_write(struct gsw_an8855 *gsw, int phy, int reg, u16 val)
|
||||
int an8855_mmd_read(struct gsw_an8855 *gsw, int addr, int devad, u16 reg)
|
||||
{
|
||||
int val;
|
||||
u32 regnum = MII_ADDR_C45 | (devad << 16) | reg;
|
||||
|
||||
if (addr < AN8855_NUM_PHYS)
|
||||
addr = (gsw->phy_base + addr) & AN8855_SMI_ADDR_MASK;
|
||||
|
||||
mutex_lock(&gsw->host_bus->mdio_lock);
|
||||
val = gsw->host_bus->read(gsw->host_bus, addr, regnum);
|
||||
|
||||
gsw->host_bus->write(gsw->host_bus, addr, 0x0d, devad);
|
||||
gsw->host_bus->write(gsw->host_bus, addr, 0x0e, reg);
|
||||
gsw->host_bus->write(gsw->host_bus, addr, 0x0d, devad | (0x4000));
|
||||
val = gsw->host_bus->read(gsw->host_bus, addr, 0xe);
|
||||
|
||||
mutex_unlock(&gsw->host_bus->mdio_lock);
|
||||
|
||||
return val;
|
||||
@@ -125,13 +134,16 @@ int an8855_mmd_read(struct gsw_an8855 *gsw, int addr, int devad, u16 reg)
|
||||
void an8855_mmd_write(struct gsw_an8855 *gsw, int addr, int devad, u16 reg,
|
||||
u16 val)
|
||||
{
|
||||
u32 regnum = MII_ADDR_C45 | (devad << 16) | reg;
|
||||
|
||||
if (addr < AN8855_NUM_PHYS)
|
||||
addr = (gsw->phy_base + addr) & AN8855_SMI_ADDR_MASK;
|
||||
|
||||
mutex_lock(&gsw->host_bus->mdio_lock);
|
||||
gsw->host_bus->write(gsw->host_bus, addr, regnum, val);
|
||||
|
||||
gsw->host_bus->write(gsw->host_bus, addr, 0x0d, devad);
|
||||
gsw->host_bus->write(gsw->host_bus, addr, 0x0e, reg);
|
||||
gsw->host_bus->write(gsw->host_bus, addr, 0x0d, devad | (0x4000));
|
||||
gsw->host_bus->write(gsw->host_bus, addr, 0x0e, val);
|
||||
|
||||
mutex_unlock(&gsw->host_bus->mdio_lock);
|
||||
}
|
||||
|
||||
@@ -146,6 +158,10 @@ static void an8855_load_port_cfg(struct gsw_an8855 *gsw)
|
||||
struct device_node *fixed_link_node;
|
||||
struct an8855_port_cfg *port_cfg;
|
||||
u32 port;
|
||||
#if (KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE)
|
||||
int ret;
|
||||
|
||||
#endif
|
||||
|
||||
for_each_child_of_node(gsw->dev->of_node, port_np) {
|
||||
if (!of_device_is_compatible(port_np, "airoha,an8855-port"))
|
||||
@@ -172,9 +188,13 @@ static void an8855_load_port_cfg(struct gsw_an8855 *gsw)
|
||||
}
|
||||
|
||||
port_cfg->np = port_np;
|
||||
|
||||
#if (KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE)
|
||||
ret = of_get_phy_mode(port_np, &port_cfg->phy_mode);
|
||||
if (ret < 0) {
|
||||
#else
|
||||
port_cfg->phy_mode = of_get_phy_mode(port_np);
|
||||
if (port_cfg->phy_mode < 0) {
|
||||
#endif
|
||||
dev_info(gsw->dev, "incorrect phy-mode %d\n", port);
|
||||
continue;
|
||||
}
|
||||
@@ -296,6 +316,7 @@ static int an8855_hw_reset(struct gsw_an8855 *gsw)
|
||||
}
|
||||
|
||||
gpio_direction_output(gsw->reset_pin, 0);
|
||||
gpio_set_value(gsw->reset_pin, 0);
|
||||
usleep_range(100000, 150000);
|
||||
gpio_set_value(gsw->reset_pin, 1);
|
||||
usleep_range(100000, 150000);
|
||||
@@ -314,6 +335,51 @@ static irqreturn_t an8855_irq_handler(int irq, void *dev)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int an8855_proc_device_read(struct seq_file *seq, void *v)
|
||||
{
|
||||
seq_printf(seq, "%s\n", ARHT_CHIP_NAME);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_proc_device_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, an8855_proc_device_read, 0);
|
||||
}
|
||||
|
||||
#if (KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE)
|
||||
static const struct proc_ops an8855_proc_device_fops = {
|
||||
.proc_open = an8855_proc_device_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
};
|
||||
#else
|
||||
static const struct file_operations an8855_proc_device_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = an8855_proc_device_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int an8855_proc_device_init(struct gsw_an8855 *gsw)
|
||||
{
|
||||
if (!proc_an8855_gsw_dir)
|
||||
proc_an8855_gsw_dir = proc_mkdir(ARHT_PROC_DIR, 0);
|
||||
|
||||
proc_create(ARHT_PROC_NODE_DEVICE, 0400, proc_an8855_gsw_dir,
|
||||
&an8855_proc_device_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void an8855_proc_device_exit(void)
|
||||
{
|
||||
remove_proc_entry(ARHT_PROC_NODE_DEVICE, 0);
|
||||
}
|
||||
|
||||
static int an8855_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct gsw_an8855 *gsw;
|
||||
@@ -355,6 +421,14 @@ static int an8855_probe(struct platform_device *pdev)
|
||||
if (of_property_read_u32(np, "airoha,smi-addr", &gsw->new_smi_addr))
|
||||
gsw->new_smi_addr = AN8855_DFL_SMI_ADDR;
|
||||
|
||||
/* Assign AN8855 interrupt pin */
|
||||
if (of_property_read_u32(np, "airoha,intr", &gsw->intr_pin))
|
||||
gsw->intr_pin = AN8855_DFL_INTR_ID;
|
||||
|
||||
/* AN8855 surge enhancement */
|
||||
if (of_property_read_u32(np, "airoha,extSurge", &gsw->extSurge))
|
||||
gsw->extSurge = AN8855_DFL_EXT_SURGE;
|
||||
|
||||
/* Get LAN/WAN port mapping */
|
||||
map = an8855_find_mapping(np);
|
||||
if (map) {
|
||||
@@ -394,6 +468,8 @@ static int an8855_probe(struct platform_device *pdev)
|
||||
|
||||
gsw->irq = platform_get_irq(pdev, 0);
|
||||
if (gsw->irq >= 0) {
|
||||
INIT_WORK(&gsw->irq_worker, an8855_irq_worker);
|
||||
|
||||
ret = devm_request_irq(gsw->dev, gsw->irq, an8855_irq_handler,
|
||||
0, dev_name(gsw->dev), gsw);
|
||||
if (ret) {
|
||||
@@ -401,8 +477,6 @@ static int an8855_probe(struct platform_device *pdev)
|
||||
gsw->irq);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
INIT_WORK(&gsw->irq_worker, an8855_irq_worker);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, gsw);
|
||||
@@ -411,6 +485,8 @@ static int an8855_probe(struct platform_device *pdev)
|
||||
|
||||
an8855_gsw_nl_init();
|
||||
|
||||
an8855_proc_device_init(gsw);
|
||||
|
||||
an8855_swconfig_init(gsw);
|
||||
|
||||
if (sw->post_init)
|
||||
@@ -441,6 +517,8 @@ static int an8855_remove(struct platform_device *pdev)
|
||||
an8855_swconfig_destroy(gsw);
|
||||
#endif
|
||||
|
||||
an8855_proc_device_exit();
|
||||
|
||||
an8855_gsw_nl_exit();
|
||||
|
||||
an8855_remove_gsw(gsw);
|
||||
|
||||
@@ -26,8 +26,8 @@ static int an8855_nl_response(struct sk_buff *skb, struct genl_info *info);
|
||||
static const struct nla_policy an8855_nl_cmd_policy[] = {
|
||||
[AN8855_ATTR_TYPE_MESG] = { .type = NLA_STRING },
|
||||
[AN8855_ATTR_TYPE_PHY] = { .type = NLA_S32 },
|
||||
[AN8855_ATTR_TYPE_REG] = { .type = NLA_S32 },
|
||||
[AN8855_ATTR_TYPE_VAL] = { .type = NLA_S32 },
|
||||
[AN8855_ATTR_TYPE_REG] = { .type = NLA_U32 },
|
||||
[AN8855_ATTR_TYPE_VAL] = { .type = NLA_U32 },
|
||||
[AN8855_ATTR_TYPE_DEV_NAME] = { .type = NLA_S32 },
|
||||
[AN8855_ATTR_TYPE_DEV_ID] = { .type = NLA_S32 },
|
||||
[AN8855_ATTR_TYPE_DEVAD] = { .type = NLA_S32 },
|
||||
@@ -202,15 +202,15 @@ err:
|
||||
static int an8855_nl_reply_read(struct genl_info *info, struct gsw_an8855 *gsw)
|
||||
{
|
||||
struct sk_buff *rep_skb = NULL;
|
||||
s32 phy, devad, reg;
|
||||
int value;
|
||||
s32 phy, devad;
|
||||
u32 reg = 0;
|
||||
int value = 0;
|
||||
int ret = 0;
|
||||
|
||||
phy = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_PHY, -1);
|
||||
devad = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_DEVAD, -1);
|
||||
reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1);
|
||||
|
||||
if (reg < 0)
|
||||
if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_REG, ®))
|
||||
goto err;
|
||||
|
||||
ret = an8855_nl_prepare_reply(info, AN8855_CMD_READ, &rep_skb);
|
||||
@@ -226,11 +226,11 @@ static int an8855_nl_reply_read(struct genl_info *info, struct gsw_an8855 *gsw)
|
||||
value = an8855_reg_read(gsw, reg);
|
||||
}
|
||||
|
||||
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
|
||||
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
|
||||
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
@@ -246,18 +246,16 @@ err:
|
||||
static int an8855_nl_reply_write(struct genl_info *info, struct gsw_an8855 *gsw)
|
||||
{
|
||||
struct sk_buff *rep_skb = NULL;
|
||||
s32 phy, devad, reg;
|
||||
u32 value;
|
||||
s32 phy, devad;
|
||||
u32 value = 0, reg = 0;
|
||||
int ret = 0;
|
||||
|
||||
phy = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_PHY, -1);
|
||||
devad = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_DEVAD, -1);
|
||||
reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1);
|
||||
|
||||
if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_VAL, &value))
|
||||
if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_REG, ®))
|
||||
goto err;
|
||||
|
||||
if (reg < 0)
|
||||
if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_VAL, &value))
|
||||
goto err;
|
||||
|
||||
ret = an8855_nl_prepare_reply(info, AN8855_CMD_WRITE, &rep_skb);
|
||||
@@ -273,11 +271,11 @@ static int an8855_nl_reply_write(struct genl_info *info, struct gsw_an8855 *gsw)
|
||||
an8855_reg_write(gsw, reg, value);
|
||||
}
|
||||
|
||||
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
|
||||
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
|
||||
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
|
||||
@@ -85,10 +85,10 @@
|
||||
#define PMCR(p) PORT_MAC_CTRL_REG(p, 0x00)
|
||||
#define PMSR(p) PORT_MAC_CTRL_REG(p, 0x10)
|
||||
|
||||
#define GMACCR (PORT_MAC_CTRL_BASE + 0x30e0)
|
||||
#define GMACCR (PORT_MAC_CTRL_BASE + 0x3e00)
|
||||
|
||||
#define MAX_RX_JUMBO_S 2
|
||||
#define MAX_RX_JUMBO_M 0x3c
|
||||
#define MAX_RX_JUMBO_S 4
|
||||
#define MAX_RX_JUMBO_M 0xf0
|
||||
#define MAX_RX_PKT_LEN_S 0
|
||||
#define MAX_RX_PKT_LEN_M 0x3
|
||||
|
||||
@@ -172,6 +172,12 @@
|
||||
#define STATS_RSFTPC 0xF8
|
||||
#define STATS_RXCDPC 0xFC
|
||||
|
||||
#define RG_CLK_CPU_ICG 0x10005034
|
||||
#define MCU_ENABLE BIT(3)
|
||||
|
||||
#define RG_TIMER_CTL 0x1000a100
|
||||
#define WDOG_ENABLE BIT(25)
|
||||
|
||||
#define SYS_CTRL 0x100050C0
|
||||
#define SW_SYS_RST BIT(31)
|
||||
|
||||
@@ -182,7 +188,10 @@
|
||||
#define SYS_INT_STS 0x1021C014
|
||||
#define PHY_LC_INT(p) BIT(p)
|
||||
|
||||
#define CKGCR (0x10213E1C)
|
||||
#define CKG_LNKDN_GLB_STOP (0x01)
|
||||
#define CKG_LNKDN_PORT_STOP (0x02)
|
||||
#define CKGCR 0x10213E1C
|
||||
#define CKG_LNKDN_GLB_STOP 0x01
|
||||
#define CKG_LNKDN_PORT_STOP 0x02
|
||||
|
||||
#define PKG_SEL 0x10000094
|
||||
#define PAG_SEL_AN8855H 0x2
|
||||
#endif /* _AN8855_REGS_H_ */
|
||||
|
||||
@@ -125,7 +125,7 @@ static int an8855_get_port_pvid(struct switch_dev *dev, int port, int *val)
|
||||
{
|
||||
struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
|
||||
|
||||
if (port >= AN8855_NUM_PORTS)
|
||||
if (port < 0 || port >= AN8855_NUM_PORTS)
|
||||
return -EINVAL;
|
||||
|
||||
*val = an8855_reg_read(gsw, PVID(port));
|
||||
@@ -138,7 +138,7 @@ static int an8855_set_port_pvid(struct switch_dev *dev, int port, int pvid)
|
||||
{
|
||||
struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
|
||||
|
||||
if (port >= AN8855_NUM_PORTS)
|
||||
if (port < 0 || port >= AN8855_NUM_PORTS)
|
||||
return -EINVAL;
|
||||
|
||||
if (pvid < AN8855_MIN_VID || pvid > AN8855_MAX_VID)
|
||||
@@ -300,18 +300,20 @@ static int an8855_set_port_link(struct switch_dev *dev, int port,
|
||||
static u64 get_mib_counter(struct gsw_an8855 *gsw, int i, int port)
|
||||
{
|
||||
unsigned int offset;
|
||||
u64 lo, hi, hi2;
|
||||
u64 lo = 0, hi = 0, hi2 = 0;
|
||||
|
||||
offset = an8855_mibs[i].offset;
|
||||
if (i >= 0) {
|
||||
offset = an8855_mibs[i].offset;
|
||||
|
||||
if (an8855_mibs[i].size == 1)
|
||||
return an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset));
|
||||
if (an8855_mibs[i].size == 1)
|
||||
return an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset));
|
||||
|
||||
do {
|
||||
hi = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4));
|
||||
lo = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset));
|
||||
hi2 = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4));
|
||||
} while (hi2 != hi);
|
||||
do {
|
||||
hi = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4));
|
||||
lo = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset));
|
||||
hi2 = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4));
|
||||
} while (hi2 != hi);
|
||||
}
|
||||
|
||||
return (hi << 32) | lo;
|
||||
}
|
||||
@@ -370,7 +372,7 @@ static void an8855_port_isolation(struct gsw_an8855 *gsw)
|
||||
an8855_reg_write(gsw, PORTMATRIX(gsw->cpu_port), PORT_MATRIX_M);
|
||||
|
||||
for (i = 0; i < AN8855_NUM_PORTS; i++) {
|
||||
u32 pvc_mode = 0x8100 << STAG_VPID_S;
|
||||
u32 pvc_mode = 0x9100 << STAG_VPID_S;
|
||||
|
||||
if (gsw->port5_cfg.stag_on && i == 5)
|
||||
pvc_mode |= PVC_PORT_STAG | PVC_STAG_REPLACE;
|
||||
|
||||
@@ -11,19 +11,19 @@ struct an8855_mapping an8855_def_mapping[] = {
|
||||
.name = "llllw",
|
||||
.pvids = { 1, 1, 1, 1, 2, 1 },
|
||||
.members = { 0, 0x2f, 0x30 },
|
||||
.etags = { 0, 0, 0x20 },
|
||||
.etags = { 0, 0, 0 },
|
||||
.vids = { 0, 1, 2 },
|
||||
}, {
|
||||
.name = "wllll",
|
||||
.pvids = { 2, 1, 1, 1, 1, 1 },
|
||||
.members = { 0, 0x3e, 0x21 },
|
||||
.etags = { 0, 0, 0x20 },
|
||||
.etags = { 0, 0, 0 },
|
||||
.vids = { 0, 1, 2 },
|
||||
}, {
|
||||
.name = "lwlll",
|
||||
.pvids = { 1, 2, 1, 1, 1, 1 },
|
||||
.members = { 0, 0x3d, 0x22 },
|
||||
.etags = { 0, 0, 0x20 },
|
||||
.etags = { 0, 0, 0 },
|
||||
.vids = { 0, 1, 2 },
|
||||
}, {
|
||||
.name = "lllll",
|
||||
@@ -124,14 +124,14 @@ void an8855_apply_vlan_config(struct gsw_an8855 *gsw)
|
||||
|
||||
/* set all untag-only ports as transparent and the rest as user port */
|
||||
for (i = 0; i < AN8855_NUM_PORTS; i++) {
|
||||
u32 pvc_mode = 0x8100 << STAG_VPID_S;
|
||||
u32 pvc_mode = 0x9100 << STAG_VPID_S;
|
||||
|
||||
if (untag_ports & BIT(i) && !(tag_ports & BIT(i)))
|
||||
pvc_mode = (0x8100 << STAG_VPID_S) |
|
||||
pvc_mode = (0x9100 << STAG_VPID_S) |
|
||||
(VA_TRANSPARENT_PORT << VLAN_ATTR_S);
|
||||
|
||||
if (gsw->port5_cfg.stag_on && i == 5)
|
||||
pvc_mode = (u32)((0x8100 << STAG_VPID_S) | PVC_PORT_STAG
|
||||
pvc_mode = (u32)((0x9100 << STAG_VPID_S) | PVC_PORT_STAG
|
||||
| PVC_STAG_REPLACE);
|
||||
|
||||
an8855_reg_write(gsw, PVC(i), pvc_mode);
|
||||
@@ -159,7 +159,8 @@ void an8855_apply_vlan_config(struct gsw_an8855 *gsw)
|
||||
u16 pvid = 0;
|
||||
u32 val;
|
||||
|
||||
if (vlan < AN8855_NUM_VLANS && gsw->vlan_entries[vlan].member)
|
||||
if ((vlan >= 0) && (vlan < AN8855_NUM_VLANS)
|
||||
&& (gsw->vlan_entries[vlan].member))
|
||||
pvid = gsw->vlan_entries[vlan].vid;
|
||||
|
||||
val = an8855_reg_read(gsw, PVID(i));
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*SPDX-License-Identifier: GPL-2.0*/
|
||||
/*FILE NAME: an8801.c
|
||||
*PURPOSE:
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*PURPOSE:
|
||||
*Airoha phy driver for Linux
|
||||
*NOTES:
|
||||
*
|
||||
@@ -635,6 +634,23 @@ static int an8801sb_of_init(struct phy_device *phydev)
|
||||
} else
|
||||
priv->surge = AIR_SURGE_0R;
|
||||
|
||||
if (of_find_property(of_node, "airoha,sgmii-mode", NULL)) {
|
||||
if (of_property_read_u32(of_node, "airoha,sgmii-mode",
|
||||
&val) != 0) {
|
||||
dev_err(phydev_dev(phydev), "airoha,sgmii-mode value is invalid.");
|
||||
return -1;
|
||||
}
|
||||
if (val < AIR_SGMII_AN ||
|
||||
val > AIR_SGMII_FORCE) {
|
||||
dev_err(phydev_dev(phydev),
|
||||
"airoha,sgmii-mode value %u out of range.",
|
||||
val);
|
||||
return -1;
|
||||
}
|
||||
priv->sgmii_mode = val;
|
||||
} else
|
||||
priv->sgmii_mode = AIR_SGMII_AN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
@@ -732,27 +748,43 @@ static int an8801sb_config_init(struct phy_device *phydev)
|
||||
u32 pbus_value = 0;
|
||||
u32 reg_value = 0;
|
||||
|
||||
reg_value = phy_read(phydev, MII_BMSR);
|
||||
if ((reg_value & MCS_LINK_STATUS_MASK) != 0) {
|
||||
ret = air_buckpbus_reg_write(phydev, 0x10220010, 0x1801);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
reg_value = air_buckpbus_reg_read(phydev, 0x10220010);
|
||||
dev_dbg(phydev_dev(phydev),
|
||||
"air_buckpbus_reg_read(0x10220010,0x%x).\n", reg_value);
|
||||
|
||||
ret = air_buckpbus_reg_write(phydev, 0x10220000, 0x9140);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
reg_value = air_buckpbus_reg_read(phydev, 0x10220000);
|
||||
dev_dbg(phydev_dev(phydev),
|
||||
"air_buckpbus_reg_read(0x10220000,0x%x).\n", reg_value);
|
||||
mdelay(80);
|
||||
}
|
||||
|
||||
ret = an8801sb_of_init(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (priv->sgmii_mode == AIR_SGMII_AN) {
|
||||
dev_info(phydev_dev(phydev), "sgmii mode - AN\n");
|
||||
reg_value = phy_read(phydev, MII_BMSR);
|
||||
if ((reg_value & MCS_LINK_STATUS_MASK) != 0) {
|
||||
ret = air_buckpbus_reg_write(phydev, 0x10220010, 0x1801);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
reg_value = air_buckpbus_reg_read(phydev, 0x10220010);
|
||||
dev_dbg(phydev_dev(phydev),
|
||||
"air_buckpbus_reg_read(0x10220010,0x%x).\n", reg_value);
|
||||
|
||||
ret = air_buckpbus_reg_write(phydev, 0x10220000, 0x9140);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
reg_value = air_buckpbus_reg_read(phydev, 0x10220000);
|
||||
dev_dbg(phydev_dev(phydev),
|
||||
"air_buckpbus_reg_read(0x10220000,0x%x).\n", reg_value);
|
||||
mdelay(80);
|
||||
}
|
||||
} else { /* SGMII force mode */
|
||||
dev_info(phydev_dev(phydev), "sgmii mode - Force\n");
|
||||
ret = air_buckpbus_reg_write(phydev, 0x102260E4, 0xFF11);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10224004, 0x0700);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10224018, 0x0);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x1022450C, 0x0700);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x1022A140, 0x5);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10226100, 0xF0000000);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10226300, 0x0);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x1022A078, 0x10050);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10220034, 0x31120009);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10220000, 0x140);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
#ifdef CONFIG_OF
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0x1022a0f8);
|
||||
pbus_value &= ~0x3;
|
||||
@@ -1347,6 +1379,7 @@ static void an8801_phy_remove(struct phy_device *phydev)
|
||||
static int an8801sb_read_status(struct phy_device *phydev)
|
||||
{
|
||||
int ret, prespeed = phydev->speed;
|
||||
struct an8801_priv *priv = phydev->priv;
|
||||
u32 reg_value = 0;
|
||||
u32 an_retry = MAX_SGMII_AN_RETRY;
|
||||
|
||||
@@ -1357,14 +1390,16 @@ static int an8801sb_read_status(struct phy_device *phydev)
|
||||
ret |= phy_write_mmd(
|
||||
phydev, MMD_DEV_VSPEC2, PHY_PRE_SPEED_REG, prespeed);
|
||||
|
||||
mdelay(10); /* delay 10 ms */
|
||||
reg_value = air_buckpbus_reg_read(phydev, 0x10220010);
|
||||
reg_value &= 0x7fff;
|
||||
air_buckpbus_reg_write(phydev, 0x10220010, reg_value);
|
||||
if (priv->sgmii_mode == AIR_SGMII_AN) {
|
||||
mdelay(10); /* delay 10 ms */
|
||||
reg_value = air_buckpbus_reg_read(phydev, 0x10220010);
|
||||
reg_value &= 0x7fff;
|
||||
air_buckpbus_reg_write(phydev, 0x10220010, reg_value);
|
||||
|
||||
reg_value = air_buckpbus_reg_read(phydev, 0x10220000);
|
||||
reg_value |= AN8801SB_SGMII_AN0_ANRESTART;
|
||||
air_buckpbus_reg_write(phydev, 0x10220000, reg_value);
|
||||
reg_value = air_buckpbus_reg_read(phydev, 0x10220000);
|
||||
reg_value |= AN8801SB_SGMII_AN0_ANRESTART;
|
||||
air_buckpbus_reg_write(phydev, 0x10220000, reg_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (prespeed != phydev->speed && phydev->link == LINK_UP) {
|
||||
@@ -1372,31 +1407,59 @@ static int an8801sb_read_status(struct phy_device *phydev)
|
||||
ret |= phy_write_mmd(
|
||||
phydev, MMD_DEV_VSPEC2, PHY_PRE_SPEED_REG, prespeed);
|
||||
dev_info(phydev_dev(phydev), "AN8801SB SPEED %d\n", prespeed);
|
||||
while (an_retry > 0) {
|
||||
mdelay(1); /* delay 1 ms */
|
||||
reg_value = air_buckpbus_reg_read(
|
||||
phydev, 0x10220b04);
|
||||
if (reg_value & AN8801SB_SGMII_AN0_AN_DONE)
|
||||
break;
|
||||
an_retry--;
|
||||
if (priv->sgmii_mode == AIR_SGMII_AN) {
|
||||
while (an_retry > 0) {
|
||||
mdelay(1); /* delay 1 ms */
|
||||
reg_value = air_buckpbus_reg_read(
|
||||
phydev, 0x10220b04);
|
||||
if (reg_value & AN8801SB_SGMII_AN0_AN_DONE)
|
||||
break;
|
||||
an_retry--;
|
||||
}
|
||||
mdelay(10); /* delay 10 ms */
|
||||
|
||||
|
||||
if (prespeed == SPEED_1000) {
|
||||
air_buckpbus_reg_write(
|
||||
phydev, 0x10220010, 0xd801);
|
||||
} else if (prespeed == SPEED_100) {
|
||||
air_buckpbus_reg_write(
|
||||
phydev, 0x10220010, 0xd401);
|
||||
} else {
|
||||
air_buckpbus_reg_write(
|
||||
phydev, 0x10220010, 0xd001);
|
||||
}
|
||||
|
||||
reg_value = air_buckpbus_reg_read(phydev, 0x10220000);
|
||||
reg_value |= (AN8801SB_SGMII_AN0_RESET | AN8801SB_SGMII_AN0_ANRESTART);
|
||||
air_buckpbus_reg_write(phydev, 0x10220000, reg_value);
|
||||
} else { /* SGMII force mode */
|
||||
if (prespeed == SPEED_1000) {
|
||||
ret = air_buckpbus_reg_write(phydev, 0x102260E4, 0xFF11);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10224004, 0x0700);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10224018, 0x0);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x1022450C, 0x0700);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x1022A140, 0x5);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10226100, 0xF0000000);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10270100, 0xF);
|
||||
} else if (prespeed == SPEED_100) {
|
||||
ret = air_buckpbus_reg_write(phydev, 0x102260E4, 0xFF11);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10224004, 0x0755);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10224018, 0x14);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x1022450C, 0x0755);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x1022A140, 0x10);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10226100, 0xF000000C);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10270100, 0xC);
|
||||
} else {
|
||||
ret = air_buckpbus_reg_write(phydev, 0x102260E4, 0xFFAA);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10224004, 0x07AA);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10224018, 0x4);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x1022450C, 0x07AA);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x1022A140, 0x20);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10226100, 0xF000000F);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x10270100, 0xC);
|
||||
}
|
||||
}
|
||||
mdelay(10); /* delay 10 ms */
|
||||
|
||||
|
||||
if (prespeed == SPEED_1000) {
|
||||
air_buckpbus_reg_write(
|
||||
phydev, 0x10220010, 0xd801);
|
||||
} else if (prespeed == SPEED_100) {
|
||||
air_buckpbus_reg_write(
|
||||
phydev, 0x10220010, 0xd401);
|
||||
} else {
|
||||
air_buckpbus_reg_write(
|
||||
phydev, 0x10220010, 0xd001);
|
||||
}
|
||||
|
||||
reg_value = air_buckpbus_reg_read(phydev, 0x10220000);
|
||||
reg_value |= (AN8801SB_SGMII_AN0_RESET | AN8801SB_SGMII_AN0_ANRESTART);
|
||||
air_buckpbus_reg_write(phydev, 0x10220000, reg_value);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*SPDX-License-Identifier: GPL-2.0*/
|
||||
/*FILE NAME: an8801.h
|
||||
*PURPOSE:
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*PURPOSE:
|
||||
*Define Airoha phy driver function
|
||||
*
|
||||
*NOTES:
|
||||
@@ -12,7 +11,7 @@
|
||||
|
||||
/* NAMING DECLARATIONS
|
||||
*/
|
||||
#define AN8801_DRIVER_VERSION "1.1.6"
|
||||
#define AN8801_DRIVER_VERSION "1.1.7"
|
||||
|
||||
#define DEBUGFS_COUNTER "counter"
|
||||
#define DEBUGFS_INFO "driver_info"
|
||||
@@ -90,7 +89,7 @@
|
||||
|
||||
#define UNIT_LED_BLINK_DURATION 780
|
||||
|
||||
/* Serdes auto negotation restart */
|
||||
/* Serdes auto negotiation restart */
|
||||
#define AN8801SB_SGMII_AN0_ANRESTART (0x0200)
|
||||
#define AN8801SB_SGMII_AN0_AN_DONE (0x0001)
|
||||
#define AN8801SB_SGMII_AN0_RESET (0x8000)
|
||||
@@ -109,8 +108,8 @@
|
||||
#define AN8801_RG_PKG_SEL_MSB BIT(5)
|
||||
|
||||
/*
|
||||
For reference only
|
||||
*/
|
||||
*For reference only
|
||||
*/
|
||||
/* User-defined.B */
|
||||
/* Link on(1G/100M/10M), no activity */
|
||||
#define AIR_LED0_ON \
|
||||
@@ -209,6 +208,7 @@ struct an8801_priv {
|
||||
#endif
|
||||
int pol;
|
||||
int surge;
|
||||
int sgmii_mode;
|
||||
};
|
||||
|
||||
enum an8801_polarity {
|
||||
@@ -224,4 +224,10 @@ enum air_surge {
|
||||
AIR_SURGE_LAST = 0xff
|
||||
};
|
||||
|
||||
enum air_sgmii_mode {
|
||||
AIR_SGMII_AN,
|
||||
AIR_SGMII_FORCE,
|
||||
AIR_SGMII_LAST = 0xff
|
||||
};
|
||||
|
||||
#endif /* End of __AN8801_H */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user