Compare commits

..

30 Commits

Author SHA1 Message Date
Paul White
b72e58b33d base-files: boot: add sync after uci-defaults
A scenario was seen where UCI config was not flushed to disk before
an AP power-cycle after uci-defaults was completed.  Since these
scripts are deleted after being ran once, there is no way to recover
without a factory reset.

Adding this sync operation proved to help avoid this situation from
happening

Signed-off-by: Paul White <paul@shasta.cloud>
2025-08-12 10:11:41 -07:00
John Crispin
68dfd58303 wireless-regdb: disable channel 14 in JP
Fixes: WIFI-14962
Signed-off-by: John Crispin <john@phrozen.org>
2025-08-07 14:51:33 +02:00
John Crispin
6ba26cba2b est_client: add a function to validate that the CN is correct
cloud_discovery will not start if the CN does not match the devices serial.
an error will be written to syslog

---
Wed Aug  6 14:23:23 2025 user.notice root: ERROR
Wed Aug  6 14:23:23 2025 user.notice root: ERROR
Wed Aug  6 14:23:23 2025 user.notice root: ERROR
Wed Aug  6 14:23:23 2025 user.notice root: The certificate used has a CN that does not match the serial of the device
Wed Aug  6 14:23:23 2025 user.notice root: ERROR
Wed Aug  6 14:23:23 2025 user.notice root: ERROR
Wed Aug  6 14:23:23 2025 user.notice root: ERROR
---

Signed-off-by: John Crispin <john@phrozen.org>
2025-08-06 16:23:57 +02:00
John Crispin
b5b276bfcc est_client: check if a cert is present inside the fwtool helper
This was causing devices without a birt cert being present from doing a
sysupgrade.

Signed-off-by: John Crispin <john@phrozen.org>
2025-08-06 11:03:59 +02:00
Tanya Singh
de7dc7e01a ipq50xx: Fix bootbank switching when firmware upgrade is triggered for Edgecore EAP104 and OAP101 series
Fixes: WIFI-14957
Signed-off-by: Tanya Singh <tanya_singh@accton.com>
2025-08-06 10:54:55 +02:00
jackcybertan
a967d67af3 qca-wifi-7: Added ramoops support for SonicFi IPQ5332 devices
Fixes: WIFI-14869
Signed-off-by: jackcybertan <jack.tsai@cybertan.com.tw>
2025-08-06 10:53:52 +02:00
John Crispin
8a68073f4f ucentral-schema: update to latest HEAD
remove a patch that was accidentally merged

Signed-off-by: John Crispin <john@phrozen.org>
2025-08-04 16:33:15 +02:00
John Crispin
efd804987e rtty: there was an error in the operationalpem passed to the client
Signed-off-by: John Crispin <john@phrozen.org>
2025-08-04 15:44:21 +02:00
jackcybertan
b036ba37e3 certificates: Store-PKI2.0-key-for-RAP6x-production
Fixes: WIFI-14951
Signed-off-by: jackcybertan <jack.tsai@cybertan.com.tw>
2025-08-04 08:39:53 +02:00
John Crispin
7352de2421 update to latest HEAD
e27ecb4 ssid: decouple batman tunnel from meshpoint interfaces

Signed-off-by: John Crispin <john@phrozen.org>
2025-08-04 08:36:13 +02:00
John Crispin
8c11eb23a3 mt7621: add insta1/2 partitions for yuncore ax820
Signed-off-by: John Crispin <john@phrozen.org>
2025-08-04 08:35:42 +02:00
Tanya Singh
83874b75f3 mediatek-sdk: Remove extra lines (for logging) from 99-mtk-sr-scene-cond
Signed-off-by: Tanya Singh <tanya_singh@accton.com>
2025-08-04 08:08:24 +02:00
John Crispin
694cf6ded8 rtty: use the operational certificate
Fixes: WIFI-14943
Signed-off-by: John Crispin <john@phrozen.org>
2025-07-31 17:50:14 +02:00
John Crispin
0a3a207584 uboot-envtools: add udaya-id5 support
Signed-off-by: John Crispin <john@phrozen.org>
2025-07-31 14:54:56 +02:00
Tanya Singh
b0e95e68a2 afc: Use either ca-cert or access-token to get authorization in curl command for the AFC server
Fixes:WIFI-14427
Signed-off-by: Tanya Singh <tanya_singh@accton.com>
2025-07-31 10:03:02 +02:00
Tanya Singh
26ed5acb60 rrmd: update timeout for RRM during self-healing and fix center channel mapping in RRM with Channel Utilization
Fixes: WIFI-14901
Signed-off-by: Tanya Singh <tanya_singh@accton.com>
2025-07-31 10:02:27 +02:00
John Crispin
d1e4c48617 cloud_discovery: add automatic reenrolment of operational certificates
The daemon will check the vailidity of the operational certificate once and hour.
If the certificate is valid for less than three days, a reenrollment is attempted.
Once the reenroll happened the connection to the cloud controller will be restarted.

Fixes: WIFI-14900
Fixes: WIFI-14694
Signed-off-by: John Crispin <john@phrozen.org>
2025-07-31 09:48:10 +02:00
Tanya Singh
3a8fc316f2 qca-wifi-7/afc: Use curl instead of uclient to send/receive AFC request/response using hostapd
Fixes: WIFI-14427
Signed-off-by: Tanya Singh <tanya_singh@accton.com>
2025-07-30 09:34:26 +02:00
jackcybertan
d85dc2a819 certificates: Enhance PKI enrollment on squashfs (SonicFi RAP6* series)
The updated flow:
- Mount /dev/mtdblock* (the certificates partition) to /mnt
- Copy its contents to /certificates
- Unmount /mnt
- Extract the PKI 2.0 certificates into /certificates

Fixes: WIFI-14904
Signed-off-by: jackcybertan <jack.tsai@cybertan.com.tw>
2025-07-30 09:04:52 +02:00
John Crispin
acca9737e4 ucentral-schema: update to latest HEAD
30c7374 Add 'access-token' to AFC server config

Fixes: WIFI-14427
Signed-off-by: John Crispin <john@phrozen.org>
2025-07-30 09:02:17 +02:00
Tanya Singh
6d2fd1de0d afc: Use curl instead of uclient to send/receive AFC request/response using hostapd
Fixes: WIFI-14427
Signed-off-by: Tanya Singh <tanya_singh@accton.com>
2025-07-30 09:02:05 +02:00
John Crispin
1d822a10d2 toolchain: use gcc11 for legacy targets
Signed-off-by: John Crispin <john@phrozen.org>
2025-07-28 09:51:18 +02:00
John Crispin
ebdc88ee1f certificates: improvements
* make the code more generic
* add udaya a2 support

Signed-off-by: John Crispin <john@phrozen.org>
2025-07-28 09:50:22 +02:00
John Crispin
778cc679a0 profiles: add more wifi-5 profiles
* edgecore_spw2ac1200
* hfcl_ion4

Signed-off-by: John Crispin <john@phrozen.org>
2025-07-27 19:35:04 +02:00
YenLin Pan
088d78faa7 qca-ssdk: adjust the amplitude level of SGMII for Zyxel NWA130BE
To fix EMI and avoid Ethernet RX stuck after reboot for Zyxel NWA130BE.
Ethernet Rx stuck was sometimes happened when we do stress reboot,
need to adjust the amplitude level of SGMII for CPU and QCA8385 side.
And those settings come from the result that Zyxel HW team and Manufacturer
co-work to fine tune for NWA130BE.

Signed-off-by: YenLin Pan <YenLin.Pan@zyxel.com.tw>
2025-07-27 19:24:15 +02:00
Tanya Singh
5306f7db27 cloud_discovery: Add 'sync' after file generation in Cloud discovery process
Fixes: WIFI-14906
Signed-off-by: Tanya Singh <tanya_singh@accton.com>
2025-07-27 17:40:03 +02:00
Tanya Singh
c8bffdc250 rrmd: Add self-healing in ucentral-state and channel switching improvements to RRM with channel utilization
Fixes: WIFI-14901
Signed-off-by: Tanya Singh <tanya_singh@accton.com>
2025-07-27 17:39:21 +02:00
John Crispin
3a3de9e146 ucentral-schema: update to latest HEAD
92fb3c1 WIFI-14901: Add rrm_chanutil status to health.uc (when it fails) and save health metric in /tmp/ucentral.health
6313892 WIFI-14906: Add 'sync' after file generation in Cloud discovery process

Signed-off-by: John Crispin <john@phrozen.org>
2025-07-27 17:03:48 +02:00
John Crispin
4d5c9a2d4c ucentral-client: update to latest HEAD
c536f69 cloud package manager

Fixes: WIFI-14588
Signed-off-by: John Crispin <john@phrozen.org>
2025-07-27 16:54:44 +02:00
John Crispin
41aa4c2978 cloud_discovery: set correct timeouts inside UCI
Fixes: WIFI-14897
Signed-off-by: John Crispin <john@phrozen.org>
2025-07-27 16:35:15 +02:00
362 changed files with 28597 additions and 45557 deletions

View File

@@ -21,7 +21,7 @@ jobs:
strategy:
fail-fast: false
matrix:
target: [ ]
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' ]
steps:
- uses: actions/checkout@v3

View File

@@ -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 = 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;
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;
let afc_location_json = fs.open("/etc/ucentral/afc-location.json", "w");
afc_location_json.write(afc_location);

View File

@@ -1,7 +1,8 @@
let libubus = require("ubus");
import { open, readfile } from "fs";
import { open, readfile, writefile } 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 = {};
@@ -893,10 +894,24 @@ return {
hostapd.ubus.disconnect();
},
afc_request: function(iface, data) {
let ret = ubus.call("afc", "request", { data });
if (type(ret) != "object")
return;
return ret.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;
}
}
},
bss_add: function(name, obj) {
bss_event("add", name);

View File

@@ -107,29 +107,42 @@ platform_do_upgrade() {
board=$(board_name)
case $board in
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|\

View File

@@ -1,15 +1,15 @@
From 991886a6f8840802d611e0f75e79aa4ec5e68ccc Mon Sep 17 00:00:00 2001
From 5c8d90efe02c47ce76a6d5383ea6aa90eb0c73d8 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 | 92 ++++++++++++++++++++++++++++++++++++
4 files changed, 123 insertions(+)
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(+)
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..f48995c 100644
index c217276..9f651f9 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -14,6 +14,7 @@
@@ -108,7 +108,7 @@ index c217276..f48995c 100644
static bool cfg80211_valid_60g_freq(u32 freq)
{
@@ -1393,3 +1394,94 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
@@ -1393,3 +1394,62 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
return false;
}
EXPORT_SYMBOL(cfg80211_any_usable_channels);
@@ -133,29 +133,26 @@ index c217276..f48995c 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(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,
+ (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,
+ 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(wiphy, bss_chandef) &&
+ !cfg80211_chandef_dfs_available(wiphy, bss_chandef))
+ if (!cfg80211_chandef_dfs_usable(wdev->wiphy, bss_chandef) &&
+ !cfg80211_chandef_dfs_available(wdev->wiphy, bss_chandef))
+ return;
+
+ if (associated && !csa_active) {
@@ -163,37 +160,8 @@ index c217276..f48995c 100644
+ event = NL80211_RADAR_STA_CAC_SKIPPED;
+ }
+
+ /* 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);
+ cfg80211_set_dfs_state(wdev->wiphy, bss_chandef, dfs_state);
+ cfg80211_sta_radar_notify(wdev->wiphy, bss_chandef, event);
+
+ if (csa_active)
+ netdev_info(wdev->netdev, "Set origin channel's DFS state to usable\n");

View File

@@ -1,4 +1,4 @@
From 70526aabf704d778796dfbaa042fe48e03aa7d61 Mon Sep 17 00:00:00 2001
From bb918e40dcc7d082f898234cf29cd545de78621e 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 | 16 +++++++-
net/mac80211/util.c | 11 ++++-
net/wireless/chan.c | 72 ++++++++++++++++++++++++++++++++
net/wireless/nl80211.c | 5 ++-
net/wireless/rdev-ops.h | 17 ++++++++
9 files changed, 226 insertions(+), 10 deletions(-)
9 files changed, 221 insertions(+), 10 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 03f072f..a443b0d 100644
@@ -272,21 +272,16 @@ index 2dbc18c..ed81ebf 100644
NL80211_RADAR_CAC_FINISHED,
GFP_KERNEL);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 26cd627..1e8420d 100644
index 26cd627..e07fe73 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3873,7 +3873,21 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
@@ -3873,7 +3873,16 @@ 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);
@@ -299,7 +294,7 @@ index 26cd627..1e8420d 100644
&chandef,
NL80211_RADAR_CAC_ABORTED,
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index f48995c..c7bfa6b 100644
index 9f651f9..f02598b 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -1262,6 +1262,78 @@ bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,

View File

@@ -1,21 +1,19 @@
From b43f0f6528bff00b4fbb25e0cbb9ac88577d1467 Mon Sep 17 00:00:00 2001
From 08661908d4c2fb5f8d7ca00e0e7e6b33a6ae6e31 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 | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
net/mac80211/cfg.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7a30ca6..2ee5b63 100644
index 3e6e903..eb73834 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3361,6 +3361,32 @@ static int ieee80211_start_radar_detection_post_csa(struct wiphy *wiphy,
@@ -3361,6 +3361,31 @@ static int ieee80211_start_radar_detection_post_csa(struct wiphy *wiphy,
return 1;
}
@@ -30,8 +28,7 @@ index 7a30ca6..2ee5b63 100644
+ &sdata->csa_chandef) &&
+ !cfg80211_reg_can_beacon_relax(local->hw.wiphy,
+ &sdata->csa_chandef,
+ sdata->wdev.iftype) &&
+ !ieee80211_is_cert_mode(&local->hw);
+ sdata->wdev.iftype);
+ /* broadcast deauth frame if CAC is required */
+ if (!send_deauth)
+ return;
@@ -48,7 +45,7 @@ index 7a30ca6..2ee5b63 100644
static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
@@ -3371,6 +3397,8 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
@@ -3371,6 +3396,8 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
lockdep_assert_held(&local->mtx);
lockdep_assert_held(&local->chanctx_mtx);
@@ -58,5 +55,5 @@ index 7a30ca6..2ee5b63 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.45.2
2.18.0

View File

@@ -1,95 +0,0 @@
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

View File

@@ -0,0 +1,58 @@
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

View File

@@ -1,56 +0,0 @@
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

View File

@@ -1,34 +0,0 @@
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

View File

@@ -1,196 +0,0 @@
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

View File

@@ -1,7 +1,7 @@
From 026c9872e3460f1632b60324e062016887b31134 Mon Sep 17 00:00:00 2001
From bad36168042569eb4c7ab6a549f7444a40e299c3 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/9902] mac80211: mtk: mask kernel version limitation and
Subject: [PATCH 9900/9903] 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 b622c76..c6625c2 100644
index 91affd5..42192cd 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4315,13 +4315,11 @@ struct ieee80211_ops {
@@ -4307,13 +4307,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 b622c76..c6625c2 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 d4723dc..91ea8b2 100644
index 9e8003f..19e2ada 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,19 +42,18 @@ index d4723dc..91ea8b2 100644
static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta *sta,
@@ -1523,7 +1522,6 @@ static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
@@ -1523,6 +1522,5 @@ static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
return ret;
}
-#endif
static inline int drv_set_qos_map(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 138ad79..4b92867 100644
index 00b0443..a7169a5 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -875,7 +875,6 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
@@ -853,7 +853,6 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
};
@@ -62,7 +61,7 @@ index 138ad79..4b92867 100644
static int ieee80211_netdev_fill_forward_path(struct net_device_path_ctx *ctx,
struct net_device_path *path)
{
@@ -933,7 +932,6 @@ out:
@@ -911,7 +910,6 @@ out:
return ret;
}
@@ -70,7 +69,7 @@ index 138ad79..4b92867 100644
static const struct net_device_ops ieee80211_dataif_8023_ops = {
#if LINUX_VERSION_IS_LESS(4,10,0)
@@ -952,9 +950,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
@@ -930,9 +928,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
#else
.ndo_get_stats64 = bp_ieee80211_get_stats64,
#endif
@@ -81,7 +80,7 @@ index 138ad79..4b92867 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 c6fc75e..6b7b46b 100644
index d15dadd..8770033 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -2899,14 +2899,12 @@ TRACE_EVENT(drv_twt_teardown_request,

View File

@@ -1,23 +1,23 @@
From e5612cde83ef67f8fa4633f7d364e05bac6e02a3 Mon Sep 17 00:00:00 2001
From 0161154c18a464bbb350bcb5ef620bd255940640 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/9902] mac80211: mtk: add fill receive path ops to get wed
Subject: [PATCH 9901/9903] 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 | 14 +++++++++++++-
net/mac80211/driver-ops.h | 13 +++++++++++++
net/mac80211/iface.c | 24 ++++++++++++++++++++++++
net/mac80211/util.c | 9 +++++++++
4 files changed, 58 insertions(+), 1 deletion(-)
4 files changed, 58 insertions(+)
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 c6625c2..cb8b28d
index 42192cd..8a71026
--- 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 c6625c2..cb8b28d
/**
* enum ieee80211_key_flags - key flags
*
@@ -3982,6 +3989,8 @@ struct ieee80211_prep_tx_info {
@@ -3975,6 +3982,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 {
@@ -4320,6 +4329,9 @@ struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -4312,6 +4321,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 91ea8b2..348f815 100644
index 19e2ada..88dedfc 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1523,6 +1523,19 @@ static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
@@ -1523,4 +1523,17 @@ static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
return ret;
}
@@ -74,20 +74,12 @@ index 91ea8b2..348f815 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 4b92867..c08bfbe 100644
index a7169a5..8a4f4e1 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -933,6 +933,29 @@ out:
@@ -911,6 +911,29 @@ out:
return ret;
}
@@ -117,7 +109,7 @@ index 4b92867..c08bfbe 100644
static const struct net_device_ops ieee80211_dataif_8023_ops = {
#if LINUX_VERSION_IS_LESS(4,10,0)
.ndo_change_mtu = __change_mtu,
@@ -951,6 +974,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
@@ -929,6 +952,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,
@@ -128,7 +120,7 @@ index 4b92867..c08bfbe 100644
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
old mode 100644
new mode 100755
index e07fe73..809eb37
index 8d36b05..d26a2b8
--- 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)

View File

@@ -1,7 +1,7 @@
From d62db23d46d1887aff58c76b0eb9960a46afb9bf Mon Sep 17 00:00:00 2001
From fdc7f27785b716eae1e02df73c095ecfe2677d9f 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/9902] mac80211: mtk: add support for letting drivers
Subject: [PATCH 9902/9903] 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 cb8b28d..6104072 100755
index 8a71026..861bc9a 100755
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3991,6 +3991,10 @@ struct ieee80211_prep_tx_info {
@@ -3984,6 +3984,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 cb8b28d..6104072 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 {
@@ -4332,6 +4336,11 @@ struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -4324,6 +4328,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 cb8b28d..6104072 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 348f815..f56a71f 100644
index 88dedfc..3ceba5e 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1536,6 +1536,23 @@ static inline int drv_net_fill_receive_path(struct ieee80211_local *local,
@@ -1536,4 +1536,21 @@ static inline int drv_net_fill_receive_path(struct ieee80211_local *local,
return ret;
}
@@ -69,14 +69,12 @@ index 348f815..f56a71f 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)
#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index bb5906d..b02ca21 100644
index 2519c14..fe7a03a 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1824,7 +1824,8 @@ void ieee80211_color_aging_work(struct work_struct *work);
@@ -1822,7 +1822,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 | \
@@ -87,10 +85,10 @@ index bb5906d..b02ca21 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 c08bfbe..ddeaa8f 100644
index 8a4f4e1..f3bf837 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -795,6 +795,21 @@ static int __change_mtu(struct net_device *ndev, int new_mtu){
@@ -773,6 +773,21 @@ static int __change_mtu(struct net_device *ndev, int new_mtu){
}
#endif
@@ -112,7 +110,7 @@ index c08bfbe..ddeaa8f 100644
static const struct net_device_ops ieee80211_dataif_ops = {
#if LINUX_VERSION_IS_LESS(4,10,0)
.ndo_change_mtu = __change_mtu,
@@ -812,6 +827,7 @@ static const struct net_device_ops ieee80211_dataif_ops = {
@@ -790,6 +805,7 @@ static const struct net_device_ops ieee80211_dataif_ops = {
#else
.ndo_get_stats64 = bp_ieee80211_get_stats64,
#endif
@@ -120,7 +118,7 @@ index c08bfbe..ddeaa8f 100644
};
@@ -975,6 +991,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
@@ -953,6 +969,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,
@@ -129,7 +127,7 @@ index c08bfbe..ddeaa8f 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 6b7b46b..5aea24a 100644
index 8770033..78d9803 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -2906,6 +2906,31 @@ DEFINE_EVENT(sta_event, drv_net_fill_forward_path,

View File

@@ -483,21 +483,20 @@
};
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_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";
};
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";
};
wbsys: wbsys@18000000 {
compatible = "mediatek,wbsys",

View File

@@ -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_208m", 1, 1),
FACTOR(CK_INFRA_FMSDC_CK, "infra_fmsdc", "emmc_400m", 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),

View File

@@ -488,16 +488,6 @@ 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),
@@ -516,7 +506,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_FLAGS(CK_INFRA_TRNG_CK, "infra_trng", "infra_hd_133m", 26, CLK_IS_CRITICAL),
GATE_INFRA0(CK_INFRA_TRNG_CK, "infra_trng", "infra_hd_133m", 26),
/* INFRA1 */
GATE_INFRA1(CK_INFRA_THERM_CK, "infra_therm", "infra_ck_f26m", 0),
GATE_INFRA1(CK_INFRA_I2CO_CK, "infra_i2co", "infra_i2cs", 1),

View File

@@ -1,93 +0,0 @@
// 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);

View File

@@ -1,113 +0,0 @@
// 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 = &ethdma_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);

View File

@@ -1,312 +0,0 @@
/*
* 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);

View File

@@ -1,57 +0,0 @@
// 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);

View File

@@ -1,310 +0,0 @@
// 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);

View File

@@ -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_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),
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),
/* 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_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_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_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",

View File

@@ -20,72 +20,12 @@
#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.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},
};
#define ARHT_AN8855_DSA_DRIVER_VER "1.0.1-L5.4"
/* String, offset, and register size in bytes if different from 4 bytes */
static const struct an8855_mib_desc an8855_mib[] = {
@@ -159,6 +99,7 @@ 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");
@@ -189,6 +130,7 @@ 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;
@@ -385,22 +327,16 @@ 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)
{
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);
regnum = MII_ADDR_C45 | (devad << 16) | regnum;
return mdiobus_read_nested(priv->bus, port, regnum);
}
static int
an8855_cl45_write(struct an8855_priv *priv, int port, int devad, int regnum,
u16 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;
regnum = MII_ADDR_C45 | (devad << 16) | regnum;
return mdiobus_write_nested(priv->bus, port, regnum, val);
}
int
@@ -521,6 +457,7 @@ 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);
@@ -542,6 +479,7 @@ 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);
}
@@ -1151,223 +1089,13 @@ 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, led_count = ARRAY_SIZE(led_cfg);
u32 val, id;
int ret, i;
/* Reset whole chip through gpio pin or memory-mapped registers for
@@ -1402,63 +1130,6 @@ 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;
@@ -1468,10 +1139,6 @@ 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);
@@ -1490,18 +1157,8 @@ 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);
@@ -1598,28 +1255,6 @@ 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);
@@ -1749,7 +1384,7 @@ an8855_set_hsgmii_mode(struct an8855_priv *priv)
val &= ~(0xf << 25);
val |= (0x1 << 25);
val &= ~(0x7 << 29);
val |= (0x6 << 29);
val |= (0x3 << 29);
an8855_write(priv, RG_QP_CDR_LPF_SETVALUE, val);
val = an8855_read(priv, RG_QP_CDR_PR_CKREF_DIV1);
@@ -1780,9 +1415,12 @@ 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(24);
val &= ~BIT(23);
val |= BIT(26);
an8855_write(priv, RX_CTRL_26, val);
@@ -1810,8 +1448,8 @@ an8855_set_hsgmii_mode(struct an8855_priv *priv)
val = an8855_read(priv, RX_CTRL_8);
val &= ~(0xfff << 16);
val |= (0x200 << 16);
val &= ~(0x7fff << 0);
val |= (0xfff << 0);
val &= ~(0x7fff << 14);
val |= (0xfff << 14);
an8855_write(priv, RX_CTRL_8, val);
/* Frequency memter */
@@ -1830,10 +1468,6 @@ 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);
@@ -1873,28 +1507,6 @@ 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);
@@ -2054,10 +1666,15 @@ 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);
val &= ~BIT(24);
val &= ~BIT(23);
if (mode == SGMII_MODE_AN)
val |= BIT(26);
an8855_write(priv, RX_CTRL_26, val);
val = an8855_read(priv, RX_DLY_0);
@@ -2104,10 +1721,6 @@ 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);
@@ -2192,6 +1805,7 @@ 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);
}
@@ -2308,6 +1922,16 @@ 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,
@@ -2570,51 +2194,6 @@ 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,
@@ -2638,6 +2217,10 @@ 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,
};
@@ -2725,13 +2308,6 @@ 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;
@@ -2748,7 +2324,6 @@ an8855_probe(struct mdio_device *mdiodev)
}
an8855_nl_init(&priv);
an8855_proc_device_init();
return 0;
}
@@ -2763,8 +2338,6 @@ an8855_remove(struct mdio_device *mdiodev)
if (priv->base)
iounmap(priv->base);
an8855_proc_device_exit();
an8855_nl_exit();
}

View File

@@ -10,13 +10,10 @@
#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,
@@ -289,8 +286,6 @@ 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)
@@ -308,14 +303,18 @@ 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 */
@@ -332,22 +331,6 @@ 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
@@ -356,15 +339,6 @@ 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)
@@ -408,8 +382,6 @@ 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)
@@ -427,7 +399,6 @@ 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)
@@ -466,74 +437,6 @@ 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.
@@ -619,13 +522,11 @@ 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 */

View File

@@ -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_U32},
[AN8855_ATTR_TYPE_VAL] = {.type = NLA_U32},
[AN8855_ATTR_TYPE_REG] = {.type = NLA_S32},
[AN8855_ATTR_TYPE_VAL] = {.type = NLA_S32},
[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;
u32 reg = 0;
int value = 0;
s32 phy, devad, reg;
int value;
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_REG, &reg))
if (reg < 0)
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_u32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
if (ret < 0)
goto err;
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
if (ret < 0)
goto err;
@@ -193,18 +193,20 @@ static int
an8855_nl_reply_write(struct genl_info *info)
{
struct sk_buff *rep_skb = NULL;
s32 phy, devad;
u32 value = 0, reg = 0;
s32 phy, devad, reg;
u32 value;
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);
if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_REG, &reg))
goto err;
reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1);
if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_VAL, &value))
goto err;
if (reg < 0)
goto err;
ret = an8855_nl_prepare_reply(info, AN8855_CMD_WRITE, &rep_skb);
if (ret < 0)
goto err;
@@ -216,11 +218,11 @@ an8855_nl_reply_write(struct genl_info *info)
value);
} else
an8855_write(an8855_sw_priv, reg, value);
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
if (ret < 0)
goto err;
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
if (ret < 0)
goto err;

View File

@@ -14,36 +14,32 @@
#include "an8855.h"
#include "an8855_phy.h"
#define AN8855_EFUSE_DATA0 0x1000a500
#define AN8855_NUM_PHYS 5
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)
static u32
an8855_phy_read_dev_reg(struct dsa_switch *ds, u32 port_num,
u32 dev_addr, u32 reg_addr)
{
u8 i;
u32 sz = sizeof(dsa_r50ohm_table)/sizeof(u8);
struct an8855_priv *priv = ds->priv;
u32 phy_val;
u32 addr;
for (i = 0; i < sz; ++i)
if (dsa_r50ohm_table[i] == base)
break;
addr = MII_ADDR_C45 | (dev_addr << 16) | (reg_addr & 0xffff);
phy_val = priv->info->phy_read(ds, port_num, addr);
if (i < 8 || i >= sz)
return 25; /* index of 94 */
return (i - 8);
return phy_val;
}
static u8 get_shift_val(u8 idx)
static void
an8855_phy_write_dev_reg(struct dsa_switch *ds, u32 port_num,
u32 dev_addr, u32 reg_addr, u32 write_data)
{
return dsa_r50ohm_table[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);
}
static void
@@ -68,10 +64,7 @@ static void
an8855_phy_setting(struct dsa_switch *ds)
{
struct an8855_priv *priv = ds->priv;
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;
int i;
u32 val;
/* Release power down */
@@ -89,89 +82,48 @@ 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_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, 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, 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, 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, 1, 0x1f, 0x700, 0x0001);
an8855_phy_write_dev_reg(ds, 1, 0x1f, 0x700, 0x0001);
for (addr = 0x200; addr <= 0x230; addr += 2)
an8855_phy_cl45_write(priv, 0, 0x1f, addr, 0x2020);
an8855_phy_write_dev_reg(ds, 0, 0x1f, addr, 0x2020);
for (addr = 0x201; addr <= 0x231; addr += 2)
an8855_phy_cl45_write(priv, 0, 0x1f, addr, 0x0020);
an8855_phy_write_dev_reg(ds, 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_cl45_write(priv, port, PHY_DEV07, PHY_DEV07_REG_03C, 0);
an8855_phy_write_dev_reg(ds, port, PHY_DEV07, PHY_DEV07_REG_03C, 0);
}
int

View File

@@ -12,8 +12,6 @@
#include <linux/bitops.h>
#define AN8855_NUM_PHYS 5
/*phy calibration use*/
#define DEV_1E 0x1E
/*global device 0x1f, always set P0*/
@@ -171,69 +169,11 @@
/* 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

View File

@@ -1,7 +0,0 @@
# 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.

View File

@@ -1,3 +0,0 @@
# 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

View File

@@ -1,272 +0,0 @@
// 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);
}

View File

@@ -1,336 +0,0 @@
/* 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 */

View File

@@ -1,51 +0,0 @@
/* 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_ */

View File

@@ -1,514 +0,0 @@
// 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;
}

View File

@@ -1,31 +0,0 @@
// 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_ */

View File

@@ -1,61 +0,0 @@
// 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);

View File

@@ -1,86 +0,0 @@
/* 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_ */

View File

@@ -1,279 +0,0 @@
/* 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_ */

View File

@@ -1,509 +0,0 @@
// 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_ */

View File

@@ -1,76 +0,0 @@
// 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_ */

View File

@@ -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_ptp.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
obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtk_hnat/

File diff suppressed because it is too large Load Diff

View File

@@ -30,24 +30,6 @@
#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
@@ -60,24 +42,6 @@
#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)
@@ -95,7 +59,6 @@
#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"
@@ -107,40 +70,6 @@
#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
@@ -171,18 +100,6 @@
#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", \
@@ -209,176 +126,55 @@
#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) \
{ \
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_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_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_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_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_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_LRO_BW_THRESHOLD(eth, x) \
{ \
const struct mtk_reg_map *reg_map = eth->soc->reg_map; \
u32 reg_val = mtk_r32(eth, reg_map->pdma.lro_ctrl_dw0 + 0x8); \
u32 reg_val = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW2); \
reg_val = (x); \
mtk_w32(eth, reg_val, reg_map->pdma.lro_ctrl_dw0 + 0x8); \
mtk_w32(eth, reg_val, MTK_PDMA_LRO_CTRL_DW2); \
}
#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); \
} \
#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)); \
}
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;
@@ -517,13 +313,23 @@ 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);
@@ -533,6 +339,5 @@ 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 */

View File

@@ -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_2P5GPHY:
return "gmac2_2p5gphy";
case MTK_ETH_PATH_GMAC2_XGMII:
return "gmac2_xgmii";
case MTK_ETH_PATH_GMAC2_GEPHY:
return "gmac2_gephy";
case MTK_ETH_PATH_GMAC3_SGMII:
@@ -104,14 +104,13 @@ static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, u64 path)
return 0;
}
static int set_mux_u3_gmac23_to_qphy(struct mtk_eth *eth, u64 path)
static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
{
unsigned int val = 0,mask=0,reg=0;
bool updated = true;
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;
@@ -136,7 +135,7 @@ static int set_mux_u3_gmac23_to_qphy(struct mtk_eth *eth, u64 path)
return 0;
}
static int set_mux_gmac2_to_2p5gphy(struct mtk_eth *eth, u64 path)
static int set_mux_gmac2_to_xgmii(struct mtk_eth *eth, u64 path)
{
unsigned int val = 0;
bool updated = true;
@@ -150,7 +149,7 @@ static int set_mux_gmac2_to_2p5gphy(struct mtk_eth *eth, u64 path)
regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
switch (path) {
case MTK_ETH_PATH_GMAC2_2P5GPHY:
case MTK_ETH_PATH_GMAC2_XGMII:
val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
mac_id = MTK_GMAC2_ID;
break;
@@ -312,13 +311,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_gmac23_to_qphy",
.cap_bit = MTK_ETH_MUX_U3_GMAC23_TO_QPHY,
.set_path = set_mux_u3_gmac23_to_qphy,
.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_gmac2_to_2p5gphy",
.cap_bit = MTK_ETH_MUX_GMAC2_TO_2P5GPHY,
.set_path = set_mux_gmac2_to_2p5gphy,
.name = "mux_gmac2_to_xgmii",
.cap_bit = MTK_ETH_MUX_GMAC2_TO_XGMII,
.set_path = set_mux_gmac2_to_xgmii,
}, {
.name = "mux_gmac1_gmac2_to_sgmii_rgmii",
.cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
@@ -404,13 +403,13 @@ int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
return 0;
}
int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id)
int mtk_gmac_xgmii_path_setup(struct mtk_eth *eth, int mac_id)
{
int err;
u64 path = 0;
if (mac_id == MTK_GMAC2_ID)
path = MTK_ETH_PATH_GMAC2_2P5GPHY;
if (mac_id == 1)
path = MTK_ETH_PATH_GMAC2_XGMII;
if (!path)
return -EINVAL;

View File

@@ -1,497 +0,0 @@
// 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(&eth->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(&eth->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(&eth->ptp_info, NULL, 0);
ptp_clock_unregister(eth->ptp_clock);
return 0;
}

View File

@@ -7,23 +7,18 @@
#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)
@@ -47,10 +42,12 @@
#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)
@@ -74,14 +71,12 @@ enum mtk_reset_event_id {
MTK_EVENT_RFIFO_UF = 19,
};
int mtk_eth_netdevice_event(struct notifier_block *n, unsigned long event, void *ptr);
extern struct notifier_block mtk_eth_netdevice_nb __read_mostly;
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 int mtk_wifi_num;
extern u32 mtk_reset_flag;
extern bool mtk_stop_fail;
irqreturn_t mtk_handle_fe_irq(int irq, void *_eth);
@@ -90,11 +85,8 @@ 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_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_dma_monitor(struct timer_list *t);
void mtk_prepare_reset_fe(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 */

View File

@@ -10,16 +10,12 @@
* 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"
@@ -80,8 +76,8 @@
#define PPE_MCAST_H_E 0xE0
#define PPE_MCAST_L_F 0x100
#define PPE_MCAST_H_F 0x104
#define PPE_MCAST_L_10 (-0x200)
#define PPE_MCAST_H_10 (-0x200 + 0x4)
#define PPE_MCAST_L_10 0xC00
#define PPE_MCAST_H_10 0xC04
#define PPE_MTU_DRP 0x108
#define PPE_MTU_VLYR_0 0x10C
#define PPE_MTU_VLYR_1 0x110
@@ -107,14 +103,32 @@
#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*/
/*--------------------------------------------------------------------------*/
@@ -131,29 +145,13 @@
#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 */
@@ -190,10 +188,8 @@
#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 */
@@ -211,12 +207,16 @@
#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,48 +359,6 @@ 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;
@@ -427,13 +385,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 sp_tag;
u16 etype;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -486,12 +444,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 */
@@ -502,7 +460,7 @@ struct hnat_ipv4_dslite {
};
u16 vlan1;
u16 sp_tag;
u16 etype;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -571,7 +529,7 @@ struct hnat_ipv4_mape {
};
u16 vlan1;
u16 sp_tag;
u16 etype;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -643,7 +601,7 @@ struct hnat_ipv6_3t_route {
u32 info_blk2;
};
u16 vlan1;
u16 sp_tag;
u16 etype;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -708,7 +666,7 @@ struct hnat_ipv6_5t_route {
};
u16 vlan1;
u16 sp_tag;
u16 etype;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -781,7 +739,7 @@ struct hnat_ipv6_6rd {
};
u16 vlan1;
u16 sp_tag;
u16 etype;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -843,7 +801,7 @@ struct hnat_ipv6_hnapt {
};
u16 vlan1;
u16 sp_tag;
u16 etype;
u32 dmac_hi;
u16 vlan2;
u16 dmac_lo;
@@ -879,7 +837,6 @@ 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;
@@ -911,12 +868,6 @@ 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.
*/
@@ -934,8 +885,6 @@ struct mib_entry {
struct hnat_accounting {
u64 bytes;
u64 packets;
struct nf_conntrack_zone zone;
u8 dir;
};
enum mtk_hnat_version {
@@ -1008,19 +957,7 @@ 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 {
@@ -1033,28 +970,11 @@ 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,
@@ -1092,11 +1012,9 @@ enum FoeIpAct {
#define HASH_MODE_3 3
/*PPE_FLOW_CFG*/
#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_FUC_FOE BIT(2)
#define BIT_FMC_FOE BIT(1)
#define BIT_FBC_FOE BIT(0)
#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)
@@ -1105,8 +1023,7 @@ 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_L2_BRG_EN BIT(15)
#define BIT_IP_PROT_CHK_BLIST BIT(16)
#define BIT_MIB_BUSY BIT(16)
#define BIT_IPV4_NAT_FRAG_EN BIT(17)
#define BIT_IPV4_HASH_GREK BIT(19)
#define BIT_IPV6_HASH_GREK BIT(20)
@@ -1115,9 +1032,6 @@ 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)
@@ -1144,14 +1058,6 @@ 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)
@@ -1238,36 +1144,22 @@ 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_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_WAN(dev) \
(!strncmp((dev)->name, hnat_priv->wan, strlen(hnat_priv->wan)))
#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)) || \
IS_BOND(dev))
#define IS_LAN2(dev) \
(!strncmp(dev->name, LAN2_DEV_NAME, strlen(LAN2_DEV_NAME)) || \
IS_BOND(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_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))
@@ -1283,25 +1175,16 @@ 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_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 MAX_PPPQ_PORT_NUM 6
#define es(entry) (entry_state[entry->bfib1.state])
#define ei(entry, end) (hnat_priv->foe_etry_num - (int)(end - entry))
@@ -1329,51 +1212,68 @@ 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_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)
#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)))
extern const struct of_device_id of_hnat_match[];
extern struct mtk_hnat *hnat_priv;
int hnat_dsa_fill_stag(const struct net_device *netdev,
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,
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
return false;
#endif
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;
}
struct foe_entry *hnat_get_foe_entry(u32 ppe_id, u32 index);
static inline bool hnat_dsa_is_enable(struct mtk_hnat *priv)
{
return false;
}
#endif
void hnat_deinit_debugfs(struct mtk_hnat *h);
int hnat_init_debugfs(struct mtk_hnat *h);
@@ -1382,14 +1282,8 @@ 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;
@@ -1397,21 +1291,9 @@ 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);
@@ -1427,41 +1309,21 @@ 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);
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)
static inline u16 foe_timestamp(struct mtk_hnat *h)
{
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;
return (readl(hnat_priv->fe_base + 0x0010)) & 0xffff;
}
#endif /* NF_HNAT_H */

View File

@@ -9,8 +9,6 @@
*
* 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>
@@ -21,21 +19,20 @@
* 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, u8 *dmac)
static int mcast_entry_get(u16 vlan_id, u32 dst_mac)
{
struct ppe_mcast_group *p = hnat_priv->pmcast->mtbl;
int index = -1;
u8 max = hnat_priv->pmcast->max_entry;
u8 i;
struct ppe_mcast_group *p = hnat_priv->pmcast->mtbl;
u8 max = hnat_priv->pmcast->max_entry;
for (i = 0; i < max; i++) {
if (p->valid) {
if ((p->vid == vlan_id) && !memcmp(p->dmac, dmac, ETH_ALEN)) {
index = i;
break;
}
} else if (index == -1) {
if ((index == -1) && (!p->valid)) {
index = i; /*get the first unused entry index*/
continue;
}
if ((p->vid == vlan_id) && (p->mac_hi == dst_mac)) {
index = i;
break;
}
p++;
@@ -46,37 +43,21 @@ static int mcast_entry_get(u16 vlan_id, u8 *dmac)
return index;
}
static int get_mac_from_mdb_entry(struct br_mdb_entry *entry, u8 *mac)
static void get_mac_from_mdb_entry(struct br_mdb_entry *entry,
u32 *mac_hi, u16 *mac_lo)
{
u32 ip;
switch (ntohs(entry->addr.proto)) {
case ETH_P_IP:
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;
*mac_lo = 0x0100;
*mac_hi = swab32((entry->addr.u.ip4 & 0xfffffe00) + 0x5e);
break;
case ETH_P_IPV6:
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;
*mac_lo = 0x3333;
*mac_hi = swab32(entry->addr.u.ip6.s6_addr32[3]);
break;
default:
return -EINVAL;
}
if (debug_level >= 7)
pr_info("%s:group mac=%pM\n", __func__, mac);
return 0;
trace_printk("%s:group mac_h=0x%08x, mac_l=0x%04x\n",
__func__, *mac_hi, *mac_lo);
}
/*set_hnat_mtbl - set ppe multicast register*/
@@ -84,8 +65,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_hi = DMAC_TO_HI16(group->dmac);
u32 mac_lo = DMAC_TO_LO32(group->dmac);
u16 mac_lo = group->mac_lo;
u32 mac_hi = group->mac_hi;
u8 mc_port = group->mc_port;
void __iomem *reg;
@@ -94,20 +75,16 @@ 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_hi == 0x0100)
if (mac_lo == 0x0100)
mcast_h.u.info.mc_mpre_sel = 0;
else if (mac_hi == 0x3333)
else if (mac_lo == 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_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);
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);
if (index < 0x10) {
reg = hnat_priv->ppe_base[ppe_id] + PPE_MCAST_H_0 + ((index) * 8);
writel(mcast_h.u.value, reg);
@@ -115,55 +92,31 @@ 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->ppe_base[ppe_id] + PPE_MCAST_H_10 + ((index) * 8);
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);
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 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
* 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
* 3.set the group info to ppe register
*/
static int hnat_mcast_table_update(int type, struct br_mdb_entry *entry)
{
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];
u32 mac_hi = 0;
u16 mac_lo = 0;
int i, index;
struct ppe_mcast_group *group;
rcu_read_lock();
dev = dev_get_by_index_rcu(&init_net, entry->ifindex);
@@ -173,242 +126,55 @@ static int hnat_mcast_table_update(int type, struct br_mdb_entry *entry)
}
rcu_read_unlock();
ret = get_mac_from_mdb_entry(entry, dmac);
if (ret < 0)
return ret;
index = mcast_entry_get(entry->vid, dmac);
get_mac_from_mdb_entry(entry, &mac_hi, &mac_lo);
index = mcast_entry_get(entry->vid, mac_hi);
if (index == -1)
return -1;
group = &hnat_priv->pmcast->mtbl[index];
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 */
}
group->mac_hi = mac_hi;
group->mac_lo = mac_lo;
switch (type) {
case RTM_NEWMDB:
group->if_num[port]++;
if (IS_LAN(dev) || IS_WAN(dev))
group->eif++;
else
group->oif++;
group->vid = entry->vid;
group->valid = true;
break;
case RTM_DELMDB:
if (group->valid)
group->if_num[port]--;
if (group->valid) {
if (IS_LAN(dev) || IS_WAN(dev))
group->eif--;
else
group->oif--;
}
break;
default:
return -1;
}
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]);
trace_printk("%s:devname=%s,eif=%d,oif=%d\n", __func__,
dev->name, group->eif, group->oif);
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 */
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));
} else {
for (i = 0; i < CFG_PPE_NUM; i++)
set_hnat_mtbl(group, i, index);
}
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;
@@ -443,19 +209,13 @@ static void hnat_mcast_nlmsg_handler(struct work_struct *work)
}
entry = (struct br_mdb_entry *)nla_data(info);
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);
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);
}
kfree_skb(skb);
}
@@ -507,7 +267,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, true);
foe_ts = foe_timestamp(hnat_priv);
if ((foe_ts - e_ts) > 0x3000)
foe_ts = (~(foe_ts)) & 0xffff;
if (abs(foe_ts - e_ts) > 20)
@@ -525,54 +285,44 @@ int hnat_mcast_enable(u32 ppe_id)
if (ppe_id >= CFG_PPE_NUM)
return -EINVAL;
if (!hnat_priv->pmcast) {
pmcast = kzalloc(sizeof(*pmcast), GFP_KERNEL);
if (!pmcast)
return -1;
pmcast = kzalloc(sizeof(*pmcast), GFP_KERNEL);
if (!pmcast)
return -1;
memset(pmcast->mtbl, 0, sizeof(struct ppe_mcast_group) * MAX_MCAST_ENTRY);
if (hnat_priv->data->version == MTK_HNAT_V1_1)
pmcast->max_entry = 0x10;
else
pmcast->max_entry = MAX_MCAST_ENTRY;
/* Initialize multicast list for unicast mode */
INIT_LIST_HEAD(&pmcast->mlist);
rwlock_init(&pmcast->mcast_lock);
INIT_WORK(&pmcast->work, hnat_mcast_nlmsg_handler);
pmcast->queue = create_singlethread_workqueue("ppe_mcast");
if (!pmcast->queue)
goto err1;
if (hnat_priv->data->version == MTK_HNAT_V1_1)
pmcast->max_entry = 0x10;
else
pmcast->max_entry = MAX_MCAST_ENTRY;
pmcast->msock = hnat_mcast_netlink_open(&init_net);
if (!pmcast->msock)
goto err2;
INIT_WORK(&pmcast->work, hnat_mcast_nlmsg_handler);
pmcast->queue = create_singlethread_workqueue("ppe_mcast");
if (!pmcast->queue)
goto err1;
hnat_priv->pmcast = pmcast;
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);
}
/* 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, NR_PDMA_PORT);
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P0_PPSE, 0);
/* multicast port1 map to GMAC1 */
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P1_PPSE, NR_GMAC1_PORT);
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P1_PPSE, 1);
/* multicast port2 map to GMAC2 */
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P2_PPSE, NR_GMAC2_PORT);
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P2_PPSE, 2);
/* multicast port3 map to QDMA */
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);
cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MCAST_PPSE, MC_P3_PPSE, 5);
return 0;
err2:
@@ -587,7 +337,6 @@ err1:
int hnat_mcast_disable(void)
{
struct ppe_mcast_table *pmcast = hnat_priv->pmcast;
int i;
if (!pmcast)
return -EINVAL;
@@ -595,16 +344,10 @@ 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;
}

View File

@@ -17,20 +17,18 @@
#define RTMGRP_MDB 0x2000000
#define MAX_MCAST_ENTRY 64
#define MAX_MCAST_PORT 5
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 */
};
#define MCAST_TO_PDMA (0x1 << 0)
#define MCAST_TO_GDMA1 (0x1 << 1)
#define MCAST_TO_GDMA2 (0x1 << 2)
struct ppe_mcast_group {
u32 mac_hi; /*multicast mac addr*/
u16 mac_lo; /*multicast mac addr*/
u16 vid;
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 */
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.*/
bool valid;
};
@@ -39,22 +37,24 @@ 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_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;
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;
} info;
} u;
};
@@ -63,29 +63,7 @@ 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

View File

@@ -6,110 +6,58 @@
#include <linux/of_device.h>
#include <net/netfilter/nf_flow_table.h>
#include "hnat.h"
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,
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)
{
#if defined(CONFIG_NET_DSA)
const struct net_device *ndev;
const unsigned int *port_reg;
const struct dsa_port *dp;
struct net_device *ndev;
int port_index;
u16 dsa_tag;
u16 sp_tag;
if (hw_path->flags & BIT(DEV_PATH_VLAN))
if (hw_path->flags & FLOW_OFFLOAD_PATH_VLAN)
ndev = hw_path->dev;
else
ndev = (struct net_device *)netdev;
ndev = 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);
/* In the case MAPE LAN --> WAN, binding entry is to CPU.
* Do not add special tag.
*/
if (IS_WAN(ndev) && mape)
return port_index;
if (!entry->bfib1.vlan_layer)
entry->bfib1.vlan_layer = 1;
else
/* VLAN existence indicator */
sp_tag |= BIT(8);
entry->bfib1.vpm = 0;
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;
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;
else
/* VLAN existence indicator */
dsa_tag |= BIT(8);
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;
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;
break;
default:
pr_info("DSA + HNAT unsupport protocol\n");
}
return port_index;
#else
return -EINVAL;
#endif
}

View File

@@ -44,11 +44,7 @@ struct hnat_desc {
u32 is_sp : 1;
u32 hf : 1;
u32 amsdu : 1;
u32 tops : 6;
u32 is_decap : 1;
u32 cdrt : 8;
u32 is_decrypt : 1;
u32 resv3 : 3;
u32 resv3 : 19;
u32 magic_tag_protect : 16;
} __packed;
#elif defined(CONFIG_MEDIATEK_NETSYS_RX_V2)
@@ -89,36 +85,12 @@ 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)
@@ -162,7 +134,6 @@ 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) \
@@ -193,8 +164,6 @@ 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))

View File

@@ -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 0;
return -1;
ss->pll = syscon_node_to_regmap(np);
if (IS_ERR(ss->pll))
@@ -77,142 +77,96 @@ 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);
}
static void mtk_sgmii_get_state(struct mtk_sgmii_pcs *mpcs)
void mtk_sgmii_reset(struct mtk_eth *eth, int id)
{
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 (id >= MTK_MAX_DEVS || !eth->toprgu)
if (!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_SGMII0_GRST;
if (mpcs->regmap_pextp)
val |= SWSYSRST_XFI_PEXPT0_GRST;
val |= SWSYSRST_XFI_PEXPT0_GRST |
SWSYSRST_SGMII0_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);
usleep_range(100, 500);
udelay(100);
/* De-assert SGMII reset */
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
val &= ~SWSYSRST_SGMII0_GRST;
if (mpcs->regmap_pextp)
val &= ~SWSYSRST_XFI_PEXPT0_GRST;
val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
SWSYSRST_SGMII0_GRST);
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
/* Disable software reset */
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
val &= ~SWSYSRST_SGMII0_GRST;
if (mpcs->regmap_pextp)
val &= ~SWSYSRST_XFI_PEXPT0_GRST;
val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
SWSYSRST_SGMII0_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_SGMII1_GRST;
if (mpcs->regmap_pextp)
val |= SWSYSRST_XFI_PEXPT1_GRST;
val |= SWSYSRST_XFI_PEXPT1_GRST |
SWSYSRST_SGMII1_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);
usleep_range(100, 500);
udelay(100);
/* De-assert SGMII reset */
regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
val &= ~SWSYSRST_SGMII1_GRST;
if (mpcs->regmap_pextp)
val &= ~SWSYSRST_XFI_PEXPT1_GRST;
val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
SWSYSRST_SGMII1_GRST);
regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
/* Disable software reset */
regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
val &= ~SWSYSRST_SGMII1_GRST;
if (mpcs->regmap_pextp)
val &= ~SWSYSRST_XFI_PEXPT1_GRST;
val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
SWSYSRST_SGMII1_GRST);
regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
break;
}
mutex_unlock(&mpcs->reset_lock);
mdelay(1);
}
usleep_range(10000, 11000);
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;
}
void mtk_sgmii_setup_phya_gen1(struct mtk_sgmii_pcs *mpcs)
@@ -272,7 +226,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);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
0x20000000);
/* Setup DA default value */
@@ -303,28 +257,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);
usleep_range(150, 500);
udelay(150);
/* Switch to P0 */
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0200C111);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0200C101);
usleep_range(15, 50);
udelay(15);
/* Switch to Gen2 */
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0201C111);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0201C101);
usleep_range(100, 500);
udelay(100);
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);
usleep_range(400, 1000);
udelay(400);
}
void mtk_sgmii_setup_phya_gen2(struct mtk_sgmii_pcs *mpcs)
@@ -384,7 +338,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);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
0x20000000);
/* Setup DA default value */
@@ -413,28 +367,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);
usleep_range(150, 500);
udelay(150);
/* Switch to P0 */
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0200C111);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0200C101);
usleep_range(15, 50);
udelay(15);
/* Switch to Gen2 */
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0201C111);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0201C101);
usleep_range(100, 500);
udelay(100);
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);
usleep_range(400, 1000);
udelay(400);
}
static int mtk_sgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
@@ -453,6 +407,8 @@ 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).
@@ -476,63 +432,55 @@ static int mtk_sgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
speed = SGMII_SPEED_1000;
}
link_timer = phylink_get_link_timer_ns(interface);
if (link_timer < 0)
return link_timer;
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;
}
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
mtk_sgmii_xfi_pll_enable(eth->sgmii);
mtk_sgmii_reset(mpcs);
}
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
mtk_sgmii_xfi_pll_enable(eth->sgmii);
mtk_sgmii_reset(eth, mpcs->id);
}
mutex_lock(&mpcs->regmap_lock);
/* 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);
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 |
@@ -541,94 +489,74 @@ 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 | SGMII_PCS_REF_CK_SEL, bmcr);
SGMII_AN_ENABLE, bmcr);
/* Release PHYA power down state */
usleep_range(50, 100);
regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
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 (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);
}
}
mutex_unlock(&mpcs->regmap_lock);
spin_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;
/* 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);
state->interface = mpcs->interface;
/* 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;
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;
}
/* Reconfiguring SGMII every second to ensure that PCS can
* link up with the Link Partner when a module is inserted.
*/
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);
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);
}
}
@@ -650,20 +578,21 @@ 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(100);
msleep(1000);
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)));
dev_warn(dev, "sgmii%d: wait link up timeout!\n", mpcs->id);
return;
pr_warn("%s wait link up timeout!\n", __func__);
exit:
/* If autoneg is enabled, the force speed and duplex
@@ -691,8 +620,6 @@ 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,
@@ -717,27 +644,15 @@ 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].polarity = 0;
ss->pcs[i].flags &= ~(MTK_SGMII_PN_SWAP);
if (of_property_read_bool(np, "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].flags |= MTK_SGMII_PN_SWAP;
ss->pcs[i].pcs.ops = &mtk_sgmii_pcs_ops;
ss->pcs[i].pcs.poll = true;
ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
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);
spin_lock_init(&ss->pcs[i].regmap_lock);
of_node_put(np);
}
@@ -755,9 +670,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, unsigned int id)
struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id)
{
if (id >= MTK_MAX_DEVS || !ss->pcs[id].regmap)
if (!ss->pcs[id].regmap)
return NULL;
return &ss->pcs[id].pcs;

View File

@@ -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 0;
return -1;
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 0;
return -1;
eth->toprgu = syscon_node_to_regmap(np);
if (IS_ERR(eth->toprgu))
@@ -91,32 +91,17 @@ 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)) {
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);
}
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);
}
}
@@ -128,30 +113,16 @@ 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)) {
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);
}
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);
}
}
@@ -215,7 +186,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);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
0x20000000);
/* Setup DA default value */
@@ -248,28 +219,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);
usleep_range(150, 500);
udelay(150);
/* Switch to P0 */
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0200C111);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0200C101);
usleep_range(15, 50);
udelay(15);
/* Switch to Gen3 */
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0202C111);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0202C101);
usleep_range(100, 500);
udelay(100);
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);
usleep_range(400, 1000);
udelay(400);
}
void mtk_usxgmii_setup_phya_5gbaser(struct mtk_usxgmii_pcs *mpcs)
@@ -329,7 +300,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);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
0x20000000);
/* Setup DA default value */
@@ -362,28 +333,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);
usleep_range(150, 500);
udelay(150);
/* Switch to P0 */
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0200C111);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0200C101);
usleep_range(15, 50);
udelay(15);
/* Switch to Gen3 */
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0202C111);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0202C101);
usleep_range(100, 500);
udelay(100);
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);
usleep_range(400, 1000);
udelay(400);
}
void mtk_usxgmii_setup_phya_10gbaser(struct mtk_usxgmii_pcs *mpcs)
@@ -443,7 +414,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);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
0x20000000);
/* Setup DA default value */
@@ -479,36 +450,34 @@ void mtk_usxgmii_setup_phya_10gbaser(struct mtk_usxgmii_pcs *mpcs)
/* Release reset */
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0200E800);
usleep_range(150, 500);
udelay(150);
/* Switch to P0 */
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0200C111);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0200C101);
usleep_range(15, 50);
udelay(15);
/* Switch to Gen3 */
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0202C111);
usleep_range(1, 5);
ndelay(1020);
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x0202C101);
usleep_range(100, 500);
udelay(100);
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);
usleep_range(400, 1000);
udelay(400);
}
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;
@@ -521,38 +490,195 @@ 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);
}
bool mtk_usxgmii_is_valid_ctle(struct mtk_usxgmii_pcs *mpcs)
void mtk_usxgmii_reset(struct mtk_eth *eth, int id)
{
unsigned int val, ctle;
mutex_lock(&mpcs->reset_lock);
regmap_write(mpcs->regmap_pextp, 0x00, 0x00000404);
regmap_write(mpcs->regmap_pextp, 0x10, 0x00d600d5);
regmap_read(mpcs->regmap_pextp, 0xd0, &val);
mutex_unlock(&mpcs->reset_lock);
ctle = FIELD_GET(GENMASK(12, 8), val);
if (ctle > 10)
return false;
return true;
}
static void mtk_usxgmii_get_state(struct mtk_usxgmii_pcs *mpcs)
{
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)];
u32 val = 0;
mutex_lock(&mpcs->reset_lock);
if (id >= MTK_MAX_DEVS || !eth->toprgu)
return;
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);
udelay(100);
/* 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);
}
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;
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 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;
regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
if (FIELD_GET(USXGMII_AN_ENABLE, val)) {
@@ -614,257 +740,13 @@ static void mtk_usxgmii_get_state(struct mtk_usxgmii_pcs *mpcs)
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 (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);
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);
}
}
@@ -886,24 +768,35 @@ 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(100);
msleep(1000);
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)));
dev_warn(dev, "usxgmii%d: wait link up timeout!\n", mpcs->id);
pr_warn("%s wait link up timeout!\n", __func__);
}
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,
@@ -927,27 +820,11 @@ 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;
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);
spin_lock_init(&ss->pcs[i].regmap_lock);
of_node_put(np);
}
@@ -963,9 +840,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, unsigned int id)
struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_usxgmii *ss, int id)
{
if (id >= MTK_MAX_DEVS || !ss->pcs[id].regmap)
if (!ss->pcs[id].regmap)
return NULL;
return &ss->pcs[id].pcs;

View File

@@ -12,13 +12,11 @@
#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
@@ -48,7 +46,7 @@
#define MII_MMD_ADDR_DATA_REG 0x0e
#define MMD_OP_MODE_DATA BIT(14)
#define EN8811H_DRIVER_VERSION "v1.3.0"
#define EN8811H_DRIVER_VERSION "v1.2.5"
#define LED_ON_CTRL(i) (0x024 + ((i)*2))
#define LED_ON_EN (1 << 15)
@@ -88,64 +86,20 @@
#define LED_BLK_DUR (0x023)
#define LED_BLK_DUR_MASK (0xffff)
#define UNIT_LED_BLINK_DURATION 780
#define UNIT_LED_BLINK_DURATION 1024
#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;
unsigned int ivy_crc32;
char buf[512];
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 {
@@ -155,18 +109,6 @@ 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,

View File

@@ -15,12 +15,10 @@
#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"
@@ -33,42 +31,8 @@
#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_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)
#define DEBUGFS_MII_CL22_OP "cl22_op"
#define DEBUGFS_MII_CL45_OP "cl45_op"
enum air_port_mode {
AIR_PORT_MODE_FORCE_100,
@@ -100,104 +64,6 @@ 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
@@ -218,10 +84,7 @@ 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_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);
int air_surge_5ohm_config(struct phy_device *phydev);
#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
int airphy_debugfs_init(struct phy_device *phydev);
void airphy_debugfs_remove(struct phy_device *phydev);

View File

@@ -35,11 +35,7 @@ MODULE_LICENSE("GPL");
* GPIO3 <-> BASE_T_LED2,
**************************/
/* User-defined.B */
/* #define AIR_MD32_FW_CHECK */
/* #define AIR_IVY_LOAD */
#ifdef AIR_IVY_LOAD
/* #define AIR_IVY_CHECK */
#endif
/*#define AIR_MD32_FW_CHECK*/
#define AIR_LED_SUPPORT
#ifdef AIR_LED_SUPPORT
static const struct air_base_t_led_cfg led_cfg[3] = {
@@ -57,20 +53,17 @@ 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 offset;
int ret = 0;
unsigned int write_data, offset;
int ret = 0, len = 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);
@@ -97,7 +90,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)
{
@@ -151,113 +144,7 @@ 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);
@@ -271,27 +158,6 @@ 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)
@@ -362,13 +228,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);
goto release;
break;
}
retry--;
} while (pbus_value != 0x1);
dev_info(dev,
"Release Software Reset successful.\n");
@@ -384,41 +250,6 @@ 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)
@@ -491,7 +322,6 @@ 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)
@@ -527,10 +357,6 @@ 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);
@@ -540,7 +366,6 @@ 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)
{
@@ -561,13 +386,11 @@ 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_2500baseT_Full_BIT,
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
phydev->supported);
return 0;
}
@@ -576,11 +399,12 @@ static int en8811h_get_features(struct phy_device *phydev)
static int en8811h_probe(struct phy_device *phydev)
{
int ret = 0;
int pid1 = 0, pid2 = 0;
u32 pbus_value = 0;
int reg_value, pid1 = 0, pid2 = 0;
u32 retry, 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);
@@ -590,30 +414,23 @@ 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");
goto priv_free;
kfree(priv);
return -ENODEV;
}
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_of_init(phydev);
if (ret < 0)
goto priv_free;
ret = en8811h_load_firmware(phydev);
if (ret < 0) {
dev_err(dev, "EN8811H load firmware fail.\n");
goto priv_free;
}
#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
ret = airphy_debugfs_init(phydev);
if (ret < 0) {
@@ -622,68 +439,69 @@ static int en8811h_probe(struct phy_device *phydev)
goto priv_free;
}
#endif /* CONFIG_AIROHA_EN8811H_PHY_DEBUGFS */
if (priv->phy_handle) {
dev_info(dev, "EN8811H Probe OK! (%s)\n", EN8811H_DRIVER_VERSION);
} else {
ret = en8811h_init_up(phydev);
if (ret < 0)
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
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;
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;
}
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);
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 (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;
}
#endif
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)
{
@@ -700,229 +518,6 @@ 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,
@@ -935,12 +530,6 @@ 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)

View File

@@ -18,16 +18,6 @@
/* 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)
@@ -71,8 +61,6 @@
#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)
@@ -90,7 +78,6 @@
#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)
@@ -119,72 +106,9 @@
/* 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)
@@ -193,114 +117,10 @@
#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);
@@ -430,7 +250,7 @@ static int an8855_set_hsgmii_mode(struct gsw_an8855 *gsw)
val &= ~(0xf << 25);
val |= (0x1 << 25);
val &= ~(0x7 << 29);
val |= (0x6 << 29);
val |= (0x3 << 29);
an8855_reg_write(gsw, RG_QP_CDR_LPF_SETVALUE, val);
val = an8855_reg_read(gsw, RG_QP_CDR_PR_CKREF_DIV1);
@@ -461,10 +281,12 @@ static int an8855_set_hsgmii_mode(struct gsw_an8855 *gsw)
val |= (0x4 << 24);
an8855_reg_write(gsw, RG_QP_CDR_PR_CKREF_DIV1, val);
/* PMA (For HW Mode) */
val = an8855_reg_read(gsw, PLL_CTRL_0);
val |= BIT(0);
an8855_reg_write(gsw, PLL_CTRL_0, val);
val = an8855_reg_read(gsw, RX_CTRL_26);
val |= BIT(23);
val &= ~BIT(24);
val &= ~BIT(23);
val |= BIT(26);
an8855_reg_write(gsw, RX_CTRL_26, val);
@@ -492,8 +314,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 << 0);
val |= (0xfff << 0);
val &= ~(0x7fff << 14);
val |= (0xfff << 14);
an8855_reg_write(gsw, RX_CTRL_8, val);
/* Frequency memter */
@@ -512,10 +334,6 @@ 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);
@@ -554,28 +372,6 @@ 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);
@@ -735,10 +531,13 @@ 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);
/* PMA (For HW Mode) */
val = an8855_reg_read(gsw, PLL_CTRL_0);
val |= BIT(0);
an8855_reg_write(gsw, PLL_CTRL_0, val);
val = an8855_reg_read(gsw, RX_CTRL_26);
val |= BIT(23);
val &= ~BIT(24);
val &= ~BIT(23);
if (mode == SGMII_MODE_AN)
val |= BIT(26);
an8855_reg_write(gsw, RX_CTRL_26, val);
@@ -787,10 +586,6 @@ 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);
@@ -875,6 +670,7 @@ 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);
}
@@ -949,9 +745,6 @@ 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);
}
@@ -979,10 +772,7 @@ static int an8855_sw_detect(struct gsw_an8855 *gsw, struct chip_rev *crev)
static void an8855_phy_setting(struct gsw_an8855 *gsw)
{
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;
int i;
u32 val;
/* Release power down */
@@ -1001,44 +791,40 @@ static void an8855_phy_setting(struct gsw_an8855 *gsw)
val |= ADVERTISE_PAUSE_ASYM;
gsw->mii_write(gsw, i, MII_ADVERTISE, val);
}
}
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))));
static void an8855_low_power_setting(struct gsw_an8855 *gsw)
{
int port, addr;
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);
}
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);
}
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)
@@ -1047,216 +833,10 @@ 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, ret = 0;
u32 val, led_count = ARRAY_SIZE(led_cfg);
int id;
int i;
u32 val;
gsw->phy_base = gsw->smi_addr & AN8855_SMI_ADDR_MASK;
@@ -1272,7 +852,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;
@@ -1285,59 +865,6 @@ 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 */
@@ -1348,7 +875,6 @@ 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;
}

View File

@@ -23,24 +23,8 @@
#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;
@@ -53,60 +37,6 @@ 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;
@@ -125,8 +55,6 @@ 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;

View File

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifian8855_gsw_ider: GPL-2.0
/*
* Copyright (c) 2023 Airoha Inc.
* Author: Min Yao <min.yao@airoha.com>
@@ -18,9 +18,6 @@
#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"
@@ -28,15 +25,11 @@
#include "an8855_nl.h"
/* AN8855 driver version */
#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"
#define ARHT_AN8855_SWCFG_DRIVER_VER "1.0.1-L5.4"
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,
@@ -60,6 +53,7 @@ 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);
@@ -84,6 +78,7 @@ 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);
}
@@ -115,17 +110,13 @@ 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);
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);
val = gsw->host_bus->read(gsw->host_bus, addr, regnum);
mutex_unlock(&gsw->host_bus->mdio_lock);
return val;
@@ -134,16 +125,13 @@ 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, 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);
gsw->host_bus->write(gsw->host_bus, addr, regnum, val);
mutex_unlock(&gsw->host_bus->mdio_lock);
}
@@ -158,10 +146,6 @@ 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"))
@@ -188,13 +172,9 @@ 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;
}
@@ -316,7 +296,6 @@ 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);
@@ -335,51 +314,6 @@ 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;
@@ -421,14 +355,6 @@ 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) {
@@ -468,8 +394,6 @@ 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) {
@@ -477,6 +401,8 @@ 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);
@@ -485,8 +411,6 @@ 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)
@@ -517,8 +441,6 @@ 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);

View File

@@ -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_U32 },
[AN8855_ATTR_TYPE_VAL] = { .type = NLA_U32 },
[AN8855_ATTR_TYPE_REG] = { .type = NLA_S32 },
[AN8855_ATTR_TYPE_VAL] = { .type = NLA_S32 },
[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;
u32 reg = 0;
int value = 0;
s32 phy, devad, reg;
int value;
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_REG, &reg))
if (reg < 0)
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_u32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
if (ret < 0)
goto err;
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
if (ret < 0)
goto err;
@@ -246,18 +246,20 @@ err:
static int an8855_nl_reply_write(struct genl_info *info, struct gsw_an8855 *gsw)
{
struct sk_buff *rep_skb = NULL;
s32 phy, devad;
u32 value = 0, reg = 0;
s32 phy, devad, reg;
u32 value;
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);
if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_REG, &reg))
goto err;
reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1);
if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_VAL, &value))
goto err;
if (reg < 0)
goto err;
ret = an8855_nl_prepare_reply(info, AN8855_CMD_WRITE, &rep_skb);
if (ret < 0)
goto err;
@@ -271,11 +273,11 @@ static int an8855_nl_reply_write(struct genl_info *info, struct gsw_an8855 *gsw)
an8855_reg_write(gsw, reg, value);
}
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
if (ret < 0)
goto err;
ret = nla_put_u32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
if (ret < 0)
goto err;

View File

@@ -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 + 0x3e00)
#define GMACCR (PORT_MAC_CTRL_BASE + 0x30e0)
#define MAX_RX_JUMBO_S 4
#define MAX_RX_JUMBO_M 0xf0
#define MAX_RX_JUMBO_S 2
#define MAX_RX_JUMBO_M 0x3c
#define MAX_RX_PKT_LEN_S 0
#define MAX_RX_PKT_LEN_M 0x3
@@ -172,12 +172,6 @@
#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)
@@ -188,10 +182,7 @@
#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 PKG_SEL 0x10000094
#define PAG_SEL_AN8855H 0x2
#define CKGCR (0x10213E1C)
#define CKG_LNKDN_GLB_STOP (0x01)
#define CKG_LNKDN_PORT_STOP (0x02)
#endif /* _AN8855_REGS_H_ */

View File

@@ -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 < 0 || port >= AN8855_NUM_PORTS)
if (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 < 0 || port >= AN8855_NUM_PORTS)
if (port >= AN8855_NUM_PORTS)
return -EINVAL;
if (pvid < AN8855_MIN_VID || pvid > AN8855_MAX_VID)
@@ -300,20 +300,18 @@ 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 = 0, hi = 0, hi2 = 0;
u64 lo, hi, hi2;
if (i >= 0) {
offset = an8855_mibs[i].offset;
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;
}
@@ -372,7 +370,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 = 0x9100 << STAG_VPID_S;
u32 pvc_mode = 0x8100 << STAG_VPID_S;
if (gsw->port5_cfg.stag_on && i == 5)
pvc_mode |= PVC_PORT_STAG | PVC_STAG_REPLACE;

View File

@@ -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, 0 },
.etags = { 0, 0, 0x20 },
.vids = { 0, 1, 2 },
}, {
.name = "wllll",
.pvids = { 2, 1, 1, 1, 1, 1 },
.members = { 0, 0x3e, 0x21 },
.etags = { 0, 0, 0 },
.etags = { 0, 0, 0x20 },
.vids = { 0, 1, 2 },
}, {
.name = "lwlll",
.pvids = { 1, 2, 1, 1, 1, 1 },
.members = { 0, 0x3d, 0x22 },
.etags = { 0, 0, 0 },
.etags = { 0, 0, 0x20 },
.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 = 0x9100 << STAG_VPID_S;
u32 pvc_mode = 0x8100 << STAG_VPID_S;
if (untag_ports & BIT(i) && !(tag_ports & BIT(i)))
pvc_mode = (0x9100 << STAG_VPID_S) |
pvc_mode = (0x8100 << STAG_VPID_S) |
(VA_TRANSPARENT_PORT << VLAN_ATTR_S);
if (gsw->port5_cfg.stag_on && i == 5)
pvc_mode = (u32)((0x9100 << STAG_VPID_S) | PVC_PORT_STAG
pvc_mode = (u32)((0x8100 << STAG_VPID_S) | PVC_PORT_STAG
| PVC_STAG_REPLACE);
an8855_reg_write(gsw, PVC(i), pvc_mode);
@@ -159,8 +159,7 @@ void an8855_apply_vlan_config(struct gsw_an8855 *gsw)
u16 pvid = 0;
u32 val;
if ((vlan >= 0) && (vlan < AN8855_NUM_VLANS)
&& (gsw->vlan_entries[vlan].member))
if (vlan < AN8855_NUM_VLANS && gsw->vlan_entries[vlan].member)
pvid = gsw->vlan_entries[vlan].vid;
val = an8855_reg_read(gsw, PVID(i));

View File

@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*PURPOSE:
/*SPDX-License-Identifier: GPL-2.0*/
/*FILE NAME: an8801.c
*PURPOSE:
*Airoha phy driver for Linux
*NOTES:
*
@@ -634,23 +635,6 @@ 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
@@ -748,43 +732,27 @@ 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;
@@ -1379,7 +1347,6 @@ 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;
@@ -1390,16 +1357,14 @@ static int an8801sb_read_status(struct phy_device *phydev)
ret |= phy_write_mmd(
phydev, MMD_DEV_VSPEC2, PHY_PRE_SPEED_REG, prespeed);
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);
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) {
@@ -1407,59 +1372,31 @@ 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);
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);
}
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);
}
return ret;
}

View File

@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*PURPOSE:
/*SPDX-License-Identifier: GPL-2.0*/
/*FILE NAME: an8801.h
*PURPOSE:
*Define Airoha phy driver function
*
*NOTES:
@@ -11,7 +12,7 @@
/* NAMING DECLARATIONS
*/
#define AN8801_DRIVER_VERSION "1.1.7"
#define AN8801_DRIVER_VERSION "1.1.6"
#define DEBUGFS_COUNTER "counter"
#define DEBUGFS_INFO "driver_info"
@@ -89,7 +90,7 @@
#define UNIT_LED_BLINK_DURATION 780
/* Serdes auto negotiation restart */
/* Serdes auto negotation restart */
#define AN8801SB_SGMII_AN0_ANRESTART (0x0200)
#define AN8801SB_SGMII_AN0_AN_DONE (0x0001)
#define AN8801SB_SGMII_AN0_RESET (0x8000)
@@ -108,8 +109,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 \
@@ -208,7 +209,6 @@ struct an8801_priv {
#endif
int pol;
int surge;
int sgmii_mode;
};
enum an8801_polarity {
@@ -224,10 +224,4 @@ 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 */

View File

@@ -26,7 +26,6 @@
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <linux/delay.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/version.h>
@@ -62,7 +61,7 @@ enum {
PHY_STATE_PROCESS = 2,
PHY_STATE_FAIL = 3,
};
#define CONFIG_EN8801S_DEBUGFS
struct en8801s_priv {
bool first_init;
u16 count;
@@ -70,9 +69,6 @@ struct en8801s_priv {
#if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE)
struct gpio_desc *hw_reset;
#endif
#ifdef CONFIG_EN8801S_DEBUGFS
struct dentry *debugfs_root;
#endif
};
/*
@@ -105,48 +101,11 @@ static const u16 led_dur = UNIT_LED_BLINK_DURATION << AIR_LED_BLK_DUR_64M;
#endif
/* User-defined.E */
#ifdef CONFIG_EN8801S_DEBUGFS
#define EN8801S_DEBUGFS_POLARITY_HELP_STRING \
"\nUsage: echo [tx_polarity] [rx_polarity] > /sys/" \
"kernel/debug/mdio-bus\':[phy_addr]/polarity" \
"\npolarity: tx_normal, tx_reverse, rx_normal, rx_reverse" \
"\ntx_normal is tx polarity is normal." \
"\ntx_reverse is tx polarity need to be swapped." \
"\nrx_normal is rx polarity is normal." \
"\nrx_reverse is rx polarity need to be swapped." \
"\nFor example tx polarity need to be swapped. " \
"But rx polarity is normal." \
"\necho tx_reverse rx_normal > /sys/" \
"kernel/debug/mdio-bus\':[phy_addr]/polarity" \
"\n"
#define EN8801S_DEBUGFS_RX_ERROR_STRING \
"\nRx param is not correct." \
"\nrx_normal: rx polarity is normal." \
"rx_reverse: rx polarity is reverse.\n"
#define EN8801S_DEBUGFS_TX_ERROR_STRING \
"\nTx param is not correct." \
"\ntx_normal: tx polarity is normal." \
"tx_reverse: tx polarity is reverse.\n"
#define EN8801S_DEBUGFS_PBUS_HELP_STRING \
"\nUsage: echo w [pbus_addr] [pbus_reg] [value] > /sys/" \
"kernel/debug/mdio-bus\':[phy_addr]/pbus_reg_op" \
"\n echo r [pbus_addr] [pbus_reg] > /sys/" \
"kernel/debug/mdio-bus\':[phy_addr]/pbus_reg_op" \
"\nRead example: PBUS addr 0x19, Register 0x19a4" \
"\necho r 0x19 0x19a4 > /sys/" \
"kernel/debug/mdio-bus\':[phy_addr]/pbus_reg_op" \
"\nWrite example: PBUS addr 0x19, Register 0xcf8 0x1a01503" \
"\necho w 0x19 0xcf8 0x1a01503> /sys/" \
"kernel/debug/mdio-bus\':[phy_addr]/pbus_reg_op" \
"\n"
#endif
/************************************************************************
* F U N C T I O N S
************************************************************************/
static int en8801s_phase2_init(struct phy_device *phydev);
static void air_debugfs_remove(struct phy_device *phydev);
static int en8801s_debugfs_init(struct phy_device *phydev);
static unsigned int airoha_cl22_read(struct mii_bus *ebus, int phy_addr,
unsigned int phy_register, unsigned int *read_data)
{
@@ -571,19 +530,20 @@ static int en8801s_phase1_init(struct phy_device *phydev)
mdelay(500);
if (priv->pro_version == 4) {
pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1900);
dev_dbg(dev, "Before 0x1900 0x%lx\n", pbus_data);
dev_dbg(dev, "Before 0x1900 0x%x\n", pbus_data);
ret = airoha_pbus_write(mbus, pbus_addr, 0x1900, 0x101009f);
if (ret < 0)
return ret;
pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1900);
dev_dbg(dev, "After 0x1900 0x%lx\n", pbus_data);
dev_dbg(dev, "After 0x1900 0x%x\n", pbus_data);
pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x19a8);
dev_dbg(dev, "Before 19a8 0x%lx\n", pbus_data);
ret = airoha_pbus_write(mbus, pbus_addr, 0x19a8, pbus_data & ~BIT(16));
dev_dbg(dev, "Before 19a8 0x%x\n", pbus_data);
ret = airoha_pbus_write(mbus, pbus_addr,
0x19a8, pbus_data & ~BIT(16));
if (ret < 0)
return ret;
pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x19a8);
dev_dbg(dev, "After 19a8 0x%lx\n", pbus_data);
dev_dbg(dev, "After 19a8 0x%x\n", pbus_data);
}
pbus_data = airoha_pbus_read(mbus, pbus_addr,
EN8801S_RG_SMI_ADDR); /* SMI ADDR */
@@ -627,7 +587,7 @@ static int en8801s_phase1_init(struct phy_device *phydev)
phydev->dev_flags = PHY_STATE_INIT;
dev_info(dev, "Phase1 initialize OK ! (%s)\n", EN8801S_DRIVER_VERSION);
dev_info(dev, "Phase1 initialize OK ! (%s) 10Te TP_IDL fixed.\n", EN8801S_DRIVER_VERSION);
if (priv->pro_version == 4) {
ret = en8801s_phase2_init(phydev);
if (ret != 0) {
@@ -851,14 +811,7 @@ static int en8801s_phase2_init(struct phy_device *phydev)
retry--;
}
pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1C38); /* RAW#2 */
ret = airoha_cl45_read(mbus, phy_addr, 0x1E, 0x12, &cl45_value);
if (ret < 0)
return ret;
GPHY_RG_1E_012.DATA = cl45_value;
GPHY_RG_1E_012.DataBitField.da_tx_i2mpb_a_tbt =
(u16)(pbus_data & 0x03f);
ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x12,
GPHY_RG_1E_012.DATA);
ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x12, 0xA018);
if (ret < 0)
return ret;
ret = airoha_cl45_read(mbus, phy_addr, 0x1E, 0x17, &cl45_value);
@@ -933,6 +886,17 @@ static int en8801s_phase2_init(struct phy_device *phydev)
}
}
//Fix 10Te TP_IDL
ret = airoha_cl45_read(mbus, phy_addr, 0x1E,
0x1A3, &cl45_value);
if (ret < 0)
return ret;
cl45_value &= ~0xf0;
ret = airoha_cl45_write(mbus, phy_addr, 0x1E,
0x1A3, cl45_value);
if (ret < 0)
return ret;
priv->first_init = false;
dev_info(phydev_dev(phydev), "Phase2 initialize OK !\n");
return 0;
@@ -1091,7 +1055,6 @@ static int en8801s_probe(struct phy_device *phydev)
unsigned long phy_addr = phydev_phy_addr(phydev);
struct mii_bus *mbus = phydev_mdio_bus(phydev);
struct device *dev = &mbus->dev;
int ret = 0;
#if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE)
struct gpio_desc *en8801s_reset;
int err = 0;
@@ -1105,15 +1068,7 @@ static int en8801s_probe(struct phy_device *phydev)
priv->count = 0;
priv->first_init = true;
phydev->priv = priv;
#ifdef CONFIG_EN8801S_DEBUGFS
ret = en8801s_debugfs_init(phydev);
if (ret < 0) {
air_debugfs_remove(phydev);
kfree(priv);
return ret;
}
#endif
#if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE)
/* Assert the optional reset signal */
en8801s_reset = gpiod_get_optional(&phydev->dev,
@@ -1144,276 +1099,6 @@ static int en8801s_probe(struct phy_device *phydev)
return 0;
}
static const char * const tx_rx_string[32] = {
"Tx Normal, Rx Reverse",
"Tx Reverse, Rx Reverse",
"Tx Normal, Rx Normal",
"Tx Reverse, Rx Normal",
};
static int en8801s_counter_show(struct seq_file *seq, void *v)
{
struct phy_device *phydev = seq->private;
struct mii_bus *mbus = phydev_mdio_bus(phydev);
int ret = 0;
u32 pkt_cnt = 0;
int pbus_addr = phydev_pbus_addr(phydev);
seq_puts(seq, "==========AIR PHY COUNTER==========\n");
seq_puts(seq, "|\t<<FCM COUNTER>>\n");
seq_puts(seq, "| Rx from Line side_S :");
pkt_cnt = airoha_pbus_read(mbus, pbus_addr, 0x1490);
seq_printf(seq, "%010u |\n", pkt_cnt);
seq_puts(seq, "| Rx from Line side_T :");
pkt_cnt = airoha_pbus_read(mbus, pbus_addr, 0x1494);
seq_printf(seq, "%010u |\n", pkt_cnt);
seq_puts(seq, "| Tx to System side_S :");
pkt_cnt = airoha_pbus_read(mbus, pbus_addr, 0x149c);
seq_printf(seq, "%010u |\n", pkt_cnt);
seq_puts(seq, "| Tx to System side_T :");
pkt_cnt = airoha_pbus_read(mbus, pbus_addr, 0x14a0);
seq_printf(seq, "%010u |\n", pkt_cnt);
seq_puts(seq, "| Rx from System side_S :");
pkt_cnt = airoha_pbus_read(mbus, pbus_addr, 0x1478);
seq_printf(seq, "%010u |\n", pkt_cnt);
seq_puts(seq, "| Rx from System side_T :");
pkt_cnt = airoha_pbus_read(mbus, pbus_addr, 0x147c);
seq_printf(seq, "%010u |\n", pkt_cnt);
seq_puts(seq, "| Tx to Line side_S :");
pkt_cnt = airoha_pbus_read(mbus, pbus_addr, 0x1484);
seq_printf(seq, "%010u |\n", pkt_cnt);
seq_puts(seq, "| Tx to Line side_T :");
pkt_cnt = airoha_pbus_read(mbus, pbus_addr, 0x1488);
seq_printf(seq, "%010u |\n", pkt_cnt);
seq_puts(seq, "| Rx from Line side_PAUSE :");
pkt_cnt = airoha_pbus_read(mbus, pbus_addr, 0x1498);
seq_printf(seq, "%010u |\n", pkt_cnt);
seq_puts(seq, "| Tx to System side_PAUSE :");
pkt_cnt = airoha_pbus_read(mbus, pbus_addr, 0x14a4);
seq_printf(seq, "%010u |\n", pkt_cnt);
seq_puts(seq, "| Rx from System side_PAUSE :");
pkt_cnt = airoha_pbus_read(mbus, pbus_addr, 0x1480);
seq_printf(seq, "%010u |\n", pkt_cnt);
seq_puts(seq, "| Tx to Line side_PAUSE :");
pkt_cnt = airoha_pbus_read(mbus, pbus_addr, 0x148c);
seq_printf(seq, "%010u |\n", pkt_cnt);
ret = airoha_pbus_write(mbus, pbus_addr, 0x1474, 0x3);
if (ret < 0)
seq_puts(seq, "\nClear Counter fail\n");
else
seq_puts(seq, "\nClear Counter!!\n");
return ret;
}
static int en8801s_counter_open(struct inode *inode, struct file *file)
{
return single_open(file, en8801s_counter_show, inode->i_private);
}
int en8801s_info_show(struct seq_file *seq, void *v)
{
struct phy_device *phydev = seq->private;
struct mii_bus *mbus = phydev_mdio_bus(phydev);
int pbus_addr = phydev_pbus_addr(phydev);
unsigned int tx_rx =
(airoha_pbus_read(mbus, pbus_addr, EN8801S_RG_LTR_CTL) & 0x3);
unsigned long pbus_data = 0;
seq_puts(seq, "<<AIR EN8801S Driver Info>>\n");
pbus_data = airoha_pbus_read(mbus, pbus_addr, EN8801S_RG_PROD_VER);
pbus_data &= 0xf;
seq_printf(seq, "| Product Version : E%ld\n", pbus_data);
seq_printf(seq, "| Driver Version : %s\n", EN8801S_DRIVER_VERSION);
pbus_data = airoha_pbus_read(mbus, pbus_addr, 0xb04);
seq_printf(seq, "| Serdes Status : Rx_Sync(%01ld), AN_Done(%01ld)\n",
GET_BIT(pbus_data, 4), GET_BIT(pbus_data, 0));
seq_printf(seq, "| Tx, Rx Polarity : %s(%02d)\n",
tx_rx_string[tx_rx], tx_rx);
seq_puts(seq, "\n");
return 0;
}
static int en8801s_info_open(struct inode *inode, struct file *file)
{
return single_open(file, en8801s_info_show, inode->i_private);
}
static int en8801s_debugfs_pbus_help(void)
{
pr_notice(EN8801S_DEBUGFS_PBUS_HELP_STRING);
return 0;
}
static ssize_t en8801s_debugfs_pbus(struct file *file,
const char __user *buffer, size_t count,
loff_t *data)
{
struct phy_device *phydev = file->private_data;
struct mii_bus *mbus = phydev_mdio_bus(phydev);
char buf[64];
int ret = 0;
unsigned int reg, addr;
unsigned long val;
memset(buf, 0, 64);
if (copy_from_user(buf, buffer, count))
return -EFAULT;
if (buf[0] == 'w') {
if (sscanf(buf, "w %x %x %lx", &addr, &reg, &val) == -1)
return -EFAULT;
if (addr > 0 && addr < 32) {
pr_notice("\nphy=0x%x, reg=0x%x, val=0x%lx\n",
addr, reg, val);
ret = airoha_pbus_write(mbus, addr, reg, val);
if (ret < 0)
return ret;
pr_notice("\nphy=%d, reg=0x%x, val=0x%lx confirm..\n",
addr, reg,
airoha_pbus_read(mbus, addr, reg));
} else {
pr_notice("addr is out of range(1~32)\n");
}
} else if (buf[0] == 'r') {
if (sscanf(buf, "r %x %x", &addr, &reg) == -1)
return -EFAULT;
if (addr > 0 && addr < 32) {
pr_notice("\nphy=0x%x, reg=0x%x, val=0x%lx\n",
addr, reg,
airoha_pbus_read(mbus, addr, reg));
} else {
pr_notice("addr is out of range(1~32)\n");
}
} else if (buf[0] == 'h') {
en8801s_debugfs_pbus_help();
}
return count;
}
static int dbg_regs_show(struct seq_file *seq, void *v)
{
struct phy_device *phydev = seq->private;
struct mii_bus *mbus = phydev_mdio_bus(phydev);
int pbus_addr = phydev_pbus_addr(phydev), reg;
seq_puts(seq, "\t<<DEBUG REG DUMP>>\n");
for (reg = MII_BMCR; reg <= MII_STAT1000; reg++) {
if ((reg <= MII_LPA) || (reg >= MII_CTRL1000))
seq_printf(seq, "| RG_MII 0x%02x : 0x%08x\n",
reg, phy_read(phydev, reg));
}
seq_printf(seq, "| RG_SERDES_1 : 0x%08lx |\n",
airoha_pbus_read(mbus, pbus_addr, 0x600));
seq_printf(seq, "| RG_SERDES_2 : 0x%08lx |\n",
airoha_pbus_read(mbus, pbus_addr, 0x10));
seq_printf(seq, "| RG_SERDES_3 : 0x%08lx |\n",
airoha_pbus_read(mbus, pbus_addr, 0x0));
seq_printf(seq, "| RG_SERDES_4 : 0x%08lx |\n",
airoha_pbus_read(mbus, pbus_addr, 0xa14));
seq_printf(seq, "| RG_SERDES_5 : 0x%08lx |\n",
airoha_pbus_read(mbus, pbus_addr, 0x1404));
seq_printf(seq, "| RG_SERDES_6 : 0x%08lx |\n",
airoha_pbus_read(mbus, pbus_addr, 0x140c));
seq_printf(seq, "| RG_SERDES_7 : 0x%08lx |\n",
airoha_pbus_read(mbus, pbus_addr, 0x1694));
return 0;
}
static int airphy_dbg_regs_show_open(struct inode *inode, struct file *file)
{
return single_open(file, dbg_regs_show, inode->i_private);
}
static const struct file_operations airphy_dbg_reg_show_fops = {
.owner = THIS_MODULE,
.open = airphy_dbg_regs_show_open,
.read = seq_read,
.llseek = noop_llseek,
.release = single_release,
};
static const struct file_operations en8801s_debugfs_pbus_fops = {
.owner = THIS_MODULE,
.open = simple_open,
.write = en8801s_debugfs_pbus,
.llseek = noop_llseek,
};
static const struct file_operations en8801s_info_fops = {
.owner = THIS_MODULE,
.open = en8801s_info_open,
.read = seq_read,
.llseek = noop_llseek,
.release = single_release,
};
static const struct file_operations en8801s_counter_fops = {
.owner = THIS_MODULE,
.open = en8801s_counter_open,
.read = seq_read,
.llseek = noop_llseek,
.release = single_release,
};
static int en8801s_debugfs_init(struct phy_device *phydev)
{
int ret = 0;
struct en8801s_priv *priv = phydev->priv;
dev_info(phydev_dev(phydev), "Debugfs init start\n");
priv->debugfs_root =
debugfs_create_dir(dev_name(phydev_dev(phydev)), NULL);
if (!priv->debugfs_root) {
dev_err(phydev_dev(phydev), "Debugfs init err\n");
ret = -ENOMEM;
}
debugfs_create_file(DEBUGFS_DRIVER_INFO, 0444,
priv->debugfs_root, phydev,
&en8801s_info_fops);
debugfs_create_file(DEBUGFS_COUNTER, 0644,
priv->debugfs_root, phydev,
&en8801s_counter_fops);
debugfs_create_file(DEBUGFS_PBUS_OP, S_IFREG | 0200,
priv->debugfs_root, phydev,
&en8801s_debugfs_pbus_fops);
debugfs_create_file(DEBUGFS_DBG_REG_SHOW, S_IFREG | 0444,
priv->debugfs_root, phydev,
&airphy_dbg_reg_show_fops);
return ret;
}
static void air_debugfs_remove(struct phy_device *phydev)
{
struct en8801s_priv *priv = phydev->priv;
if (priv->debugfs_root != NULL) {
debugfs_remove_recursive(priv->debugfs_root);
priv->debugfs_root = NULL;
}
}
static void en8801s_phy_remove(struct phy_device *phydev)
{
struct en8801s_priv *priv = (struct en8801s_priv *)phydev->priv;
if (priv) {
#ifdef CONFIG_EN8801S_DEBUGFS
air_debugfs_remove(phydev);
#endif
kfree(priv);
dev_info(phydev_dev(phydev), "EN8801S remove OK!\n");
}
}
#if (KERNEL_VERSION(4, 5, 0) < LINUX_VERSION_CODE)
static int airoha_mmd_read(struct phy_device *phydev,
int devad, u16 reg)

View File

@@ -12,7 +12,7 @@
/* NAMING DECLARATIONS
*/
#define EN8801S_DRIVER_VERSION "1.1.9_Generic"
#define EN8801S_DRIVER_VERSION "1.1.8_Generic"
#define EN8801S_PBUS_DEFAULT_ADDR 0x1e
#define EN8801S_PHY_DEFAULT_ADDR 0x1d
#define EN8801S_RG_ETHER_PHY_OUI 0x19a4
@@ -26,12 +26,6 @@
#define EN8801S_PHY_ID2 0x9461
#define EN8801SC_PHY_ID 0x03a29471
#define DEBUGFS_COUNTER "counter"
#define DEBUGFS_DRIVER_INFO "driver_info"
#define DEBUGFS_PBUS_OP "pbus_op"
#define DEBUGFS_POLARITY "polarity"
#define DEBUGFS_DBG_REG_SHOW "dbg_regs_show"
#define LED_ON_CTRL(i) (0x024 + ((i)*2))
#define LED_ON_EN (1 << 15)
#define LED_ON_POL (1 << 14)

View File

@@ -1,38 +0,0 @@
# SPDX-License-Identifier: GPL-2.0-only
config MTK_NET_PHYLIB
tristate
config MEDIATEK_GE_PHY
tristate "MediaTek Gigabit Ethernet PHYs"
select MTK_NET_PHYLIB
help
Supports the MediaTek non-built-in Gigabit Ethernet PHYs.
Non-built-in Gigabit Ethernet PHYs include mt7530/mt7531.
You may find mt7530 inside mt7621. This driver shares some
common operations with MediaTek SoC built-in Gigabit
Ethernet PHYs.
config MEDIATEK_GE_SOC_PHY
tristate "MediaTek SoC Ethernet PHYs"
depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
select NVMEM_MTK_EFUSE
select MTK_NET_PHYLIB
help
Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
Include support for built-in Ethernet PHYs which are present in
the MT7981 and MT7988 SoCs. These PHYs need calibration data
present in the SoCs efuse and will dynamically calibrate VCM
(common-mode voltage) during startup.
config MEDIATEK_2P5GE_PHY
tristate "MediaTek 2.5Gb Ethernet PHYs"
depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
select MTK_NET_PHYLIB
help
Supports MediaTek SoC built-in 2.5Gb Ethernet PHYs.
This will load necessary firmware and add appropriate time delay.
Accelerate this procedure through internal pbus instead of MDIO
bus. Certain link-up issues will also be fixed here.

View File

@@ -1,5 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_MTK_NET_PHYLIB) += mtk-phy-lib.o
obj-$(CONFIG_MEDIATEK_GE_PHY) += mtk-ge.o
obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mtk-ge-soc.o
obj-$(CONFIG_MEDIATEK_2P5GE_PHY) += mtk-2p5ge.o

View File

@@ -1,730 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
#include <linux/bitfield.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/pinctrl/consumer.h>
#include <linux/phy.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include "mtk.h"
#define MTK_2P5GPHY_ID_MT7987 (0x00339c91)
#define MTK_2P5GPHY_ID_MT7988 (0x00339c11)
#define MT7987_2P5GE_PMB_FW "mediatek/mt7987/i2p5ge-phy-pmb.bin"
#define MT7987_2P5GE_PMB_FW_SIZE (0x18000)
#define MT7987_2P5GE_DSPBITTB \
"mediatek/mt7987/i2p5ge-phy-DSPBitTb.bin"
#define MT7987_2P5GE_DSPBITTB_SIZE (0x7000)
#define MT7988_2P5GE_PMB_FW "mediatek/mt7988/i2p5ge-phy-pmb.bin"
#define MT7988_2P5GE_PMB_FW_SIZE (0x20000)
#define MT7988_2P5GE_PMB_FW_BASE (0x0f100000)
#define MT7988_2P5GE_PMB_FW_LEN (0x20000)
#define MTK_2P5GPHY_PMD_REG_BASE (0x0f010000)
#define MTK_2P5GPHY_PMD_REG_LEN (0x210)
#define DO_NOT_RESET (0x28)
#define DO_NOT_RESET_XBZ BIT(0)
#define DO_NOT_RESET_PMA BIT(3)
#define DO_NOT_RESET_RX BIT(5)
#define FNPLL_PWR_CTRL1 (0x208)
#define RG_SPEED_MASK GENMASK(3, 0)
#define RG_SPEED_2500 BIT(3)
#define RG_SPEED_100 BIT(0)
#define FNPLL_PWR_CTRL_STATUS (0x20c)
#define RG_STABLE_MASK GENMASK(3, 0)
#define RG_SPEED_2500_STABLE BIT(3)
#define RG_SPEED_100_STABLE BIT(0)
#define MTK_2P5GPHY_XBZ_PCS_REG_BASE (0x0f030000)
#define MTK_2P5GPHY_XBZ_PCS_REG_LEN (0x844)
#define PHY_CTRL_CONFIG (0x200)
#define PMU_WP (0x800)
#define WRITE_PROTECT_KEY (0xCAFEF00D)
#define PMU_PMA_AUTO_CFG (0x820)
#define POWER_ON_AUTO_MODE BIT(16)
#define PMU_AUTO_MODE_EN BIT(0)
#define PMU_PMA_STATUS (0x840)
#define CLK_IS_DISABLED BIT(3)
#define MTK_2P5GPHY_XBZ_PMA_RX_BASE (0x0f080000)
#define MTK_2P5GPHY_XBZ_PMA_RX_LEN (0x5228)
#define SMEM_WDAT0 (0x5000)
#define SMEM_WDAT1 (0x5004)
#define SMEM_WDAT2 (0x5008)
#define SMEM_WDAT3 (0x500c)
#define SMEM_CTRL (0x5024)
#define SMEM_HW_RDATA_ZERO BIT(24)
#define SMEM_ADDR_REF_ADDR (0x502c)
#define CM_CTRL_P01 (0x5100)
#define CM_CTRL_P23 (0x5124)
#define DM_CTRL_P01 (0x5200)
#define DM_CTRL_P23 (0x5224)
#define MTK_2P5GPHY_CHIP_SCU_BASE (0x0f0cf800)
#define MTK_2P5GPHY_CHIP_SCU_LEN (0x12c)
#define SYS_SW_RESET (0x128)
#define RESET_RST_CNT BIT(0)
#define MTK_2P5GPHY_MCU_CSR_BASE (0x0f0f0000)
#define MTK_2P5GPHY_MCU_CSR_LEN (0x20)
#define MD32_EN_CFG (0x18)
#define MD32_EN BIT(0)
#define MTK_2P5GPHY_PMB_FW_BASE (0x0f100000)
//#define MTK_2P5GPHY_PMB_FW_LEN MT7988_2P5GE_PMB_FW_SIZE
#define MTK_2P5GPHY_APB_BASE (0x11c30000)
#define MTK_2P5GPHY_APB_LEN (0x9c)
#define SW_RESET (0x94)
#define MD32_RESTART_EN_CLEAR BIT(9)
#define BASE100T_STATUS_EXTEND (0x10)
#define BASE1000T_STATUS_EXTEND (0x11)
#define EXTEND_CTRL_AND_STATUS (0x16)
#define PHY_AUX_CTRL_STATUS (0x1d)
#define PHY_AUX_DPX_MASK GENMASK(5, 5)
#define PHY_AUX_SPEED_MASK GENMASK(4, 2)
/* Registers on MDIO_MMD_VEND1 */
#define MTK_PHY_LINK_STATUS_RELATED (0x147)
#define MTK_PHY_BYPASS_LINK_STATUS_OK BIT(4)
#define MTK_PHY_FORCE_LINK_STATUS_HCD BIT(3)
#define MTK_PHY_PMA_PMD_SPPED_ABILITY 0x300
#define MTK_PHY_AN_FORCE_SPEED_REG (0x313)
#define MTK_PHY_MASTER_FORCE_SPEED_SEL_EN BIT(7)
#define MTK_PHY_MASTER_FORCE_SPEED_SEL_MASK GENMASK(6, 0)
#define MTK_PHY_LPI_PCS_DSP_CTRL (0x121)
#define MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK GENMASK(12, 8)
/* Registers on Token Ring debug nodes */
/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */
#define AUTO_NP_10XEN BIT(6)
struct mtk_i2p5ge_phy_priv {
bool fw_loaded;
int pd_en;
};
enum {
PHY_AUX_SPD_10 = 0,
PHY_AUX_SPD_100,
PHY_AUX_SPD_1000,
PHY_AUX_SPD_2500,
};
static int mt7987_2p5ge_phy_load_fw(struct phy_device *phydev)
{
struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
struct device *dev = &phydev->mdio.dev;
void __iomem *xbz_pcs_reg_base;
void __iomem *xbz_pma_rx_base;
void __iomem *chip_scu_base;
void __iomem *pmd_reg_base;
void __iomem *mcu_csr_base;
const struct firmware *fw;
void __iomem *apb_base;
void __iomem *pmb_addr;
int ret, i;
u32 reg;
if (priv->fw_loaded)
return 0;
apb_base = ioremap(MTK_2P5GPHY_APB_BASE,
MTK_2P5GPHY_APB_LEN);
if (!apb_base)
return -ENOMEM;
pmd_reg_base = ioremap(MTK_2P5GPHY_PMD_REG_BASE,
MTK_2P5GPHY_PMD_REG_LEN);
if (!pmd_reg_base) {
ret = -ENOMEM;
goto free_apb;
}
xbz_pcs_reg_base = ioremap(MTK_2P5GPHY_XBZ_PCS_REG_BASE,
MTK_2P5GPHY_XBZ_PCS_REG_LEN);
if (!xbz_pcs_reg_base) {
ret = -ENOMEM;
goto free_pmd;
}
xbz_pma_rx_base = ioremap(MTK_2P5GPHY_XBZ_PMA_RX_BASE,
MTK_2P5GPHY_XBZ_PMA_RX_LEN);
if (!xbz_pma_rx_base) {
ret = -ENOMEM;
goto free_pcs;
}
chip_scu_base = ioremap(MTK_2P5GPHY_CHIP_SCU_BASE,
MTK_2P5GPHY_CHIP_SCU_LEN);
if (!chip_scu_base) {
ret = -ENOMEM;
goto free_pma;
}
mcu_csr_base = ioremap(MTK_2P5GPHY_MCU_CSR_BASE,
MTK_2P5GPHY_MCU_CSR_LEN);
if (!mcu_csr_base) {
ret = -ENOMEM;
goto free_chip_scu;
}
pmb_addr = ioremap(MTK_2P5GPHY_PMB_FW_BASE, MT7987_2P5GE_PMB_FW_SIZE);
if (!pmb_addr) {
return -ENOMEM;
goto free_mcu_csr;
}
ret = request_firmware(&fw, MT7987_2P5GE_PMB_FW, dev);
if (ret) {
dev_err(dev, "failed to load firmware: %s, ret: %d\n",
MT7987_2P5GE_PMB_FW, ret);
goto free_pmb_addr;
}
if (fw->size != MT7987_2P5GE_PMB_FW_SIZE) {
dev_err(dev, "PMb firmware size 0x%zx != 0x%x\n",
fw->size, MT7987_2P5GE_PMB_FW_SIZE);
ret = -EINVAL;
goto release_fw;
}
/* Force 2.5Gphy back to AN state */
phy_set_bits(phydev, MII_BMCR, BMCR_RESET);
usleep_range(5000, 6000);
phy_set_bits(phydev, MII_BMCR, BMCR_PDOWN);
reg = readw(apb_base + SW_RESET);
writew(reg & ~MD32_RESTART_EN_CLEAR, apb_base + SW_RESET);
writew(reg | MD32_RESTART_EN_CLEAR, apb_base + SW_RESET);
writew(reg & ~MD32_RESTART_EN_CLEAR, apb_base + SW_RESET);
reg = readw(mcu_csr_base + MD32_EN_CFG);
writew(reg & ~MD32_EN, mcu_csr_base + MD32_EN_CFG);
for (i = 0; i < MT7987_2P5GE_PMB_FW_SIZE - 1; i += 4)
writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);
dev_info(dev, "Firmware date code: %x/%x/%x, version: %x.%x\n",
be16_to_cpu(*((__be16 *)(fw->data +
MT7987_2P5GE_PMB_FW_SIZE - 8))),
*(fw->data + MT7987_2P5GE_PMB_FW_SIZE - 6),
*(fw->data + MT7987_2P5GE_PMB_FW_SIZE - 5),
*(fw->data + MT7987_2P5GE_PMB_FW_SIZE - 2),
*(fw->data + MT7987_2P5GE_PMB_FW_SIZE - 1));
release_firmware(fw);
/* Enable 100Mbps module clock. */
writel(FIELD_PREP(RG_SPEED_MASK, RG_SPEED_100),
pmd_reg_base + FNPLL_PWR_CTRL1);
/* Check if 100Mbps module clock is ready. */
ret = readl_poll_timeout(pmd_reg_base + FNPLL_PWR_CTRL_STATUS, reg,
reg & RG_SPEED_100_STABLE, 1, 10000);
if (ret)
dev_err(dev, "Fail to enable 100Mbps module clock: %d\n", ret);
/* Enable 2.5Gbps module clock. */
writel(FIELD_PREP(RG_SPEED_MASK, RG_SPEED_2500),
pmd_reg_base + FNPLL_PWR_CTRL1);
/* Check if 2.5Gbps module clock is ready. */
ret = readl_poll_timeout(pmd_reg_base + FNPLL_PWR_CTRL_STATUS, reg,
reg & RG_SPEED_2500_STABLE, 1, 10000);
if (ret)
dev_err(dev, "Fail to enable 2.5Gbps module clock: %d\n", ret);
/* Disable AN */
phy_clear_bits(phydev, MII_BMCR, BMCR_ANENABLE);
/* Force to run at 2.5G speed */
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_AN_FORCE_SPEED_REG,
MTK_PHY_MASTER_FORCE_SPEED_SEL_MASK,
MTK_PHY_MASTER_FORCE_SPEED_SEL_EN |
FIELD_PREP(MTK_PHY_MASTER_FORCE_SPEED_SEL_MASK, 0x1b));
phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LINK_STATUS_RELATED,
MTK_PHY_BYPASS_LINK_STATUS_OK |
MTK_PHY_FORCE_LINK_STATUS_HCD);
/* Set xbz, pma and rx as "do not reset" in order to input DSP code. */
reg = readl(pmd_reg_base + DO_NOT_RESET);
reg |= DO_NOT_RESET_XBZ | DO_NOT_RESET_PMA | DO_NOT_RESET_RX;
writel(reg, pmd_reg_base + DO_NOT_RESET);
reg = readl(chip_scu_base + SYS_SW_RESET);
writel(reg & ~RESET_RST_CNT, chip_scu_base + SYS_SW_RESET);
writel(WRITE_PROTECT_KEY, xbz_pcs_reg_base + PMU_WP);
reg = readl(xbz_pcs_reg_base + PMU_PMA_AUTO_CFG);
reg |= PMU_AUTO_MODE_EN | POWER_ON_AUTO_MODE;
writel(reg, xbz_pcs_reg_base + PMU_PMA_AUTO_CFG);
/* Check if clock in auto mode is disabled. */
ret = readl_poll_timeout(xbz_pcs_reg_base + PMU_PMA_STATUS, reg,
(reg & CLK_IS_DISABLED) == 0x0, 1, 100000);
if (ret)
dev_err(dev, "Clock isn't disabled in auto mode: %d\n", ret);
reg = readl(xbz_pma_rx_base + SMEM_CTRL);
writel(reg | SMEM_HW_RDATA_ZERO, xbz_pma_rx_base + SMEM_CTRL);
reg = readl(xbz_pcs_reg_base + PHY_CTRL_CONFIG);
writel(reg | BIT(16), xbz_pcs_reg_base + PHY_CTRL_CONFIG);
/* Initialize data memory */
reg = readl(xbz_pma_rx_base + DM_CTRL_P01);
writel(reg | BIT(28), xbz_pma_rx_base + DM_CTRL_P01);
reg = readl(xbz_pma_rx_base + DM_CTRL_P23);
writel(reg | BIT(28), xbz_pma_rx_base + DM_CTRL_P23);
/* Initialize coefficient memory */
reg = readl(xbz_pma_rx_base + CM_CTRL_P01);
writel(reg | BIT(28), xbz_pma_rx_base + CM_CTRL_P01);
reg = readl(xbz_pma_rx_base + CM_CTRL_P23);
writel(reg | BIT(28), xbz_pma_rx_base + CM_CTRL_P23);
/* Initilize PM offset */
writel(0, xbz_pma_rx_base + SMEM_ADDR_REF_ADDR);
ret = request_firmware(&fw, MT7987_2P5GE_DSPBITTB, dev);
if (ret) {
dev_err(dev, "failed to load firmware: %s, ret: %d\n",
MT7987_2P5GE_DSPBITTB, ret);
goto free_pmb_addr;
}
if (fw->size != MT7987_2P5GE_DSPBITTB_SIZE) {
dev_err(dev, "DSPBITTB size 0x%zx != 0x%x\n",
fw->size, MT7987_2P5GE_DSPBITTB_SIZE);
ret = -EINVAL;
goto release_fw;
}
for (i = 0; i < fw->size - 1; i += 16) {
writel(*((uint32_t *)(fw->data + i)),
xbz_pma_rx_base + SMEM_WDAT0);
writel(*((uint32_t *)(fw->data + i + 0x4)),
xbz_pma_rx_base + SMEM_WDAT1);
writel(*((uint32_t *)(fw->data + i + 0x8)),
xbz_pma_rx_base + SMEM_WDAT2);
writel(*((uint32_t *)(fw->data + i + 0xc)),
xbz_pma_rx_base + SMEM_WDAT3);
}
reg = readl(xbz_pma_rx_base + DM_CTRL_P01);
writel(reg & ~BIT(28), xbz_pma_rx_base + DM_CTRL_P01);
reg = readl(xbz_pma_rx_base + DM_CTRL_P23);
writel(reg & ~BIT(28), xbz_pma_rx_base + DM_CTRL_P23);
reg = readl(xbz_pma_rx_base + CM_CTRL_P01);
writel(reg & ~BIT(28), xbz_pma_rx_base + CM_CTRL_P01);
reg = readl(xbz_pma_rx_base + CM_CTRL_P23);
writel(reg & ~BIT(28), xbz_pma_rx_base + CM_CTRL_P23);
reg = readw(mcu_csr_base + MD32_EN_CFG);
writew(reg | MD32_EN, mcu_csr_base + MD32_EN_CFG);
phy_set_bits(phydev, MII_BMCR, BMCR_RESET);
/* We need a delay here to stabilize initialization of MCU */
usleep_range(7000, 8000);
dev_info(dev, "Firmware loading/trigger ok.\n");
priv->fw_loaded = true;
release_fw:
release_firmware(fw);
free_pmb_addr:
iounmap(pmb_addr);
free_mcu_csr:
iounmap(mcu_csr_base);
free_chip_scu:
iounmap(chip_scu_base);
free_pma:
iounmap(xbz_pma_rx_base);
free_pcs:
iounmap(xbz_pcs_reg_base);
free_pmd:
iounmap(pmd_reg_base);
free_apb:
iounmap(apb_base);
return ret;
}
static int mt7988_2p5ge_phy_load_fw(struct phy_device *phydev)
{
struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
void __iomem *mcu_csr_base, *pmb_addr;
struct device *dev = &phydev->mdio.dev;
const struct firmware *fw;
int ret, i;
u32 reg;
if (priv->fw_loaded)
return 0;
pmb_addr = ioremap(MT7988_2P5GE_PMB_FW_BASE, MT7988_2P5GE_PMB_FW_LEN);
if (!pmb_addr)
return -ENOMEM;
mcu_csr_base = ioremap(MTK_2P5GPHY_MCU_CSR_BASE,
MTK_2P5GPHY_MCU_CSR_LEN);
if (!mcu_csr_base) {
ret = -ENOMEM;
goto free_pmb;
}
ret = request_firmware(&fw, MT7988_2P5GE_PMB_FW, dev);
if (ret) {
dev_err(dev, "failed to load firmware: %s, ret: %d\n",
MT7988_2P5GE_PMB_FW, ret);
goto free;
}
if (fw->size != MT7988_2P5GE_PMB_FW_SIZE) {
dev_err(dev, "Firmware size 0x%zx != 0x%x\n",
fw->size, MT7988_2P5GE_PMB_FW_SIZE);
ret = -EINVAL;
goto release_fw;
}
reg = readw(mcu_csr_base + MD32_EN_CFG);
if (reg & MD32_EN) {
phy_set_bits(phydev, MII_BMCR, BMCR_RESET);
usleep_range(10000, 11000);
}
phy_set_bits(phydev, MII_BMCR, BMCR_PDOWN);
/* Write magic number to safely stall MCU */
phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800e, 0x1100);
phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800f, 0x00df);
for (i = 0; i < MT7988_2P5GE_PMB_FW_SIZE - 1; i += 4)
writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);
dev_info(dev, "Firmware date code: %x/%x/%x, version: %x.%x\n",
be16_to_cpu(*((__be16 *)(fw->data +
MT7988_2P5GE_PMB_FW_SIZE - 8))),
*(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 6),
*(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 5),
*(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 2),
*(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 1));
writew(reg & ~MD32_EN, mcu_csr_base + MD32_EN_CFG);
writew(reg | MD32_EN, mcu_csr_base + MD32_EN_CFG);
phy_set_bits(phydev, MII_BMCR, BMCR_RESET);
/* We need a delay here to stabilize initialization of MCU */
usleep_range(7000, 8000);
dev_info(dev, "Firmware loading/trigger ok.\n");
priv->fw_loaded = true;
release_fw:
release_firmware(fw);
free:
iounmap(mcu_csr_base);
free_pmb:
iounmap(pmb_addr);
return ret;
}
static int mt798x_2p5ge_phy_config_init(struct phy_device *phydev)
{
struct pinctrl *pinctrl;
int ret;
/* Check if PHY interface type is compatible */
if (phydev->interface != PHY_INTERFACE_MODE_INTERNAL)
return -ENODEV;
switch (phydev->drv->phy_id) {
case MTK_2P5GPHY_ID_MT7987:
ret = mt7987_2p5ge_phy_load_fw(phydev);
phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
MTK_PHY_LED_ON_POLARITY);
break;
case MTK_2P5GPHY_ID_MT7988:
ret = mt7988_2p5ge_phy_load_fw(phydev);
phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
MTK_PHY_LED_ON_POLARITY);
break;
default:
return -EINVAL;
}
if (ret < 0)
return ret;
/* Setup LED */
phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
MTK_PHY_LED_ON_LINK10 | MTK_PHY_LED_ON_LINK100 |
MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK2500);
phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX);
/* Switch pinctrl after setting polarity to avoid bogus blinking */
pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "i2p5gbe-led");
if (IS_ERR(pinctrl))
dev_err(&phydev->mdio.dev, "Fail to set LED pins!\n");
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LPI_PCS_DSP_CTRL,
MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK, 0);
/* Enable 16-bit next page exchange bit if 1000-BT isn't advertising */
mtk_tr_modify(phydev, 0x0, 0xf, 0x3c, AUTO_NP_10XEN,
FIELD_PREP(AUTO_NP_10XEN, 0x1));
/* Enable HW auto downshift */
phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED_1,
MTK_PHY_AUX_CTRL_AND_STATUS,
0, MTK_PHY_ENABLE_DOWNSHIFT);
return 0;
}
static int mt798x_2p5ge_phy_config_aneg(struct phy_device *phydev)
{
struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
bool changed = false;
u32 adv;
int ret;
if (phydev->autoneg == AUTONEG_DISABLE)
goto out;
ret = genphy_c45_an_config_aneg(phydev);
if (ret < 0)
return ret;
if (ret > 0)
changed = true;
/* Clause 45 doesn't define 1000BaseT support. Use Clause 22 instead in
* our design.
*/
adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
ret = phy_modify_changed(phydev, MII_CTRL1000, ADVERTISE_1000FULL, adv);
if (ret < 0)
return ret;
if (ret > 0)
changed = true;
out:
if (priv->pd_en) {
phy_write_mmd(phydev, MDIO_MMD_VEND1,
MTK_PHY_PMA_PMD_SPPED_ABILITY, 0xf7cf);
phy_modify_paged(phydev, MTK_PHY_PAGE_STANDARD,
MII_ADVERTISE, 0,
ADVERTISE_100HALF | ADVERTISE_10HALF);
}
if (phydev->autoneg == AUTONEG_DISABLE)
return genphy_c45_pma_setup_forced(phydev);
else
return genphy_c45_check_and_restart_aneg(phydev, changed);
}
static int mt798x_2p5ge_phy_get_features(struct phy_device *phydev)
{
int ret;
ret = genphy_c45_pma_read_abilities(phydev);
if (ret)
return ret;
/* This phy can't handle collision, and neither can (XFI)MAC it's
* connected to. Although it can do HDX handshake, it doesn't support
* CSMA/CD that HDX requires.
*/
linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
phydev->supported);
return 0;
}
static int mt798x_2p5ge_phy_read_status(struct phy_device *phydev)
{
int ret;
/* When MDIO_STAT1_LSTATUS is raised genphy_c45_read_link(), this phy
* actually hasn't finished AN. So use CL22's link update function
* instead.
*/
ret = genphy_update_link(phydev);
if (ret)
return ret;
phydev->speed = SPEED_UNKNOWN;
phydev->duplex = DUPLEX_UNKNOWN;
phydev->pause = 0;
phydev->asym_pause = 0;
/* We'll read link speed through vendor specific registers down below.
* So remove phy_resolve_aneg_linkmode (AN on) & genphy_c45_read_pma
* (AN off).
*/
if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) {
ret = genphy_c45_read_lpa(phydev);
if (ret < 0)
return ret;
/* Clause 45 doesn't define 1000BaseT support. Read the link
* partner's 1G advertisement via Clause 22.
*/
ret = phy_read(phydev, MII_STAT1000);
if (ret < 0)
return ret;
mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ret);
} else if (phydev->autoneg == AUTONEG_DISABLE) {
linkmode_zero(phydev->lp_advertising);
}
if (phydev->link) {
ret = phy_read(phydev, PHY_AUX_CTRL_STATUS);
if (ret < 0)
return ret;
switch (FIELD_GET(PHY_AUX_SPEED_MASK, ret)) {
case PHY_AUX_SPD_10:
phydev->speed = SPEED_10;
break;
case PHY_AUX_SPD_100:
phydev->speed = SPEED_100;
break;
case PHY_AUX_SPD_1000:
phydev->speed = SPEED_1000;
break;
case PHY_AUX_SPD_2500:
phydev->speed = SPEED_2500;
break;
}
phydev->duplex = DUPLEX_FULL;
/* FIXME:
* The current firmware always enables rate adaptation mode.
*/
phydev->rate_matching = RATE_MATCH_PAUSE;
}
return 0;
}
static int mt798x_2p5ge_phy_get_rate_matching(struct phy_device *phydev,
phy_interface_t iface)
{
return RATE_MATCH_PAUSE;
}
static ssize_t pd_en_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct phy_device *phydev = container_of(dev, struct phy_device,
mdio.dev);
struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
return sprintf(buf, "%d\n", priv->pd_en);
}
static ssize_t pd_en_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct phy_device *phydev = container_of(dev, struct phy_device,
mdio.dev);
struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
int val;
if (kstrtoint(buf, 0, &val) == 0)
priv->pd_en = !!val;
return count;
}
static DEVICE_ATTR_RW(pd_en);
static int mt798x_2p5ge_phy_probe(struct phy_device *phydev)
{
struct mtk_i2p5ge_phy_priv *priv;
priv = devm_kzalloc(&phydev->mdio.dev,
sizeof(struct mtk_i2p5ge_phy_priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
switch (phydev->drv->phy_id) {
case MTK_2P5GPHY_ID_MT7987:
case MTK_2P5GPHY_ID_MT7988:
/* The original hardware only sets MDIO_DEVS_PMAPMD */
phydev->c45_ids.devices_in_package |= MDIO_DEVS_PCS |
MDIO_DEVS_AN |
MDIO_DEVS_VEND1 |
MDIO_DEVS_VEND2;
break;
default:
return -EINVAL;
}
priv->fw_loaded = false;
phydev->priv = priv;
priv->pd_en = 1;
device_create_file(&phydev->mdio.dev, &dev_attr_pd_en);
return 0;
}
static struct phy_driver mtk_2p5gephy_driver[] = {
{
PHY_ID_MATCH_MODEL(MTK_2P5GPHY_ID_MT7987),
.name = "MediaTek MT7987 2.5GbE PHY",
.probe = mt798x_2p5ge_phy_probe,
.config_init = mt798x_2p5ge_phy_config_init,
.config_aneg = mt798x_2p5ge_phy_config_aneg,
.get_features = mt798x_2p5ge_phy_get_features,
.read_status = mt798x_2p5ge_phy_read_status,
.get_rate_matching = mt798x_2p5ge_phy_get_rate_matching,
.suspend = genphy_suspend,
.resume = genphy_resume,
.read_page = mtk_phy_read_page,
.write_page = mtk_phy_write_page,
},
{
PHY_ID_MATCH_MODEL(MTK_2P5GPHY_ID_MT7988),
.name = "MediaTek MT7988 2.5GbE PHY",
.probe = mt798x_2p5ge_phy_probe,
.config_init = mt798x_2p5ge_phy_config_init,
.config_aneg = mt798x_2p5ge_phy_config_aneg,
.get_features = mt798x_2p5ge_phy_get_features,
.read_status = mt798x_2p5ge_phy_read_status,
.get_rate_matching = mt798x_2p5ge_phy_get_rate_matching,
.suspend = genphy_suspend,
.resume = genphy_resume,
.read_page = mtk_phy_read_page,
.write_page = mtk_phy_write_page,
},
};
module_phy_driver(mtk_2p5gephy_driver);
static struct mdio_device_id __maybe_unused mtk_2p5ge_phy_tbl[] = {
{ PHY_ID_MATCH_VENDOR(0x00339c00) },
{ }
};
MODULE_DESCRIPTION("MediaTek 2.5Gb Ethernet PHY driver");
MODULE_AUTHOR("SkyLake Huang <SkyLake.Huang@mediatek.com>");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(mdio, mtk_2p5ge_phy_tbl);
MODULE_FIRMWARE(MT7988_2P5GE_PMB_FW);

View File

@@ -1,143 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/phy.h>
#include "mtk.h"
#define MTK_GPHY_ID_MT7530 0x03a29412
#define MTK_GPHY_ID_MT7531 0x03a29441
#define MTK_PHY_PAGE_EXTENDED_2 0x0002
#define MTK_PHY_PAGE_EXTENDED_3 0x0003
#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11 0x11
#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
/* Registers on Token Ring debug nodes */
/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x17 */
#define SLAVE_DSP_READY_TIME_MASK GENMASK(22, 15)
/* Registers on MDIO_MMD_VEND1 */
#define MTK_PHY_GBE_MODE_TX_DELAY_SEL 0x13
#define MTK_PHY_TEST_MODE_TX_DELAY_SEL 0x14
#define MTK_TX_DELAY_PAIR_B_MASK GENMASK(10, 8)
#define MTK_TX_DELAY_PAIR_D_MASK GENMASK(2, 0)
#define MTK_PHY_MCC_CTRL_AND_TX_POWER_CTRL 0xa6
#define MTK_MCC_NEARECHO_OFFSET_MASK GENMASK(15, 8)
#define MTK_PHY_RXADC_CTRL_RG7 0xc6
#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8)
#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG123 0x123
#define MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK GENMASK(15, 8)
#define MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK GENMASK(7, 0)
static void mtk_gephy_config_init(struct phy_device *phydev)
{
/* Enable HW auto downshift */
phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED_1,
MTK_PHY_AUX_CTRL_AND_STATUS,
0, MTK_PHY_ENABLE_DOWNSHIFT);
/* Increase SlvDPSready time */
mtk_tr_modify(phydev, 0x1, 0xf, 0x17, SLAVE_DSP_READY_TIME_MASK,
FIELD_PREP(SLAVE_DSP_READY_TIME_MASK, 0x5e));
/* Adjust 100_mse_threshold */
phy_modify_mmd(phydev, MDIO_MMD_VEND1,
MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG123,
MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK |
MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK,
FIELD_PREP(MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK,
0xff) |
FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK,
0xff));
/* If echo time is narrower than 0x3, it will be regarded as noise */
phy_modify_mmd(phydev, MDIO_MMD_VEND1,
MTK_PHY_MCC_CTRL_AND_TX_POWER_CTRL,
MTK_MCC_NEARECHO_OFFSET_MASK,
FIELD_PREP(MTK_MCC_NEARECHO_OFFSET_MASK, 0x3));
}
static int mt7530_phy_config_init(struct phy_device *phydev)
{
mtk_gephy_config_init(phydev);
/* Increase post_update_timer */
phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3,
MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11, 0x4b);
return 0;
}
static int mt7531_phy_config_init(struct phy_device *phydev)
{
mtk_gephy_config_init(phydev);
/* PHY link down power saving enable */
phy_set_bits(phydev, 0x17, BIT(4));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
MTK_PHY_DA_AD_BUF_BIAS_LP_MASK,
FIELD_PREP(MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3));
/* Set TX Pair delay selection */
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_GBE_MODE_TX_DELAY_SEL,
MTK_TX_DELAY_PAIR_B_MASK | MTK_TX_DELAY_PAIR_D_MASK,
FIELD_PREP(MTK_TX_DELAY_PAIR_B_MASK, 0x4) |
FIELD_PREP(MTK_TX_DELAY_PAIR_D_MASK, 0x4));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TEST_MODE_TX_DELAY_SEL,
MTK_TX_DELAY_PAIR_B_MASK | MTK_TX_DELAY_PAIR_D_MASK,
FIELD_PREP(MTK_TX_DELAY_PAIR_B_MASK, 0x4) |
FIELD_PREP(MTK_TX_DELAY_PAIR_D_MASK, 0x4));
return 0;
}
static struct phy_driver mtk_gephy_driver[] = {
{
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530),
.name = "MediaTek MT7530 PHY",
.config_init = mt7530_phy_config_init,
/* Interrupts are handled by the switch, not the PHY
* itself.
*/
.config_intr = genphy_no_config_intr,
.handle_interrupt = genphy_no_ack_interrupt,
.suspend = genphy_suspend,
.resume = genphy_resume,
.read_page = mtk_phy_read_page,
.write_page = mtk_phy_write_page,
},
{
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531),
.name = "MediaTek MT7531 PHY",
.config_init = mt7531_phy_config_init,
.read_status = mtk_gphy_cl22_read_status,
/* Interrupts are handled by the switch, not the PHY
* itself.
*/
.config_intr = genphy_no_config_intr,
.handle_interrupt = genphy_no_ack_interrupt,
.suspend = genphy_suspend,
.resume = genphy_resume,
.read_page = mtk_phy_read_page,
.write_page = mtk_phy_write_page,
},
};
module_phy_driver(mtk_gephy_driver);
static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530) },
{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531) },
{ }
};
MODULE_DESCRIPTION("MediaTek Gigabit Ethernet PHY driver");
MODULE_AUTHOR("DENG, Qingfang <dqfext@gmail.com>");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(mdio, mtk_gephy_tbl);

View File

@@ -1,452 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/phy.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include "mtk.h"
/* Difference between functions with mtk_tr* and __mtk_tr* prefixes is
* mtk_tr* functions: wrapped by page switching operations
* __mtk_tr* functions: no page switching operations
*/
static void __mtk_tr_access(struct phy_device *phydev, bool read, u8 ch_addr,
u8 node_addr, u8 data_addr)
{
u16 tr_cmd = BIT(15); /* bit 14 & 0 are reserved */
if (read)
tr_cmd |= BIT(13);
tr_cmd |= (((ch_addr & 0x3) << 11) |
((node_addr & 0xf) << 7) |
((data_addr & 0x3f) << 1));
dev_dbg(&phydev->mdio.dev, "tr_cmd: 0x%x\n", tr_cmd);
__phy_write(phydev, 0x10, tr_cmd);
}
static void __mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
u8 data_addr, u16 *tr_high, u16 *tr_low)
{
__mtk_tr_access(phydev, true, ch_addr, node_addr, data_addr);
*tr_low = __phy_read(phydev, 0x11);
*tr_high = __phy_read(phydev, 0x12);
dev_dbg(&phydev->mdio.dev, "tr_high read: 0x%x, tr_low read: 0x%x\n",
*tr_high, *tr_low);
}
u32 mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
u8 data_addr)
{
u16 tr_high;
u16 tr_low;
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
__mtk_tr_read(phydev, ch_addr, node_addr, data_addr, &tr_high, &tr_low);
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
return (tr_high << 16) | tr_low;
}
EXPORT_SYMBOL_GPL(mtk_tr_read);
static void __mtk_tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
u8 data_addr, u32 tr_data)
{
__phy_write(phydev, 0x11, tr_data & 0xffff);
__phy_write(phydev, 0x12, tr_data >> 16);
dev_dbg(&phydev->mdio.dev, "tr_high write: 0x%x, tr_low write: 0x%x\n",
tr_data >> 16, tr_data & 0xffff);
__mtk_tr_access(phydev, false, ch_addr, node_addr, data_addr);
}
void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
u8 data_addr, u32 mask, u32 set)
{
u32 tr_data;
u16 tr_high;
u16 tr_low;
__mtk_tr_read(phydev, ch_addr, node_addr, data_addr, &tr_high, &tr_low);
tr_data = (tr_high << 16) | tr_low;
tr_data = (tr_data & ~mask) | set;
__mtk_tr_write(phydev, ch_addr, node_addr, data_addr, tr_data);
}
EXPORT_SYMBOL_GPL(__mtk_tr_modify);
void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
u8 data_addr, u32 mask, u32 set)
{
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
__mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, mask, set);
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
}
EXPORT_SYMBOL_GPL(mtk_tr_modify);
void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
u8 data_addr, u32 set)
{
__mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, 0, set);
}
EXPORT_SYMBOL_GPL(__mtk_tr_set_bits);
void __mtk_tr_clr_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
u8 data_addr, u32 clr)
{
__mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, clr, 0);
}
EXPORT_SYMBOL_GPL(__mtk_tr_clr_bits);
int mtk_phy_read_page(struct phy_device *phydev)
{
return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
}
EXPORT_SYMBOL_GPL(mtk_phy_read_page);
int mtk_phy_write_page(struct phy_device *phydev, int page)
{
return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
}
EXPORT_SYMBOL_GPL(mtk_phy_write_page);
/* This function deals with the case that 1G AN starts but isn't completed. We
* set AN_NEW_LP_CNT_LIMIT with different values time after time to let our
* 1G->100Mbps hardware automatic downshift to fit more partner devices.
*/
static int extend_an_new_lp_cnt_limit(struct phy_device *phydev)
{
int mmd_read_ret;
u32 reg_val;
int timeout;
/* According to table 28-9 & Figure 28-18 in IEEE 802.3,
* link_fail_inhibit_timer of 10/100/1000 Mbps devices ranges from 750
* to "1000ms". Once MTK_PHY_FINAL_SPEED_1000 is set, it means that we
* enter "FLP LINK GOOD CHECK" state, link_fail_inhibit_timer starts and
* this PHY's 1G training starts. If 1G training never starts, we do
* nothing but leave.
*/
timeout = read_poll_timeout(mmd_read_ret = phy_read_mmd, reg_val,
(mmd_read_ret < 0) ||
reg_val & MTK_PHY_FINAL_SPEED_1000,
10000, 1000000, false, phydev,
MDIO_MMD_VEND1, MTK_PHY_LINK_STATUS_MISC);
if (mmd_read_ret < 0)
return mmd_read_ret;
if (!timeout) {
/* Once we found MTK_PHY_FINAL_SPEED_1000 is set, no matter 1G
* AN is completed or not, we'll set AN_NEW_LP_CNT_LIMIT again
* and again.
*/
mtk_tr_modify(phydev, 0x0, 0xf, 0x3c, AN_NEW_LP_CNT_LIMIT_MASK,
FIELD_PREP(AN_NEW_LP_CNT_LIMIT_MASK, 0xf));
mdelay(1500);
timeout = read_poll_timeout(mtk_tr_read, reg_val,
(reg_val & AN_STATE_MASK) !=
(AN_STATE_TX_DISABLE <<
AN_STATE_SHIFT),
10000, 1000000, false, phydev,
0x0, 0xf, 0x2);
if (!timeout) {
mdelay(625);
mtk_tr_modify(phydev, 0x0, 0xf, 0x3c,
AN_NEW_LP_CNT_LIMIT_MASK,
FIELD_PREP(AN_NEW_LP_CNT_LIMIT_MASK,
0x8));
mdelay(500);
mtk_tr_modify(phydev, 0x0, 0xf, 0x3c,
AN_NEW_LP_CNT_LIMIT_MASK,
FIELD_PREP(AN_NEW_LP_CNT_LIMIT_MASK,
0xf));
} else {
return -ETIMEDOUT;
}
}
return 0;
}
int mtk_gphy_cl22_read_status(struct phy_device *phydev)
{
int ret;
ret = genphy_read_status(phydev);
if (ret)
return ret;
if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete) {
ret = phy_read_paged(phydev, MTK_PHY_PAGE_EXTENDED_1,
MTK_PHY_AUX_CTRL_AND_STATUS);
if (ret < 0)
return ret;
/* Once LP_DETECTED is set, it means that"ability_match" in
* IEEE 802.3 Figure 28-18 is set. This happens after we plug in
* cable. Also, LP_DETECTED will be cleared after AN complete.
*/
if (!FIELD_GET(MTK_PHY_LP_DETECTED_MASK, ret))
return 0;
ret = phy_read(phydev, MII_CTRL1000);
if (ret & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) {
ret = extend_an_new_lp_cnt_limit(phydev);
if (ret < 0)
return ret;
}
}
return 0;
}
EXPORT_SYMBOL_GPL(mtk_gphy_cl22_read_status);
#if 0
int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
unsigned long rules,
unsigned long supported_triggers)
{
if (index > 1)
return -EINVAL;
/* All combinations of the supported triggers are allowed */
if (rules & ~supported_triggers)
return -EOPNOTSUPP;
return 0;
}
EXPORT_SYMBOL_GPL(mtk_phy_led_hw_is_supported);
int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index,
unsigned long *rules, unsigned long *led_state,
u16 on_set, u16 rx_blink_set, u16 tx_blink_set)
{
unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
(index ? 16 : 0);
unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
int on, blink;
if (index > 1)
return -EINVAL;
on = phy_read_mmd(phydev, MDIO_MMD_VEND2,
index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL);
if (on < 0)
return -EIO;
blink = phy_read_mmd(phydev, MDIO_MMD_VEND2,
index ? MTK_PHY_LED1_BLINK_CTRL :
MTK_PHY_LED0_BLINK_CTRL);
if (blink < 0)
return -EIO;
if ((on & (on_set | MTK_PHY_LED_ON_FDX |
MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) ||
(blink & (rx_blink_set | tx_blink_set)))
set_bit(bit_netdev, led_state);
else
clear_bit(bit_netdev, led_state);
if (on & MTK_PHY_LED_ON_FORCE_ON)
set_bit(bit_on, led_state);
else
clear_bit(bit_on, led_state);
if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK)
set_bit(bit_blink, led_state);
else
clear_bit(bit_blink, led_state);
if (!rules)
return 0;
if (on & on_set)
*rules |= BIT(TRIGGER_NETDEV_LINK);
if (on & MTK_PHY_LED_ON_LINK10)
*rules |= BIT(TRIGGER_NETDEV_LINK_10);
if (on & MTK_PHY_LED_ON_LINK100)
*rules |= BIT(TRIGGER_NETDEV_LINK_100);
if (on & MTK_PHY_LED_ON_LINK1000)
*rules |= BIT(TRIGGER_NETDEV_LINK_1000);
if (on & MTK_PHY_LED_ON_LINK2500)
*rules |= BIT(TRIGGER_NETDEV_LINK_2500);
if (on & MTK_PHY_LED_ON_FDX)
*rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
if (on & MTK_PHY_LED_ON_HDX)
*rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
if (blink & rx_blink_set)
*rules |= BIT(TRIGGER_NETDEV_RX);
if (blink & tx_blink_set)
*rules |= BIT(TRIGGER_NETDEV_TX);
return 0;
}
EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_get);
int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index,
unsigned long rules, unsigned long *led_state,
u16 on_set, u16 rx_blink_set, u16 tx_blink_set)
{
unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
u16 on = 0, blink = 0;
int ret;
if (index > 1)
return -EINVAL;
if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
on |= MTK_PHY_LED_ON_FDX;
if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
on |= MTK_PHY_LED_ON_HDX;
if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
on |= MTK_PHY_LED_ON_LINK10;
if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
on |= MTK_PHY_LED_ON_LINK100;
if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
on |= MTK_PHY_LED_ON_LINK1000;
if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK)))
on |= MTK_PHY_LED_ON_LINK2500;
if (rules & BIT(TRIGGER_NETDEV_RX)) {
if (on & on_set) {
if (on & MTK_PHY_LED_ON_LINK10)
blink |= MTK_PHY_LED_BLINK_10RX;
if (on & MTK_PHY_LED_ON_LINK100)
blink |= MTK_PHY_LED_BLINK_100RX;
if (on & MTK_PHY_LED_ON_LINK1000)
blink |= MTK_PHY_LED_BLINK_1000RX;
if (on & MTK_PHY_LED_ON_LINK2500)
blink |= MTK_PHY_LED_BLINK_2500RX;
} else {
blink |= rx_blink_set;
}
}
if (rules & BIT(TRIGGER_NETDEV_TX)) {
if (on & on_set) {
if (on & MTK_PHY_LED_ON_LINK10)
blink |= MTK_PHY_LED_BLINK_10TX;
if (on & MTK_PHY_LED_ON_LINK100)
blink |= MTK_PHY_LED_BLINK_100TX;
if (on & MTK_PHY_LED_ON_LINK1000)
blink |= MTK_PHY_LED_BLINK_1000TX;
if (on & MTK_PHY_LED_ON_LINK2500)
blink |= MTK_PHY_LED_BLINK_2500TX;
} else {
blink |= tx_blink_set;
}
}
if (blink || on)
set_bit(bit_netdev, led_state);
else
clear_bit(bit_netdev, led_state);
ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX | on_set,
on);
if (ret)
return ret;
return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
MTK_PHY_LED1_BLINK_CTRL :
MTK_PHY_LED0_BLINK_CTRL, blink);
}
EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_set);
int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on,
unsigned long *delay_off, bool *blinking)
{
if (index > 1)
return -EINVAL;
if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) {
*blinking = true;
*delay_on = 50;
*delay_off = 50;
}
return 0;
}
EXPORT_SYMBOL_GPL(mtk_phy_led_num_dly_cfg);
int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
unsigned long *led_state, u16 led_on_mask, bool on)
{
unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
bool changed;
if (on)
changed = !test_and_set_bit(bit_on, led_state);
else
changed = !!test_and_clear_bit(bit_on, led_state);
changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV +
(index ? 16 : 0), led_state);
if (changed)
return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
MTK_PHY_LED1_ON_CTRL :
MTK_PHY_LED0_ON_CTRL,
led_on_mask,
on ? MTK_PHY_LED_ON_FORCE_ON : 0);
else
return 0;
}
EXPORT_SYMBOL_GPL(mtk_phy_hw_led_on_set);
int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
unsigned long *led_state, bool blinking)
{
unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
(index ? 16 : 0);
bool changed;
if (blinking)
changed = !test_and_set_bit(bit_blink, led_state);
else
changed = !!test_and_clear_bit(bit_blink, led_state);
changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV +
(index ? 16 : 0), led_state);
if (changed)
return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
MTK_PHY_LED1_BLINK_CTRL :
MTK_PHY_LED0_BLINK_CTRL,
blinking ?
MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
else
return 0;
}
EXPORT_SYMBOL_GPL(mtk_phy_hw_led_blink_set);
void mtk_phy_leds_state_init(struct phy_device *phydev)
{
int i;
for (i = 0; i < 2; ++i)
phydev->drv->led_hw_control_get(phydev, i, NULL);
}
EXPORT_SYMBOL_GPL(mtk_phy_leds_state_init);
#endif
MODULE_DESCRIPTION("MediaTek Ethernet PHY driver common");
MODULE_AUTHOR("Sky Huang <SkyLake.Huang@mediatek.com>");
MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
MODULE_LICENSE("GPL");

View File

@@ -1,119 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0
*
* Common definition for Mediatek Ethernet PHYs
* Author: SkyLake Huang <SkyLake.Huang@mediatek.com>
* Copyright (c) 2024 MediaTek Inc.
*/
#ifndef _MTK_EPHY_H_
#define _MTK_EPHY_H_
#define MTK_EXT_PAGE_ACCESS 0x1f
#define MTK_PHY_PAGE_STANDARD 0x0000
#define MTK_PHY_PAGE_EXTENDED_1 0x0001
#define MTK_PHY_AUX_CTRL_AND_STATUS 0x14
/* suprv_media_select_RefClk */
#define MTK_PHY_LP_DETECTED_MASK GENMASK(7, 6)
#define MTK_PHY_ENABLE_DOWNSHIFT BIT(4)
#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
/* Registers on Token Ring debug nodes */
/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x2 */
#define AN_STATE_MASK GENMASK(22, 19)
#define AN_STATE_SHIFT 19
#define AN_STATE_TX_DISABLE 1
/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */
#define AN_NEW_LP_CNT_LIMIT_MASK GENMASK(23, 20)
#define AUTO_NP_10XEN BIT(6)
/* Registers on MDIO_MMD_VEND1 */
#define MTK_PHY_LINK_STATUS_MISC (0xa2)
#define MTK_PHY_FINAL_SPEED_1000 BIT(3)
/* Registers on MDIO_MMD_VEND2 */
#define MTK_PHY_LED0_ON_CTRL 0x24
#define MTK_PHY_LED1_ON_CTRL 0x26
#define MTK_GPHY_LED_ON_MASK GENMASK(6, 0)
#define MTK_2P5GPHY_LED_ON_MASK GENMASK(7, 0)
#define MTK_PHY_LED_ON_LINK1000 BIT(0)
#define MTK_PHY_LED_ON_LINK100 BIT(1)
#define MTK_PHY_LED_ON_LINK10 BIT(2)
#define MTK_PHY_LED_ON_LINKDOWN BIT(3)
#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */
#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */
#define MTK_PHY_LED_ON_FORCE_ON BIT(6)
#define MTK_PHY_LED_ON_LINK2500 BIT(7)
#define MTK_PHY_LED_ON_POLARITY BIT(14)
#define MTK_PHY_LED_ON_ENABLE BIT(15)
#define MTK_PHY_LED0_BLINK_CTRL 0x25
#define MTK_PHY_LED1_BLINK_CTRL 0x27
#define MTK_PHY_LED_BLINK_1000TX BIT(0)
#define MTK_PHY_LED_BLINK_1000RX BIT(1)
#define MTK_PHY_LED_BLINK_100TX BIT(2)
#define MTK_PHY_LED_BLINK_100RX BIT(3)
#define MTK_PHY_LED_BLINK_10TX BIT(4)
#define MTK_PHY_LED_BLINK_10RX BIT(5)
#define MTK_PHY_LED_BLINK_COLLISION BIT(6)
#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7)
#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8)
#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9)
#define MTK_PHY_LED_BLINK_2500TX BIT(10)
#define MTK_PHY_LED_BLINK_2500RX BIT(11)
#define MTK_GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK1000 | \
MTK_PHY_LED_ON_LINK100 | \
MTK_PHY_LED_ON_LINK10)
#define MTK_GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \
MTK_PHY_LED_BLINK_100RX | \
MTK_PHY_LED_BLINK_10RX)
#define MTK_GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \
MTK_PHY_LED_BLINK_100RX | \
MTK_PHY_LED_BLINK_10RX)
#define MTK_2P5GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK2500 | \
MTK_GPHY_LED_ON_SET)
#define MTK_2P5GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \
MTK_GPHY_LED_RX_BLINK_SET)
#define MTK_2P5GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \
MTK_GPHY_LED_TX_BLINK_SET)
#define MTK_PHY_LED_STATE_FORCE_ON 0
#define MTK_PHY_LED_STATE_FORCE_BLINK 1
#define MTK_PHY_LED_STATE_NETDEV 2
u32 mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
u8 data_addr);
void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
u8 data_addr, u32 mask, u32 set);
void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
u8 data_addr, u32 mask, u32 set);
void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
u8 data_addr, u32 set);
void __mtk_tr_clr_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
u8 data_addr, u32 clr);
int mtk_phy_read_page(struct phy_device *phydev);
int mtk_phy_write_page(struct phy_device *phydev, int page);
int mtk_gphy_cl22_read_status(struct phy_device *phydev);
/*int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
unsigned long rules,
unsigned long supported_triggers);
int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index,
unsigned long rules, unsigned long *led_state,
u16 on_set, u16 rx_blink_set, u16 tx_blink_set);
int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index,
unsigned long *rules, unsigned long *led_state,
u16 on_set, u16 rx_blink_set, u16 tx_blink_set);
int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on,
unsigned long *delay_off, bool *blinking);
int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
unsigned long *led_state, u16 led_on_mask, bool on);
int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
unsigned long *led_state, bool blinking);
void mtk_phy_leds_state_init(struct phy_device *phydev);*/
#endif /* _MTK_EPHY_H_ */

View File

@@ -491,7 +491,6 @@ static int mt7531_mac_port_setup(struct gsw_mt753x *gsw, u32 port,
mt7531_set_port_rgmii(gsw, port);
break;
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_2500BASEX:
if (port_cfg->force_link)
mt7531_set_port_sgmii_force_mode(gsw, port, port_cfg);
else

View File

@@ -765,8 +765,6 @@ static int mt753x_probe(struct platform_device *pdev)
gsw->irq = platform_get_irq(pdev, 0);
if (gsw->irq >= 0) {
INIT_WORK(&gsw->irq_worker, mt753x_irq_worker);
ret = devm_request_irq(gsw->dev, gsw->irq, mt753x_irq_handler,
0, dev_name(gsw->dev), gsw);
if (ret) {
@@ -774,6 +772,8 @@ static int mt753x_probe(struct platform_device *pdev)
gsw->irq);
goto fail;
}
INIT_WORK(&gsw->irq_worker, mt753x_irq_worker);
}
platform_set_drvdata(pdev, gsw);

View File

@@ -196,7 +196,6 @@ struct mtk_pcie_port {
struct mtk_msi_set msi_sets[PCIE_MSI_SET_NUM];
enum mtk_msi_group_type msi_group_type;
struct mutex lock;
bool soft_off;
DECLARE_BITMAP(msi_irq_in_use, PCIE_MSI_IRQS_NUM);
};
@@ -235,11 +234,6 @@ static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
struct mtk_pcie_port *port = bus->sysdata;
if (port->soft_off)
return 0;
mtk_pcie_config_tlp_header(bus, devfn, where, size);
return pci_generic_config_read32(bus, devfn, where, size, val);
@@ -248,11 +242,6 @@ static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
struct mtk_pcie_port *port = bus->sysdata;
if (port->soft_off)
return 0;
mtk_pcie_config_tlp_header(bus, devfn, where, size);
if (size <= 2)
@@ -1268,95 +1257,6 @@ static int __maybe_unused mtk_pcie_turn_off_link(struct mtk_pcie_port *port)
50 * USEC_PER_MSEC);
}
int mtk_pcie_soft_off(struct pci_bus *bus)
{
struct pci_host_bridge *host;
struct mtk_pcie_port *port;
struct pci_dev *dev;
int ret;
u32 val;
if (!bus) {
dev_err(port->dev, "There is no bus, please check the host driver\n");
return -ENODEV;
}
port = bus->sysdata;
if (port->soft_off) {
dev_err(port->dev, "The soft_off is true, can't soft off\n");
return -EPERM;
}
host = pci_host_bridge_from_priv(port);
dev = pci_get_slot(host->bus, 0);
if (!dev) {
dev_err(port->dev, "Failed to get device from bus\n");
return -ENODEV;
}
/* Trigger link to L2 state */
ret = mtk_pcie_turn_off_link(port);
pci_save_state(dev);
pci_dev_put(dev);
mtk_pcie_irq_save(port);
port->soft_off = true;
mtk_pcie_power_down(port);
dev_info(port->dev, "mtk pcie soft off done\n");
return ret;
}
EXPORT_SYMBOL(mtk_pcie_soft_off);
int mtk_pcie_soft_on(struct pci_bus *bus)
{
struct pci_host_bridge *host;
struct mtk_pcie_port *port;
struct pci_dev *dev;
int ret;
if (!bus) {
dev_err(port->dev, "There is no bus, please check the host driver\n");
return -ENODEV;
}
port = bus->sysdata;
if (!port->soft_off) {
dev_err(port->dev, "The soft_off is false, can't soft on\n");
return -EPERM;
}
host = pci_host_bridge_from_priv(port);
dev = pci_get_slot(host->bus, 0);
if (!dev) {
dev_err(port->dev, "Failed to get device from bus\n");
return -ENODEV;
}
ret = mtk_pcie_power_up(port);
if (ret) {
dev_err(port->dev, "Failed to power up RC\n");
return ret;
}
ret = mtk_pcie_startup_port(port);
if (ret) {
dev_err(port->dev, "Failed to detect EP\n");
return ret;
}
port->soft_off = false;
mtk_pcie_irq_restore(port);
pci_restore_state(dev);
pci_dev_put(dev);
dev_info(port->dev, "mtk pcie soft on done\n");
return ret;
}
EXPORT_SYMBOL(mtk_pcie_soft_on);
static int __maybe_unused mtk_pcie_suspend_noirq(struct device *dev)
{
struct mtk_pcie_port *port = dev_get_drvdata(dev);

View File

@@ -1,769 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* The MT7987 driver based on Linux generic pinctrl binding.
*
* Copyright (C) 2020 MediaTek Inc.
* Author: Tim.Kuo <Tim.Kuo@mediatek.com>
*/
#include "pinctrl-moore.h"
enum MT7987_PINCTRL_REG_PAGE {
GPIO_BASE,
IOCFG_RB_BASE,
IOCFG_LB_BASE,
IOCFG_RT1_BASE,
IOCFG_RT2_BASE,
IOCFG_TL_BASE,
};
#define MT7987_PIN(_number, _name) MTK_PIN(_number, _name, 0, _number, DRV_GRP4)
#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \
_x_bits) \
PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \
_x_bits, 32, 0)
#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \
_x_bits) \
PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \
_x_bits, 32, 0)
#define PINS_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \
_x_bits) \
PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \
_x_bits, 32, 1)
static const struct mtk_pin_field_calc mt7987_pin_mode_range[] = {
PIN_FIELD(0, 49, 0x300, 0x10, 0, 4),
};
static const struct mtk_pin_field_calc mt7987_pin_dir_range[] = {
PIN_FIELD(0, 49, 0x0, 0x10, 0, 1),
};
static const struct mtk_pin_field_calc mt7987_pin_di_range[] = {
PIN_FIELD(0, 49, 0x200, 0x10, 0, 1),
};
static const struct mtk_pin_field_calc mt7987_pin_do_range[] = {
PIN_FIELD(0, 49, 0x100, 0x10, 0, 1),
};
static const struct mtk_pin_field_calc mt7987_pin_ies_range[] = {
PIN_FIELD_BASE(0, 0, IOCFG_RT2_BASE, 0x20, 0x10, 3, 1),
PIN_FIELD_BASE(1, 1, IOCFG_RT2_BASE, 0x20, 0x10, 2, 1),
PIN_FIELD_BASE(2, 2, IOCFG_RT2_BASE, 0x20, 0x10, 11, 1),
PIN_FIELD_BASE(3, 3, IOCFG_TL_BASE, 0x20, 0x10, 2, 1),
PIN_FIELD_BASE(4, 4, IOCFG_TL_BASE, 0x20, 0x10, 1, 1),
PIN_FIELD_BASE(5, 5, IOCFG_TL_BASE, 0x20, 0x10, 3, 1),
PIN_FIELD_BASE(6, 6, IOCFG_TL_BASE, 0x20, 0x10, 0, 1),
PIN_FIELD_BASE(7, 7, IOCFG_TL_BASE, 0x20, 0x10, 4, 1),
PIN_FIELD_BASE(8, 8, IOCFG_RB_BASE, 0x10, 0x10, 2, 1),
PIN_FIELD_BASE(9, 9, IOCFG_RB_BASE, 0x10, 0x10, 1, 1),
PIN_FIELD_BASE(10, 10, IOCFG_RB_BASE, 0x10, 0x10, 0, 1),
PIN_FIELD_BASE(11, 11, IOCFG_RB_BASE, 0x10, 0x10, 3, 1),
PIN_FIELD_BASE(12, 12, IOCFG_RB_BASE, 0x10, 0x10, 4, 1),
PIN_FIELD_BASE(13, 13, IOCFG_RT1_BASE, 0x20, 0x10, 0, 1),
PIN_FIELD_BASE(14, 14, IOCFG_RT1_BASE, 0x20, 0x10, 15, 1),
PIN_FIELD_BASE(15, 15, IOCFG_RT1_BASE, 0x20, 0x10, 3, 1),
PIN_FIELD_BASE(16, 16, IOCFG_RT1_BASE, 0x20, 0x10, 7, 1),
PIN_FIELD_BASE(17, 17, IOCFG_RT1_BASE, 0x20, 0x10, 6, 1),
PIN_FIELD_BASE(18, 18, IOCFG_RT1_BASE, 0x20, 0x10, 4, 1),
PIN_FIELD_BASE(19, 19, IOCFG_RT1_BASE, 0x20, 0x10, 5, 1),
PIN_FIELD_BASE(20, 20, IOCFG_RT1_BASE, 0x20, 0x10, 8, 1),
PIN_FIELD_BASE(21, 21, IOCFG_RT1_BASE, 0x20, 0x10, 9, 1),
PIN_FIELD_BASE(22, 22, IOCFG_RT1_BASE, 0x20, 0x10, 12, 1),
PIN_FIELD_BASE(23, 23, IOCFG_RT1_BASE, 0x20, 0x10, 11, 1),
PIN_FIELD_BASE(24, 24, IOCFG_RT1_BASE, 0x20, 0x10, 10, 1),
PIN_FIELD_BASE(25, 25, IOCFG_RT1_BASE, 0x20, 0x10, 13, 1),
PIN_FIELD_BASE(26, 26, IOCFG_RT1_BASE, 0x20, 0x10, 14, 1),
PIN_FIELD_BASE(27, 27, IOCFG_RT2_BASE, 0x20, 0x10, 9, 1),
PIN_FIELD_BASE(28, 28, IOCFG_RT2_BASE, 0x20, 0x10, 7, 1),
PIN_FIELD_BASE(29, 29, IOCFG_RT2_BASE, 0x20, 0x10, 8, 1),
PIN_FIELD_BASE(30, 30, IOCFG_RT2_BASE, 0x20, 0x10, 10, 1),
PIN_FIELD_BASE(31, 31, IOCFG_TL_BASE, 0x20, 0x10, 5, 1),
PIN_FIELD_BASE(32, 32, IOCFG_TL_BASE, 0x20, 0x10, 6, 1),
PIN_FIELD_BASE(33, 33, IOCFG_LB_BASE, 0x20, 0x10, 2, 1),
PIN_FIELD_BASE(34, 34, IOCFG_LB_BASE, 0x20, 0x10, 0, 1),
PIN_FIELD_BASE(35, 35, IOCFG_LB_BASE, 0x20, 0x10, 4, 1),
PIN_FIELD_BASE(36, 36, IOCFG_LB_BASE, 0x20, 0x10, 3, 1),
PIN_FIELD_BASE(37, 37, IOCFG_LB_BASE, 0x20, 0x10, 1, 1),
PIN_FIELD_BASE(38, 38, IOCFG_LB_BASE, 0x20, 0x10, 5, 1),
PIN_FIELD_BASE(39, 39, IOCFG_RT1_BASE, 0x20, 0x10, 1, 1),
PIN_FIELD_BASE(40, 40, IOCFG_RT1_BASE, 0x20, 0x10, 2, 1),
PIN_FIELD_BASE(41, 41, IOCFG_RT2_BASE, 0x20, 0x10, 0, 1),
PIN_FIELD_BASE(42, 42, IOCFG_RT2_BASE, 0x20, 0x10, 1, 1),
PIN_FIELD_BASE(43, 43, IOCFG_RT2_BASE, 0x20, 0x10, 4, 1),
PIN_FIELD_BASE(44, 44, IOCFG_RT2_BASE, 0x20, 0x10, 5, 1),
PIN_FIELD_BASE(45, 45, IOCFG_RT2_BASE, 0x20, 0x10, 6, 1),
PIN_FIELD_BASE(46, 46, IOCFG_TL_BASE, 0x20, 0x10, 9, 1),
PIN_FIELD_BASE(47, 47, IOCFG_TL_BASE, 0x20, 0x10, 10, 1),
PIN_FIELD_BASE(48, 48, IOCFG_TL_BASE, 0x20, 0x10, 7, 1),
PIN_FIELD_BASE(49, 49, IOCFG_TL_BASE, 0x20, 0x10, 8, 1),
};
static const struct mtk_pin_field_calc mt7987_pin_smt_range[] = {
PIN_FIELD_BASE(0, 0, IOCFG_RT2_BASE, 0x90, 0x10, 3, 1),
PIN_FIELD_BASE(1, 1, IOCFG_RT2_BASE, 0x90, 0x10, 2, 1),
PIN_FIELD_BASE(2, 2, IOCFG_RT2_BASE, 0x90, 0x10, 11, 1),
PIN_FIELD_BASE(3, 3, IOCFG_TL_BASE, 0x90, 0x10, 2, 1),
PIN_FIELD_BASE(4, 4, IOCFG_TL_BASE, 0x90, 0x10, 1, 1),
PIN_FIELD_BASE(5, 5, IOCFG_TL_BASE, 0x90, 0x10, 3, 1),
PIN_FIELD_BASE(6, 6, IOCFG_TL_BASE, 0x90, 0x10, 0, 1),
PIN_FIELD_BASE(7, 7, IOCFG_TL_BASE, 0x90, 0x10, 4, 1),
PIN_FIELD_BASE(8, 8, IOCFG_RB_BASE, 0x70, 0x10, 2, 1),
PIN_FIELD_BASE(9, 9, IOCFG_RB_BASE, 0x70, 0x10, 1, 1),
PIN_FIELD_BASE(10, 10, IOCFG_RB_BASE, 0x70, 0x10, 0, 1),
PIN_FIELD_BASE(11, 11, IOCFG_RB_BASE, 0x70, 0x10, 3, 1),
PIN_FIELD_BASE(12, 12, IOCFG_RB_BASE, 0x70, 0x10, 4, 1),
PIN_FIELD_BASE(13, 13, IOCFG_RT1_BASE, 0xA0, 0x10, 0, 1),
PIN_FIELD_BASE(14, 14, IOCFG_RT1_BASE, 0xA0, 0x10, 15, 1),
PIN_FIELD_BASE(15, 15, IOCFG_RT1_BASE, 0xA0, 0x10, 3, 1),
PIN_FIELD_BASE(16, 16, IOCFG_RT1_BASE, 0xA0, 0x10, 7, 1),
PIN_FIELD_BASE(17, 17, IOCFG_RT1_BASE, 0xA0, 0x10, 6, 1),
PIN_FIELD_BASE(18, 18, IOCFG_RT1_BASE, 0xA0, 0x10, 4, 1),
PIN_FIELD_BASE(19, 19, IOCFG_RT1_BASE, 0xA0, 0x10, 5, 1),
PIN_FIELD_BASE(20, 20, IOCFG_RT1_BASE, 0xA0, 0x10, 8, 1),
PIN_FIELD_BASE(21, 21, IOCFG_RT1_BASE, 0xA0, 0x10, 9, 1),
PIN_FIELD_BASE(22, 22, IOCFG_RT1_BASE, 0xA0, 0x10, 12, 1),
PIN_FIELD_BASE(23, 23, IOCFG_RT1_BASE, 0xA0, 0x10, 11, 1),
PIN_FIELD_BASE(24, 24, IOCFG_RT1_BASE, 0xA0, 0x10, 10, 1),
PIN_FIELD_BASE(25, 25, IOCFG_RT1_BASE, 0xA0, 0x10, 13, 1),
PIN_FIELD_BASE(26, 26, IOCFG_RT1_BASE, 0xA0, 0x10, 14, 1),
PIN_FIELD_BASE(27, 27, IOCFG_RT2_BASE, 0x90, 0x10, 9, 1),
PIN_FIELD_BASE(28, 28, IOCFG_RT2_BASE, 0x90, 0x10, 7, 1),
PIN_FIELD_BASE(29, 29, IOCFG_RT2_BASE, 0x90, 0x10, 8, 1),
PIN_FIELD_BASE(30, 30, IOCFG_RT2_BASE, 0x90, 0x10, 10, 1),
PIN_FIELD_BASE(31, 31, IOCFG_TL_BASE, 0x90, 0x10, 5, 1),
PIN_FIELD_BASE(32, 32, IOCFG_TL_BASE, 0x90, 0x10, 6, 1),
PIN_FIELD_BASE(33, 33, IOCFG_LB_BASE, 0x60, 0x10, 2, 1),
PIN_FIELD_BASE(34, 34, IOCFG_LB_BASE, 0x60, 0x10, 0, 1),
PIN_FIELD_BASE(35, 35, IOCFG_LB_BASE, 0x60, 0x10, 4, 1),
PIN_FIELD_BASE(36, 36, IOCFG_LB_BASE, 0x60, 0x10, 3, 1),
PIN_FIELD_BASE(37, 37, IOCFG_LB_BASE, 0x60, 0x10, 1, 1),
PIN_FIELD_BASE(38, 38, IOCFG_LB_BASE, 0x60, 0x10, 5, 1),
PIN_FIELD_BASE(39, 39, IOCFG_RT1_BASE, 0xA0, 0x10, 1, 1),
PIN_FIELD_BASE(40, 40, IOCFG_RT1_BASE, 0xA0, 0x10, 2, 1),
PIN_FIELD_BASE(41, 41, IOCFG_RT2_BASE, 0x90, 0x10, 0, 1),
PIN_FIELD_BASE(42, 42, IOCFG_RT2_BASE, 0x90, 0x10, 1, 1),
PIN_FIELD_BASE(43, 43, IOCFG_RT2_BASE, 0x90, 0x10, 4, 1),
PIN_FIELD_BASE(44, 44, IOCFG_RT2_BASE, 0x90, 0x10, 5, 1),
PIN_FIELD_BASE(45, 45, IOCFG_RT2_BASE, 0x90, 0x10, 6, 1),
PIN_FIELD_BASE(46, 46, IOCFG_TL_BASE, 0x90, 0x10, 9, 1),
PIN_FIELD_BASE(47, 47, IOCFG_TL_BASE, 0x90, 0x10, 10, 1),
PIN_FIELD_BASE(48, 48, IOCFG_TL_BASE, 0x90, 0x10, 7, 1),
PIN_FIELD_BASE(49, 49, IOCFG_TL_BASE, 0x90, 0x10, 8, 1),
};
static const struct mtk_pin_field_calc mt7987_pin_pu_range[] = {
PIN_FIELD_BASE(33, 33, IOCFG_LB_BASE, 0x40, 0x10, 2, 1),
PIN_FIELD_BASE(34, 34, IOCFG_LB_BASE, 0x40, 0x10, 0, 1),
PIN_FIELD_BASE(35, 35, IOCFG_LB_BASE, 0x40, 0x10, 4, 1),
PIN_FIELD_BASE(36, 36, IOCFG_LB_BASE, 0x40, 0x10, 3, 1),
PIN_FIELD_BASE(37, 37, IOCFG_LB_BASE, 0x40, 0x10, 1, 1),
PIN_FIELD_BASE(38, 38, IOCFG_LB_BASE, 0x40, 0x10, 5, 1),
};
static const struct mtk_pin_field_calc mt7987_pin_pd_range[] = {
PIN_FIELD_BASE(33, 33, IOCFG_LB_BASE, 0x30, 0x10, 2, 1),
PIN_FIELD_BASE(34, 34, IOCFG_LB_BASE, 0x30, 0x10, 0, 1),
PIN_FIELD_BASE(35, 35, IOCFG_LB_BASE, 0x30, 0x10, 4, 1),
PIN_FIELD_BASE(36, 36, IOCFG_LB_BASE, 0x30, 0x10, 3, 1),
PIN_FIELD_BASE(37, 37, IOCFG_LB_BASE, 0x30, 0x10, 1, 1),
PIN_FIELD_BASE(38, 38, IOCFG_LB_BASE, 0x30, 0x10, 5, 1),
};
static const struct mtk_pin_field_calc mt7987_pin_drv_range[] = {
PIN_FIELD_BASE(0, 0, IOCFG_RT2_BASE, 0x0, 0x10, 9, 3),
PIN_FIELD_BASE(1, 1, IOCFG_RT2_BASE, 0x0, 0x10, 6, 3),
PIN_FIELD_BASE(2, 2, IOCFG_RT2_BASE, 0x10, 0x10, 3, 3),
PIN_FIELD_BASE(3, 3, IOCFG_TL_BASE, 0x0, 0x10, 6, 3),
PIN_FIELD_BASE(4, 4, IOCFG_TL_BASE, 0x0, 0x10, 3, 3),
PIN_FIELD_BASE(5, 5, IOCFG_TL_BASE, 0x0, 0x10, 9, 3),
PIN_FIELD_BASE(6, 6, IOCFG_TL_BASE, 0x0, 0x10, 0, 3),
PIN_FIELD_BASE(7, 7, IOCFG_TL_BASE, 0x0, 0x10, 12, 3),
PIN_FIELD_BASE(8, 8, IOCFG_RB_BASE, 0x0, 0x10, 6, 3),
PIN_FIELD_BASE(9, 9, IOCFG_RB_BASE, 0x0, 0x10, 3, 3),
PIN_FIELD_BASE(10, 10, IOCFG_RB_BASE, 0x0, 0x10, 0, 3),
PIN_FIELD_BASE(11, 11, IOCFG_RB_BASE, 0x0, 0x10, 9, 3),
PIN_FIELD_BASE(12, 12, IOCFG_RB_BASE, 0x0, 0x10, 12, 3),
PIN_FIELD_BASE(13, 13, IOCFG_RT1_BASE, 0x0, 0x10, 0, 3),
PIN_FIELD_BASE(14, 14, IOCFG_RT1_BASE, 0x10, 0x10, 15, 3),
PIN_FIELD_BASE(15, 15, IOCFG_RT1_BASE, 0x0, 0x10, 9, 3),
PIN_FIELD_BASE(16, 16, IOCFG_RT1_BASE, 0x0, 0x10, 21, 3),
PIN_FIELD_BASE(17, 17, IOCFG_RT1_BASE, 0x0, 0x10, 18, 3),
PIN_FIELD_BASE(18, 18, IOCFG_RT1_BASE, 0x0, 0x10, 12, 3),
PIN_FIELD_BASE(19, 19, IOCFG_RT1_BASE, 0x0, 0x10, 15, 3),
PIN_FIELD_BASE(20, 20, IOCFG_RT1_BASE, 0x0, 0x10, 24, 3),
PIN_FIELD_BASE(21, 21, IOCFG_RT1_BASE, 0x0, 0x10, 27, 3),
PIN_FIELD_BASE(22, 22, IOCFG_RT1_BASE, 0x10, 0x10, 6, 3),
PIN_FIELD_BASE(23, 23, IOCFG_RT1_BASE, 0x10, 0x10, 3, 3),
PIN_FIELD_BASE(24, 24, IOCFG_RT1_BASE, 0x10, 0x10, 0, 3),
PIN_FIELD_BASE(25, 25, IOCFG_RT1_BASE, 0x10, 0x10, 9, 3),
PIN_FIELD_BASE(26, 26, IOCFG_RT1_BASE, 0x10, 0x10, 12, 3),
PIN_FIELD_BASE(27, 27, IOCFG_RT2_BASE, 0x0, 0x10, 27, 3),
PIN_FIELD_BASE(28, 28, IOCFG_RT2_BASE, 0x0, 0x10, 21, 3),
PIN_FIELD_BASE(29, 29, IOCFG_RT2_BASE, 0x0, 0x10, 24, 3),
PIN_FIELD_BASE(30, 30, IOCFG_RT2_BASE, 0x10, 0x10, 0, 3),
PIN_FIELD_BASE(31, 31, IOCFG_TL_BASE, 0x0, 0x10, 15, 3),
PIN_FIELD_BASE(32, 32, IOCFG_TL_BASE, 0x0, 0x10, 18, 3),
PIN_FIELD_BASE(33, 33, IOCFG_LB_BASE, 0x0, 0x10, 6, 3),
PIN_FIELD_BASE(34, 34, IOCFG_LB_BASE, 0x0, 0x10, 0, 3),
PIN_FIELD_BASE(35, 35, IOCFG_LB_BASE, 0x0, 0x10, 12, 3),
PIN_FIELD_BASE(36, 36, IOCFG_LB_BASE, 0x0, 0x10, 9, 3),
PIN_FIELD_BASE(37, 37, IOCFG_LB_BASE, 0x0, 0x10, 3, 3),
PIN_FIELD_BASE(38, 38, IOCFG_LB_BASE, 0x0, 0x10, 15, 3),
PIN_FIELD_BASE(39, 39, IOCFG_RT1_BASE, 0x0, 0x10, 3, 3),
PIN_FIELD_BASE(40, 40, IOCFG_RT1_BASE, 0x0, 0x10, 6, 3),
PIN_FIELD_BASE(41, 41, IOCFG_RT2_BASE, 0x0, 0x10, 0, 3),
PIN_FIELD_BASE(42, 42, IOCFG_RT2_BASE, 0x0, 0x10, 3, 3),
PIN_FIELD_BASE(43, 43, IOCFG_RT2_BASE, 0x0, 0x10, 12, 3),
PIN_FIELD_BASE(44, 44, IOCFG_RT2_BASE, 0x0, 0x10, 15, 3),
PIN_FIELD_BASE(45, 45, IOCFG_RT2_BASE, 0x0, 0x10, 18, 3),
PIN_FIELD_BASE(46, 46, IOCFG_TL_BASE, 0x0, 0x10, 27, 3),
PIN_FIELD_BASE(47, 47, IOCFG_TL_BASE, 0x10, 0x10, 0, 3),
PIN_FIELD_BASE(48, 48, IOCFG_TL_BASE, 0x0, 0x10, 21, 3),
PIN_FIELD_BASE(49, 49, IOCFG_TL_BASE, 0x0, 0x10, 24, 3),
};
static const struct mtk_pin_field_calc mt7987_pin_pupd_range[] = {
PIN_FIELD_BASE(0, 0, IOCFG_RT2_BASE, 0x30, 0x10, 3, 1),
PIN_FIELD_BASE(1, 1, IOCFG_RT2_BASE, 0x30, 0x10, 2, 1),
PIN_FIELD_BASE(2, 2, IOCFG_RT2_BASE, 0x30, 0x10, 11, 1),
PIN_FIELD_BASE(3, 3, IOCFG_TL_BASE, 0x30, 0x10, 2, 1),
PIN_FIELD_BASE(4, 4, IOCFG_TL_BASE, 0x30, 0x10, 1, 1),
PIN_FIELD_BASE(5, 5, IOCFG_TL_BASE, 0x30, 0x10, 3, 1),
PIN_FIELD_BASE(6, 6, IOCFG_TL_BASE, 0x30, 0x10, 0, 1),
PIN_FIELD_BASE(7, 7, IOCFG_TL_BASE, 0x30, 0x10, 4, 1),
PIN_FIELD_BASE(8, 8, IOCFG_RB_BASE, 0x20, 0x10, 2, 1),
PIN_FIELD_BASE(9, 9, IOCFG_RB_BASE, 0x20, 0x10, 1, 1),
PIN_FIELD_BASE(10, 10, IOCFG_RB_BASE, 0x20, 0x10, 0, 1),
PIN_FIELD_BASE(11, 11, IOCFG_RB_BASE, 0x20, 0x10, 3, 1),
PIN_FIELD_BASE(12, 12, IOCFG_RB_BASE, 0x20, 0x10, 4, 1),
PIN_FIELD_BASE(13, 13, IOCFG_RT1_BASE, 0x30, 0x10, 0, 1),
PIN_FIELD_BASE(14, 14, IOCFG_RT1_BASE, 0x30, 0x10, 15, 1),
PIN_FIELD_BASE(15, 15, IOCFG_RT1_BASE, 0x30, 0x10, 3, 1),
PIN_FIELD_BASE(16, 16, IOCFG_RT1_BASE, 0x30, 0x10, 7, 1),
PIN_FIELD_BASE(17, 17, IOCFG_RT1_BASE, 0x30, 0x10, 6, 1),
PIN_FIELD_BASE(18, 18, IOCFG_RT1_BASE, 0x30, 0x10, 4, 1),
PIN_FIELD_BASE(19, 19, IOCFG_RT1_BASE, 0x30, 0x10, 5, 1),
PIN_FIELD_BASE(20, 20, IOCFG_RT1_BASE, 0x30, 0x10, 8, 1),
PIN_FIELD_BASE(21, 21, IOCFG_RT1_BASE, 0x30, 0x10, 9, 1),
PIN_FIELD_BASE(22, 22, IOCFG_RT1_BASE, 0x30, 0x10, 12, 1),
PIN_FIELD_BASE(23, 23, IOCFG_RT1_BASE, 0x30, 0x10, 11, 1),
PIN_FIELD_BASE(24, 24, IOCFG_RT1_BASE, 0x30, 0x10, 10, 1),
PIN_FIELD_BASE(25, 25, IOCFG_RT1_BASE, 0x30, 0x10, 13, 1),
PIN_FIELD_BASE(26, 26, IOCFG_RT1_BASE, 0x30, 0x10, 14, 1),
PIN_FIELD_BASE(27, 27, IOCFG_RT2_BASE, 0x30, 0x10, 9, 1),
PIN_FIELD_BASE(28, 28, IOCFG_RT2_BASE, 0x30, 0x10, 7, 1),
PIN_FIELD_BASE(29, 29, IOCFG_RT2_BASE, 0x30, 0x10, 8, 1),
PIN_FIELD_BASE(30, 30, IOCFG_RT2_BASE, 0x30, 0x10, 10, 1),
PIN_FIELD_BASE(31, 31, IOCFG_TL_BASE, 0x30, 0x10, 5, 1),
PIN_FIELD_BASE(32, 32, IOCFG_TL_BASE, 0x30, 0x10, 6, 1),
PIN_FIELD_BASE(39, 39, IOCFG_RT1_BASE, 0x30, 0x10, 1, 1),
PIN_FIELD_BASE(40, 40, IOCFG_RT1_BASE, 0x30, 0x10, 2, 1),
PIN_FIELD_BASE(41, 41, IOCFG_RT2_BASE, 0x30, 0x10, 0, 1),
PIN_FIELD_BASE(42, 42, IOCFG_RT2_BASE, 0x30, 0x10, 1, 1),
PIN_FIELD_BASE(43, 43, IOCFG_RT2_BASE, 0x30, 0x10, 4, 1),
PIN_FIELD_BASE(44, 44, IOCFG_RT2_BASE, 0x30, 0x10, 5, 1),
PIN_FIELD_BASE(45, 45, IOCFG_RT2_BASE, 0x30, 0x10, 6, 1),
PIN_FIELD_BASE(46, 46, IOCFG_TL_BASE, 0x30, 0x10, 9, 1),
PIN_FIELD_BASE(47, 47, IOCFG_TL_BASE, 0x30, 0x10, 10, 1),
PIN_FIELD_BASE(48, 48, IOCFG_TL_BASE, 0x30, 0x10, 7, 1),
PIN_FIELD_BASE(49, 49, IOCFG_TL_BASE, 0x30, 0x10, 8, 1),
};
static const struct mtk_pin_field_calc mt7987_pin_r0_range[] = {
PIN_FIELD_BASE(0, 0, IOCFG_RT2_BASE, 0x40, 0x10, 3, 1),
PIN_FIELD_BASE(1, 1, IOCFG_RT2_BASE, 0x40, 0x10, 2, 1),
PIN_FIELD_BASE(2, 2, IOCFG_RT2_BASE, 0x40, 0x10, 11, 1),
PIN_FIELD_BASE(3, 3, IOCFG_TL_BASE, 0x40, 0x10, 2, 1),
PIN_FIELD_BASE(4, 4, IOCFG_TL_BASE, 0x40, 0x10, 1, 1),
PIN_FIELD_BASE(5, 5, IOCFG_TL_BASE, 0x40, 0x10, 3, 1),
PIN_FIELD_BASE(6, 6, IOCFG_TL_BASE, 0x40, 0x10, 0, 1),
PIN_FIELD_BASE(7, 7, IOCFG_TL_BASE, 0x40, 0x10, 4, 1),
PIN_FIELD_BASE(8, 8, IOCFG_RB_BASE, 0x30, 0x10, 2, 1),
PIN_FIELD_BASE(9, 9, IOCFG_RB_BASE, 0x30, 0x10, 1, 1),
PIN_FIELD_BASE(10, 10, IOCFG_RB_BASE, 0x30, 0x10, 0, 1),
PIN_FIELD_BASE(11, 11, IOCFG_RB_BASE, 0x30, 0x10, 3, 1),
PIN_FIELD_BASE(12, 12, IOCFG_RB_BASE, 0x30, 0x10, 4, 1),
PIN_FIELD_BASE(13, 13, IOCFG_RT1_BASE, 0x40, 0x10, 0, 1),
PIN_FIELD_BASE(14, 14, IOCFG_RT1_BASE, 0x40, 0x10, 15, 1),
PIN_FIELD_BASE(15, 15, IOCFG_RT1_BASE, 0x40, 0x10, 3, 1),
PIN_FIELD_BASE(16, 16, IOCFG_RT1_BASE, 0x40, 0x10, 7, 1),
PIN_FIELD_BASE(17, 17, IOCFG_RT1_BASE, 0x40, 0x10, 6, 1),
PIN_FIELD_BASE(18, 18, IOCFG_RT1_BASE, 0x40, 0x10, 4, 1),
PIN_FIELD_BASE(19, 19, IOCFG_RT1_BASE, 0x40, 0x10, 5, 1),
PIN_FIELD_BASE(20, 20, IOCFG_RT1_BASE, 0x40, 0x10, 8, 1),
PIN_FIELD_BASE(21, 21, IOCFG_RT1_BASE, 0x40, 0x10, 9, 1),
PIN_FIELD_BASE(22, 22, IOCFG_RT1_BASE, 0x40, 0x10, 12, 1),
PIN_FIELD_BASE(23, 23, IOCFG_RT1_BASE, 0x40, 0x10, 11, 1),
PIN_FIELD_BASE(24, 24, IOCFG_RT1_BASE, 0x40, 0x10, 10, 1),
PIN_FIELD_BASE(25, 25, IOCFG_RT1_BASE, 0x40, 0x10, 13, 1),
PIN_FIELD_BASE(26, 26, IOCFG_RT1_BASE, 0x40, 0x10, 14, 1),
PIN_FIELD_BASE(27, 27, IOCFG_RT2_BASE, 0x40, 0x10, 9, 1),
PIN_FIELD_BASE(28, 28, IOCFG_RT2_BASE, 0x40, 0x10, 7, 1),
PIN_FIELD_BASE(29, 29, IOCFG_RT2_BASE, 0x40, 0x10, 8, 1),
PIN_FIELD_BASE(30, 30, IOCFG_RT2_BASE, 0x40, 0x10, 10, 1),
PIN_FIELD_BASE(31, 31, IOCFG_TL_BASE, 0x40, 0x10, 5, 1),
PIN_FIELD_BASE(32, 32, IOCFG_TL_BASE, 0x40, 0x10, 6, 1),
PIN_FIELD_BASE(39, 39, IOCFG_RT1_BASE, 0x40, 0x10, 1, 1),
PIN_FIELD_BASE(40, 40, IOCFG_RT1_BASE, 0x40, 0x10, 2, 1),
PIN_FIELD_BASE(41, 41, IOCFG_RT2_BASE, 0x40, 0x10, 0, 1),
PIN_FIELD_BASE(42, 42, IOCFG_RT2_BASE, 0x40, 0x10, 1, 1),
PIN_FIELD_BASE(43, 43, IOCFG_RT2_BASE, 0x40, 0x10, 4, 1),
PIN_FIELD_BASE(44, 44, IOCFG_RT2_BASE, 0x40, 0x10, 5, 1),
PIN_FIELD_BASE(45, 45, IOCFG_RT2_BASE, 0x40, 0x10, 6, 1),
PIN_FIELD_BASE(46, 46, IOCFG_TL_BASE, 0x40, 0x10, 9, 1),
PIN_FIELD_BASE(47, 47, IOCFG_TL_BASE, 0x40, 0x10, 10, 1),
PIN_FIELD_BASE(48, 48, IOCFG_TL_BASE, 0x40, 0x10, 7, 1),
PIN_FIELD_BASE(49, 49, IOCFG_TL_BASE, 0x40, 0x10, 8, 1),
};
static const struct mtk_pin_field_calc mt7987_pin_r1_range[] = {
PIN_FIELD_BASE(0, 0, IOCFG_RT2_BASE, 0x50, 0x10, 3, 1),
PIN_FIELD_BASE(1, 1, IOCFG_RT2_BASE, 0x50, 0x10, 2, 1),
PIN_FIELD_BASE(2, 2, IOCFG_RT2_BASE, 0x50, 0x10, 11, 1),
PIN_FIELD_BASE(3, 3, IOCFG_TL_BASE, 0x50, 0x10, 2, 1),
PIN_FIELD_BASE(4, 4, IOCFG_TL_BASE, 0x50, 0x10, 1, 1),
PIN_FIELD_BASE(5, 5, IOCFG_TL_BASE, 0x50, 0x10, 3, 1),
PIN_FIELD_BASE(6, 6, IOCFG_TL_BASE, 0x50, 0x10, 0, 1),
PIN_FIELD_BASE(7, 7, IOCFG_TL_BASE, 0x50, 0x10, 4, 1),
PIN_FIELD_BASE(8, 8, IOCFG_RB_BASE, 0x40, 0x10, 2, 1),
PIN_FIELD_BASE(9, 9, IOCFG_RB_BASE, 0x40, 0x10, 1, 1),
PIN_FIELD_BASE(10, 10, IOCFG_RB_BASE, 0x40, 0x10, 0, 1),
PIN_FIELD_BASE(11, 11, IOCFG_RB_BASE, 0x40, 0x10, 3, 1),
PIN_FIELD_BASE(12, 12, IOCFG_RB_BASE, 0x40, 0x10, 4, 1),
PIN_FIELD_BASE(13, 13, IOCFG_RT1_BASE, 0x50, 0x10, 0, 1),
PIN_FIELD_BASE(14, 14, IOCFG_RT1_BASE, 0x50, 0x10, 15, 1),
PIN_FIELD_BASE(15, 15, IOCFG_RT1_BASE, 0x50, 0x10, 3, 1),
PIN_FIELD_BASE(16, 16, IOCFG_RT1_BASE, 0x50, 0x10, 7, 1),
PIN_FIELD_BASE(17, 17, IOCFG_RT1_BASE, 0x50, 0x10, 6, 1),
PIN_FIELD_BASE(18, 18, IOCFG_RT1_BASE, 0x50, 0x10, 4, 1),
PIN_FIELD_BASE(19, 19, IOCFG_RT1_BASE, 0x50, 0x10, 5, 1),
PIN_FIELD_BASE(20, 20, IOCFG_RT1_BASE, 0x50, 0x10, 8, 1),
PIN_FIELD_BASE(21, 21, IOCFG_RT1_BASE, 0x50, 0x10, 9, 1),
PIN_FIELD_BASE(22, 22, IOCFG_RT1_BASE, 0x50, 0x10, 12, 1),
PIN_FIELD_BASE(23, 23, IOCFG_RT1_BASE, 0x50, 0x10, 11, 1),
PIN_FIELD_BASE(24, 24, IOCFG_RT1_BASE, 0x50, 0x10, 10, 1),
PIN_FIELD_BASE(25, 25, IOCFG_RT1_BASE, 0x50, 0x10, 13, 1),
PIN_FIELD_BASE(26, 26, IOCFG_RT1_BASE, 0x50, 0x10, 14, 1),
PIN_FIELD_BASE(27, 27, IOCFG_RT2_BASE, 0x50, 0x10, 9, 1),
PIN_FIELD_BASE(28, 28, IOCFG_RT2_BASE, 0x50, 0x10, 7, 1),
PIN_FIELD_BASE(29, 29, IOCFG_RT2_BASE, 0x50, 0x10, 8, 1),
PIN_FIELD_BASE(30, 30, IOCFG_RT2_BASE, 0x50, 0x10, 10, 1),
PIN_FIELD_BASE(31, 31, IOCFG_TL_BASE, 0x50, 0x10, 5, 1),
PIN_FIELD_BASE(32, 32, IOCFG_TL_BASE, 0x50, 0x10, 6, 1),
PIN_FIELD_BASE(39, 39, IOCFG_RT1_BASE, 0x50, 0x10, 1, 1),
PIN_FIELD_BASE(40, 40, IOCFG_RT1_BASE, 0x50, 0x10, 2, 1),
PIN_FIELD_BASE(41, 41, IOCFG_RT2_BASE, 0x50, 0x10, 0, 1),
PIN_FIELD_BASE(42, 42, IOCFG_RT2_BASE, 0x50, 0x10, 1, 1),
PIN_FIELD_BASE(43, 43, IOCFG_RT2_BASE, 0x50, 0x10, 4, 1),
PIN_FIELD_BASE(44, 44, IOCFG_RT2_BASE, 0x50, 0x10, 5, 1),
PIN_FIELD_BASE(45, 45, IOCFG_RT2_BASE, 0x50, 0x10, 6, 1),
PIN_FIELD_BASE(46, 46, IOCFG_TL_BASE, 0x50, 0x10, 9, 1),
PIN_FIELD_BASE(47, 47, IOCFG_TL_BASE, 0x50, 0x10, 10, 1),
PIN_FIELD_BASE(48, 48, IOCFG_TL_BASE, 0x50, 0x10, 7, 1),
PIN_FIELD_BASE(49, 49, IOCFG_TL_BASE, 0x50, 0x10, 8, 1),
};
static const unsigned int mt7987_pull_type[] = {
MTK_PULL_PUPD_R1R0_TYPE,/*0*/ MTK_PULL_PUPD_R1R0_TYPE,/*1*/
MTK_PULL_PUPD_R1R0_TYPE,/*2*/ MTK_PULL_PUPD_R1R0_TYPE,/*3*/
MTK_PULL_PUPD_R1R0_TYPE,/*4*/ MTK_PULL_PUPD_R1R0_TYPE,/*5*/
MTK_PULL_PUPD_R1R0_TYPE,/*6*/ MTK_PULL_PUPD_R1R0_TYPE,/*7*/
MTK_PULL_PUPD_R1R0_TYPE,/*8*/ MTK_PULL_PUPD_R1R0_TYPE,/*9*/
MTK_PULL_PUPD_R1R0_TYPE,/*10*/ MTK_PULL_PUPD_R1R0_TYPE,/*11*/
MTK_PULL_PUPD_R1R0_TYPE,/*12*/ MTK_PULL_PUPD_R1R0_TYPE,/*13*/
MTK_PULL_PUPD_R1R0_TYPE,/*14*/ MTK_PULL_PUPD_R1R0_TYPE,/*15*/
MTK_PULL_PUPD_R1R0_TYPE,/*16*/ MTK_PULL_PUPD_R1R0_TYPE,/*17*/
MTK_PULL_PUPD_R1R0_TYPE,/*18*/ MTK_PULL_PUPD_R1R0_TYPE,/*19*/
MTK_PULL_PUPD_R1R0_TYPE,/*20*/ MTK_PULL_PUPD_R1R0_TYPE,/*21*/
MTK_PULL_PUPD_R1R0_TYPE,/*22*/ MTK_PULL_PUPD_R1R0_TYPE,/*23*/
MTK_PULL_PUPD_R1R0_TYPE,/*24*/ MTK_PULL_PUPD_R1R0_TYPE,/*25*/
MTK_PULL_PUPD_R1R0_TYPE,/*26*/ MTK_PULL_PUPD_R1R0_TYPE,/*27*/
MTK_PULL_PUPD_R1R0_TYPE,/*28*/ MTK_PULL_PUPD_R1R0_TYPE,/*29*/
MTK_PULL_PUPD_R1R0_TYPE,/*30*/ MTK_PULL_PUPD_R1R0_TYPE,/*31*/
MTK_PULL_PUPD_R1R0_TYPE,/*32*/ MTK_PULL_PU_PD_TYPE,/*33*/
MTK_PULL_PU_PD_TYPE,/*34*/ MTK_PULL_PU_PD_TYPE,/*35*/
MTK_PULL_PU_PD_TYPE,/*36*/ MTK_PULL_PU_PD_TYPE,/*37*/
MTK_PULL_PU_PD_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/
MTK_PULL_PUPD_R1R0_TYPE,/*40*/ MTK_PULL_PUPD_R1R0_TYPE,/*41*/
MTK_PULL_PUPD_R1R0_TYPE,/*42*/ MTK_PULL_PUPD_R1R0_TYPE,/*43*/
MTK_PULL_PUPD_R1R0_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/
MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/
MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/
};
static const struct mtk_pin_reg_calc mt7987_reg_cals[] = {
[PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7987_pin_mode_range),
[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7987_pin_dir_range),
[PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7987_pin_di_range),
[PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7987_pin_do_range),
[PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7987_pin_smt_range),
[PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7987_pin_ies_range),
[PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7987_pin_pu_range),
[PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7987_pin_pd_range),
[PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7987_pin_drv_range),
[PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7987_pin_pupd_range),
[PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7987_pin_r0_range),
[PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7987_pin_r1_range),
};
static const struct mtk_pin_desc mt7987_pins[] = {
MT7987_PIN(0, "GPIO_WPS"),
MT7987_PIN(1, "GPIO_RESET"),
MT7987_PIN(2, "SYS_WATCHDOG"),
MT7987_PIN(3, "JTAG_JTDO"),
MT7987_PIN(4, "JTAG_JTDI"),
MT7987_PIN(5, "JTAG_JTMS"),
MT7987_PIN(6, "JTAG_JTCLK"),
MT7987_PIN(7, "JTAG_JTRST_N"),
MT7987_PIN(8, "PCM_DTX_I2S_DOUT"),
MT7987_PIN(9, "PCM_DRX_I2S_DIN"),
MT7987_PIN(10, "PCM_CLK_I2S_BCLK"),
MT7987_PIN(11, "PCM_FS_I2S_LRCK"),
MT7987_PIN(12, "PCM_MCK_I2S_MCLK"),
MT7987_PIN(13, "PWM0"),
MT7987_PIN(14, "USB_VBUS"),
MT7987_PIN(15, "SPI0_CLK"),
MT7987_PIN(16, "SPI0_MOSI"),
MT7987_PIN(17, "SPI0_MISO"),
MT7987_PIN(18, "SPI0_CS"),
MT7987_PIN(19, "SPI0_HOLD"),
MT7987_PIN(20, "SPI0_WP"),
MT7987_PIN(21, "SPI1_CLK"),
MT7987_PIN(22, "SPI1_MOSI"),
MT7987_PIN(23, "SPI1_MISO"),
MT7987_PIN(24, "SPI1_CS"),
MT7987_PIN(25, "SPI2_CLK"),
MT7987_PIN(26, "SPI2_MOSI"),
MT7987_PIN(27, "SPI2_MISO"),
MT7987_PIN(28, "SPI2_CS"),
MT7987_PIN(29, "SPI2_HOLD"),
MT7987_PIN(30, "SPI2_WP"),
MT7987_PIN(31, "UART0_RXD"),
MT7987_PIN(32, "UART0_TXD"),
MT7987_PIN(33, "PCIE_PERESET_N_0"),
MT7987_PIN(34, "PCIE_CLK_REQ_0"),
MT7987_PIN(35, "PCIE_WAKE_N_0"),
MT7987_PIN(36, "PCIE_PERESET_N_1"),
MT7987_PIN(37, "PCIE_CLK_REQ_1"),
MT7987_PIN(38, "PCIE_WAKE_N_1"),
MT7987_PIN(39, "SMI_MDC"),
MT7987_PIN(40, "SMI_MDIO"),
MT7987_PIN(41, "GBE_INT"),
MT7987_PIN(42, "GBE_RESET"),
MT7987_PIN(43, "I2C_SCLK"),
MT7987_PIN(44, "I2C_SDATA"),
MT7987_PIN(45, "2P5G_LED0"),
MT7987_PIN(46, "UART1_RXD"),
MT7987_PIN(47, "UART1_TXD"),
MT7987_PIN(48, "UART1_CTS"),
MT7987_PIN(49, "UART1_RTS"),
};
/* watchdog */
static const int mt7987_watchdog_pins[] = {2};
static const int mt7987_watchdog_funcs[] = {1};
/* jtag */
static const int mt7987_jtag_pins[] = {3, 4, 5, 6, 7};
static const int mt7987_jtag_funcs[] = {1, 1, 1, 1, 1};
/* pcm */
static const int mt7987_pcm0_0_pins[] = {3, 4, 5, 6, 7};
static const int mt7987_pcm0_0_funcs[] = {2, 2, 2, 2, 2};
static const int mt7987_pcm0_1_pins[] = {8, 9, 10, 11, 12};
static const int mt7987_pcm0_1_funcs[] = {1, 1, 1, 1, 1};
/* uart */
static const int mt7987_uart0_pins[] = {31, 32};
static const int mt7987_uart0_funcs[] = {1, 1};
static const int mt7987_uart1_0_pins[] = {3, 4, 5, 6};
static const int mt7987_uart1_0_funcs[] = {3, 3, 3, 3};
static const int mt7987_uart1_1_pins[] = {21, 22, 23, 24};
static const int mt7987_uart1_1_funcs[] = {3, 3, 3, 3};
static const int mt7987_uart1_2_pins[] = {46, 47, 48, 49};
static const int mt7987_uart1_2_funcs[] = {1, 1, 1, 1};
static const int mt7987_uart2_0_pins[] = {8, 9, 10, 11};
static const int mt7987_uart2_0_funcs[] = {2, 2, 2, 2};
static const int mt7987_uart2_1_pins[] = {25, 26, 27, 28};
static const int mt7987_uart2_1_funcs[] = {2, 2, 2, 2};
/* pwm */
static const int mt7987_pwm0_pins[] = {13};
static const int mt7987_pwm0_funcs[] = {1};
static const int mt7987_pwm1_0_pins[] = {7};
static const int mt7987_pwm1_0_funcs[] = {3};
static const int mt7987_pwm1_1_pins[] = {43};
static const int mt7987_pwm1_1_funcs[] = {2};
static const int mt7987_pwm2_0_pins[] = {12};
static const int mt7987_pwm2_0_funcs[] = {2};
static const int mt7987_pwm2_1_pins[] = {44};
static const int mt7987_pwm2_1_funcs[] = {2};
/* vbus */
static const int mt7987_drv_vbus_p1_pins[] = {14};
static const int mt7987_drv_vbus_p1_funcs[] = {1};
static const int mt7987_drv_vbus_pins[] = {48};
static const int mt7987_drv_vbus_funcs[] = {3};
/* 2p5gbe_led */
static const int mt7987_2p5gbe_led0_pins[] = {45};
static const int mt7987_2p5gbe_led0_funcs[] = {1};
static const int mt7987_2p5gbe_led1_0_pins[] = {13};
static const int mt7987_2p5gbe_led1_0_funcs[] = {2};
static const int mt7987_2p5gbe_led1_1_pins[] = {49};
static const int mt7987_2p5gbe_led1_1_funcs[] = {3};
/* mdc, mdio */
static const int mt7987_2p5g_ext_mdc_mdio_pins[] = {23, 24};
static const int mt7987_2p5g_ext_mdc_mdio_funcs[] = {4, 4};
static const int mt7987_mdc_mdio_pins[] = {39, 40};
static const int mt7987_mdc_mdio_funcs[] = {1, 1};
/* spi */
static const int mt7987_spi0_pins[] = {15, 16, 17, 18};
static const int mt7987_spi0_funcs[] = {1, 1, 1, 1};
static const int mt7987_spi0_wp_hold_pins[] = {19, 20};
static const int mt7987_spi0_wp_hold_funcs[] = {1, 1};
static const int mt7987_spi1_pins[] = {21, 22, 23, 24};
static const int mt7987_spi1_funcs[] = {1, 1, 1, 1};
static const int mt7987_spi1_1_pins[] = {46, 47, 48, 49};
static const int mt7987_spi1_1_funcs[] = {2, 2, 2, 2};
static const int mt7987_spi2_pins[] = {25, 26, 27, 28};
static const int mt7987_spi2_funcs[] = {1, 1, 1, 1};
static const int mt7987_spi2_wp_hold_pins[] = {29, 30};
static const int mt7987_spi2_wp_hold_funcs[] = {1, 1};
/* emmc */
static const int mt7987_emmc_45_pins[] = {14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
static const int mt7987_emmc_45_funcs[] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
/* sd */
static const int mt7987_sd_pins[] = {15, 16, 17, 18, 23, 24};
static const int mt7987_sd_funcs[] = {2, 2, 2, 2, 2, 2};
/* i2c */
static const int mt7987_i2c0_0_pins[] = {29, 30};
static const int mt7987_i2c0_0_funcs[] = {2, 2};
static const int mt7987_i2c0_1_pins[] = {39, 40};
static const int mt7987_i2c0_1_funcs[] = {2, 2};
static const int mt7987_i2c0_2_pins[] = {43, 44};
static const int mt7987_i2c0_2_funcs[] = {1, 1};
/* pcie */
static const int mt7987_pcie0_pereset_pins[] = {33};
static const int mt7987_pcie0_pereset_funcs[] = {1};
static const int mt7987_pcie0_clkreq_pins[] = {34};
static const int mt7987_pcie0_clkreq_funcs[] = {1};
static const int mt7987_pcie0_wake_pins[] = {35};
static const int mt7987_pcie0_wake_funcs[] = {1};
static const int mt7987_pcie1_pereset_pins[] = {36};
static const int mt7987_pcie1_pereset_funcs[] = {1};
static const int mt7987_pcie1_clkreq_pins[] = {37};
static const int mt7987_pcie1_clkreq_funcs[] = {1};
static const int mt7987_pcie1_wake_pins[] = {38};
static const int mt7987_pcie1_wake_funcs[] = {1};
static const int mt7987_pcie_phy_i2c_pins[] = {43, 44};
static const int mt7987_pcie_phy_i2c_funcs[] = {3, 3};
/* snfi */
static const int mt7987_snfi_pins[] = {25, 26, 27, 28, 29, 30};
static const int mt7987_snfi_funcs[] = {3, 3, 3, 3, 3, 3};
/*
* - int hsgmii :
* For pin41 and pin46, they now can only be used as gpio mode for polling
* event. Hence, there's no need to open their pinctrl setting.
* - dfd, udi :
* Due to dfd & udi functions are only used as detection pins for cpu during
* dvt testing stage, we also remove their pinctrl setting.
*/
//static mt7987_hsgmii_pins[] = {};
//static mt7987_hsgmii_functs[] = {};
//static mt7987_dfd_pins[] = {};
//static mt7987_dfd_functs[] = {};
//static mt7987_udi_pins[] = {};
//static mt7987_udi_functs[] = {};
static const struct group_desc mt7987_groups[] = {
PINCTRL_PIN_GROUP("watchdog", mt7987_watchdog),
PINCTRL_PIN_GROUP("jtag", mt7987_jtag),
PINCTRL_PIN_GROUP("pcm0_0", mt7987_pcm0_0),
PINCTRL_PIN_GROUP("pcm0_1", mt7987_pcm0_1),
PINCTRL_PIN_GROUP("uart0", mt7987_uart0),
PINCTRL_PIN_GROUP("uart1_0", mt7987_uart1_0),
PINCTRL_PIN_GROUP("uart1_1", mt7987_uart1_1),
PINCTRL_PIN_GROUP("uart1_2", mt7987_uart1_2),
PINCTRL_PIN_GROUP("uart2_0", mt7987_uart2_0),
PINCTRL_PIN_GROUP("uart2_1", mt7987_uart2_1),
PINCTRL_PIN_GROUP("pwm0", mt7987_pwm0),
PINCTRL_PIN_GROUP("pwm1_0", mt7987_pwm1_0),
PINCTRL_PIN_GROUP("pwm1_1", mt7987_pwm1_1),
PINCTRL_PIN_GROUP("pwm2_0", mt7987_pwm2_0),
PINCTRL_PIN_GROUP("pwm2_1", mt7987_pwm2_1),
PINCTRL_PIN_GROUP("drv_vbus_p1", mt7987_drv_vbus_p1),
PINCTRL_PIN_GROUP("drv_vbus", mt7987_drv_vbus),
PINCTRL_PIN_GROUP("2p5gbe_led0", mt7987_2p5gbe_led0),
PINCTRL_PIN_GROUP("2p5gbe_led1_0", mt7987_2p5gbe_led1_0),
PINCTRL_PIN_GROUP("2p5gbe_led1_1", mt7987_2p5gbe_led1_1),
PINCTRL_PIN_GROUP("2p5g_ext_mdc_mdio", mt7987_2p5g_ext_mdc_mdio),
PINCTRL_PIN_GROUP("mdc_mdio", mt7987_mdc_mdio),
PINCTRL_PIN_GROUP("spi0", mt7987_spi0),
PINCTRL_PIN_GROUP("spi0_wp_hold", mt7987_spi0_wp_hold),
PINCTRL_PIN_GROUP("spi1", mt7987_spi1),
PINCTRL_PIN_GROUP("spi1_1", mt7987_spi1_1),
PINCTRL_PIN_GROUP("spi2", mt7987_spi2),
PINCTRL_PIN_GROUP("spi2_wp_hold", mt7987_spi2_wp_hold),
PINCTRL_PIN_GROUP("emmc_45", mt7987_emmc_45),
PINCTRL_PIN_GROUP("sd", mt7987_sd),
PINCTRL_PIN_GROUP("i2c0_0", mt7987_i2c0_0),
PINCTRL_PIN_GROUP("i2c0_1", mt7987_i2c0_1),
PINCTRL_PIN_GROUP("i2c0_2", mt7987_i2c0_2),
PINCTRL_PIN_GROUP("pcie0_pereset", mt7987_pcie0_pereset),
PINCTRL_PIN_GROUP("pcie0_clkreq", mt7987_pcie0_clkreq),
PINCTRL_PIN_GROUP("pcie0_wake", mt7987_pcie0_wake),
PINCTRL_PIN_GROUP("pcie1_pereset", mt7987_pcie1_pereset),
PINCTRL_PIN_GROUP("pcie1_clkreq", mt7987_pcie1_clkreq),
PINCTRL_PIN_GROUP("pcie1_wake", mt7987_pcie1_wake),
PINCTRL_PIN_GROUP("pcie1_pcie_phy_i2c", mt7987_pcie_phy_i2c),
PINCTRL_PIN_GROUP("snfi", mt7987_snfi),
};
static const char *const mt7987_wdt_groups[] = {"watchdog",};
static const char *const mt7987_jtag_groups[] = {"jtag",};
static const char *const mt7987_pcm_groups[] = {"pcm0_0", "pcm0_1"};
static const char *const mt7987_uart_groups[] = {"uart0", "uart1_0", "uart1_1",
"uart1_2", "uart2_0", "uart2_1",};
static const char *const mt7987_pwm_groups[] = {"pwm0", "pwm1_0", "pwm1_1", "pwm2_0",
"pwm2_1",};
static const char *const mt7987_usb_groups[] = {"drv_vbus_p1", "drv_vbus",};
static const char *const mt7987_led_groups[] = {"2p5gbe_led0", "2p5gbe_led1_0",
"2p5gbe_led1_1",};
static const char *const mt7987_ethernet_groups[] = {"2p5g_ext_mdc_mdio", "mdc_mdio",};
static const char *const mt7987_spi_groups[] = {"spi0", "spi0_wp_hold", "spi1",
"spi1_1", "spi2", "spi2_wp_hold",};
static const char *const mt7987_flash_groups[] = {"emmc_45", "snfi", "sd"};
static const char *const mt7987_i2c_groups[] = {"i2c0_0", "i2c0_1", "i2c0_2",};
static const char *const mt7987_pcie_groups[] = {"pcie_phy_i2c", "pcie0_pereset",
"pcie0_clkreq", "pcie0_wake",
"pcie1_pereset", "pcie1_clkreq",
"pcie1_wake",};
static const char *const mt7987_i2s_groups[] = {"pcm0_0", "pcm0_1"};
static const struct function_desc mt7987_functions[] = {
{"wdt", mt7987_wdt_groups, ARRAY_SIZE(mt7987_wdt_groups)},
{"jtag", mt7987_jtag_groups, ARRAY_SIZE(mt7987_jtag_groups)},
{"pcm", mt7987_pcm_groups, ARRAY_SIZE(mt7987_pcm_groups)},
{"uart", mt7987_uart_groups, ARRAY_SIZE(mt7987_uart_groups)},
{"pwm", mt7987_pwm_groups, ARRAY_SIZE(mt7987_pwm_groups)},
{"usb", mt7987_usb_groups, ARRAY_SIZE(mt7987_usb_groups)},
{"led", mt7987_led_groups, ARRAY_SIZE(mt7987_led_groups)},
{"eth", mt7987_ethernet_groups, ARRAY_SIZE(mt7987_ethernet_groups)},
{"spi", mt7987_spi_groups, ARRAY_SIZE(mt7987_spi_groups)},
{"flash", mt7987_flash_groups, ARRAY_SIZE(mt7987_flash_groups)},
{"i2c", mt7987_i2c_groups, ARRAY_SIZE(mt7987_i2c_groups)},
{"pcie", mt7987_pcie_groups, ARRAY_SIZE(mt7987_pcie_groups)},
{"i2s", mt7987_i2s_groups, ARRAY_SIZE(mt7987_i2s_groups)},
};
static const struct mtk_eint_hw mt7987_eint_hw = {
.port_mask = 7,
.ports = 7,
.ap_num = ARRAY_SIZE(mt7987_pins),
.db_cnt = 16,
};
static const char * const mt7987_pinctrl_register_base_names[] = {
"gpio_base", "iocfg_rb_base", "iocfg_lb_base", "iocfg_rt1_base",
"iocfg_rt2_base", "iocfg_tl_base",
};
static struct mtk_pin_soc mt7987_data = {
.reg_cal = mt7987_reg_cals,
.pins = mt7987_pins,
.npins = ARRAY_SIZE(mt7987_pins),
.grps = mt7987_groups,
.ngrps = ARRAY_SIZE(mt7987_groups),
.funcs = mt7987_functions,
.nfuncs = ARRAY_SIZE(mt7987_functions),
.eint_hw = &mt7987_eint_hw,
.gpio_m = 0,
.ies_present = false,
.base_names = mt7987_pinctrl_register_base_names,
.nbase_names = ARRAY_SIZE(mt7987_pinctrl_register_base_names),
.bias_disable_set = mtk_pinconf_bias_disable_set,
.bias_disable_get = mtk_pinconf_bias_disable_get,
.bias_set = mtk_pinconf_bias_set,
.bias_get = mtk_pinconf_bias_get,
.pull_type = mt7987_pull_type,
.bias_set_combo = mtk_pinconf_bias_set_combo,
.bias_get_combo = mtk_pinconf_bias_get_combo,
.drive_set = mtk_pinconf_drive_set_rev1,
.drive_get = mtk_pinconf_drive_get_rev1,
.adv_pull_get = mtk_pinconf_adv_pull_get,
.adv_pull_set = mtk_pinconf_adv_pull_set,
};
static const struct of_device_id mt7987_pinctrl_of_match[] = {
{
.compatible = "mediatek,mt7987-pinctrl",
},
{}
};
static int mt7987_pinctrl_probe(struct platform_device *pdev)
{
return mtk_moore_pinctrl_probe(pdev, &mt7987_data);
}
static struct platform_driver mt7987_pinctrl_driver = {
.driver = {
.name = "mt7987-pinctrl",
.of_match_table = mt7987_pinctrl_of_match,
},
.probe = mt7987_pinctrl_probe,
};
static int __init mt7987_pinctrl_init(void)
{
return platform_driver_register(&mt7987_pinctrl_driver);
}
arch_initcall(mt7987_pinctrl_init);

View File

@@ -23,36 +23,10 @@
#include <linux/string.h>
#include <linux/thermal.h>
#include "soc_temp_lvts.h"
#include "../thermal_hwmon.h"
/*
* Definition or macro function
*/
#define STOP_COUNTING_V6 (DEVICE_WRITE | RG_TSFM_CTRL_0 << 8 | 0x00)
#define SET_RG_TSFM_LPDLY_V6 (DEVICE_WRITE | RG_TSFM_CTRL_4 << 8 | 0xA6)
#define SET_COUNTING_WINDOW_20US1_V6 (DEVICE_WRITE | RG_TSFM_CTRL_2 << 8 | 0x00)
#define SET_COUNTING_WINDOW_20US2_V6 (DEVICE_WRITE | RG_TSFM_CTRL_1 << 8 | 0x20)
#define TOGGLE_TSDIV_EN_AND_TSVCO_TG_1_V6 \
(DEVICE_WRITE | RG_TSV2F_CTRL_0 << 8 | 0xC7)
#define TOGGLE_TSDIV_EN_AND_TSVCO_TG_2_V6 \
(DEVICE_WRITE | RG_TSV2F_CTRL_0 << 8 | 0xCE)
#define SET_TS_EN_V6 (DEVICE_WRITE | RG_TSV2F_CTRL_0 << 8 | 0xC7)
#define SET_TSBG_CHOP_EN_V6 (DEVICE_WRITE | RG_TSV2F_CTRL_1 << 8 | 0x8D)
#define SET_TS_RSV_V6 (DEVICE_WRITE | RG_TSV2F_CTRL_4 << 8 | 0x7C)
#define SET_TSBG_RSV_V6 (DEVICE_WRITE | RG_TSV2F_CTRL_2 << 8 | 0xA8)
#define SET_STR_EN_V6 (DEVICE_WRITE | RG_TSV2F_CTRL_3 << 8 | 0x04)
#define SET_MANUAL_RCK_V6 (DEVICE_WRITE | RG_TSV2F_CTRL_6 << 8 | 0x00)
#define SET_RG_TSV2F_RSV_V6 (DEVICE_WRITE | RG_TSV2F_CTRL_3 << 8 | 0x0C)
#define SELECT_SENSOR_RCK_V6(id) (DEVICE_WRITE | RG_TSV2F_CTRL_5 << 8 | (id))
#define SET_DEVICE_SINGLE_MODE_V6 (DEVICE_WRITE | RG_TSFM_CTRL_3 << 8 | 0x78)
#define KICK_OFF_RCK_COUNTING_V6 (DEVICE_WRITE | RG_TSFM_CTRL_0 << 8 | 0x02)
#define GET_RCK_COUNT_DATA_V6 (DEVICE_WRITE | RG_TSFM_DATA_0 << 8 | 0x02)
#define SET_SENSOR_NO_RCK_V6(id) \
(DEVICE_WRITE | RG_TSV2F_CTRL_5 << 8 | 0x10 | (id))
#define SET_DEVICE_LOW_POWER_SINGLE_MODE_V6 \
(DEVICE_WRITE | RG_TSFM_CTRL_3 << 8 | 0xB8)
#define STOP_COUNTING_V5 (DEVICE_WRITE | RG_TSFM_CTRL_0 << 8 | 0x00)
#define SET_RG_TSFM_LPDLY_V5 (DEVICE_WRITE | RG_TSFM_CTRL_4 << 8 | 0xA6)
#define SET_COUNTING_WINDOW_20US1_V5 (DEVICE_WRITE | RG_TSFM_CTRL_2 << 8 | 0x00)
@@ -937,8 +911,6 @@ static int lvts_register_thermal_zones(struct lvts_data *lvts_data)
lvts_close(lvts_data);
return ret;
}
thermal_add_hwmon_sysfs(tzdev);
}
return 0;
@@ -1262,105 +1234,6 @@ static int device_read_count_rc_n_v5(struct lvts_data *lvts_data)
return 0;
}
/*
* LVTS v6 common code
*/
static void device_enable_and_init_v6(struct lvts_data *lvts_data)
{
unsigned int i;
for (i = 0; i < lvts_data->num_tc; i++) {
lvts_write_device(lvts_data, STOP_COUNTING_V6, i);
lvts_write_device(lvts_data, SET_COUNTING_WINDOW_20US2_V6, i);
lvts_write_device(lvts_data, SET_COUNTING_WINDOW_20US1_V6, i);
lvts_write_device(lvts_data, SET_RG_TSFM_LPDLY_V6, i);
lvts_write_device(lvts_data, SET_TS_EN_V6, i);
lvts_write_device(lvts_data, SET_TSBG_CHOP_EN_V6, i);
lvts_write_device(lvts_data, SET_TS_RSV_V6, i);
lvts_write_device(lvts_data, SET_TSBG_RSV_V6, i);
lvts_write_device(lvts_data, TOGGLE_TSDIV_EN_AND_TSVCO_TG_2_V6,
i);
lvts_write_device(lvts_data, TOGGLE_TSDIV_EN_AND_TSVCO_TG_1_V6,
i);
lvts_write_device(lvts_data, SET_STR_EN_V6, i);
}
lvts_data->counting_window_us = 20;
}
static int device_read_count_rc_n_v6(struct lvts_data *lvts_data)
{
/* Resistor-Capacitor Calibration */
/* count_RC_N: count RC now */
struct device *dev = lvts_data->dev;
struct tc_settings *tc = lvts_data->tc;
struct sensor_cal_data *cal_data = &lvts_data->cal_data;
unsigned int offset, size, s_index, data;
void __iomem *base;
int ret, i, j;
char buffer[512];
cal_data->count_rc_now =
devm_kcalloc(dev, lvts_data->num_sensor,
sizeof(*cal_data->count_rc_now), GFP_KERNEL);
if (!cal_data->count_rc_now)
return -ENOMEM;
for (i = 0; i < lvts_data->num_tc; i++) {
base = GET_BASE_ADDR(i);
lvts_write_device(lvts_data, SET_MANUAL_RCK_V6, i);
for (j = 0; j < tc[i].num_sensor; j++) {
s_index = tc[i].sensor_map[j];
lvts_write_device(lvts_data, SET_RG_TSV2F_RSV_V6, i);
lvts_write_device(lvts_data, SELECT_SENSOR_RCK_V6(j),
i);
lvts_write_device(lvts_data, SET_DEVICE_SINGLE_MODE_V6,
i);
lvts_write_device(lvts_data, KICK_OFF_RCK_COUNTING_V6,
i);
lvts_write_device(lvts_data, GET_RCK_COUNT_DATA_V6, i);
udelay(50);
ret = readl_poll_timeout(
LVTS_CONFIG_0 + base, data,
!(data & DEVICE_SENSING_STATUS), 2, 200);
if (ret)
dev_err(dev,
"Error: LVTS %d DEVICE_SENSING_STATUS didn't ready\n",
i);
data = lvts_read_device(lvts_data, 0x00, i);
cal_data->count_rc_now[s_index] =
(data & GENMASK(23, 0));
/* Recover Setting for Normal Access on
* temperature fetch
*/
lvts_write_device(lvts_data, SET_SENSOR_NO_RCK_V6(j),
i);
lvts_write_device(lvts_data,
SET_DEVICE_LOW_POWER_SINGLE_MODE_V6,
i);
}
}
size = sizeof(buffer);
offset = snprintf(buffer, size, "[COUNT_RC_NOW] ");
for (i = 0; i < lvts_data->num_sensor; i++)
offset += snprintf(buffer + offset, size - offset, "%d:%d ", i,
cal_data->count_rc_now[i]);
buffer[offset] = '\0';
dev_info(dev, "%s\n", buffer);
return 0;
}
/*
* LVTS MT6873
*/
@@ -1606,8 +1479,8 @@ static struct tc_settings mt7988_tc_settings[] = {
MT7988_TS2_3},
.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
.hw_filter = LVTS_FILTER_16_OF_18,
.dominator_sensing_point = ALL_SENSING_POINTS,
.hw_reboot_trip_point = 125000,
.dominator_sensing_point = SENSING_POINT0,
.hw_reboot_trip_point = 117000,
.irq_bit = BIT(4),
},
[1] = {
@@ -1618,8 +1491,8 @@ static struct tc_settings mt7988_tc_settings[] = {
MT7988_TS3_3},
.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
.hw_filter = LVTS_FILTER_16_OF_18,
.dominator_sensing_point = ALL_SENSING_POINTS,
.hw_reboot_trip_point = 125000,
.dominator_sensing_point = SENSING_POINT0,
.hw_reboot_trip_point = 117000,
.irq_bit = BIT(5),
}
@@ -1652,72 +1525,6 @@ static struct lvts_data mt7988_lvts_data = {
},
};
/*
* LVTS MT7987
*/
#define MT7987_NUM_LVTS (ARRAY_SIZE(mt7987_tc_settings))
enum mt7987_lvts_domain { MT7987_AP_DOMAIN, MT7987_NUM_DOMAIN };
enum mt7987_lvts_sensor_enum {
MT7987_TS2_0,
MT7987_TS2_1,
MT7987_NUM_TS
};
static void mt7987_efuse_to_cal_data(struct lvts_data *lvts_data)
{
struct sensor_cal_data *cal_data = &lvts_data->cal_data;
cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, 31, 24);
cal_data->count_r[MT7987_TS2_0] = GET_CAL_DATA_BITMASK(1, 31, 0);
cal_data->count_r[MT7987_TS2_1] = GET_CAL_DATA_BITMASK(2, 31, 0);
cal_data->count_rc[MT7987_TS2_0] = GET_CAL_DATA_BITMASK(3, 31, 0);
}
static struct tc_settings mt7987_tc_settings[] = {
[0] = {
.domain_index = MT7987_AP_DOMAIN,
.addr_offset = 0x0,
.num_sensor = 2,
.sensor_map = {MT7987_TS2_0, MT7987_TS2_1},
.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
.hw_filter = LVTS_FILTER_16_OF_18,
.dominator_sensing_point = ALL_SENSING_POINTS,
.hw_reboot_trip_point = 125000,
.irq_bit = BIT(4),
},
};
static struct lvts_data mt7987_lvts_data = {
.num_domain = MT7987_NUM_DOMAIN,
.num_tc = MT7987_NUM_LVTS,
.tc = mt7987_tc_settings,
.num_sensor = MT7987_NUM_TS,
.ops = {
.efuse_to_cal_data = mt7987_efuse_to_cal_data,
.device_enable_and_init = device_enable_and_init_v6,
.device_enable_auto_rck = device_enable_auto_rck_v4,
.device_read_count_rc_n = device_read_count_rc_n_v6,
.set_cal_data = set_calibration_data_v4,
.init_controller = init_controller_v4,
},
.feature_bitmap = 0,
.num_efuse_addr = 4,
.num_efuse_block = 1,
.cal_data = {
.default_golden_temp = 60,
.default_count_r = 19380,
.default_count_rc = 5330,
},
.coeff = {
.a = -204650,
.b = 204650,
},
};
/*
* LVTS MT8195
*/
@@ -2067,10 +1874,6 @@ static const struct of_device_id lvts_of_match[] = {
.compatible = "mediatek,mt7988-lvts",
.data = (void *)&mt7988_lvts_data,
},
{
.compatible = "mediatek,mt7987-lvts",
.data = (void *)&mt7987_lvts_data,
},
{},
};
MODULE_DEVICE_TABLE(of, lvts_of_match);

View File

@@ -1,213 +0,0 @@
/*
* 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.
*/
#ifndef _DT_BINDINGS_CLK_MT7987_H
#define _DT_BINDINGS_CLK_MT7987_H
/* INFRACFG_AO */
#define CK_INFRA_MUX_UART0_SEL 0
#define CK_INFRA_MUX_UART1_SEL 1
#define CK_INFRA_MUX_UART2_SEL 2
#define CK_INFRA_MUX_SPI0_SEL 3
#define CK_INFRA_MUX_SPI1_SEL 4
#define CK_INFRA_MUX_SPI2_BCK_SEL 5
#define CK_INFRA_PWM_BCK_SEL 6
#define CK_INFRA_PCIE_GFMUX_TL_O_P0_SEL 7
#define CK_INFRA_PCIE_GFMUX_TL_O_P1_SEL 8
#define CK_INFRA_66M_GPT_BCK 9
#define CK_INFRA_66M_PWM_HCK 10
#define CK_INFRA_66M_PWM_BCK 11
#define CK_INFRA_133M_CQDMA_BCK 12
#define CK_INFRA_66M_AUD_SLV_BCK 13
#define CK_INFRA_AUD_26M 14
#define CK_INFRA_AUD_L 15
#define CK_INFRA_AUD_AUD 16
#define CK_INFRA_AUD_EG2 17
#define CK_INFRA_DRAMC_F26M 18
#define CK_INFRA_133M_DBG_ACKM 19
#define CK_INFRA_66M_AP_DMA_BCK 20
#define CK_INFRA_MSDC200_SRC 21
#define CK_INFRA_66M_SEJ_BCK 22
#define CK_INFRA_PRE_CK_SEJ_F13M 23
#define CK_INFRA_66M_TRNG 24
#define CK_INFRA_26M_THERM_SYSTEM 25
#define CK_INFRA_I2C_BCK 26
#define CK_INFRA_66M_UART0_PCK 27
#define CK_INFRA_66M_UART1_PCK 28
#define CK_INFRA_66M_UART2_PCK 29
#define CK_INFRA_52M_UART0_CK 30
#define CK_INFRA_52M_UART1_CK 31
#define CK_INFRA_52M_UART2_CK 32
#define CK_INFRA_NFI 33
#define CK_INFRA_66M_NFI_HCK 34
#define CK_INFRA_104M_SPI0 35
#define CK_INFRA_104M_SPI1 36
#define CK_INFRA_104M_SPI2_BCK 37
#define CK_INFRA_66M_SPI0_HCK 38
#define CK_INFRA_66M_SPI1_HCK 39
#define CK_INFRA_66M_SPI2_HCK 40
#define CK_INFRA_66M_FLASHIF_AXI 41
#define CK_INFRA_RTC 42
#define CK_INFRA_26M_ADC_BCK 43
#define CK_INFRA_RC_ADC 44
#define CK_INFRA_MSDC400 45
#define CK_INFRA_MSDC2_HCK 46
#define CK_INFRA_133M_MSDC_0_HCK 47
#define CK_INFRA_66M_MSDC_0_HCK 48
#define CK_INFRA_133M_CPUM_BCK 49
#define CK_INFRA_BIST2FPC 50
#define CK_INFRA_I2C_X16W_MCK_CK_P1 51
#define CK_INFRA_I2C_X16W_PCK_CK_P1 52
#define CK_INFRA_133M_USB_HCK 53
#define CK_INFRA_133M_USB_HCK_CK_P1 54
#define CK_INFRA_66M_USB_HCK 55
#define CK_INFRA_66M_USB_HCK_CK_P1 56
#define CK_INFRA_USB_SYS_CK_P1 57
#define CK_INFRA_USB_CK_P1 58
#define CK_INFRA_USB_FRMCNT_CK_P1 59
#define CK_INFRA_USB_PIPE_CK_P1 60
#define CK_INFRA_USB_UTMI_CK_P1 61
#define CK_INFRA_USB_XHCI_CK_P1 62
#define CK_INFRA_PCIE_GFMUX_TL_P0 63
#define CK_INFRA_PCIE_GFMUX_TL_P1 64
#define CK_INFRA_PCIE_PIPE_P0 65
#define CK_INFRA_PCIE_PIPE_P1 66
#define CK_INFRA_133M_PCIE_CK_P0 67
#define CK_INFRA_133M_PCIE_CK_P1 68
#define CK_INFRA_PCIE_PERI_26M_CK_P0 69
#define CK_INFRA_PCIE_PERI_26M_CK_P1 70
#define CLK_INFRA_NR_CLK 71
/* TOPCKGEN */
#define CK_TOP_CB_M_D2 0
#define CK_TOP_CB_M_D3 1
#define CK_TOP_M_D3_D2 2
#define CK_TOP_CB_M_D4 3
#define CK_TOP_CB_M_D8 4
#define CK_TOP_M_D8_D2 5
#define CK_TOP_CB_APLL2_D4 6
#define CK_TOP_CB_NET1_D3 7
#define CK_TOP_CB_NET1_D4 8
#define CK_TOP_CB_NET1_D5 9
#define CK_TOP_NET1_D5_D2 10
#define CK_TOP_NET1_D5_D4 11
#define CK_TOP_CB_NET1_D7 12
#define CK_TOP_NET1_D7_D2 13
#define CK_TOP_NET1_D7_D4 14
#define CK_TOP_NET1_D8_D2 15
#define CK_TOP_NET1_D8_D4 16
#define CK_TOP_NET1_D8_D8 17
#define CK_TOP_NET1_D8_D16 18
#define CK_TOP_CB_NET2_D2 19
#define CK_TOP_CB_NET2_D4 20
#define CK_TOP_NET2_D4_D4 21
#define CK_TOP_NET2_D4_D8 22
#define CK_TOP_CB_NET2_D6 23
#define CK_TOP_NET2_D7_D2 24
#define CK_TOP_CB_NET2_D8 25
#define CK_TOP_MSDC_D2 26
#define CK_TOP_CB_CKSQ_40M 27
#define CK_TOP_CKSQ_40M_D2 28
#define CK_TOP_CB_RTC_32K 29
#define CK_TOP_CB_RTC_32P7K 30
#define CK_TOP_NETSYS_SEL 31
#define CK_TOP_NETSYS_500M_SEL 32
#define CK_TOP_NETSYS_2X_SEL 33
#define CK_TOP_ETH_GMII_SEL 34
#define CK_TOP_EIP_SEL 35
#define CK_TOP_AXI_INFRA_SEL 36
#define CK_TOP_UART_SEL 37
#define CK_TOP_EMMC_250M_SEL 38
#define CK_TOP_EMMC_400M_SEL 39
#define CK_TOP_SPI_SEL 40
#define CK_TOP_SPIM_MST_SEL 41
#define CK_TOP_NFI_SEL 42
#define CK_TOP_PWM_SEL 43
#define CK_TOP_I2C_SEL 44
#define CK_TOP_PCIE_MBIST_250M_SEL 45
#define CK_TOP_PEXTP_TL_SEL 46
#define CK_TOP_PEXTP_TL_P1_SEL 47
#define CK_TOP_USB_SYS_P1_SEL 48
#define CK_TOP_USB_XHCI_P1_SEL 49
#define CK_TOP_AUD_SEL 50
#define CK_TOP_A1SYS_SEL 51
#define CK_TOP_AUD_L_SEL 52
#define CK_TOP_A_TUNER_SEL 53
#define CK_TOP_USB_PHY_SEL 54
#define CK_TOP_SGM_0_SEL 55
#define CK_TOP_SGM_SBUS_0_SEL 56
#define CK_TOP_SGM_1_SEL 57
#define CK_TOP_SGM_SBUS_1_SEL 58
#define CK_TOP_SYSAXI_SEL 59
#define CK_TOP_SYSAPB_SEL 60
#define CK_TOP_ETH_REFCK_50M_SEL 61
#define CK_TOP_ETH_SYS_200M_SEL 62
#define CK_TOP_ETH_SYS_SEL 63
#define CK_TOP_ETH_XGMII_SEL 64
#define CK_TOP_DRAMC_SEL 65
#define CK_TOP_DRAMC_MD32_SEL 66
#define CK_TOP_INFRA_F26M_SEL 67
#define CK_TOP_PEXTP_P0_SEL 68
#define CK_TOP_PEXTP_P1_SEL 69
#define CK_TOP_DA_XTP_GLB_P0_SEL 70
#define CK_TOP_DA_XTP_GLB_P1_SEL 71
#define CK_TOP_CKM_SEL 72
#define CK_TOP_DA_CKM_XTAL_SEL 73
#define CK_TOP_PEXTP_SEL 74
#define CK_TOP_ETH_MII_SEL 75
#define CK_TOP_EMMC_200M_SEL 76
#define CK_TOP_AUD_I2S_M 77
#define CLK_TOP_NR_CLK 78
/* APMIXEDSYS */
#define CK_APMIXED_MPLL 0
#define CK_APMIXED_APLL2 1
#define CK_APMIXED_NET1PLL 2
#define CK_APMIXED_NET2PLL 3
#define CK_APMIXED_WEDMCUPLL 4
#define CK_APMIXED_SGMPLL 5
#define CK_APMIXED_ARM_LL 6
#define CK_APMIXED_MSDCPLL 7
#define CLK_APMIXED_NR_CLK 8
/* MCUSYS */
#define CK_MCU_BUS_DIV_SEL 0
#define CLK_MCU_NR_CLK 1
/* SGMIISYS_0 */
#define CK_SGM0_TX_EN 0
#define CK_SGM0_RX_EN 1
#define CLK_SGMII0_NR_CLK 2
/* SGMIISYS_1 */
#define CK_SGM1_TX_EN 0
#define CK_SGM1_RX_EN 1
#define CLK_SGMII1_NR_CLK 2
/* ETHDMA */
#define CK_ETHDMA_FE_EN 0
#define CK_ETHDMA_GP2_EN 1
#define CK_ETHDMA_GP1_EN 2
#define CK_ETHDMA_GP3_EN 3
#define CLK_ETHDMA_NR_CLK 4
#endif /* _DT_BINDINGS_CLK_MT7987_H */

View File

@@ -387,21 +387,6 @@ struct cb_rx_desc_info4 {
(((struct pdma_rx_desc_info4 *)((long)((skb_end_pointer(skb)) - FOE_INFO_LEN)))->WCID)
#define FOE_BSS_ID_TAIL(skb) \
(((struct pdma_rx_desc_info4 *)((long)((skb_end_pointer(skb)) - FOE_INFO_LEN)))->BSSID)
#define FOE_USR_INFO_TAIL(skb) \
(((struct dmad_rx_descinfo4 *)((long)((skb_end_pointer(skb)) - FOE_INFO_LEN)))->USR_INFO)
#define FOE_TID_TAIL(skb) \
(((struct dmad_rx_descinfo4 *)((long)((skb_end_pointer(skb)) - FOE_INFO_LEN)))->TID)
#define FOE_IS_FIXEDRATE_TAIL(skb) \
(((struct dmad_rx_descinfo4 *) \
((long)((skb_end_pointer(skb)) - FOE_INFO_LEN)))->IS_FIXEDRATE)
#define FOE_IS_PRIOR_TAIL(skb) \
(((struct dmad_rx_descinfo4 *)((long)((skb_end_pointer(skb)) - FOE_INFO_LEN)))->IS_PRIOR)
#define FOE_IS_SP_TAIL(skb) \
(((struct dmad_rx_descinfo4 *)((long)((skb_end_pointer(skb)) - FOE_INFO_LEN)))->IS_SP)
#define FOE_HF_TAIL(skb) \
(((struct dmad_rx_descinfo4 *)((long)((skb_end_pointer(skb)) - FOE_INFO_LEN)))->HF)
#define FOE_AMSDU_TAIL(skb) \
(((struct dmad_rx_descinfo4 *)((long)((skb_end_pointer(skb)) - FOE_INFO_LEN)))->AMSDU)
#define FOE_PPE_TAIL(skb) \
(((struct pdma_rx_desc_info4 *)((long)((skb_end_pointer(skb)) - FOE_INFO_LEN)))->ppe)

View File

@@ -1,207 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* net/dsa/tag_mxl862xx.c - DSA driver Special Tag support for MaxLinear 862xx switch chips
*
* 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 <linux/bitops.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <net/dsa.h>
#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(6, 2, 0))
#include "dsa_priv.h"
#else
#include "tag.h"
#endif
#define MXL862_NAME "mxl862xx"
/* To define the outgoing port and to discover the incoming port a special
* tag is used by the GSW1xx.
*
* Dest MAC Src MAC special TAG EtherType
* ...| 1 2 3 4 5 6 | 1 2 3 4 5 6 | 1 2 3 4 5 6 7 8 | 1 2 |...
* |<--------------->|
*/
/* special tag in TX path header */
#define MXL862_TX_HEADER_LEN 8
#define MXL862_RX_HEADER_LEN 8
/* Byte 7 */
#define MXL862_IGP_EGP_SHIFT 0
#define MXL862_IGP_EGP_MASK GENMASK(3, 0)
static struct sk_buff *mxl862_tag_xmit(struct sk_buff *skb,
struct net_device *dev)
{
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
int err;
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0))
struct dsa_port *dp = dsa_slave_to_port(dev);
#else
struct dsa_port *dp = dsa_user_to_port(dev);
#endif
struct dsa_port *cpu_dp = dp->cpu_dp;
unsigned int cpu_port = cpu_dp->index + 1;
unsigned int usr_port = dp->index + 1;
u8 *mxl862_tag;
if (skb == NULL)
return skb;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
err = skb_cow_head(skb, MXL862_TX_HEADER_LEN);
if (err)
return NULL;
#endif
/* provide additional space 'MXL862_TX_HEADER_LEN' bytes */
skb_push(skb, MXL862_TX_HEADER_LEN);
/* shift MAC address to the beginnig of the enlarged buffer,
* releasing the space required for DSA tag (between MAC address and Ethertype) */
memmove(skb->data, skb->data + MXL862_TX_HEADER_LEN, 2 * ETH_ALEN);
/* special tag ingress */
mxl862_tag = skb->data + 2 * ETH_ALEN;
mxl862_tag[0] = 0x88;
mxl862_tag[1] = 0xc3;
mxl862_tag[2] = 0;
mxl862_tag[3] = 0;
mxl862_tag[4] = 0;
mxl862_tag[5] = usr_port + 16 - cpu_port;
mxl862_tag[6] = 0;
mxl862_tag[7] = (cpu_port)&MXL862_IGP_EGP_MASK;
return skb;
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0))
static struct sk_buff *mxl862_tag_rcv(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt)
#else
static struct sk_buff *mxl862_tag_rcv(struct sk_buff *skb,
struct net_device *dev)
#endif
{
int port;
u8 *mxl862_tag;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0))
struct dsa_port *dp;
#endif
if (unlikely(!pskb_may_pull(skb, MXL862_RX_HEADER_LEN))) {
dev_warn_ratelimited(&dev->dev,
"Dropping packet, cannot pull SKB\n");
return NULL;
}
mxl862_tag = skb->data - 2;
if ((mxl862_tag[0] != 0x88) && (mxl862_tag[1] != 0xc3)) {
dev_warn_ratelimited(
&dev->dev,
"Dropping packet due to invalid special tag marker\n");
dev_warn_ratelimited(
&dev->dev,
"Rx Packet Tag: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
mxl862_tag[0], mxl862_tag[1], mxl862_tag[2],
mxl862_tag[3], mxl862_tag[4], mxl862_tag[5],
mxl862_tag[6], mxl862_tag[7]);
return NULL;
}
/* Get source port information */
port = (mxl862_tag[7] & MXL862_IGP_EGP_MASK) >> MXL862_IGP_EGP_SHIFT;
port = port - 1;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0))
skb->dev = dsa_master_find_slave(dev, 0, port);
#else
skb->dev = dsa_conduit_find_user(dev, 0, port);
#endif
if (!skb->dev) {
dev_warn_ratelimited(
&dev->dev,
"Dropping packet due to invalid source port\n");
dev_warn_ratelimited(
&dev->dev,
"Rx Packet Tag: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
mxl862_tag[0], mxl862_tag[1], mxl862_tag[2],
mxl862_tag[3], mxl862_tag[4], mxl862_tag[5],
mxl862_tag[6], mxl862_tag[7]);
return NULL;
}
/* remove the MxL862xx special tag between the MAC addresses and the current ethertype field. */
skb_pull_rcsum(skb, MXL862_RX_HEADER_LEN);
memmove(skb->data - ETH_HLEN,
skb->data - (ETH_HLEN + MXL862_RX_HEADER_LEN), 2 * ETH_ALEN);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0))
dp = dsa_slave_to_port(skb->dev);
if (dp->bridge_dev)
skb->offload_fwd_mark = 1;
#else
dsa_default_offload_fwd_mark(skb);
#endif
return skb;
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0))
const struct dsa_device_ops mxl862_netdev_ops = {
.xmit = mxl862_tag_xmit,
.rcv = mxl862_tag_rcv,
};
#else
static const struct dsa_device_ops mxl862_netdev_ops = {
.name = "mxl862",
.proto = DSA_TAG_PROTO_MXL862,
.xmit = mxl862_tag_xmit,
.rcv = mxl862_tag_rcv,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0))
.overhead = MXL862_RX_HEADER_LEN,
#else
.needed_headroom = MXL862_RX_HEADER_LEN,
#endif
};
MODULE_LICENSE("GPL");
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0))
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_MXL862);
#else
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_MXL862, MXL862_NAME);
#endif
module_dsa_tag_driver(mxl862_netdev_ops);
#endif
MODULE_LICENSE("GPL");

View File

@@ -1,190 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* net/dsa/tag_mxl862xx_8021q.c - DSA driver 802.1q based Special Tag support for MaxLinear 862xx switch chips
*
* 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 LINUX_VERSION_CODE
#include <linux/version.h>
#else
#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
#endif
#include <linux/dsa/8021q.h>
#if (LINUX_VERSION_CODE > KERNEL_VERSION(6, 1, 0))
#include "tag_8021q.h"
#endif
#include <net/dsa.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0))
#include "dsa_priv.h"
#else
#include "tag.h"
#endif
#define MXL862_NAME "mxl862xx"
/* To define the outgoing port and to discover the incoming port
* a special 4-byte outer VLAN tag is used by the MxL862xx.
*
* Dest MAC Src MAC special optional EtherType
* outer inner
* VLAN tag tag(s)
* ...| 1 2 3 4 5 6 | 1 2 3 4 5 6 | 1 2 3 4 | 1 2 3 4 | 1 2 |...
* |<------->|
*/
/* special tag in TX path header */
/* The mxl862_8021q 4-byte tagging is not yet supported in
* kernels >= 5.16 due to differences in DSA 8021q tagging handlers.
* DSA tx/rx vid functions are not avaliable, so dummy
* functions are here to make the code compilable. */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION (5, 16, 0))
static u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port)
{
return 0;
}
static u16 dsa_8021q_tx_vid(struct dsa_switch *ds, int port)
{
return 0;
}
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION (5, 14, 0))
static void dsa_8021q_rcv(struct sk_buff *skb, int *source_port, int *switch_id)
{
u16 vid, tci;
skb_push_rcsum(skb, ETH_HLEN);
if (skb_vlan_tag_present(skb)) {
tci = skb_vlan_tag_get(skb);
__vlan_hwaccel_clear_tag(skb);
} else {
__skb_vlan_pop(skb, &tci);
}
skb_pull_rcsum(skb, ETH_HLEN);
vid = tci & VLAN_VID_MASK;
*source_port = dsa_8021q_rx_source_port(vid);
*switch_id = dsa_8021q_rx_switch_id(vid);
skb->priority = (tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
}
/* If the ingress port offloads the bridge, we mark the frame as autonomously
* forwarded by hardware, so the software bridge doesn't forward in twice, back
* to us, because we already did. However, if we're in fallback mode and we do
* software bridging, we are not offloading it, therefore the dp->bridge_dev
* pointer is not populated, and flooding needs to be done by software (we are
* effectively operating in standalone ports mode).
*/
static inline void dsa_default_offload_fwd_mark(struct sk_buff *skb)
{
struct dsa_port *dp = dsa_slave_to_port(skb->dev);
skb->offload_fwd_mark = !!(dp->bridge_dev);
}
#endif
static struct sk_buff *mxl862_8021q_tag_xmit(struct sk_buff *skb,
struct net_device *dev)
{
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0))
struct dsa_port *dp = dsa_slave_to_port(dev);
#else
struct dsa_port *dp = dsa_user_to_port(dev);
#endif
unsigned int port = dp->index ;
u16 tx_vid = dsa_8021q_tx_vid(dp->ds, port);
u16 queue_mapping = skb_get_queue_mapping(skb);
u8 pcp = netdev_txq_to_tc(dev, queue_mapping);
dsa_8021q_xmit(skb, dev, ETH_P_8021Q,
((pcp << VLAN_PRIO_SHIFT) | tx_vid));
return skb;
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0))
static struct sk_buff *mxl862_8021q_tag_rcv(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt)
#else
static struct sk_buff *mxl862_8021q_tag_rcv(struct sk_buff *skb,
struct net_device *dev)
#endif
{
uint16_t vlan = ntohs(*(uint16_t*)(skb->data));
int port = dsa_8021q_rx_source_port(vlan);
int src_port = -1;
int switch_id = -1;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0))
skb->dev = dsa_master_find_slave(dev, 0, port);
#else
skb->dev = dsa_conduit_find_user(dev, 0, port);
#endif
if (!skb->dev) {
dev_warn_ratelimited(&dev->dev,"Dropping packet due to invalid source port:%d\n", port);
return NULL;
}
/* removes Outer VLAN tag */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
dsa_8021q_rcv(skb, &src_port, &switch_id);
#else
dsa_8021q_rcv(skb, &src_port, &switch_id, NULL);
#endif
dsa_default_offload_fwd_mark(skb);
return skb;
}
static const struct dsa_device_ops mxl862_8021q_netdev_ops = {
.name = "mxl862_8021q",
.proto = DSA_TAG_PROTO_MXL862_8021Q,
.xmit = mxl862_8021q_tag_xmit,
.rcv = mxl862_8021q_tag_rcv,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0))
.overhead = VLAN_HLEN,
#else
.needed_headroom = VLAN_HLEN,
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0) && \
LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 0))
.promisc_on_master = true,
#elif (LINUX_VERSION_CODE > KERNEL_VERSION(6, 7, 0))
.promisc_on_conduit = true,
#endif
};
MODULE_LICENSE("GPL");
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0))
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_MXL862_8021Q);
#else
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_MXL862_8021Q, MXL862_NAME);
#endif
module_dsa_tag_driver(mxl862_8021q_netdev_ops);

View File

@@ -67,35 +67,6 @@ endef
$(eval $(call KernelPackage,crypto-eip197))
define KernelPackage/crypto-eip196
TITLE:= EIP-196 Crypto Engine module
DEPENDS:=@TARGET_mediatek_mt7987 +eip197-mini-firmware
DEFAULT:=y
KCONFIG:= \
CONFIG_CRYPTO_HW=y \
CONFIG_CRYPTO_AUTHENC=y \
CONFIG_CRYPTO_AES=y \
CONFIG_CRYPTO_AEAD=y \
CONFIG_CRYPTO_DES=y \
CONFIG_CRYPTO_MD5=y \
CONFIG_CRYPTO_SHA1=y \
CONFIG_CRYPTO_SHA256=y \
CONFIG_CRYPTO_SHA512=y \
CONFIG_CRYPTO_SHA3=y \
CONFIG_CRYPTO_HMAC=y \
CONFIG_CRYPTO_CHACHA20POLY1305=y \
CONFIG_CRYPTO_DEV_SAFEXCEL
FILES:=$(LINUX_DIR)/drivers/crypto/inside-secure/crypto_safexcel.ko
AUTOLOAD:=$(call AutoLoad,90,crypto-safexcel)
$(call AddDepends/crypto)
endef
define KernelPackage/crypto-eip196/description
EIP-196 Cryptographic Engine driver.
endef
$(eval $(call KernelPackage,crypto-eip196))
define KernelPackage/mediatek_hnat
SUBMENU:=Network Devices
TITLE:=Mediatek HNAT module

View File

@@ -1,6 +1,5 @@
CONFIG_64BIT=y
CONFIG_AHCI_MTK=y
# CONFIG_AN8855_GSW is not set
CONFIG_ARCH_CLOCKSOURCE_DATA=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
@@ -274,13 +273,8 @@ CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_NET_DEVLINK=y
CONFIG_NET_DSA=y
# CONFIG_NET_DSA_AN8855 is not set
CONFIG_NET_DSA_MT7530=y
# CONFIG_NET_DSA_MXL862 is not set
# CONFIG_NET_DSA_TAG_AIROHA is not set
CONFIG_NET_DSA_TAG_MTK=y
# CONFIG_NET_DSA_TAG_MXL862 is not set
# CONFIG_NET_DSA_TAG_MXL862_8021Q is not set
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_MEDIATEK_SOC=y
CONFIG_NET_SWITCHDEV=y

View File

@@ -34,13 +34,11 @@ case "$board" in
if [ -f "$phy0_file" ]; then
check_phy0=$(cat $phy0_file)
echo "check_phy0 = $check_phy0"
[ "$check_phy0" == 0 ] && echo 1 > $phy0_file
fi
if [ -f "$phy1_file" ]; then
check_phy1=$(cat $phy1_file)
echo "check_phy1 = $check_phy1"
[ "$check_phy1" == 0 ] && echo 1 > $phy1_file
fi

View File

@@ -2,7 +2,6 @@ CONFIG_64BIT=y
CONFIG_AHCI_MTK=y
CONFIG_AIROHA_EN8801SC_PHY=y
# CONFIG_AIROHA_EN8811H_PHY is not set
# CONFIG_AIROHA_AN8801_PHY is not set
CONFIG_AN8855_GSW=y
CONFIG_ARCH_CLOCKSOURCE_DATA=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
@@ -293,7 +292,6 @@ CONFIG_MTD_UBI_BLOCK=y
CONFIG_MTD_UBI_WL_THRESHOLD=4096
# CONFIG_MTK_CMDQ is not set
# CONFIG_MTK_CQDMA is not set
# CONFIG_MTK_DEVAPC is not set
CONFIG_MTK_EFUSE=y
CONFIG_MTK_HSDMA=y
CONFIG_MTK_ICE_DEBUG=y
@@ -318,8 +316,6 @@ CONFIG_NET_DSA_AN8855=y
CONFIG_NET_DSA_MT7530=y
CONFIG_NET_DSA_TAG_ARHT=y
CONFIG_NET_DSA_TAG_MTK=y
# CONFIG_NET_DSA_TAG_MXL862 is not set
# CONFIG_NET_DSA_TAG_MXL862_8021Q is not set
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_MEDIATEK_SOC=y
CONFIG_NET_SWITCHDEV=y
@@ -516,7 +512,6 @@ CONFIG_ZONE_DMA32=y
# CONFIG_FUNCTION_ERROR_INJECTION is not set
CONFIG_RICHTEK_RTQ6056=y
CONFIG_ZTS8032=y
# CONFIG_ZTS8232 is not set
# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set
# CONFIG_CRYPTO_CAVP_TEST is not set
# CONFIG_CRYPTO_CPU_JITTERENTROPY_DEBUG is not set

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