mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-29 09:32:34 +00:00 
			
		
		
		
	Compare commits
	
		
			93 Commits
		
	
	
		
			staging-mt
			...
			v4.1.1-RC1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 9d06b517dc | ||
|   | f2afe49977 | ||
|   | 04cc064026 | ||
|   | 14778e1d2f | ||
|   | 9712ce581f | ||
|   | a4dbeb376e | ||
|   | 02b0457b28 | ||
|   | 42007a147f | ||
|   | d1e18425b0 | ||
|   | 125c75c49b | ||
|   | d98e18a143 | ||
|   | fd170fabed | ||
|   | 9b2d80f2b4 | ||
|   | 5c892e7a0c | ||
|   | 6ed93db422 | ||
|   | 92d67c15dd | ||
|   | 460180f42e | ||
|   | ed57759824 | ||
|   | 957e3ca997 | ||
|   | 7c2b8e8de0 | ||
|   | 741007178f | ||
|   | e9d3e39d5e | ||
|   | b82a2c5da1 | ||
|   | 15429f39d8 | ||
|   | 5df274325b | ||
|   | 2e4972e9ad | ||
|   | a25480d479 | ||
|   | 2f625c35f0 | ||
|   | b5422f80e4 | ||
|   | 1ed503613d | ||
|   | f8954418f1 | ||
|   | 3abc6a4463 | ||
|   | 5bd8fe1249 | ||
|   | 593cdba4d7 | ||
|   | f811aa6b73 | ||
|   | 7213dc6dcb | ||
|   | 811b63de93 | ||
|   | c66020fbc6 | ||
|   | da7682166f | ||
|   | bd50dfdf96 | ||
|   | cbf0e536df | ||
|   | 20a7a48c9f | ||
|   | 7dd139cf3b | ||
|   | 544b687f46 | ||
|   | c27b015a63 | ||
|   | 02c2e6945b | ||
|   | e7cd5038ac | ||
|   | 34e4a01e25 | ||
|   | 60e9fb2645 | ||
|   | 462ff4f813 | ||
|   | 71b738f8ee | ||
|   | b995833a03 | ||
|   | 9866d4a86e | ||
|   | 4ad04c7948 | ||
|   | 143d4e3b58 | ||
|   | 0735fd8c9a | ||
|   | c7f9061eee | ||
|   | f4a58c0989 | ||
|   | cd78a832e3 | ||
|   | 7b6fc736f6 | ||
|   | f997f8dff0 | ||
|   | c4b3eeed81 | ||
|   | b2ba9d7c1b | ||
|   | b982f3f4c2 | ||
|   | 68dfd58303 | ||
|   | 6ba26cba2b | ||
|   | b5b276bfcc | ||
|   | de7dc7e01a | ||
|   | a967d67af3 | ||
|   | 8a68073f4f | ||
|   | efd804987e | ||
|   | b036ba37e3 | ||
|   | 7352de2421 | ||
|   | 8c11eb23a3 | ||
|   | 83874b75f3 | ||
|   | 694cf6ded8 | ||
|   | 0a3a207584 | ||
|   | b0e95e68a2 | ||
|   | 26ed5acb60 | ||
|   | d1e4c48617 | ||
|   | 3a8fc316f2 | ||
|   | d85dc2a819 | ||
|   | acca9737e4 | ||
|   | 6d2fd1de0d | ||
|   | 1d822a10d2 | ||
|   | ebdc88ee1f | ||
|   | 778cc679a0 | ||
|   | 088d78faa7 | ||
|   | 5306f7db27 | ||
|   | c8bffdc250 | ||
|   | 3a3de9e146 | ||
|   | 4d5c9a2d4c | ||
|   | 41aa4c2978 | 
							
								
								
									
										2
									
								
								.github/workflows/build-dev.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build-dev.yml
									
									
									
									
										vendored
									
									
								
							| @@ -21,7 +21,7 @@ jobs: | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         target: [ ] | ||||
|         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 | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,14 @@ | ||||
| --- a/hostapd/ctrl_iface.c	2025-09-24 14:15:25.135668867 +0800 | ||||
| +++ b/hostapd/ctrl_iface.c	2025-09-24 15:32:46.082317382 +0800 | ||||
| @@ -2657,6 +2657,11 @@ static int hostapd_ctrl_iface_chan_switc | ||||
|  		break; | ||||
|  	} | ||||
|   | ||||
| +    /* Initialize HT/VHT/HE parameters */ | ||||
| +    settings.freq_params.ht_enabled = iface->conf->ieee80211n; | ||||
| +    settings.freq_params.vht_enabled = iface->conf->ieee80211ac; | ||||
| +    settings.freq_params.he_enabled = iface->conf->ieee80211ax; | ||||
| + | ||||
|  	if (settings.freq_params.center_freq1) | ||||
|  		dfs_range += hostapd_is_dfs_overlap( | ||||
|  			iface, bandwidth, settings.freq_params.center_freq1); | ||||
| @@ -47,6 +47,10 @@ ALLWIFIBOARDS:= \ | ||||
| 	indio-um-310ax-v1 \ | ||||
| 	indio-um-510axp-v1 \ | ||||
| 	indio-um-510axm-v1 \ | ||||
| 	indio-um-325ax-v2 \ | ||||
| 	indio-um-335ax \ | ||||
| 	indio-um-525axp \ | ||||
| 	indio-um-525axm \ | ||||
| 	muxi-ap3220l \ | ||||
| 	plasmacloud-pax1800 \ | ||||
| 	wallys-dr5018 \ | ||||
| @@ -441,6 +445,10 @@ $(eval $(call generate-ath11k-wifi-package,liteon-wpx8324,Liteon WPX8324)) | ||||
| $(eval $(call generate-ath11k-wifi-package,indio-um-310ax-v1,Indio UM-310AX V1)) | ||||
| $(eval $(call generate-ath11k-wifi-package,indio-um-510axp-v1,Indio UM-510AXP V1)) | ||||
| $(eval $(call generate-ath11k-wifi-package,indio-um-510axm-v1,Indio UM-510AXM V1)) | ||||
| $(eval $(call generate-ath11k-wifi-package,indio-um-325ax-v2,Indio UM-325AX V2)) | ||||
| $(eval $(call generate-ath11k-wifi-package,indio-um-335ax,Indio UM-335AX)) | ||||
| $(eval $(call generate-ath11k-wifi-package,indio-um-525axp,Indio UM-525AXP)) | ||||
| $(eval $(call generate-ath11k-wifi-package,indio-um-525axm,Indio UM-525AXM)) | ||||
| $(eval $(call generate-ath11k-wifi-package,sonicfi-rap630c-311g,Sonicfi RAP630C 311G)) | ||||
| $(eval $(call generate-ath11k-wifi-package,sonicfi-rap630w-311g,Sonicfi RAP630W 311G)) | ||||
| $(eval $(call generate-ath11k-wifi-package,sonicfi-rap630w-312g,Sonicfi RAP630W 312G)) | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-325ax-v2.bin.IPQ5018
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-325ax-v2.bin.IPQ5018
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-325ax-v2.bin.QCN6122
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-325ax-v2.bin.QCN6122
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-335ax.bin.IPQ5018
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-335ax.bin.IPQ5018
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-335ax.bin.QCN9074
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-335ax.bin.QCN9074
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-525axm.bin.IPQ5018
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-525axm.bin.IPQ5018
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-525axm.bin.QCN6122
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-525axm.bin.QCN6122
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-525axp.bin.IPQ5018
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-525axp.bin.IPQ5018
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-525axp.bin.QCN6122
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								feeds/ipq807x_v5.4/ath11k-wifi/board-indio-um-525axp.bin.QCN6122
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -4,19 +4,19 @@ let fs = require("fs"); | ||||
| let ubus = require('ubus').connect(); | ||||
|  | ||||
| let gps_info = ubus.call('gps', 'info'); | ||||
| let latitude = gps_info.latitude ?? 0; | ||||
| let longitude = gps_info.longitude ?? 0; | ||||
| let latitude = gps_info.latitude || 0; | ||||
| let longitude = gps_info.longitude || 0; | ||||
|  | ||||
| // afc-location.json file content | ||||
| let afc_location = {}; | ||||
| afc_location.location_type = "ellipse"; | ||||
| afc_location.location = longitude + ":" + latitude ; | ||||
| afc_location.height = gps_info.elevation ?? 0; | ||||
| afc_location.height = gps_info.elevation || 0; | ||||
| afc_location.height_type = "AMSL"; | ||||
| afc_location.major_axis = 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); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -16,6 +16,14 @@ edgecore,eap104) | ||||
| 	ucidef_set_led_netdev "wan" "wan" "yellow:uplink" "eth0" | ||||
|         ucidef_set_led_default "power" "POWER" "green:power" "on" | ||||
| 	;; | ||||
| indio,um-325ax-v2|\ | ||||
| indio,um-335ax|\ | ||||
| indio,um-525axm|\ | ||||
| indio,um-525axp) | ||||
| 	ucidef_set_led_wlan "wlan2g" "WLAN2G" "led_2g" "phy0tpt" | ||||
| 	ucidef_set_led_wlan "wlan5g" "WLAN5G" "led_5g" "phy1tpt" | ||||
| 	ucidef_set_led_default "power" "POWER" "led_sys" "on" | ||||
| 	;; | ||||
| cig,wf186h|\ | ||||
| cig,wf186w) | ||||
|         ucidef_set_led_default "power" "POWER" "green:status" "on" | ||||
|   | ||||
| @@ -48,6 +48,15 @@ qcom_setup_interfaces() | ||||
| 		ucidef_add_switch "switch1" \ | ||||
| 			"6u@eth1" "1:lan" "2:lan" "3:lan" "4:lan" | ||||
| 		;; | ||||
| 	indio,um-325ax-v2|\ | ||||
| 	indio,um-335ax|\ | ||||
| 	indio,um-525axm|\ | ||||
| 	indio,um-525axp) | ||||
| 		ucidef_set_interface_wan "eth1" | ||||
| 		ucidef_set_interface_lan "eth0" | ||||
| 		ucidef_add_switch "switch1" \ | ||||
| 			"6@eth1" "1:lan" "2:lan" "3:lan" "4:lan" | ||||
| 		;; | ||||
| 	emplus,wap385c|\ | ||||
| 	hfcl,ion4x_w|\ | ||||
| 	hfcl,ion4xi_w) | ||||
|   | ||||
| @@ -142,6 +142,10 @@ ath11k/IPQ5018/hw1.0/caldata.bin) | ||||
| 	emplus,wap385c|\ | ||||
| 	hfcl,ion4x_w|\ | ||||
| 	hfcl,ion4xi_w|\ | ||||
| 	indio,um-325ax-v2|\ | ||||
| 	indio,um-335ax|\ | ||||
| 	indio,um-525axm|\ | ||||
| 	indio,um-525axp|\ | ||||
| 	optimcloud,d60|\ | ||||
| 	optimcloud,d60-5g|\ | ||||
| 	optimcloud,d50|\ | ||||
| @@ -183,6 +187,9 @@ ath11k/qcn6122/hw1.0/caldata_1.bin) | ||||
| 	;; | ||||
| ath11k/qcn6122/hw1.0/caldata_2.bin) | ||||
| 	case "$board" in | ||||
| 	indio,um-325ax-v2|\ | ||||
| 	indio,um-525axm|\ | ||||
| 	indio,um-525axp|\ | ||||
| 	wallys,dr5018|\ | ||||
| 	edgecore,eap104|\ | ||||
| 	edgecore,oap101-6e|\ | ||||
| @@ -201,6 +208,7 @@ ath11k/qcn6122/hw1.0/caldata_2.bin) | ||||
| 	;; | ||||
| ath11k/QCN9074/hw1.0/caldata_1.bin) | ||||
| 	case "$board" in | ||||
| 	indio,um-335ax|\ | ||||
| 	optimcloud,d60|\ | ||||
| 	optimcloud,d60-5g|\ | ||||
| 	optimcloud,d50|\ | ||||
| @@ -234,6 +242,9 @@ ath11k-macs) | ||||
| 	edgecore,oap101|\ | ||||
| 	edgecore,oap101-6e|\ | ||||
| 	edgecore,oap101e-6e|\ | ||||
| 	indio,um-325ax-v2|\ | ||||
| 	indio,um-525axp|\ | ||||
| 	indio,um-525axm|\ | ||||
| 	optimcloud,d60|\ | ||||
| 	optimcloud,d60-5g|\ | ||||
| 	optimcloud,d50|\ | ||||
|   | ||||
| @@ -81,6 +81,10 @@ platform_check_image() { | ||||
| 	wallys,dr5018|\ | ||||
| 	hfcl,ion4x_w|\ | ||||
| 	hfcl,ion4xi_w|\ | ||||
| 	indio,um-325ax-v2|\ | ||||
| 	indio,um-335ax|\ | ||||
| 	indio,um-525axp|\ | ||||
| 	indio,um-525axm|\ | ||||
| 	optimcloud,d60|\ | ||||
| 	optimcloud,d60-5g|\ | ||||
| 	optimcloud,d50|\ | ||||
| @@ -107,29 +111,46 @@ platform_do_upgrade() { | ||||
|  | ||||
| 	board=$(board_name) | ||||
| 	case $board in | ||||
| 	glinet,b3000|\ | ||||
| 	indio,um-325ax-v2|\ | ||||
| 	indio,um-335ax|\ | ||||
| 	indio,um-525axp|\ | ||||
| 	indio,um-525axm|\ | ||||
| 	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|\ | ||||
|   | ||||
| @@ -0,0 +1,941 @@ | ||||
| /dts-v1/; | ||||
| /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. | ||||
|  * | ||||
|  * Permission to use, copy, modify, and/or distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include "ipq5018.dtsi" | ||||
| #include <dt-bindings/input/input.h> | ||||
|  | ||||
| / { | ||||
| 	#address-cells = <0x2>; | ||||
| 	#size-cells = <0x2>; | ||||
| 	model = "Indio UM-325AX V2"; | ||||
| 	compatible = "indio,um-325ax-v2", "qcom,ipq5018-mp03.5-c1", "qcom,ipq5018"; | ||||
| 	interrupt-parent = <&intc>; | ||||
|  | ||||
| 	aliases { | ||||
| 		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ | ||||
| 		serial0 = &blsp1_uart1; | ||||
| 		serial1 = &blsp1_uart2; | ||||
| 		ethernet0 = "/soc/dp1"; | ||||
| 		ethernet1 = "/soc/dp2"; | ||||
|                 //led-failsafe = &led_red; | ||||
|                 //led-running = &led_green; | ||||
|                 //led-upgrade = &led_green; | ||||
|                 //led-gateway = &led_blue; | ||||
|                 //led-factory = &led_blue; | ||||
| 	}; | ||||
|  | ||||
| 	chosen { | ||||
| 		bootargs = "console=ttyMSM0,115200,n8 rw init=/init"; | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 		bootargs-append = " swiotlb=1"; | ||||
| 	#else | ||||
| 		bootargs-append = " swiotlb=1 coherent_pool=2M"; | ||||
| 	#endif | ||||
| 		stdout-path = "serial0"; | ||||
| 	}; | ||||
|  | ||||
| 	reserved-memory { | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 	/*                   256 MB Profile | ||||
| 	 * +==========+==============+=========================+ | ||||
| 	 * |          |              |                         | | ||||
| 	 * |  Region  | Start Offset |          Size           | | ||||
| 	 * |          |              |                         | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    NSS   |  0x40000000  |           8MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   Linux  |  0x40800000  | Depends on total memory | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   uboot  |  0x4A600000  |           4MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    SBL   |  0x4AA00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   smem   |  0x4AB00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    TZ    |  0x4AC00000  |           4MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    Q6    |              |                         | | ||||
| 	 * |   code/  |  0x4B000000  |          20MB           | | ||||
| 	 * |   data   |              |                         | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |   data   |  0x4C400000  |          13MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |  M3 Dump |  0x4D100000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |   QDSS   |  0x4D200000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |   data   |  0x4D300000  |          15MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |  M3 Dump |  0x4E200000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |   QDSS   |  0x4E300000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |   data   |  0x4E400000  |          15MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |  M3 Dump |  0x4F300000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |   QDSS   |  0x4F400000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |                                                   | | ||||
| 	 * |            Rest of the memory for Linux           | | ||||
| 	 * |                                                   | | ||||
| 	 * +===================================================+ | ||||
| 	 */ | ||||
| 		q6_mem_regions: q6_mem_regions@4B000000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4B000000 0x0 0x4500000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_code_data: q6_code_data@4B000000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4B000000 0x0 0x1400000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_ipq5018_data: q6_ipq5018_data@4C400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4C400000 0x0 0xD00000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump: m3_dump@4D100000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D100000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_etr_region: q6_etr_dump@4D200000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D200000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_data1: q6_qcn6122_data1@4D300000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D300000 0x0 0xF00000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E200000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E200000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E300000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E300000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_data2: q6_qcn6122_data2@4E400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E400000 0x0 0xF00000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump_qcn6122_2: m3_dump_qcn6122_2@4F300000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4F300000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_etr_2: q6_qcn6122_etr_2@4F400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4F400000 0x0 0x100000>; | ||||
| 		}; | ||||
| 		 | ||||
| 	#else | ||||
| 	/*                 512MB/1GB Profiles | ||||
| 	 * +==========+==============+=========================+ | ||||
| 	 * |          |              |                         | | ||||
| 	 * |  Region  | Start Offset |          Size           | | ||||
| 	 * |          |              |                         | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    NSS   |  0x40000000  |          16MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   Linux  |  0x41000000  | Depends on total memory | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   uboot  |  0x4A600000  |           4MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    SBL   |  0x4AA00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   smem   |  0x4AB00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    TZ    |  0x4AC00000  |           4MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    Q6    |              |                         | | ||||
| 	 * |   code/  |  0x4B000000  |          20MB           | | ||||
| 	 * |   data   |              |                         | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |   data   |  0x4C400000  |          14MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |  M3 Dump |  0x4D200000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |   QDSS   |  0x4D300000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |  Caldb   |  0x4D400000  |           2MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |   data   |  0x4D600000  |          16MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |  M3 Dump |  0x4E600000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |   QDSS   |  0x4E700000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |  Caldb   |  0x4E800000  |           5MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |   data   |  0x4ED00000  |          16MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |  M3 Dump |  0x4FD00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |   QDSS   |  0x4FE00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |  Caldb   |  0x4FF00000  |           5MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |                                                   | | ||||
| 	 * |            Rest of the memory for Linux           | | ||||
| 	 * |                                                   | | ||||
| 	 * +===================================================+ | ||||
| 	 */ | ||||
| 		q6_mem_regions: q6_mem_regions@4B000000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4B000000 0x0 0x5400000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_code_data: q6_code_data@4B000000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4B000000 0x0 01400000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_ipq5018_data: q6_ipq5018_data@4C400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4C400000 0x0 0xE00000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump: m3_dump@4D200000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D200000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_etr_region: q6_etr_dump@4D300000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D300000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_caldb_region: q6_caldb_region@4D400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D400000 0x0 0x200000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_data1: q6_qcn6122_data1@4D600000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D600000 0x0 0x1000000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E600000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E600000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E700000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E700000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_caldb_1: q6_qcn6122_caldb_1@4E800000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E800000 0x0 0x500000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_data2: q6_qcn6122_data2@4E900000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4ED00000 0x0 0x1000000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump_qcn6122_2: m3_dump_qcn6122_2@4FD00000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4FD00000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_etr_2: q6_qcn6122_etr_2@4FE00000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4FE00000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_caldb_2: q6_qcn6122_caldb_2@4FF00000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4FF00000 0x0 0x500000>; | ||||
| 		}; | ||||
|  | ||||
| 	#endif | ||||
| 	}; | ||||
|  | ||||
| 	soc { | ||||
| 		gpio-watchdog { | ||||
| 			compatible = "linux,wdt-gpio"; | ||||
| 			gpios = <&tlmm 27 GPIO_ACTIVE_LOW>; | ||||
| 			hw_algo = "toggle"; | ||||
| 			hw_margin_ms = <5000>; | ||||
| 			always-running; | ||||
| 		}; | ||||
|  | ||||
| 		serial@78af000 { | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		blsp1_uart2: serial@78b0000 { | ||||
| 			pinctrl-0 = <&blsp1_uart_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 		}; | ||||
|  | ||||
| 		qpic_bam: dma@7984000{ | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		nand: qpic-nand@79b0000 { | ||||
| 			pinctrl-0 = <&qspi_nand_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		spi_0: spi@78b5000 { /* BLSP1 QUP0 */ | ||||
| 			pinctrl-0 = <&blsp0_spi_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			cs-select = <0>; | ||||
| 			status = "ok"; | ||||
|  | ||||
| 			m25p80@0 { | ||||
| 				#address-cells = <1>; | ||||
| 				#size-cells = <1>; | ||||
| 				reg = <0>; | ||||
| 				compatible = "n25q128a11"; | ||||
| 				linux,modalias = "m25p80", "n25q128a11"; | ||||
| 				spi-max-frequency = <50000000>; | ||||
| 				use-default-sizes; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		mdio0: mdio@88000 { | ||||
| 			status = "ok"; | ||||
|  | ||||
| 			ethernet-phy@0 { | ||||
| 				reg = <7>; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		mdio1: mdio@90000 { | ||||
| 			status = "ok"; | ||||
| 			pinctrl-0 = <&mdio1_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			phy-reset-gpio = <&tlmm 39 0>; | ||||
|  | ||||
| 			ethernet-phy@0 { | ||||
| 				reg = <28>; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		ess-instance { | ||||
| 			num_devices = <0x1>; | ||||
| 			ess-switch@0x39c00000 { | ||||
| 				switch_mac_mode = <0xf>; /* mac mode for uniphy instance*/ | ||||
| 				cmnblk_clk = "internal_96MHz"; /* cmnblk clk*/ | ||||
| 				qcom,port_phyinfo { | ||||
| 					port@0 { | ||||
| 						port_id = <1>; | ||||
| 						phy_address = <7>; | ||||
| 						mdiobus = <&mdio0>; | ||||
| 					}; | ||||
| 					port@1 { | ||||
| 						port_id = <2>; | ||||
| 						phy_address = <0x1c>; | ||||
| 						mdiobus = <&mdio1>; | ||||
| 						port_mac_sel = "QGMAC_PORT"; | ||||
| 					}; | ||||
| 				}; | ||||
| 				led_source@0 { | ||||
| 					source = <0>; | ||||
| 					mode = "normal"; | ||||
| 					speed = "all"; | ||||
| 					blink_en = "enable"; | ||||
| 					active = "high"; | ||||
| 				}; | ||||
| 			}; | ||||
| 				ess-switch1@1 { | ||||
| 				compatible = "qcom,ess-switch-qca83xx"; | ||||
| 				device_id = <1>; | ||||
| 				switch_access_mode = "mdio"; | ||||
| 				mdio-bus = <&mdio1>; | ||||
| 				reset_gpio = <0x28>; | ||||
| 				switch_cpu_bmp = <0x40>;  /* cpu port bitmap */ | ||||
| 				switch_lan_bmp = <0x1e>; /* lan port bitmap */ | ||||
| 				switch_wan_bmp = <0x0>;  /* wan port bitmap */ | ||||
| 				qca,ar8327-initvals = < | ||||
| 						0x00004 0x7600000   /* PAD0_MODE */ | ||||
| 						0x00008 0x1000000   /* PAD5_MODE */ | ||||
| 						0x0000c 0x80        /* PAD6_MODE */ | ||||
| 						0x00010 0x2613a0    /* PORT6 FORCE MODE*/ | ||||
| 						0x000e4 0xaa545     /* MAC_POWER_SEL */ | ||||
| 						0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||
| 						0x0007c 0x4e        /* PORT0_STATUS */ | ||||
| 						0x00094 0x4e        /* PORT6_STATUS */ | ||||
| 				>; | ||||
| 				qcom,port_phyinfo { | ||||
| 					port@0 { | ||||
| 						port_id = <1>; | ||||
| 						phy_address = <28>; | ||||
| 					}; | ||||
| 				}; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		dp1 { | ||||
| 			device_type = "network"; | ||||
| 			compatible = "qcom,nss-dp"; | ||||
| 			clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>; | ||||
| 			clock-names = "nss-snoc-gmac-axi-clk"; | ||||
| 			qcom,id = <1>; | ||||
| 			reg = <0x39C00000 0x10000>; | ||||
| 			interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; | ||||
| 			qcom,mactype = <2>; | ||||
| 			qcom,link-poll = <1>; | ||||
| 			qcom,phy-mdio-addr = <7>; | ||||
| 			mdio-bus = <&mdio0>; | ||||
| 			local-mac-address = [000000000000]; | ||||
| 			phy-mode = "sgmii"; | ||||
| 		}; | ||||
|  | ||||
| 		dp2 { | ||||
| 			device_type = "network"; | ||||
| 			compatible = "qcom,nss-dp"; | ||||
| 			clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>; | ||||
| 			clock-names = "nss-snoc-gmac-axi-clk"; | ||||
| 			qcom,id = <2>; | ||||
| 			reg = <0x39D00000 0x10000>; | ||||
| 			interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>; | ||||
| 			qcom,mactype = <2>; | ||||
| 			qcom,link-poll = <1>; | ||||
| 			qcom,phy-mdio-addr = <28>; | ||||
| 			mdio-bus = <&mdio1>; | ||||
| 			local-mac-address = [000000000000]; | ||||
| 			phy-mode = "sgmii"; | ||||
| 		}; | ||||
|  | ||||
| 		qcom,test@0 { | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		nss-macsec1 { | ||||
| 			compatible = "qcom,nss-macsec"; | ||||
| 			phy_addr = <0x1c>; | ||||
| 			mdiobus = <&mdio1>; | ||||
| 		}; | ||||
|  | ||||
| 		lpass: lpass@0xA000000{ | ||||
| 			status = "disabled"; | ||||
| 		}; | ||||
|  | ||||
| 		pcm: pcm@0xA3C0000{ | ||||
| 			pinctrl-0 = <&audio_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			status = "disabled"; | ||||
| 		}; | ||||
|  | ||||
| 		pcm_lb: pcm_lb@0 { | ||||
| 			status = "disabled"; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	thermal-zones { | ||||
| 		status = "ok"; | ||||
| 	}; | ||||
|  | ||||
| }; | ||||
|  | ||||
| &tlmm { | ||||
| 	pinctrl-0 = <&blsp0_uart_pins &phy_led_pins>; | ||||
| 	pinctrl-names = "default"; | ||||
|  | ||||
| 	blsp0_uart_pins: uart_pins { | ||||
| 		blsp0_uart_rx_tx { | ||||
| 			pins = "gpio20", "gpio21"; | ||||
| 			function = "blsp0_uart0"; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	blsp1_uart_pins: blsp1_uart_pins { | ||||
| 		blsp1_uart_rx_tx { | ||||
| 			pins = "gpio22", "gpio24", "gpio23", "gpio25"; | ||||
| 			function = "blsp1_uart2"; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	blsp0_spi_pins: blsp0_spi_pins { | ||||
| 		mux { | ||||
| 			pins = "gpio10", "gpio11", "gpio12", "gpio13"; | ||||
| 			function = "blsp0_spi"; | ||||
| 			drive-strength = <2>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	qspi_nand_pins: qspi_nand_pins { | ||||
| 		qspi_clock { | ||||
| 			pins = "gpio9"; | ||||
| 			function = "qspi_clk"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_cs { | ||||
| 			pins = "gpio8"; | ||||
| 			function = "qspi_cs"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_0 { | ||||
| 			pins = "gpio7"; | ||||
| 			function = "qspi0"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_1 { | ||||
| 			pins = "gpio6"; | ||||
| 			function = "qspi1"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_2 { | ||||
| 			pins = "gpio5"; | ||||
| 			function = "qspi2"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_3 { | ||||
| 			pins = "gpio4"; | ||||
| 			function = "qspi3"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	mdio1_pins: mdio_pinmux { | ||||
| 		mux_0 { | ||||
| 			pins = "gpio36"; | ||||
| 			function = "mdc"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-up; | ||||
| 		}; | ||||
|  | ||||
| 		mux_1 { | ||||
| 			pins = "gpio37"; | ||||
| 			function = "mdio"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-up; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	phy_led_pins: phy_led_pins { | ||||
| 		gephy_led_pin { | ||||
| 			pins = "gpio46"; | ||||
| 			function = "led0"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-down; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	i2c_pins: i2c_pins { | ||||
| 		i2c_scl { | ||||
| 			pins = "gpio25"; | ||||
| 			function = "blsp2_i2c1"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
|  | ||||
| 		i2c_sda { | ||||
| 			pins = "gpio26"; | ||||
| 			function = "blsp2_i2c1"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	button_pins: button_pins { | ||||
| 		reset_button { | ||||
| 			pins = "gpio38"; | ||||
| 			function = "gpio"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-up; | ||||
| 		}; | ||||
| 	}; | ||||
| audio_pins: audio_pinmux { | ||||
| }; | ||||
|         leds_pins: leds_pins { | ||||
|                 led_5g { | ||||
|                         pins = "gpio34"; | ||||
|                         function = "gpio"; | ||||
|                         drive-strength = <8>; | ||||
|                         bias-pull-down; | ||||
|                 }; | ||||
|                 led_2g { | ||||
|                         pins = "gpio33"; | ||||
|                         function = "gpio"; | ||||
|                         drive-strength = <8>; | ||||
|                         bias-pull-down; | ||||
|                 }; | ||||
|                 led_sys { | ||||
|                         pins = "gpio26"; | ||||
|                         function = "gpio"; | ||||
|                         drive-strength = <8>; | ||||
|                         bias-pull-down; | ||||
|                 }; | ||||
| 		led_onekey { | ||||
|                         pins = "gpio28"; | ||||
|                         function = "gpio"; | ||||
|                         drive-strength = <8>; | ||||
|                         bias-pull-down; | ||||
|                 }; | ||||
|         }; | ||||
| }; | ||||
|  | ||||
| &soc { | ||||
| 	gpio_keys { | ||||
| 		compatible = "gpio-keys"; | ||||
| 		pinctrl-0 = <&button_pins>; | ||||
| 		pinctrl-names = "default"; | ||||
|  | ||||
| 		button@1 { | ||||
| 			label = "reset"; | ||||
| 			linux,code = <KEY_RESTART>; | ||||
| 			gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; | ||||
| 			linux,input-type = <1>; | ||||
| 			debounce-interval = <60>; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
|         leds { | ||||
|                 compatible = "gpio-leds"; | ||||
|                 pinctrl-0 = <&leds_pins>; | ||||
|                 pinctrl-names = "default"; | ||||
|  | ||||
|                 led_blue: led@34 { | ||||
|                         label = "led_5g"; | ||||
|                         gpios = <&tlmm 34 GPIO_ACTIVE_LOW>; | ||||
|                         linux,default-trigger = "led_5g"; | ||||
|                         default-state = "off"; | ||||
|                 }; | ||||
|                 led_green: led@33 { | ||||
|                         label = "led_2g"; | ||||
|                         gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; | ||||
|                         linux,default-trigger = "led_2g"; | ||||
|                         default-state = "off"; | ||||
|                 }; | ||||
|                 led_red: led@26 { | ||||
|                         label = "led_sys"; | ||||
|                         gpios = <&tlmm 26 GPIO_ACTIVE_LOW>; | ||||
|                         linux,default-trigger = "led_sys"; | ||||
|                         default-state = "off"; | ||||
|                 }; | ||||
| 		led@28 { | ||||
|                         label = "led_onekey"; | ||||
|                         gpios = <&tlmm 28 GPIO_ACTIVE_LOW>; | ||||
|                         linux,default-trigger = "led_onekey"; | ||||
|                         default-state = "off"; | ||||
|                 }; | ||||
|         }; | ||||
| }; | ||||
|  | ||||
| &q6v5_wcss { | ||||
| 	compatible = "qcom,ipq5018-q6-mpd"; | ||||
| 	#address-cells = <1>; | ||||
| 	#size-cells = <1>; | ||||
| 	ranges; | ||||
| 	firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 	reg = <0x0cd00000 0x4040>, | ||||
| 		<0x1938000 0x8>, | ||||
| 		<0x193d204 0x4>; | ||||
| 	reg-names = "qdsp6", | ||||
| 			"tcsr-msip", | ||||
| 			"tcsr-q6"; | ||||
| 	resets = <&gcc GCC_WCSSAON_RESET>, | ||||
| 			<&gcc GCC_WCSS_Q6_BCR>; | ||||
|  | ||||
| 	reset-names = "wcss_aon_reset", | ||||
| 			"wcss_q6_reset"; | ||||
|  | ||||
| 	clocks = <&gcc GCC_Q6_AXIS_CLK>, | ||||
| 		<&gcc GCC_WCSS_ECAHB_CLK>, | ||||
| 		<&gcc GCC_Q6_AXIM_CLK>, | ||||
| 		<&gcc GCC_Q6_AXIM2_CLK>, | ||||
| 		<&gcc GCC_Q6_AHB_CLK>, | ||||
| 		<&gcc GCC_Q6_AHB_S_CLK>, | ||||
| 		<&gcc GCC_WCSS_AXI_S_CLK>; | ||||
| 	clock-names = "gcc_q6_axis_clk", | ||||
| 		"gcc_wcss_ecahb_clk", | ||||
| 		"gcc_q6_axim_clk", | ||||
| 		"gcc_q6_axim2_clk", | ||||
| 		"gcc_q6_ahb_clk", | ||||
| 		"gcc_q6_ahb_s_clk", | ||||
| 		"gcc_wcss_axi_s_clk"; | ||||
|  | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 		memory-region = <&q6_mem_regions>, <&q6_etr_region>; | ||||
| 	#else | ||||
| 		memory-region = <&q6_mem_regions>, <&q6_etr_region>, | ||||
| 				<&q6_caldb_region>; | ||||
| 	#endif | ||||
|  | ||||
| 	qcom,rproc = <&q6v5_wcss>; | ||||
| 	qcom,bootargs_smem = <507>; | ||||
| 	boot-args = <0x1 0x4 0x3 0x0F 0x0 0x0>, | ||||
| 			<0x2 0x4 0x2 0x12 0x0 0x0>; | ||||
| 	status = "ok"; | ||||
| 	q6_wcss_pd1: remoteproc_pd1@4ab000 { | ||||
| 		compatible = "qcom,ipq5018-wcss-ahb-mpd"; | ||||
| 		reg = <0x4ab000 0x20>; | ||||
| 		reg-names = "rmb"; | ||||
| 		firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 		m3_firmware = "IPQ5018/m3_fw.mdt"; | ||||
| 		interrupts-extended = <&wcss_smp2p_in 8 0>, | ||||
| 					<&wcss_smp2p_in 9 0>, | ||||
| 					<&wcss_smp2p_in 12 0>, | ||||
| 					<&wcss_smp2p_in 11 0>; | ||||
| 		interrupt-names = "fatal", | ||||
| 					"ready", | ||||
| 					"spawn-ack", | ||||
| 					"stop-ack"; | ||||
|  | ||||
| 		resets = <&gcc GCC_WCSSAON_RESET>, | ||||
| 				<&gcc GCC_WCSS_BCR>, | ||||
| 				<&gcc GCC_CE_BCR>; | ||||
| 		reset-names = "wcss_aon_reset", | ||||
| 				"wcss_reset", | ||||
| 				"ce_reset"; | ||||
|  | ||||
| 		clocks = <&gcc GCC_WCSS_AHB_S_CLK>, | ||||
| 				<&gcc GCC_WCSS_ACMT_CLK>, | ||||
| 				<&gcc GCC_WCSS_AXI_M_CLK>; | ||||
| 		clock-names = "gcc_wcss_ahb_s_clk", | ||||
| 					"gcc_wcss_acmt_clk", | ||||
| 					"gcc_wcss_axi_m_clk"; | ||||
|  | ||||
| 		qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>; | ||||
|  | ||||
| 		qcom,smem-states = <&wcss_smp2p_out 8>, | ||||
| 					<&wcss_smp2p_out 9>, | ||||
| 					<&wcss_smp2p_out 10>; | ||||
| 		qcom,smem-state-names = "shutdown", | ||||
| 					"stop", | ||||
| 					"spawn"; | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 		memory-region = <&q6_ipq5018_data>, <&m3_dump>, | ||||
| 				<&q6_etr_region>; | ||||
| 	#else | ||||
| 		memory-region = <&q6_ipq5018_data>, <&m3_dump>, | ||||
| 				<&q6_etr_region>, <&q6_caldb_region>; | ||||
| 	#endif | ||||
|  | ||||
| 	}; | ||||
|  | ||||
| 	q6_wcss_pd2: remoteproc_pd2 { | ||||
| 		compatible = "qcom,ipq5018-wcss-pcie-mpd"; | ||||
| 		firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 		m3_firmware = "qcn6122/m3_fw.mdt"; | ||||
| 		interrupts-extended = <&wcss_smp2p_in 16 0>, | ||||
| 					<&wcss_smp2p_in 17 0>, | ||||
| 					<&wcss_smp2p_in 20 0>, | ||||
| 					<&wcss_smp2p_in 19 0>; | ||||
| 		interrupt-names = "fatal", | ||||
| 					"ready", | ||||
| 					"spawn-ack", | ||||
| 					"stop-ack"; | ||||
|  | ||||
| 		qcom,smem-states = <&wcss_smp2p_out 16>, | ||||
| 					<&wcss_smp2p_out 17>, | ||||
| 					<&wcss_smp2p_out 18>; | ||||
| 		qcom,smem-state-names = "shutdown", | ||||
| 					"stop", | ||||
| 					"spawn"; | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 		memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>, | ||||
| 				<&q6_qcn6122_etr_1>; | ||||
| 	#else | ||||
| 		memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>, | ||||
| 				<&q6_qcn6122_etr_1>, <&q6_qcn6122_caldb_1>; | ||||
| 	#endif | ||||
|  | ||||
| 	}; | ||||
|  | ||||
| 	q6_wcss_pd3: remoteproc_pd3 { | ||||
| 		compatible = "qcom,ipq5018-wcss-pcie-mpd"; | ||||
| 		firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 		interrupts-extended = <&wcss_smp2p_in 24 0>, | ||||
| 					<&wcss_smp2p_in 25 0>, | ||||
| 					<&wcss_smp2p_in 28 0>, | ||||
| 					<&wcss_smp2p_in 27 0>; | ||||
| 		interrupt-names = "fatal", | ||||
| 					"ready", | ||||
| 					"spawn-ack", | ||||
| 					"stop-ack"; | ||||
|  | ||||
| 		qcom,smem-states = <&wcss_smp2p_out 24>, | ||||
| 					<&wcss_smp2p_out 25>, | ||||
| 					<&wcss_smp2p_out 26>; | ||||
| 		qcom,smem-state-names = "shutdown", | ||||
| 					"stop", | ||||
| 					"spawn"; | ||||
| 	#ifdef	__IPQ_MEM_PROFILE_256_MB__ | ||||
| 		memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>, | ||||
| 				<&q6_qcn6122_etr_2>; | ||||
| 	#else | ||||
| 		memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>, | ||||
| 				<&q6_qcn6122_etr_2>, <&q6_qcn6122_caldb_2>; | ||||
| 	#endif | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| &i2c_0 { | ||||
| 	pinctrl-0 = <&i2c_pins>; | ||||
| 	pinctrl-names = "default"; | ||||
| 	status = "disabled"; | ||||
| }; | ||||
|  | ||||
| &wifi0 { | ||||
| 	/* IPQ5018 */ | ||||
| 	qcom,multipd_arch; | ||||
| 	qcom,rproc = <&q6_wcss_pd1>; | ||||
| 	qcom,userpd-subsys-name = "q6v5_wcss_userpd1"; | ||||
| #ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 	qcom,tgt-mem-mode = <2>; | ||||
| #else | ||||
| 	qcom,tgt-mem-mode = <1>; | ||||
| #endif | ||||
| 	qcom,board_id = <0x24>; | ||||
| #ifdef __CNSS2__ | ||||
| 	qcom,bdf-addr = <0x4C400000 0x4C400000 0x4C400000 0x0 0x0>; | ||||
| 	qcom,caldb-addr = <0x4D400000 0x4D400000 0 0 0>; | ||||
| 	qcom,caldb-size = <0x200000>; | ||||
| 	mem-region = <&q6_ipq5018_data>; | ||||
| #else | ||||
| 	memory-region = <&q6_ipq5018_data>; | ||||
| #endif | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &wifi1 { | ||||
| 	/* QCN6122 5G */ | ||||
| 	qcom,multipd_arch; | ||||
| 	qcom,userpd-subsys-name = "q6v5_wcss_userpd2"; | ||||
| 	qcom,rproc = <&q6_wcss_pd2>; | ||||
| #ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 	qcom,tgt-mem-mode = <2>; | ||||
| #else | ||||
| 	qcom,tgt-mem-mode = <1>; | ||||
| #endif | ||||
| 	qcom,board_id = <0x50>; | ||||
| #ifdef __CNSS2__ | ||||
| 	qcom,bdf-addr = <0x4D600000 0x4D600000 0x4D300000 0x0 0x0>; | ||||
| 	qcom,caldb-addr = <0x4E800000 0x4E800000 0 0 0>; | ||||
| 	qcom,caldb-size = <0x500000>; | ||||
| 	mem-region = <&q6_qcn6122_data1>; | ||||
| #else | ||||
| 	memory-region = <&q6_qcn6122_data1>; | ||||
| #endif | ||||
| 	status = "disabled"; | ||||
| }; | ||||
|  | ||||
| &wifi2 { | ||||
| 	/* QCN6122 6G */ | ||||
| 	qcom,multipd_arch; | ||||
| 	qcom,userpd-subsys-name = "q6v5_wcss_userpd3"; | ||||
| 	qcom,rproc = <&q6_wcss_pd3>; | ||||
| #ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 	qcom,tgt-mem-mode = <2>; | ||||
| #else | ||||
| 	qcom,tgt-mem-mode = <1>; | ||||
| #endif | ||||
| 	qcom,board_id = <0xb0>; | ||||
| #ifdef __CNSS2__ | ||||
| 	qcom,bdf-addr = <0x4ED00000 0x4ED00000 0x4E400000 0x0 0x0>; | ||||
| 	qcom,caldb-addr = <0x4FF00000 0x4FF00000 0 0 0>; | ||||
| 	qcom,caldb-size = <0x500000>; | ||||
| 	mem-region = <&q6_qcn6122_data2>; | ||||
| #else | ||||
| 	memory-region = <&q6_qcn6122_data2>; | ||||
| #endif | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
|  | ||||
| &usb3 { | ||||
| 	status = "ok"; | ||||
| 	device-power-gpio = <&tlmm 24 1>; | ||||
| }; | ||||
|  | ||||
| &dwc_0 { | ||||
| 	/delete-property/ #phy-cells; | ||||
| 	/delete-property/ phys; | ||||
| 	/delete-property/ phy-names; | ||||
| }; | ||||
| &hs_m31phy_0 { | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &eud { | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &pcie_x1 { | ||||
| 	#status = "disabled"; | ||||
| 	#perst-gpio = <&tlmm 18 1>; | ||||
| 	perst-gpio = <&tlmm 18 GPIO_ACTIVE_LOW>; | ||||
| }; | ||||
|  | ||||
| &pcie_x2 { | ||||
| 	#status = "disabled"; | ||||
| 	#perst-gpio = <&tlmm 15 1>; | ||||
| 	perst-gpio = <&tlmm 15 GPIO_ACTIVE_LOW>; | ||||
| }; | ||||
|  | ||||
| &pcie_x1_rp { | ||||
|         status = "disabled"; | ||||
|  | ||||
| 	mhi_0: qcom,mhi@0 { | ||||
| 		reg = <0 0 0 0 0 >; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| &pcie_x2_rp { | ||||
|         status = "disabled"; | ||||
|  | ||||
| 	mhi_1: qcom,mhi@1 { | ||||
| 		reg = <0 0 0 0 0 >; | ||||
|  | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| @@ -0,0 +1,731 @@ | ||||
| /dts-v1/; | ||||
| /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. | ||||
|  * Copyright (c) 2025, Shubham Vishwakarma <shubhamvis98@fossfrog.in>. | ||||
|  * | ||||
|  * Permission to use, copy, modify, and/or distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include "ipq5018.dtsi" | ||||
| #include <dt-bindings/input/input.h> | ||||
|  | ||||
| / { | ||||
| 	#address-cells = <0x2>; | ||||
| 	#size-cells = <0x2>; | ||||
| 	model = "Indio UM-335AX"; | ||||
| 	compatible = "indio,um-335ax", "qcom,ipq5018-ap-mp03.1", "qcom,ipq5018-mp03.1", "qcom,ipq5018"; | ||||
| 	interrupt-parent = <&intc>; | ||||
|  | ||||
| 	aliases { | ||||
| 		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ | ||||
| 		serial0 = &blsp1_uart1; | ||||
| 		serial1 = &blsp1_uart2; | ||||
| 		ethernet0 = "/soc/dp1"; | ||||
| 		ethernet1 = "/soc/dp2"; | ||||
| 		led-boot = &led_red; | ||||
| 		led-failsafe = &led_red; | ||||
| 		led-running = &led_red; | ||||
| 		led-upgrade = &led_red; | ||||
|  | ||||
| 	}; | ||||
|  | ||||
| 	chosen { | ||||
| 		bootargs = "console=ttyMSM0,115200,n8 rw init=/init"; | ||||
| 		bootargs-append = " swiotlb=1 coherent_pool=2M"; | ||||
| 		stdout-path = "serial0"; | ||||
| 	}; | ||||
|  | ||||
| 	gpio-watchdog { | ||||
| 		compatible = "linux,wdt-gpio"; | ||||
| 		gpios = <&tlmm 27 GPIO_ACTIVE_LOW>; | ||||
| 		hw_algo = "toggle"; | ||||
| 		hw_margin_ms = <5000>; | ||||
| 		always-running; | ||||
| 	}; | ||||
|  | ||||
| 	reserved-memory { | ||||
| 		q6_mem_regions: q6_mem_regions@4B000000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4B000000 0x0 0x1800000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_ipq5018_data: q6_ipq5018_data@4C400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4C400000 0x0 0xE00000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump: m3_dump@4C800000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4C800000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_etr_region: q6_etr_dump@4C900000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4C900000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_caldb_region: q6_caldb_region@4CA00000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4CA00000 0x0 0x200000>; | ||||
| 		}; | ||||
|  | ||||
| 		qcn9000_pcie0: qcn9000_pcie0@4cc00000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4CC00000 0x0 0x2600000>; | ||||
| 		}; | ||||
|  | ||||
| 	#if defined(__CNSS2__) | ||||
| 		mhi_region1: dma_pool1@4F200000 { | ||||
| 			compatible = "shared-dma-pool"; | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4F200000 0x0 0x900000>; | ||||
| 		}; | ||||
| 	#endif | ||||
| 	}; | ||||
|  | ||||
| 	soc { | ||||
| 		serial@78af000 { | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		blsp1_uart2: serial@78b0000 { | ||||
| 			pinctrl-0 = <&blsp1_uart_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 		}; | ||||
|  | ||||
| 		qpic_bam: dma@7984000{ | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		nand: qpic-nand@79b0000 { | ||||
| 			pinctrl-0 = <&qspi_nand_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		spi_0: spi@78b5000 { /* BLSP1 QUP0 */ | ||||
| 			pinctrl-0 = <&blsp0_spi_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			cs-select = <0>; | ||||
| 			status = "ok"; | ||||
|  | ||||
| 			m25p80@0 { | ||||
| 				#address-cells = <1>; | ||||
| 				#size-cells = <1>; | ||||
| 				reg = <0>; | ||||
| 				compatible = "n25q128a11"; | ||||
| 				linux,modalias = "m25p80", "n25q128a11"; | ||||
| 				spi-max-frequency = <50000000>; | ||||
| 				use-default-sizes; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		mdio0: mdio@88000 { | ||||
| 			status = "ok"; | ||||
|  | ||||
| 			ethernet-phy@0 { | ||||
| 				reg = <7>; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		mdio1: mdio@90000 { | ||||
| 			status = "ok"; | ||||
| 			pinctrl-0 = <&mdio1_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			phy-reset-gpio = <&tlmm 39 0>; | ||||
|  | ||||
| 			ethernet-phy@0 { | ||||
| 				reg = <28>; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		ess-instance { | ||||
| 			num_devices = <0x1>; | ||||
| 			ess-switch@0x39c00000 { | ||||
| 				switch_mac_mode = <0xf>; /* mac mode for uniphy instance*/ | ||||
| 				cmnblk_clk = "internal_96MHz"; /* cmnblk clk*/ | ||||
| 				qcom,port_phyinfo { | ||||
| 					port@0 { | ||||
| 						port_id = <1>; | ||||
| 						phy_address = <7>; | ||||
| 						mdiobus = <&mdio0>; | ||||
| 					}; | ||||
| 					port@1 { | ||||
| 						port_id = <2>; | ||||
| 						phy_address = <0x1c>; | ||||
| 						mdiobus = <&mdio1>; | ||||
| 						port_mac_sel = "QGMAC_PORT"; | ||||
| 					}; | ||||
| 				}; | ||||
| 				led_source@0 { | ||||
| 					source = <0>; | ||||
| 					mode = "normal"; | ||||
| 					speed = "all"; | ||||
| 					blink_en = "enable"; | ||||
| 					active = "high"; | ||||
| 				}; | ||||
| 			}; | ||||
| 				ess-switch1@1 { | ||||
| 				compatible = "qcom,ess-switch-qca83xx"; | ||||
| 				device_id = <1>; | ||||
| 				switch_access_mode = "mdio"; | ||||
| 				mdio-bus = <&mdio1>; | ||||
| 				reset_gpio = <0x28>; | ||||
| 				switch_cpu_bmp = <0x40>;  /* cpu port bitmap */ | ||||
| 				switch_lan_bmp = <0x1e>; /* lan port bitmap */ | ||||
| 				switch_wan_bmp = <0x0>;  /* wan port bitmap */ | ||||
| 				qca,ar8327-initvals = < | ||||
| 						0x00004 0x7600000   /* PAD0_MODE */ | ||||
| 						0x00008 0x1000000   /* PAD5_MODE */ | ||||
| 						0x0000c 0x80        /* PAD6_MODE */ | ||||
| 						0x00010 0x2613a0    /* PORT6 FORCE MODE*/ | ||||
| 						0x000e4 0xaa545     /* MAC_POWER_SEL */ | ||||
| 						0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||
| 						0x0007c 0x4e        /* PORT0_STATUS */ | ||||
| 						0x00094 0x4e        /* PORT6_STATUS */ | ||||
| 				>; | ||||
| 				qcom,port_phyinfo { | ||||
| 					port@0 { | ||||
| 						port_id = <1>; | ||||
| 						phy_address = <28>; | ||||
| 					}; | ||||
| 				}; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		dp1 { | ||||
| 			device_type = "network"; | ||||
| 			compatible = "qcom,nss-dp"; | ||||
| 			clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>; | ||||
| 			clock-names = "nss-snoc-gmac-axi-clk"; | ||||
| 			qcom,id = <1>; | ||||
| 			reg = <0x39C00000 0x10000>; | ||||
| 			interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; | ||||
| 			qcom,mactype = <2>; | ||||
| 			qcom,link-poll = <1>; | ||||
| 			qcom,phy-mdio-addr = <7>; | ||||
| 			mdio-bus = <&mdio0>; | ||||
| 			local-mac-address = [000000000000]; | ||||
| 			phy-mode = "sgmii"; | ||||
| 		}; | ||||
|  | ||||
| 		dp2 { | ||||
| 			device_type = "network"; | ||||
| 			compatible = "qcom,nss-dp"; | ||||
| 			clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>; | ||||
| 			clock-names = "nss-snoc-gmac-axi-clk"; | ||||
| 			qcom,id = <2>; | ||||
| 			reg = <0x39D00000 0x10000>; | ||||
| 			interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>; | ||||
| 			qcom,mactype = <2>; | ||||
| 			qcom,link-poll = <1>; | ||||
| 			qcom,phy-mdio-addr = <28>; | ||||
| 			mdio-bus = <&mdio1>; | ||||
| 			local-mac-address = [000000000000]; | ||||
| 			phy-mode = "sgmii"; | ||||
| 		}; | ||||
|  | ||||
| 		qcom,test@0 { | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		nss-macsec1 { | ||||
| 			compatible = "qcom,nss-macsec"; | ||||
| 			phy_addr = <0x1c>; | ||||
| 			mdiobus = <&mdio1>; | ||||
| 		}; | ||||
|  | ||||
| 		lpass: lpass@0xA000000{ | ||||
| 			status = "disabled"; | ||||
| 		}; | ||||
|  | ||||
| 		pcm: pcm@0xA3C0000{ | ||||
| 			pinctrl-0 = <&audio_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			status = "disabled"; | ||||
| 		}; | ||||
|  | ||||
| 		pcm_lb: pcm_lb@0 { | ||||
| 			status = "disabled"; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	thermal-zones { | ||||
| 		status = "ok"; | ||||
| 	}; | ||||
|  | ||||
| }; | ||||
|  | ||||
| &tlmm { | ||||
| 	pinctrl-0 = <&blsp0_uart_pins &phy_led_pins>; | ||||
| 	pinctrl-names = "default"; | ||||
|  | ||||
| 	blsp0_uart_pins: uart_pins { | ||||
| 		blsp0_uart_rx_tx { | ||||
| 			pins = "gpio20", "gpio21"; | ||||
| 			function = "blsp0_uart0"; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	blsp1_uart_pins: blsp1_uart_pins { | ||||
| 		blsp1_uart_rx_tx { | ||||
| 			pins = "gpio22", "gpio24", "gpio23", "gpio25"; | ||||
| 			function = "blsp1_uart2"; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	blsp0_spi_pins: blsp0_spi_pins { | ||||
| 		mux { | ||||
| 			pins = "gpio10", "gpio11", "gpio12", "gpio13"; | ||||
| 			function = "blsp0_spi"; | ||||
| 			drive-strength = <2>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	qspi_nand_pins: qspi_nand_pins { | ||||
| 		qspi_clock { | ||||
| 			pins = "gpio9"; | ||||
| 			function = "qspi_clk"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_cs { | ||||
| 			pins = "gpio8"; | ||||
| 			function = "qspi_cs"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_0 { | ||||
| 			pins = "gpio7"; | ||||
| 			function = "qspi0"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_1 { | ||||
| 			pins = "gpio6"; | ||||
| 			function = "qspi1"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_2 { | ||||
| 			pins = "gpio5"; | ||||
| 			function = "qspi2"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_3 { | ||||
| 			pins = "gpio4"; | ||||
| 			function = "qspi3"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	mdio1_pins: mdio_pinmux { | ||||
| 		mux_0 { | ||||
| 			pins = "gpio36"; | ||||
| 			function = "mdc"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-up; | ||||
| 		}; | ||||
|  | ||||
| 		mux_1 { | ||||
| 			pins = "gpio37"; | ||||
| 			function = "mdio"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-up; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	phy_led_pins: phy_led_pins { | ||||
| 		gephy_led_pin { | ||||
| 			pins = "gpio46"; | ||||
| 			function = "led0"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-down; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	i2c_pins: i2c_pins { | ||||
| 		i2c_scl { | ||||
| 			pins = "gpio25"; | ||||
| 			function = "blsp2_i2c1"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
|  | ||||
| 		i2c_sda { | ||||
| 			pins = "gpio26"; | ||||
| 			function = "blsp2_i2c1"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	button_pins: button_pins { | ||||
| 		reset_button { | ||||
| 			pins = "gpio38"; | ||||
| 			function = "gpio"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-up; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	audio_pins: audio_pinmux { | ||||
| 	}; | ||||
|  | ||||
| 	leds_pins: leds_pins { | ||||
| 		led_blue: led_5g { | ||||
| 			label = "led_5g"; | ||||
| 			pins = "gpio34"; | ||||
| 			function = "gpio"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-down; | ||||
| 		}; | ||||
|  | ||||
| 		led_green: led_2g { | ||||
| 			label = "led_2g"; | ||||
| 			pins = "gpio33"; | ||||
| 			function = "gpio"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-down; | ||||
| 		}; | ||||
|  | ||||
| 		led_red: led_sys { | ||||
| 			label = "led_sys"; | ||||
| 			pins = "gpio26"; | ||||
| 			function = "gpio"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-down; | ||||
| 		}; | ||||
|  | ||||
| 		led_onekey { | ||||
| 			pins = "gpio28"; | ||||
| 			function = "gpio"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-down; | ||||
| 		}; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| &soc { | ||||
| 	gpio_keys { | ||||
| 		compatible = "gpio-keys"; | ||||
| 		pinctrl-0 = <&button_pins>; | ||||
| 		pinctrl-names = "default"; | ||||
|  | ||||
| 		button@1 { | ||||
| 			label = "reset"; | ||||
| 			linux,code = <KEY_RESTART>; | ||||
| 			gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; | ||||
| 			linux,input-type = <1>; | ||||
| 			debounce-interval = <60>; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	leds { | ||||
| 		compatible = "gpio-leds"; | ||||
| 		pinctrl-0 = <&leds_pins>; | ||||
| 		pinctrl-names = "default"; | ||||
|  | ||||
| 		led@33 { | ||||
| 			label = "led_5g"; | ||||
| 			gpios = <&tlmm 34 GPIO_ACTIVE_LOW>; | ||||
| 			linux,default-trigger = "led_5g"; | ||||
| 			default-state = "off"; | ||||
| 		}; | ||||
| 		led@34 { | ||||
| 			label = "led_2g"; | ||||
| 			gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; | ||||
| 			linux,default-trigger = "led_2g"; | ||||
| 			default-state = "off"; | ||||
| 		}; | ||||
| 		led@26 { | ||||
| 			label = "led_sys"; | ||||
| 			gpios = <&tlmm 26 GPIO_ACTIVE_LOW>; | ||||
| 			linux,default-trigger = "led_sys"; | ||||
| 			default-state = "on"; | ||||
| 		}; | ||||
| 		led@28 { | ||||
| 			label = "led_onekey"; | ||||
| 			gpios = <&tlmm 28 GPIO_ACTIVE_LOW>; | ||||
| 			linux,default-trigger = "led_onekey"; | ||||
| 			default-state = "off"; | ||||
| 		}; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| &q6v5_wcss { | ||||
| 	compatible = "qcom,ipq5018-q6-mpd"; | ||||
| 	#address-cells = <1>; | ||||
| 	#size-cells = <1>; | ||||
| 	ranges; | ||||
| 	firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 	reg = <0x0cd00000 0x4040>, | ||||
| 		<0x1938000 0x8>, | ||||
| 		<0x193d204 0x4>; | ||||
| 	reg-names = "qdsp6", | ||||
| 			"tcsr-msip", | ||||
| 			"tcsr-q6"; | ||||
| 	resets = <&gcc GCC_WCSSAON_RESET>, | ||||
| 			<&gcc GCC_WCSS_Q6_BCR>; | ||||
|  | ||||
| 	reset-names = "wcss_aon_reset", | ||||
| 			"wcss_q6_reset"; | ||||
|  | ||||
| 	clocks = <&gcc GCC_Q6_AXIS_CLK>, | ||||
| 		<&gcc GCC_WCSS_ECAHB_CLK>, | ||||
| 		<&gcc GCC_Q6_AXIM_CLK>, | ||||
| 		<&gcc GCC_Q6_AXIM2_CLK>, | ||||
| 		<&gcc GCC_Q6_AHB_CLK>, | ||||
| 		<&gcc GCC_Q6_AHB_S_CLK>, | ||||
| 		<&gcc GCC_WCSS_AXI_S_CLK>; | ||||
| 	clock-names = "gcc_q6_axis_clk", | ||||
| 		"gcc_wcss_ecahb_clk", | ||||
| 		"gcc_q6_axim_clk", | ||||
| 		"gcc_q6_axim2_clk", | ||||
| 		"gcc_q6_ahb_clk", | ||||
| 		"gcc_q6_ahb_s_clk", | ||||
| 		"gcc_wcss_axi_s_clk"; | ||||
|  | ||||
| 	memory-region = <&q6_mem_regions>, <&q6_etr_region>, | ||||
| 			<&q6_caldb_region>; | ||||
|  | ||||
| 	qcom,rproc = <&q6v5_wcss>; | ||||
| 	qcom,bootargs_smem = <507>; | ||||
| 	boot-args = <0x1 0x4 0x3 0x0F 0x0 0x0>, | ||||
| 			<0x2 0x4 0x2 0x12 0x0 0x0>; | ||||
| 	status = "ok"; | ||||
| 	q6_wcss_pd1: remoteproc_pd1@4ab000 { | ||||
| 		compatible = "qcom,ipq5018-wcss-ahb-mpd"; | ||||
| 		reg = <0x4ab000 0x20>; | ||||
| 		reg-names = "rmb"; | ||||
| 		firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 		m3_firmware = "IPQ5018/m3_fw.mdt"; | ||||
| 		interrupts-extended = <&wcss_smp2p_in 8 0>, | ||||
| 					<&wcss_smp2p_in 9 0>, | ||||
| 					<&wcss_smp2p_in 12 0>, | ||||
| 					<&wcss_smp2p_in 11 0>; | ||||
| 		interrupt-names = "fatal", | ||||
| 					"ready", | ||||
| 					"spawn-ack", | ||||
| 					"stop-ack"; | ||||
|  | ||||
| 		resets = <&gcc GCC_WCSSAON_RESET>, | ||||
| 				<&gcc GCC_WCSS_BCR>, | ||||
| 				<&gcc GCC_CE_BCR>; | ||||
| 		reset-names = "wcss_aon_reset", | ||||
| 				"wcss_reset", | ||||
| 				"ce_reset"; | ||||
|  | ||||
| 		clocks = <&gcc GCC_WCSS_AHB_S_CLK>, | ||||
| 				<&gcc GCC_WCSS_ACMT_CLK>, | ||||
| 				<&gcc GCC_WCSS_AXI_M_CLK>; | ||||
| 		clock-names = "gcc_wcss_ahb_s_clk", | ||||
| 					"gcc_wcss_acmt_clk", | ||||
| 					"gcc_wcss_axi_m_clk"; | ||||
|  | ||||
| 		qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>; | ||||
|  | ||||
| 		qcom,smem-states = <&wcss_smp2p_out 8>, | ||||
| 					<&wcss_smp2p_out 9>, | ||||
| 					<&wcss_smp2p_out 10>; | ||||
| 		qcom,smem-state-names = "shutdown", | ||||
| 					"stop", | ||||
| 					"spawn"; | ||||
| 		memory-region = <&q6_ipq5018_data>, <&m3_dump>, | ||||
| 				<&q6_etr_region>, <&q6_caldb_region>; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| &i2c_0 { | ||||
| 	pinctrl-0 = <&i2c_pins>; | ||||
| 	pinctrl-names = "default"; | ||||
| 	// status = "disabled"; | ||||
| }; | ||||
|  | ||||
| &usb3 { | ||||
| 	status = "ok"; | ||||
| 	device-power-gpio = <&tlmm 24 1>; | ||||
| }; | ||||
|  | ||||
| &dwc_0 { | ||||
| 	/delete-property/ #phy-cells; | ||||
| 	/delete-property/ phys; | ||||
| 	/delete-property/ phy-names; | ||||
| }; | ||||
|  | ||||
| &blsp1_uart1 { | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &ssuniphy_0 { | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &hs_m31phy_0 { | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &eud { | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &pcie_x1 { | ||||
| 	perst-gpio = <&tlmm 18 GPIO_ACTIVE_LOW>; | ||||
| }; | ||||
|  | ||||
| &pcie_x2 { | ||||
| 	status = "ok"; | ||||
| 	perst-gpio = <&tlmm 15 GPIO_ACTIVE_LOW>; | ||||
| }; | ||||
|  | ||||
| &wcss { | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &pcie_x2phy { | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &pcie_x1_rp { | ||||
| 	status = "disabled"; | ||||
|  | ||||
| 	mhi_0: qcom,mhi@0 { | ||||
| 		reg = <0 0 0 0 0 >; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| &pcie_x2_rp { | ||||
| 	status = "ok"; | ||||
|  | ||||
| 	mhi_1: qcom,mhi@1 { | ||||
| 		reg = <0 0 0 0 0 >; | ||||
| 		qrtr_instance_id = <0x20>; | ||||
| 		qti,disable-rddm-prealloc; | ||||
| 		qti,rddm-seg-len = <0x1000>; | ||||
| 		#address-cells = <0x2>; | ||||
| 		#size-cells = <0x2>; | ||||
| #if defined(__CNSS2__) | ||||
| 		memory-region = <0>,<&mhi_region1>; | ||||
| #else | ||||
| 		base-addr = <0x4CB00000>; | ||||
| 		m3-dump-addr = <0x4DF00000>; | ||||
| 		etr-addr = <0x4E000000>; | ||||
| 		qcom,caldb-addr = <0x4E100000>; | ||||
| 		pageable-addr = <0x4E900000>; | ||||
| 		qcom,tgt-mem-mode = <0x1>; | ||||
| #endif | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| &wifi0 { | ||||
| 	/* IPQ5018 */ | ||||
| 	qcom,multipd_arch; | ||||
| 	qcom,rproc = <&q6_wcss_pd1>; | ||||
| 	qcom,userpd-subsys-name = "q6v5_wcss_userpd1"; | ||||
| 	qcom,tgt-mem-mode = <1>; | ||||
| 	qcom,board_id = <0x24>; | ||||
| #ifdef __CNSS2__ | ||||
| 	qcom,bdf-addr = <0x4C400000 0x4C400000 0x4C400000 0x0 0x0>; | ||||
| 	qcom,caldb-addr = <0x4D400000 0x4D400000 0 0 0>; | ||||
| 	qcom,caldb-size = <0x200000>; | ||||
| 	mem-region = <&q6_ipq5018_data>; | ||||
| #else | ||||
| 	memory-region = <&q6_ipq5018_data>; | ||||
| #endif | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &wifi3 { | ||||
| 	/* QCN9000 5G */ | ||||
| 	board_id = <0xa0>; | ||||
| 	hremote_node = <&qcn9000_pcie0>; | ||||
| #ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 	/* QCN9000 tgt-mem-mode=2 layout - 17MB | ||||
| 	 * +=========+==============+=========+ | ||||
| 	 * |  Region | Start Offset |   Size  | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * | HREMOTE |  0x4C900000  |   11MB  | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * | M3 Dump |  0x4D400000  |   1MB   | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * |   ETR   |  0x4D500000  |   1MB   | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * | Pageable|  0x4D600000  |   4MB   | | ||||
| 	 * +==================================+ | ||||
| 	 */ | ||||
| 	base-addr = <0x4C900000>; | ||||
| 	m3-dump-addr = <0x4D400000>; | ||||
| 	etr-addr = <0x4D500000>; | ||||
| 	caldb-addr = <0>; | ||||
| 	pageable-addr = <0x4D600000>; | ||||
| 	caldb-size = <0>; | ||||
| 	hremote-size = <0xB00000>; | ||||
| 	tgt-mem-mode = <0x2>; | ||||
| 	pageable-size = <0x400000>; | ||||
| #elif __IPQ_MEM_PROFILE_512_MB__ | ||||
| 	/* QCN9000 tgt-mem-mode=1 layout - 26MB | ||||
| 	 * +=========+==============+=========+ | ||||
| 	 * |  Region | Start Offset |   Size  | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * | HREMOTE |  0x4CB00000  |   12MB  | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * | M3 Dump |  0x4D700000  |   1MB   | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * |   ETR   |  0x4D800000  |   1MB   | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * |  Caldb  |  0x4D900000  |   8MB   | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * | Pageable|  0x4E100000  |   4MB   | | ||||
| 	 * +==================================+ | ||||
| 	 */ | ||||
| 	base-addr = <0x4CB00000>; | ||||
| 	m3-dump-addr = <0x4D700000>; | ||||
| 	etr-addr = <0x4D800000>; | ||||
| 	caldb-addr = <0x4D900000>; | ||||
| 	pageable-addr = <0x4E100000>; | ||||
| 	caldb-size = <0x800000>; | ||||
| 	hremote-size = <0xC00000>; | ||||
| 	tgt-mem-mode = <0x1>; | ||||
| 	pageable-size = <0x400000>; | ||||
| #else | ||||
| 	/* QCN9000 tgt-mem-mode=0 layout - 53MB | ||||
| 	 * +=========+==============+=========+ | ||||
| 	 * |  Region | Start Offset |   Size  | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * | HREMOTE |  0x4CB00000  |   35MB  | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * | M3 Dump |  0x4EE00000  |   1MB   | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * |   ETR   |  0x4EF00000  |   1MB   | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * |  Caldb  |  0x4F000000  |   8MB   | | ||||
| 	 * +---------+--------------+---------+ | ||||
| 	 * | Pageable|  0x4F800000  |   8MB   | | ||||
| 	 * +==================================+ | ||||
| 	 */ | ||||
| 	base-addr = <0x4CB00000>; | ||||
| 	m3-dump-addr = <0x4EE00000>; | ||||
| 	etr-addr = <0x4EF00000>; | ||||
| 	caldb-addr = <0x4F000000>; | ||||
| 	pageable-addr = <0x4F800000>; | ||||
| 	hremote-size = <0x2300000>; | ||||
| 	caldb-size = <0x800000>; | ||||
| 	tgt-mem-mode = <0x0>; | ||||
| 	pageable-size = <0x800000>; | ||||
| #endif | ||||
| 	status = "ok"; | ||||
| }; | ||||
| @@ -0,0 +1,941 @@ | ||||
| /dts-v1/; | ||||
| /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. | ||||
|  * | ||||
|  * Permission to use, copy, modify, and/or distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include "ipq5018.dtsi" | ||||
| #include <dt-bindings/input/input.h> | ||||
|  | ||||
| / { | ||||
| 	#address-cells = <0x2>; | ||||
| 	#size-cells = <0x2>; | ||||
| 	model = "Indio UM-525AXM"; | ||||
| 	compatible = "indio,um-525axm", "qcom,ipq5018-mp03.5-c1", "qcom,ipq5018"; | ||||
| 	interrupt-parent = <&intc>; | ||||
|  | ||||
| 	aliases { | ||||
| 		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ | ||||
| 		serial0 = &blsp1_uart1; | ||||
| 		serial1 = &blsp1_uart2; | ||||
| 		ethernet0 = "/soc/dp1"; | ||||
| 		ethernet1 = "/soc/dp2"; | ||||
|                 //led-failsafe = &led_red; | ||||
|                 //led-running = &led_green; | ||||
|                 //led-upgrade = &led_green; | ||||
|                 //led-gateway = &led_blue; | ||||
|                 //led-factory = &led_blue; | ||||
| 	}; | ||||
|  | ||||
| 	chosen { | ||||
| 		bootargs = "console=ttyMSM0,115200,n8 rw init=/init"; | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 		bootargs-append = " swiotlb=1"; | ||||
| 	#else | ||||
| 		bootargs-append = " swiotlb=1 coherent_pool=2M"; | ||||
| 	#endif | ||||
| 		stdout-path = "serial0"; | ||||
| 	}; | ||||
|  | ||||
| 	reserved-memory { | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 	/*                   256 MB Profile | ||||
| 	 * +==========+==============+=========================+ | ||||
| 	 * |          |              |                         | | ||||
| 	 * |  Region  | Start Offset |          Size           | | ||||
| 	 * |          |              |                         | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    NSS   |  0x40000000  |           8MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   Linux  |  0x40800000  | Depends on total memory | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   uboot  |  0x4A600000  |           4MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    SBL   |  0x4AA00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   smem   |  0x4AB00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    TZ    |  0x4AC00000  |           4MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    Q6    |              |                         | | ||||
| 	 * |   code/  |  0x4B000000  |          20MB           | | ||||
| 	 * |   data   |              |                         | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |   data   |  0x4C400000  |          13MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |  M3 Dump |  0x4D100000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |   QDSS   |  0x4D200000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |   data   |  0x4D300000  |          15MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |  M3 Dump |  0x4E200000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |   QDSS   |  0x4E300000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |   data   |  0x4E400000  |          15MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |  M3 Dump |  0x4F300000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |   QDSS   |  0x4F400000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |                                                   | | ||||
| 	 * |            Rest of the memory for Linux           | | ||||
| 	 * |                                                   | | ||||
| 	 * +===================================================+ | ||||
| 	 */ | ||||
| 		q6_mem_regions: q6_mem_regions@4B000000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4B000000 0x0 0x4500000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_code_data: q6_code_data@4B000000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4B000000 0x0 0x1400000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_ipq5018_data: q6_ipq5018_data@4C400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4C400000 0x0 0xD00000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump: m3_dump@4D100000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D100000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_etr_region: q6_etr_dump@4D200000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D200000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_data1: q6_qcn6122_data1@4D300000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D300000 0x0 0xF00000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E200000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E200000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E300000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E300000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_data2: q6_qcn6122_data2@4E400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E400000 0x0 0xF00000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump_qcn6122_2: m3_dump_qcn6122_2@4F300000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4F300000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_etr_2: q6_qcn6122_etr_2@4F400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4F400000 0x0 0x100000>; | ||||
| 		}; | ||||
| 		 | ||||
| 	#else | ||||
| 	/*                 512MB/1GB Profiles | ||||
| 	 * +==========+==============+=========================+ | ||||
| 	 * |          |              |                         | | ||||
| 	 * |  Region  | Start Offset |          Size           | | ||||
| 	 * |          |              |                         | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    NSS   |  0x40000000  |          16MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   Linux  |  0x41000000  | Depends on total memory | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   uboot  |  0x4A600000  |           4MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    SBL   |  0x4AA00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   smem   |  0x4AB00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    TZ    |  0x4AC00000  |           4MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    Q6    |              |                         | | ||||
| 	 * |   code/  |  0x4B000000  |          20MB           | | ||||
| 	 * |   data   |              |                         | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |   data   |  0x4C400000  |          14MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |  M3 Dump |  0x4D200000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |   QDSS   |  0x4D300000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |  Caldb   |  0x4D400000  |           2MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |   data   |  0x4D600000  |          16MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |  M3 Dump |  0x4E600000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |   QDSS   |  0x4E700000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |  Caldb   |  0x4E800000  |           5MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |   data   |  0x4ED00000  |          16MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |  M3 Dump |  0x4FD00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |   QDSS   |  0x4FE00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |  Caldb   |  0x4FF00000  |           5MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |                                                   | | ||||
| 	 * |            Rest of the memory for Linux           | | ||||
| 	 * |                                                   | | ||||
| 	 * +===================================================+ | ||||
| 	 */ | ||||
| 		q6_mem_regions: q6_mem_regions@4B000000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4B000000 0x0 0x5400000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_code_data: q6_code_data@4B000000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4B000000 0x0 01400000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_ipq5018_data: q6_ipq5018_data@4C400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4C400000 0x0 0xE00000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump: m3_dump@4D200000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D200000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_etr_region: q6_etr_dump@4D300000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D300000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_caldb_region: q6_caldb_region@4D400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D400000 0x0 0x200000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_data1: q6_qcn6122_data1@4D600000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D600000 0x0 0x1000000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E600000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E600000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E700000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E700000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_caldb_1: q6_qcn6122_caldb_1@4E800000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E800000 0x0 0x500000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_data2: q6_qcn6122_data2@4E900000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4ED00000 0x0 0x1000000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump_qcn6122_2: m3_dump_qcn6122_2@4FD00000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4FD00000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_etr_2: q6_qcn6122_etr_2@4FE00000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4FE00000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_caldb_2: q6_qcn6122_caldb_2@4FF00000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4FF00000 0x0 0x500000>; | ||||
| 		}; | ||||
|  | ||||
| 	#endif | ||||
| 	}; | ||||
|  | ||||
| 	soc { | ||||
| 		gpio-watchdog { | ||||
| 			compatible = "linux,wdt-gpio"; | ||||
| 			gpios = <&tlmm 27 GPIO_ACTIVE_LOW>; | ||||
| 			hw_algo = "toggle"; | ||||
| 			hw_margin_ms = <5000>; | ||||
| 			always-running; | ||||
| 		}; | ||||
|  | ||||
| 		serial@78af000 { | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		blsp1_uart2: serial@78b0000 { | ||||
| 			pinctrl-0 = <&blsp1_uart_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 		}; | ||||
|  | ||||
| 		qpic_bam: dma@7984000{ | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		nand: qpic-nand@79b0000 { | ||||
| 			pinctrl-0 = <&qspi_nand_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		spi_0: spi@78b5000 { /* BLSP1 QUP0 */ | ||||
| 			pinctrl-0 = <&blsp0_spi_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			cs-select = <0>; | ||||
| 			status = "ok"; | ||||
|  | ||||
| 			m25p80@0 { | ||||
| 				#address-cells = <1>; | ||||
| 				#size-cells = <1>; | ||||
| 				reg = <0>; | ||||
| 				compatible = "n25q128a11"; | ||||
| 				linux,modalias = "m25p80", "n25q128a11"; | ||||
| 				spi-max-frequency = <50000000>; | ||||
| 				use-default-sizes; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		mdio0: mdio@88000 { | ||||
| 			status = "ok"; | ||||
|  | ||||
| 			ethernet-phy@0 { | ||||
| 				reg = <7>; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		mdio1: mdio@90000 { | ||||
| 			status = "ok"; | ||||
| 			pinctrl-0 = <&mdio1_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			phy-reset-gpio = <&tlmm 39 0>; | ||||
|  | ||||
| 			ethernet-phy@0 { | ||||
| 				reg = <28>; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		ess-instance { | ||||
| 			num_devices = <0x1>; | ||||
| 			ess-switch@0x39c00000 { | ||||
| 				switch_mac_mode = <0xf>; /* mac mode for uniphy instance*/ | ||||
| 				cmnblk_clk = "internal_96MHz"; /* cmnblk clk*/ | ||||
| 				qcom,port_phyinfo { | ||||
| 					port@0 { | ||||
| 						port_id = <1>; | ||||
| 						phy_address = <7>; | ||||
| 						mdiobus = <&mdio0>; | ||||
| 					}; | ||||
| 					port@1 { | ||||
| 						port_id = <2>; | ||||
| 						phy_address = <0x1c>; | ||||
| 						mdiobus = <&mdio1>; | ||||
| 						port_mac_sel = "QGMAC_PORT"; | ||||
| 					}; | ||||
| 				}; | ||||
| 				led_source@0 { | ||||
| 					source = <0>; | ||||
| 					mode = "normal"; | ||||
| 					speed = "all"; | ||||
| 					blink_en = "enable"; | ||||
| 					active = "high"; | ||||
| 				}; | ||||
| 			}; | ||||
| 				ess-switch1@1 { | ||||
| 				compatible = "qcom,ess-switch-qca83xx"; | ||||
| 				device_id = <1>; | ||||
| 				switch_access_mode = "mdio"; | ||||
| 				mdio-bus = <&mdio1>; | ||||
| 				reset_gpio = <0x28>; | ||||
| 				switch_cpu_bmp = <0x40>;  /* cpu port bitmap */ | ||||
| 				switch_lan_bmp = <0x1e>; /* lan port bitmap */ | ||||
| 				switch_wan_bmp = <0x0>;  /* wan port bitmap */ | ||||
| 				qca,ar8327-initvals = < | ||||
| 						0x00004 0x7600000   /* PAD0_MODE */ | ||||
| 						0x00008 0x1000000   /* PAD5_MODE */ | ||||
| 						0x0000c 0x80        /* PAD6_MODE */ | ||||
| 						0x00010 0x2613a0    /* PORT6 FORCE MODE*/ | ||||
| 						0x000e4 0xaa545     /* MAC_POWER_SEL */ | ||||
| 						0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||
| 						0x0007c 0x4e        /* PORT0_STATUS */ | ||||
| 						0x00094 0x4e        /* PORT6_STATUS */ | ||||
| 				>; | ||||
| 				qcom,port_phyinfo { | ||||
| 					port@0 { | ||||
| 						port_id = <1>; | ||||
| 						phy_address = <28>; | ||||
| 					}; | ||||
| 				}; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		dp1 { | ||||
| 			device_type = "network"; | ||||
| 			compatible = "qcom,nss-dp"; | ||||
| 			clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>; | ||||
| 			clock-names = "nss-snoc-gmac-axi-clk"; | ||||
| 			qcom,id = <1>; | ||||
| 			reg = <0x39C00000 0x10000>; | ||||
| 			interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; | ||||
| 			qcom,mactype = <2>; | ||||
| 			qcom,link-poll = <1>; | ||||
| 			qcom,phy-mdio-addr = <7>; | ||||
| 			mdio-bus = <&mdio0>; | ||||
| 			local-mac-address = [000000000000]; | ||||
| 			phy-mode = "sgmii"; | ||||
| 		}; | ||||
|  | ||||
| 		dp2 { | ||||
| 			device_type = "network"; | ||||
| 			compatible = "qcom,nss-dp"; | ||||
| 			clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>; | ||||
| 			clock-names = "nss-snoc-gmac-axi-clk"; | ||||
| 			qcom,id = <2>; | ||||
| 			reg = <0x39D00000 0x10000>; | ||||
| 			interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>; | ||||
| 			qcom,mactype = <2>; | ||||
| 			qcom,link-poll = <1>; | ||||
| 			qcom,phy-mdio-addr = <28>; | ||||
| 			mdio-bus = <&mdio1>; | ||||
| 			local-mac-address = [000000000000]; | ||||
| 			phy-mode = "sgmii"; | ||||
| 		}; | ||||
|  | ||||
| 		qcom,test@0 { | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		nss-macsec1 { | ||||
| 			compatible = "qcom,nss-macsec"; | ||||
| 			phy_addr = <0x1c>; | ||||
| 			mdiobus = <&mdio1>; | ||||
| 		}; | ||||
|  | ||||
| 		lpass: lpass@0xA000000{ | ||||
| 			status = "disabled"; | ||||
| 		}; | ||||
|  | ||||
| 		pcm: pcm@0xA3C0000{ | ||||
| 			pinctrl-0 = <&audio_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			status = "disabled"; | ||||
| 		}; | ||||
|  | ||||
| 		pcm_lb: pcm_lb@0 { | ||||
| 			status = "disabled"; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	thermal-zones { | ||||
| 		status = "ok"; | ||||
| 	}; | ||||
|  | ||||
| }; | ||||
|  | ||||
| &tlmm { | ||||
| 	pinctrl-0 = <&blsp0_uart_pins &phy_led_pins>; | ||||
| 	pinctrl-names = "default"; | ||||
|  | ||||
| 	blsp0_uart_pins: uart_pins { | ||||
| 		blsp0_uart_rx_tx { | ||||
| 			pins = "gpio20", "gpio21"; | ||||
| 			function = "blsp0_uart0"; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	blsp1_uart_pins: blsp1_uart_pins { | ||||
| 		blsp1_uart_rx_tx { | ||||
| 			pins = "gpio22", "gpio24", "gpio23", "gpio25"; | ||||
| 			function = "blsp1_uart2"; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	blsp0_spi_pins: blsp0_spi_pins { | ||||
| 		mux { | ||||
| 			pins = "gpio10", "gpio11", "gpio12", "gpio13"; | ||||
| 			function = "blsp0_spi"; | ||||
| 			drive-strength = <2>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	qspi_nand_pins: qspi_nand_pins { | ||||
| 		qspi_clock { | ||||
| 			pins = "gpio9"; | ||||
| 			function = "qspi_clk"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_cs { | ||||
| 			pins = "gpio8"; | ||||
| 			function = "qspi_cs"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_0 { | ||||
| 			pins = "gpio7"; | ||||
| 			function = "qspi0"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_1 { | ||||
| 			pins = "gpio6"; | ||||
| 			function = "qspi1"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_2 { | ||||
| 			pins = "gpio5"; | ||||
| 			function = "qspi2"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_3 { | ||||
| 			pins = "gpio4"; | ||||
| 			function = "qspi3"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	mdio1_pins: mdio_pinmux { | ||||
| 		mux_0 { | ||||
| 			pins = "gpio36"; | ||||
| 			function = "mdc"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-up; | ||||
| 		}; | ||||
|  | ||||
| 		mux_1 { | ||||
| 			pins = "gpio37"; | ||||
| 			function = "mdio"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-up; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	phy_led_pins: phy_led_pins { | ||||
| 		gephy_led_pin { | ||||
| 			pins = "gpio46"; | ||||
| 			function = "led0"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-down; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	i2c_pins: i2c_pins { | ||||
| 		i2c_scl { | ||||
| 			pins = "gpio25"; | ||||
| 			function = "blsp2_i2c1"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
|  | ||||
| 		i2c_sda { | ||||
| 			pins = "gpio26"; | ||||
| 			function = "blsp2_i2c1"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	button_pins: button_pins { | ||||
| 		reset_button { | ||||
| 			pins = "gpio38"; | ||||
| 			function = "gpio"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-up; | ||||
| 		}; | ||||
| 	}; | ||||
| audio_pins: audio_pinmux { | ||||
| }; | ||||
|         leds_pins: leds_pins { | ||||
|                 led_5g { | ||||
|                         pins = "gpio34"; | ||||
|                         function = "gpio"; | ||||
|                         drive-strength = <8>; | ||||
|                         bias-pull-down; | ||||
|                 }; | ||||
|                 led_2g { | ||||
|                         pins = "gpio33"; | ||||
|                         function = "gpio"; | ||||
|                         drive-strength = <8>; | ||||
|                         bias-pull-down; | ||||
|                 }; | ||||
|                 led_sys { | ||||
|                         pins = "gpio26"; | ||||
|                         function = "gpio"; | ||||
|                         drive-strength = <8>; | ||||
|                         bias-pull-down; | ||||
|                 }; | ||||
| 		led_onekey { | ||||
|                         pins = "gpio28"; | ||||
|                         function = "gpio"; | ||||
|                         drive-strength = <8>; | ||||
|                         bias-pull-down; | ||||
|                 }; | ||||
|         }; | ||||
| }; | ||||
|  | ||||
| &soc { | ||||
| 	gpio_keys { | ||||
| 		compatible = "gpio-keys"; | ||||
| 		pinctrl-0 = <&button_pins>; | ||||
| 		pinctrl-names = "default"; | ||||
|  | ||||
| 		button@1 { | ||||
| 			label = "reset"; | ||||
| 			linux,code = <KEY_RESTART>; | ||||
| 			gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; | ||||
| 			linux,input-type = <1>; | ||||
| 			debounce-interval = <60>; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
|         leds { | ||||
|                 compatible = "gpio-leds"; | ||||
|                 pinctrl-0 = <&leds_pins>; | ||||
|                 pinctrl-names = "default"; | ||||
|  | ||||
|                 led_blue: led@34 { | ||||
|                         label = "led_5g"; | ||||
|                         gpios = <&tlmm 34 GPIO_ACTIVE_LOW>; | ||||
|                         linux,default-trigger = "led_5g"; | ||||
|                         default-state = "off"; | ||||
|                 }; | ||||
|                 led_green: led@33 { | ||||
|                         label = "led_2g"; | ||||
|                         gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; | ||||
|                         linux,default-trigger = "led_2g"; | ||||
|                         default-state = "off"; | ||||
|                 }; | ||||
|                 led_red: led@26 { | ||||
|                         label = "led_sys"; | ||||
|                         gpios = <&tlmm 26 GPIO_ACTIVE_LOW>; | ||||
|                         linux,default-trigger = "led_sys"; | ||||
|                         default-state = "off"; | ||||
|                 }; | ||||
| 		led@28 { | ||||
|                         label = "led_onekey"; | ||||
|                         gpios = <&tlmm 28 GPIO_ACTIVE_LOW>; | ||||
|                         linux,default-trigger = "led_onekey"; | ||||
|                         default-state = "off"; | ||||
|                 }; | ||||
|         }; | ||||
| }; | ||||
|  | ||||
| &q6v5_wcss { | ||||
| 	compatible = "qcom,ipq5018-q6-mpd"; | ||||
| 	#address-cells = <1>; | ||||
| 	#size-cells = <1>; | ||||
| 	ranges; | ||||
| 	firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 	reg = <0x0cd00000 0x4040>, | ||||
| 		<0x1938000 0x8>, | ||||
| 		<0x193d204 0x4>; | ||||
| 	reg-names = "qdsp6", | ||||
| 			"tcsr-msip", | ||||
| 			"tcsr-q6"; | ||||
| 	resets = <&gcc GCC_WCSSAON_RESET>, | ||||
| 			<&gcc GCC_WCSS_Q6_BCR>; | ||||
|  | ||||
| 	reset-names = "wcss_aon_reset", | ||||
| 			"wcss_q6_reset"; | ||||
|  | ||||
| 	clocks = <&gcc GCC_Q6_AXIS_CLK>, | ||||
| 		<&gcc GCC_WCSS_ECAHB_CLK>, | ||||
| 		<&gcc GCC_Q6_AXIM_CLK>, | ||||
| 		<&gcc GCC_Q6_AXIM2_CLK>, | ||||
| 		<&gcc GCC_Q6_AHB_CLK>, | ||||
| 		<&gcc GCC_Q6_AHB_S_CLK>, | ||||
| 		<&gcc GCC_WCSS_AXI_S_CLK>; | ||||
| 	clock-names = "gcc_q6_axis_clk", | ||||
| 		"gcc_wcss_ecahb_clk", | ||||
| 		"gcc_q6_axim_clk", | ||||
| 		"gcc_q6_axim2_clk", | ||||
| 		"gcc_q6_ahb_clk", | ||||
| 		"gcc_q6_ahb_s_clk", | ||||
| 		"gcc_wcss_axi_s_clk"; | ||||
|  | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 		memory-region = <&q6_mem_regions>, <&q6_etr_region>; | ||||
| 	#else | ||||
| 		memory-region = <&q6_mem_regions>, <&q6_etr_region>, | ||||
| 				<&q6_caldb_region>; | ||||
| 	#endif | ||||
|  | ||||
| 	qcom,rproc = <&q6v5_wcss>; | ||||
| 	qcom,bootargs_smem = <507>; | ||||
| 	boot-args = <0x1 0x4 0x3 0x0F 0x0 0x0>, | ||||
| 			<0x2 0x4 0x2 0x12 0x0 0x0>; | ||||
| 	status = "ok"; | ||||
| 	q6_wcss_pd1: remoteproc_pd1@4ab000 { | ||||
| 		compatible = "qcom,ipq5018-wcss-ahb-mpd"; | ||||
| 		reg = <0x4ab000 0x20>; | ||||
| 		reg-names = "rmb"; | ||||
| 		firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 		m3_firmware = "IPQ5018/m3_fw.mdt"; | ||||
| 		interrupts-extended = <&wcss_smp2p_in 8 0>, | ||||
| 					<&wcss_smp2p_in 9 0>, | ||||
| 					<&wcss_smp2p_in 12 0>, | ||||
| 					<&wcss_smp2p_in 11 0>; | ||||
| 		interrupt-names = "fatal", | ||||
| 					"ready", | ||||
| 					"spawn-ack", | ||||
| 					"stop-ack"; | ||||
|  | ||||
| 		resets = <&gcc GCC_WCSSAON_RESET>, | ||||
| 				<&gcc GCC_WCSS_BCR>, | ||||
| 				<&gcc GCC_CE_BCR>; | ||||
| 		reset-names = "wcss_aon_reset", | ||||
| 				"wcss_reset", | ||||
| 				"ce_reset"; | ||||
|  | ||||
| 		clocks = <&gcc GCC_WCSS_AHB_S_CLK>, | ||||
| 				<&gcc GCC_WCSS_ACMT_CLK>, | ||||
| 				<&gcc GCC_WCSS_AXI_M_CLK>; | ||||
| 		clock-names = "gcc_wcss_ahb_s_clk", | ||||
| 					"gcc_wcss_acmt_clk", | ||||
| 					"gcc_wcss_axi_m_clk"; | ||||
|  | ||||
| 		qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>; | ||||
|  | ||||
| 		qcom,smem-states = <&wcss_smp2p_out 8>, | ||||
| 					<&wcss_smp2p_out 9>, | ||||
| 					<&wcss_smp2p_out 10>; | ||||
| 		qcom,smem-state-names = "shutdown", | ||||
| 					"stop", | ||||
| 					"spawn"; | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 		memory-region = <&q6_ipq5018_data>, <&m3_dump>, | ||||
| 				<&q6_etr_region>; | ||||
| 	#else | ||||
| 		memory-region = <&q6_ipq5018_data>, <&m3_dump>, | ||||
| 				<&q6_etr_region>, <&q6_caldb_region>; | ||||
| 	#endif | ||||
|  | ||||
| 	}; | ||||
|  | ||||
| 	q6_wcss_pd2: remoteproc_pd2 { | ||||
| 		compatible = "qcom,ipq5018-wcss-pcie-mpd"; | ||||
| 		firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 		m3_firmware = "qcn6122/m3_fw.mdt"; | ||||
| 		interrupts-extended = <&wcss_smp2p_in 16 0>, | ||||
| 					<&wcss_smp2p_in 17 0>, | ||||
| 					<&wcss_smp2p_in 20 0>, | ||||
| 					<&wcss_smp2p_in 19 0>; | ||||
| 		interrupt-names = "fatal", | ||||
| 					"ready", | ||||
| 					"spawn-ack", | ||||
| 					"stop-ack"; | ||||
|  | ||||
| 		qcom,smem-states = <&wcss_smp2p_out 16>, | ||||
| 					<&wcss_smp2p_out 17>, | ||||
| 					<&wcss_smp2p_out 18>; | ||||
| 		qcom,smem-state-names = "shutdown", | ||||
| 					"stop", | ||||
| 					"spawn"; | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 		memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>, | ||||
| 				<&q6_qcn6122_etr_1>; | ||||
| 	#else | ||||
| 		memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>, | ||||
| 				<&q6_qcn6122_etr_1>, <&q6_qcn6122_caldb_1>; | ||||
| 	#endif | ||||
|  | ||||
| 	}; | ||||
|  | ||||
| 	q6_wcss_pd3: remoteproc_pd3 { | ||||
| 		compatible = "qcom,ipq5018-wcss-pcie-mpd"; | ||||
| 		firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 		interrupts-extended = <&wcss_smp2p_in 24 0>, | ||||
| 					<&wcss_smp2p_in 25 0>, | ||||
| 					<&wcss_smp2p_in 28 0>, | ||||
| 					<&wcss_smp2p_in 27 0>; | ||||
| 		interrupt-names = "fatal", | ||||
| 					"ready", | ||||
| 					"spawn-ack", | ||||
| 					"stop-ack"; | ||||
|  | ||||
| 		qcom,smem-states = <&wcss_smp2p_out 24>, | ||||
| 					<&wcss_smp2p_out 25>, | ||||
| 					<&wcss_smp2p_out 26>; | ||||
| 		qcom,smem-state-names = "shutdown", | ||||
| 					"stop", | ||||
| 					"spawn"; | ||||
| 	#ifdef	__IPQ_MEM_PROFILE_256_MB__ | ||||
| 		memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>, | ||||
| 				<&q6_qcn6122_etr_2>; | ||||
| 	#else | ||||
| 		memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>, | ||||
| 				<&q6_qcn6122_etr_2>, <&q6_qcn6122_caldb_2>; | ||||
| 	#endif | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| &i2c_0 { | ||||
| 	pinctrl-0 = <&i2c_pins>; | ||||
| 	pinctrl-names = "default"; | ||||
| 	status = "disabled"; | ||||
| }; | ||||
|  | ||||
| &wifi0 { | ||||
| 	/* IPQ5018 */ | ||||
| 	qcom,multipd_arch; | ||||
| 	qcom,rproc = <&q6_wcss_pd1>; | ||||
| 	qcom,userpd-subsys-name = "q6v5_wcss_userpd1"; | ||||
| #ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 	qcom,tgt-mem-mode = <2>; | ||||
| #else | ||||
| 	qcom,tgt-mem-mode = <1>; | ||||
| #endif | ||||
| 	qcom,board_id = <0x24>; | ||||
| #ifdef __CNSS2__ | ||||
| 	qcom,bdf-addr = <0x4C400000 0x4C400000 0x4C400000 0x0 0x0>; | ||||
| 	qcom,caldb-addr = <0x4D400000 0x4D400000 0 0 0>; | ||||
| 	qcom,caldb-size = <0x200000>; | ||||
| 	mem-region = <&q6_ipq5018_data>; | ||||
| #else | ||||
| 	memory-region = <&q6_ipq5018_data>; | ||||
| #endif | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &wifi1 { | ||||
| 	/* QCN6122 5G */ | ||||
| 	qcom,multipd_arch; | ||||
| 	qcom,userpd-subsys-name = "q6v5_wcss_userpd2"; | ||||
| 	qcom,rproc = <&q6_wcss_pd2>; | ||||
| #ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 	qcom,tgt-mem-mode = <2>; | ||||
| #else | ||||
| 	qcom,tgt-mem-mode = <1>; | ||||
| #endif | ||||
| 	qcom,board_id = <0x50>; | ||||
| #ifdef __CNSS2__ | ||||
| 	qcom,bdf-addr = <0x4D600000 0x4D600000 0x4D300000 0x0 0x0>; | ||||
| 	qcom,caldb-addr = <0x4E800000 0x4E800000 0 0 0>; | ||||
| 	qcom,caldb-size = <0x500000>; | ||||
| 	mem-region = <&q6_qcn6122_data1>; | ||||
| #else | ||||
| 	memory-region = <&q6_qcn6122_data1>; | ||||
| #endif | ||||
| 	status = "disabled"; | ||||
| }; | ||||
|  | ||||
| &wifi2 { | ||||
| 	/* QCN6122 6G */ | ||||
| 	qcom,multipd_arch; | ||||
| 	qcom,userpd-subsys-name = "q6v5_wcss_userpd3"; | ||||
| 	qcom,rproc = <&q6_wcss_pd3>; | ||||
| #ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 	qcom,tgt-mem-mode = <2>; | ||||
| #else | ||||
| 	qcom,tgt-mem-mode = <1>; | ||||
| #endif | ||||
| 	qcom,board_id = <0xb0>; | ||||
| #ifdef __CNSS2__ | ||||
| 	qcom,bdf-addr = <0x4ED00000 0x4ED00000 0x4E400000 0x0 0x0>; | ||||
| 	qcom,caldb-addr = <0x4FF00000 0x4FF00000 0 0 0>; | ||||
| 	qcom,caldb-size = <0x500000>; | ||||
| 	mem-region = <&q6_qcn6122_data2>; | ||||
| #else | ||||
| 	memory-region = <&q6_qcn6122_data2>; | ||||
| #endif | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
|  | ||||
| &usb3 { | ||||
| 	status = "ok"; | ||||
| 	device-power-gpio = <&tlmm 24 1>; | ||||
| }; | ||||
|  | ||||
| &dwc_0 { | ||||
| 	/delete-property/ #phy-cells; | ||||
| 	/delete-property/ phys; | ||||
| 	/delete-property/ phy-names; | ||||
| }; | ||||
| &hs_m31phy_0 { | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &eud { | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &pcie_x1 { | ||||
| 	#status = "disabled"; | ||||
| 	#perst-gpio = <&tlmm 18 1>; | ||||
| 	perst-gpio = <&tlmm 18 GPIO_ACTIVE_LOW>; | ||||
| }; | ||||
|  | ||||
| &pcie_x2 { | ||||
| 	#status = "disabled"; | ||||
| 	#perst-gpio = <&tlmm 15 1>; | ||||
| 	perst-gpio = <&tlmm 15 GPIO_ACTIVE_LOW>; | ||||
| }; | ||||
|  | ||||
| &pcie_x1_rp { | ||||
|         status = "disabled"; | ||||
|  | ||||
| 	mhi_0: qcom,mhi@0 { | ||||
| 		reg = <0 0 0 0 0 >; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| &pcie_x2_rp { | ||||
|         status = "disabled"; | ||||
|  | ||||
| 	mhi_1: qcom,mhi@1 { | ||||
| 		reg = <0 0 0 0 0 >; | ||||
|  | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| @@ -0,0 +1,941 @@ | ||||
| /dts-v1/; | ||||
| /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. | ||||
|  * | ||||
|  * Permission to use, copy, modify, and/or distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include "ipq5018.dtsi" | ||||
| #include <dt-bindings/input/input.h> | ||||
|  | ||||
| / { | ||||
| 	#address-cells = <0x2>; | ||||
| 	#size-cells = <0x2>; | ||||
| 	model = "Indio UM-525AXP"; | ||||
| 	compatible = "indio,um-525axp", "qcom,ipq5018-mp03.5-c1", "qcom,ipq5018"; | ||||
| 	interrupt-parent = <&intc>; | ||||
|  | ||||
| 	aliases { | ||||
| 		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ | ||||
| 		serial0 = &blsp1_uart1; | ||||
| 		serial1 = &blsp1_uart2; | ||||
| 		ethernet0 = "/soc/dp1"; | ||||
| 		ethernet1 = "/soc/dp2"; | ||||
|                 //led-failsafe = &led_red; | ||||
|                 //led-running = &led_green; | ||||
|                 //led-upgrade = &led_green; | ||||
|                 //led-gateway = &led_blue; | ||||
|                 //led-factory = &led_blue; | ||||
| 	}; | ||||
|  | ||||
| 	chosen { | ||||
| 		bootargs = "console=ttyMSM0,115200,n8 rw init=/init"; | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 		bootargs-append = " swiotlb=1"; | ||||
| 	#else | ||||
| 		bootargs-append = " swiotlb=1 coherent_pool=2M"; | ||||
| 	#endif | ||||
| 		stdout-path = "serial0"; | ||||
| 	}; | ||||
|  | ||||
| 	reserved-memory { | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 	/*                   256 MB Profile | ||||
| 	 * +==========+==============+=========================+ | ||||
| 	 * |          |              |                         | | ||||
| 	 * |  Region  | Start Offset |          Size           | | ||||
| 	 * |          |              |                         | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    NSS   |  0x40000000  |           8MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   Linux  |  0x40800000  | Depends on total memory | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   uboot  |  0x4A600000  |           4MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    SBL   |  0x4AA00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   smem   |  0x4AB00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    TZ    |  0x4AC00000  |           4MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    Q6    |              |                         | | ||||
| 	 * |   code/  |  0x4B000000  |          20MB           | | ||||
| 	 * |   data   |              |                         | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |   data   |  0x4C400000  |          13MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |  M3 Dump |  0x4D100000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |   QDSS   |  0x4D200000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |   data   |  0x4D300000  |          15MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |  M3 Dump |  0x4E200000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |   QDSS   |  0x4E300000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |   data   |  0x4E400000  |          15MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |  M3 Dump |  0x4F300000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |   QDSS   |  0x4F400000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |                                                   | | ||||
| 	 * |            Rest of the memory for Linux           | | ||||
| 	 * |                                                   | | ||||
| 	 * +===================================================+ | ||||
| 	 */ | ||||
| 		q6_mem_regions: q6_mem_regions@4B000000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4B000000 0x0 0x4500000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_code_data: q6_code_data@4B000000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4B000000 0x0 0x1400000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_ipq5018_data: q6_ipq5018_data@4C400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4C400000 0x0 0xD00000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump: m3_dump@4D100000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D100000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_etr_region: q6_etr_dump@4D200000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D200000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_data1: q6_qcn6122_data1@4D300000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D300000 0x0 0xF00000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E200000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E200000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E300000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E300000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_data2: q6_qcn6122_data2@4E400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E400000 0x0 0xF00000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump_qcn6122_2: m3_dump_qcn6122_2@4F300000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4F300000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_etr_2: q6_qcn6122_etr_2@4F400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4F400000 0x0 0x100000>; | ||||
| 		}; | ||||
| 		 | ||||
| 	#else | ||||
| 	/*                 512MB/1GB Profiles | ||||
| 	 * +==========+==============+=========================+ | ||||
| 	 * |          |              |                         | | ||||
| 	 * |  Region  | Start Offset |          Size           | | ||||
| 	 * |          |              |                         | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    NSS   |  0x40000000  |          16MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   Linux  |  0x41000000  | Depends on total memory | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   uboot  |  0x4A600000  |           4MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    SBL   |  0x4AA00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |   smem   |  0x4AB00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    TZ    |  0x4AC00000  |           4MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |    Q6    |              |                         | | ||||
| 	 * |   code/  |  0x4B000000  |          20MB           | | ||||
| 	 * |   data   |              |                         | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |   data   |  0x4C400000  |          14MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |  M3 Dump |  0x4D200000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |   QDSS   |  0x4D300000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |  IPQ5018 |              |                         | | ||||
| 	 * |  Caldb   |  0x4D400000  |           2MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |   data   |  0x4D600000  |          16MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |  M3 Dump |  0x4E600000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |   QDSS   |  0x4E700000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_1|              |                         | | ||||
| 	 * |  Caldb   |  0x4E800000  |           5MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |   data   |  0x4ED00000  |          16MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |  M3 Dump |  0x4FD00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |   QDSS   |  0x4FE00000  |           1MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * | QCN6122_2|              |                         | | ||||
| 	 * |  Caldb   |  0x4FF00000  |           5MB           | | ||||
| 	 * +----------+--------------+-------------------------+ | ||||
| 	 * |                                                   | | ||||
| 	 * |            Rest of the memory for Linux           | | ||||
| 	 * |                                                   | | ||||
| 	 * +===================================================+ | ||||
| 	 */ | ||||
| 		q6_mem_regions: q6_mem_regions@4B000000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4B000000 0x0 0x5400000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_code_data: q6_code_data@4B000000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4B000000 0x0 01400000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_ipq5018_data: q6_ipq5018_data@4C400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4C400000 0x0 0xE00000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump: m3_dump@4D200000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D200000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_etr_region: q6_etr_dump@4D300000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D300000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_caldb_region: q6_caldb_region@4D400000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D400000 0x0 0x200000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_data1: q6_qcn6122_data1@4D600000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4D600000 0x0 0x1000000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E600000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E600000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E700000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E700000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_caldb_1: q6_qcn6122_caldb_1@4E800000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4E800000 0x0 0x500000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_data2: q6_qcn6122_data2@4E900000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4ED00000 0x0 0x1000000>; | ||||
| 		}; | ||||
|  | ||||
| 		m3_dump_qcn6122_2: m3_dump_qcn6122_2@4FD00000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4FD00000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_etr_2: q6_qcn6122_etr_2@4FE00000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4FE00000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		q6_qcn6122_caldb_2: q6_qcn6122_caldb_2@4FF00000 { | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4FF00000 0x0 0x500000>; | ||||
| 		}; | ||||
|  | ||||
| 	#endif | ||||
| 	}; | ||||
|  | ||||
| 	soc { | ||||
| 		gpio-watchdog { | ||||
| 			compatible = "linux,wdt-gpio"; | ||||
| 			gpios = <&tlmm 27 GPIO_ACTIVE_LOW>; | ||||
| 			hw_algo = "toggle"; | ||||
| 			hw_margin_ms = <5000>; | ||||
| 			always-running; | ||||
| 		}; | ||||
|  | ||||
| 		serial@78af000 { | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		blsp1_uart2: serial@78b0000 { | ||||
| 			pinctrl-0 = <&blsp1_uart_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 		}; | ||||
|  | ||||
| 		qpic_bam: dma@7984000{ | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		nand: qpic-nand@79b0000 { | ||||
| 			pinctrl-0 = <&qspi_nand_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		spi_0: spi@78b5000 { /* BLSP1 QUP0 */ | ||||
| 			pinctrl-0 = <&blsp0_spi_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			cs-select = <0>; | ||||
| 			status = "ok"; | ||||
|  | ||||
| 			m25p80@0 { | ||||
| 				#address-cells = <1>; | ||||
| 				#size-cells = <1>; | ||||
| 				reg = <0>; | ||||
| 				compatible = "n25q128a11"; | ||||
| 				linux,modalias = "m25p80", "n25q128a11"; | ||||
| 				spi-max-frequency = <50000000>; | ||||
| 				use-default-sizes; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		mdio0: mdio@88000 { | ||||
| 			status = "ok"; | ||||
|  | ||||
| 			ethernet-phy@0 { | ||||
| 				reg = <7>; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		mdio1: mdio@90000 { | ||||
| 			status = "ok"; | ||||
| 			pinctrl-0 = <&mdio1_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			phy-reset-gpio = <&tlmm 39 0>; | ||||
|  | ||||
| 			ethernet-phy@0 { | ||||
| 				reg = <28>; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		ess-instance { | ||||
| 			num_devices = <0x1>; | ||||
| 			ess-switch@0x39c00000 { | ||||
| 				switch_mac_mode = <0xf>; /* mac mode for uniphy instance*/ | ||||
| 				cmnblk_clk = "internal_96MHz"; /* cmnblk clk*/ | ||||
| 				qcom,port_phyinfo { | ||||
| 					port@0 { | ||||
| 						port_id = <1>; | ||||
| 						phy_address = <7>; | ||||
| 						mdiobus = <&mdio0>; | ||||
| 					}; | ||||
| 					port@1 { | ||||
| 						port_id = <2>; | ||||
| 						phy_address = <0x1c>; | ||||
| 						mdiobus = <&mdio1>; | ||||
| 						port_mac_sel = "QGMAC_PORT"; | ||||
| 					}; | ||||
| 				}; | ||||
| 				led_source@0 { | ||||
| 					source = <0>; | ||||
| 					mode = "normal"; | ||||
| 					speed = "all"; | ||||
| 					blink_en = "enable"; | ||||
| 					active = "high"; | ||||
| 				}; | ||||
| 			}; | ||||
| 				ess-switch1@1 { | ||||
| 				compatible = "qcom,ess-switch-qca83xx"; | ||||
| 				device_id = <1>; | ||||
| 				switch_access_mode = "mdio"; | ||||
| 				mdio-bus = <&mdio1>; | ||||
| 				reset_gpio = <0x28>; | ||||
| 				switch_cpu_bmp = <0x40>;  /* cpu port bitmap */ | ||||
| 				switch_lan_bmp = <0x1e>; /* lan port bitmap */ | ||||
| 				switch_wan_bmp = <0x0>;  /* wan port bitmap */ | ||||
| 				qca,ar8327-initvals = < | ||||
| 						0x00004 0x7600000   /* PAD0_MODE */ | ||||
| 						0x00008 0x1000000   /* PAD5_MODE */ | ||||
| 						0x0000c 0x80        /* PAD6_MODE */ | ||||
| 						0x00010 0x2613a0    /* PORT6 FORCE MODE*/ | ||||
| 						0x000e4 0xaa545     /* MAC_POWER_SEL */ | ||||
| 						0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||
| 						0x0007c 0x4e        /* PORT0_STATUS */ | ||||
| 						0x00094 0x4e        /* PORT6_STATUS */ | ||||
| 				>; | ||||
| 				qcom,port_phyinfo { | ||||
| 					port@0 { | ||||
| 						port_id = <1>; | ||||
| 						phy_address = <28>; | ||||
| 					}; | ||||
| 				}; | ||||
| 			}; | ||||
| 		}; | ||||
|  | ||||
| 		dp1 { | ||||
| 			device_type = "network"; | ||||
| 			compatible = "qcom,nss-dp"; | ||||
| 			clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>; | ||||
| 			clock-names = "nss-snoc-gmac-axi-clk"; | ||||
| 			qcom,id = <1>; | ||||
| 			reg = <0x39C00000 0x10000>; | ||||
| 			interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; | ||||
| 			qcom,mactype = <2>; | ||||
| 			qcom,link-poll = <1>; | ||||
| 			qcom,phy-mdio-addr = <7>; | ||||
| 			mdio-bus = <&mdio0>; | ||||
| 			local-mac-address = [000000000000]; | ||||
| 			phy-mode = "sgmii"; | ||||
| 		}; | ||||
|  | ||||
| 		dp2 { | ||||
| 			device_type = "network"; | ||||
| 			compatible = "qcom,nss-dp"; | ||||
| 			clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>; | ||||
| 			clock-names = "nss-snoc-gmac-axi-clk"; | ||||
| 			qcom,id = <2>; | ||||
| 			reg = <0x39D00000 0x10000>; | ||||
| 			interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>; | ||||
| 			qcom,mactype = <2>; | ||||
| 			qcom,link-poll = <1>; | ||||
| 			qcom,phy-mdio-addr = <28>; | ||||
| 			mdio-bus = <&mdio1>; | ||||
| 			local-mac-address = [000000000000]; | ||||
| 			phy-mode = "sgmii"; | ||||
| 		}; | ||||
|  | ||||
| 		qcom,test@0 { | ||||
| 			status = "ok"; | ||||
| 		}; | ||||
|  | ||||
| 		nss-macsec1 { | ||||
| 			compatible = "qcom,nss-macsec"; | ||||
| 			phy_addr = <0x1c>; | ||||
| 			mdiobus = <&mdio1>; | ||||
| 		}; | ||||
|  | ||||
| 		lpass: lpass@0xA000000{ | ||||
| 			status = "disabled"; | ||||
| 		}; | ||||
|  | ||||
| 		pcm: pcm@0xA3C0000{ | ||||
| 			pinctrl-0 = <&audio_pins>; | ||||
| 			pinctrl-names = "default"; | ||||
| 			status = "disabled"; | ||||
| 		}; | ||||
|  | ||||
| 		pcm_lb: pcm_lb@0 { | ||||
| 			status = "disabled"; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	thermal-zones { | ||||
| 		status = "ok"; | ||||
| 	}; | ||||
|  | ||||
| }; | ||||
|  | ||||
| &tlmm { | ||||
| 	pinctrl-0 = <&blsp0_uart_pins &phy_led_pins>; | ||||
| 	pinctrl-names = "default"; | ||||
|  | ||||
| 	blsp0_uart_pins: uart_pins { | ||||
| 		blsp0_uart_rx_tx { | ||||
| 			pins = "gpio20", "gpio21"; | ||||
| 			function = "blsp0_uart0"; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	blsp1_uart_pins: blsp1_uart_pins { | ||||
| 		blsp1_uart_rx_tx { | ||||
| 			pins = "gpio22", "gpio24", "gpio23", "gpio25"; | ||||
| 			function = "blsp1_uart2"; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	blsp0_spi_pins: blsp0_spi_pins { | ||||
| 		mux { | ||||
| 			pins = "gpio10", "gpio11", "gpio12", "gpio13"; | ||||
| 			function = "blsp0_spi"; | ||||
| 			drive-strength = <2>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	qspi_nand_pins: qspi_nand_pins { | ||||
| 		qspi_clock { | ||||
| 			pins = "gpio9"; | ||||
| 			function = "qspi_clk"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_cs { | ||||
| 			pins = "gpio8"; | ||||
| 			function = "qspi_cs"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_0 { | ||||
| 			pins = "gpio7"; | ||||
| 			function = "qspi0"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_1 { | ||||
| 			pins = "gpio6"; | ||||
| 			function = "qspi1"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_2 { | ||||
| 			pins = "gpio5"; | ||||
| 			function = "qspi2"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 		qspi_data_3 { | ||||
| 			pins = "gpio4"; | ||||
| 			function = "qspi3"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	mdio1_pins: mdio_pinmux { | ||||
| 		mux_0 { | ||||
| 			pins = "gpio36"; | ||||
| 			function = "mdc"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-up; | ||||
| 		}; | ||||
|  | ||||
| 		mux_1 { | ||||
| 			pins = "gpio37"; | ||||
| 			function = "mdio"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-up; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	phy_led_pins: phy_led_pins { | ||||
| 		gephy_led_pin { | ||||
| 			pins = "gpio46"; | ||||
| 			function = "led0"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-down; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	i2c_pins: i2c_pins { | ||||
| 		i2c_scl { | ||||
| 			pins = "gpio25"; | ||||
| 			function = "blsp2_i2c1"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
|  | ||||
| 		i2c_sda { | ||||
| 			pins = "gpio26"; | ||||
| 			function = "blsp2_i2c1"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-disable; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	button_pins: button_pins { | ||||
| 		reset_button { | ||||
| 			pins = "gpio38"; | ||||
| 			function = "gpio"; | ||||
| 			drive-strength = <8>; | ||||
| 			bias-pull-up; | ||||
| 		}; | ||||
| 	}; | ||||
| audio_pins: audio_pinmux { | ||||
| }; | ||||
|         leds_pins: leds_pins { | ||||
|                 led_5g { | ||||
|                         pins = "gpio34"; | ||||
|                         function = "gpio"; | ||||
|                         drive-strength = <8>; | ||||
|                         bias-pull-down; | ||||
|                 }; | ||||
|                 led_2g { | ||||
|                         pins = "gpio33"; | ||||
|                         function = "gpio"; | ||||
|                         drive-strength = <8>; | ||||
|                         bias-pull-down; | ||||
|                 }; | ||||
|                 led_sys { | ||||
|                         pins = "gpio26"; | ||||
|                         function = "gpio"; | ||||
|                         drive-strength = <8>; | ||||
|                         bias-pull-down; | ||||
|                 }; | ||||
| 		led_onekey { | ||||
|                         pins = "gpio28"; | ||||
|                         function = "gpio"; | ||||
|                         drive-strength = <8>; | ||||
|                         bias-pull-down; | ||||
|                 }; | ||||
|         }; | ||||
| }; | ||||
|  | ||||
| &soc { | ||||
| 	gpio_keys { | ||||
| 		compatible = "gpio-keys"; | ||||
| 		pinctrl-0 = <&button_pins>; | ||||
| 		pinctrl-names = "default"; | ||||
|  | ||||
| 		button@1 { | ||||
| 			label = "reset"; | ||||
| 			linux,code = <KEY_RESTART>; | ||||
| 			gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; | ||||
| 			linux,input-type = <1>; | ||||
| 			debounce-interval = <60>; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
|         leds { | ||||
|                 compatible = "gpio-leds"; | ||||
|                 pinctrl-0 = <&leds_pins>; | ||||
|                 pinctrl-names = "default"; | ||||
|  | ||||
|                 led_blue: led@34 { | ||||
|                         label = "led_5g"; | ||||
|                         gpios = <&tlmm 34 GPIO_ACTIVE_LOW>; | ||||
|                         linux,default-trigger = "led_5g"; | ||||
|                         default-state = "off"; | ||||
|                 }; | ||||
|                 led_green: led@33 { | ||||
|                         label = "led_2g"; | ||||
|                         gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; | ||||
|                         linux,default-trigger = "led_2g"; | ||||
|                         default-state = "off"; | ||||
|                 }; | ||||
|                 led_red: led@26 { | ||||
|                         label = "led_sys"; | ||||
|                         gpios = <&tlmm 26 GPIO_ACTIVE_LOW>; | ||||
|                         linux,default-trigger = "led_sys"; | ||||
|                         default-state = "off"; | ||||
|                 }; | ||||
| 		led@28 { | ||||
|                         label = "led_onekey"; | ||||
|                         gpios = <&tlmm 28 GPIO_ACTIVE_LOW>; | ||||
|                         linux,default-trigger = "led_onekey"; | ||||
|                         default-state = "off"; | ||||
|                 }; | ||||
|         }; | ||||
| }; | ||||
|  | ||||
| &q6v5_wcss { | ||||
| 	compatible = "qcom,ipq5018-q6-mpd"; | ||||
| 	#address-cells = <1>; | ||||
| 	#size-cells = <1>; | ||||
| 	ranges; | ||||
| 	firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 	reg = <0x0cd00000 0x4040>, | ||||
| 		<0x1938000 0x8>, | ||||
| 		<0x193d204 0x4>; | ||||
| 	reg-names = "qdsp6", | ||||
| 			"tcsr-msip", | ||||
| 			"tcsr-q6"; | ||||
| 	resets = <&gcc GCC_WCSSAON_RESET>, | ||||
| 			<&gcc GCC_WCSS_Q6_BCR>; | ||||
|  | ||||
| 	reset-names = "wcss_aon_reset", | ||||
| 			"wcss_q6_reset"; | ||||
|  | ||||
| 	clocks = <&gcc GCC_Q6_AXIS_CLK>, | ||||
| 		<&gcc GCC_WCSS_ECAHB_CLK>, | ||||
| 		<&gcc GCC_Q6_AXIM_CLK>, | ||||
| 		<&gcc GCC_Q6_AXIM2_CLK>, | ||||
| 		<&gcc GCC_Q6_AHB_CLK>, | ||||
| 		<&gcc GCC_Q6_AHB_S_CLK>, | ||||
| 		<&gcc GCC_WCSS_AXI_S_CLK>; | ||||
| 	clock-names = "gcc_q6_axis_clk", | ||||
| 		"gcc_wcss_ecahb_clk", | ||||
| 		"gcc_q6_axim_clk", | ||||
| 		"gcc_q6_axim2_clk", | ||||
| 		"gcc_q6_ahb_clk", | ||||
| 		"gcc_q6_ahb_s_clk", | ||||
| 		"gcc_wcss_axi_s_clk"; | ||||
|  | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 		memory-region = <&q6_mem_regions>, <&q6_etr_region>; | ||||
| 	#else | ||||
| 		memory-region = <&q6_mem_regions>, <&q6_etr_region>, | ||||
| 				<&q6_caldb_region>; | ||||
| 	#endif | ||||
|  | ||||
| 	qcom,rproc = <&q6v5_wcss>; | ||||
| 	qcom,bootargs_smem = <507>; | ||||
| 	boot-args = <0x1 0x4 0x3 0x0F 0x0 0x0>, | ||||
| 			<0x2 0x4 0x2 0x12 0x0 0x0>; | ||||
| 	status = "ok"; | ||||
| 	q6_wcss_pd1: remoteproc_pd1@4ab000 { | ||||
| 		compatible = "qcom,ipq5018-wcss-ahb-mpd"; | ||||
| 		reg = <0x4ab000 0x20>; | ||||
| 		reg-names = "rmb"; | ||||
| 		firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 		m3_firmware = "IPQ5018/m3_fw.mdt"; | ||||
| 		interrupts-extended = <&wcss_smp2p_in 8 0>, | ||||
| 					<&wcss_smp2p_in 9 0>, | ||||
| 					<&wcss_smp2p_in 12 0>, | ||||
| 					<&wcss_smp2p_in 11 0>; | ||||
| 		interrupt-names = "fatal", | ||||
| 					"ready", | ||||
| 					"spawn-ack", | ||||
| 					"stop-ack"; | ||||
|  | ||||
| 		resets = <&gcc GCC_WCSSAON_RESET>, | ||||
| 				<&gcc GCC_WCSS_BCR>, | ||||
| 				<&gcc GCC_CE_BCR>; | ||||
| 		reset-names = "wcss_aon_reset", | ||||
| 				"wcss_reset", | ||||
| 				"ce_reset"; | ||||
|  | ||||
| 		clocks = <&gcc GCC_WCSS_AHB_S_CLK>, | ||||
| 				<&gcc GCC_WCSS_ACMT_CLK>, | ||||
| 				<&gcc GCC_WCSS_AXI_M_CLK>; | ||||
| 		clock-names = "gcc_wcss_ahb_s_clk", | ||||
| 					"gcc_wcss_acmt_clk", | ||||
| 					"gcc_wcss_axi_m_clk"; | ||||
|  | ||||
| 		qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>; | ||||
|  | ||||
| 		qcom,smem-states = <&wcss_smp2p_out 8>, | ||||
| 					<&wcss_smp2p_out 9>, | ||||
| 					<&wcss_smp2p_out 10>; | ||||
| 		qcom,smem-state-names = "shutdown", | ||||
| 					"stop", | ||||
| 					"spawn"; | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 		memory-region = <&q6_ipq5018_data>, <&m3_dump>, | ||||
| 				<&q6_etr_region>; | ||||
| 	#else | ||||
| 		memory-region = <&q6_ipq5018_data>, <&m3_dump>, | ||||
| 				<&q6_etr_region>, <&q6_caldb_region>; | ||||
| 	#endif | ||||
|  | ||||
| 	}; | ||||
|  | ||||
| 	q6_wcss_pd2: remoteproc_pd2 { | ||||
| 		compatible = "qcom,ipq5018-wcss-pcie-mpd"; | ||||
| 		firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 		m3_firmware = "qcn6122/m3_fw.mdt"; | ||||
| 		interrupts-extended = <&wcss_smp2p_in 16 0>, | ||||
| 					<&wcss_smp2p_in 17 0>, | ||||
| 					<&wcss_smp2p_in 20 0>, | ||||
| 					<&wcss_smp2p_in 19 0>; | ||||
| 		interrupt-names = "fatal", | ||||
| 					"ready", | ||||
| 					"spawn-ack", | ||||
| 					"stop-ack"; | ||||
|  | ||||
| 		qcom,smem-states = <&wcss_smp2p_out 16>, | ||||
| 					<&wcss_smp2p_out 17>, | ||||
| 					<&wcss_smp2p_out 18>; | ||||
| 		qcom,smem-state-names = "shutdown", | ||||
| 					"stop", | ||||
| 					"spawn"; | ||||
| 	#ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 		memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>, | ||||
| 				<&q6_qcn6122_etr_1>; | ||||
| 	#else | ||||
| 		memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>, | ||||
| 				<&q6_qcn6122_etr_1>, <&q6_qcn6122_caldb_1>; | ||||
| 	#endif | ||||
|  | ||||
| 	}; | ||||
|  | ||||
| 	q6_wcss_pd3: remoteproc_pd3 { | ||||
| 		compatible = "qcom,ipq5018-wcss-pcie-mpd"; | ||||
| 		firmware = "IPQ5018/q6_fw.mdt"; | ||||
| 		interrupts-extended = <&wcss_smp2p_in 24 0>, | ||||
| 					<&wcss_smp2p_in 25 0>, | ||||
| 					<&wcss_smp2p_in 28 0>, | ||||
| 					<&wcss_smp2p_in 27 0>; | ||||
| 		interrupt-names = "fatal", | ||||
| 					"ready", | ||||
| 					"spawn-ack", | ||||
| 					"stop-ack"; | ||||
|  | ||||
| 		qcom,smem-states = <&wcss_smp2p_out 24>, | ||||
| 					<&wcss_smp2p_out 25>, | ||||
| 					<&wcss_smp2p_out 26>; | ||||
| 		qcom,smem-state-names = "shutdown", | ||||
| 					"stop", | ||||
| 					"spawn"; | ||||
| 	#ifdef	__IPQ_MEM_PROFILE_256_MB__ | ||||
| 		memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>, | ||||
| 				<&q6_qcn6122_etr_2>; | ||||
| 	#else | ||||
| 		memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>, | ||||
| 				<&q6_qcn6122_etr_2>, <&q6_qcn6122_caldb_2>; | ||||
| 	#endif | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| &i2c_0 { | ||||
| 	pinctrl-0 = <&i2c_pins>; | ||||
| 	pinctrl-names = "default"; | ||||
| 	status = "disabled"; | ||||
| }; | ||||
|  | ||||
| &wifi0 { | ||||
| 	/* IPQ5018 */ | ||||
| 	qcom,multipd_arch; | ||||
| 	qcom,rproc = <&q6_wcss_pd1>; | ||||
| 	qcom,userpd-subsys-name = "q6v5_wcss_userpd1"; | ||||
| #ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 	qcom,tgt-mem-mode = <2>; | ||||
| #else | ||||
| 	qcom,tgt-mem-mode = <1>; | ||||
| #endif | ||||
| 	qcom,board_id = <0x24>; | ||||
| #ifdef __CNSS2__ | ||||
| 	qcom,bdf-addr = <0x4C400000 0x4C400000 0x4C400000 0x0 0x0>; | ||||
| 	qcom,caldb-addr = <0x4D400000 0x4D400000 0 0 0>; | ||||
| 	qcom,caldb-size = <0x200000>; | ||||
| 	mem-region = <&q6_ipq5018_data>; | ||||
| #else | ||||
| 	memory-region = <&q6_ipq5018_data>; | ||||
| #endif | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &wifi1 { | ||||
| 	/* QCN6122 5G */ | ||||
| 	qcom,multipd_arch; | ||||
| 	qcom,userpd-subsys-name = "q6v5_wcss_userpd2"; | ||||
| 	qcom,rproc = <&q6_wcss_pd2>; | ||||
| #ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 	qcom,tgt-mem-mode = <2>; | ||||
| #else | ||||
| 	qcom,tgt-mem-mode = <1>; | ||||
| #endif | ||||
| 	qcom,board_id = <0x50>; | ||||
| #ifdef __CNSS2__ | ||||
| 	qcom,bdf-addr = <0x4D600000 0x4D600000 0x4D300000 0x0 0x0>; | ||||
| 	qcom,caldb-addr = <0x4E800000 0x4E800000 0 0 0>; | ||||
| 	qcom,caldb-size = <0x500000>; | ||||
| 	mem-region = <&q6_qcn6122_data1>; | ||||
| #else | ||||
| 	memory-region = <&q6_qcn6122_data1>; | ||||
| #endif | ||||
| 	status = "disabled"; | ||||
| }; | ||||
|  | ||||
| &wifi2 { | ||||
| 	/* QCN6122 6G */ | ||||
| 	qcom,multipd_arch; | ||||
| 	qcom,userpd-subsys-name = "q6v5_wcss_userpd3"; | ||||
| 	qcom,rproc = <&q6_wcss_pd3>; | ||||
| #ifdef __IPQ_MEM_PROFILE_256_MB__ | ||||
| 	qcom,tgt-mem-mode = <2>; | ||||
| #else | ||||
| 	qcom,tgt-mem-mode = <1>; | ||||
| #endif | ||||
| 	qcom,board_id = <0xb0>; | ||||
| #ifdef __CNSS2__ | ||||
| 	qcom,bdf-addr = <0x4ED00000 0x4ED00000 0x4E400000 0x0 0x0>; | ||||
| 	qcom,caldb-addr = <0x4FF00000 0x4FF00000 0 0 0>; | ||||
| 	qcom,caldb-size = <0x500000>; | ||||
| 	mem-region = <&q6_qcn6122_data2>; | ||||
| #else | ||||
| 	memory-region = <&q6_qcn6122_data2>; | ||||
| #endif | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
|  | ||||
| &usb3 { | ||||
| 	status = "ok"; | ||||
| 	device-power-gpio = <&tlmm 24 1>; | ||||
| }; | ||||
|  | ||||
| &dwc_0 { | ||||
| 	/delete-property/ #phy-cells; | ||||
| 	/delete-property/ phys; | ||||
| 	/delete-property/ phy-names; | ||||
| }; | ||||
| &hs_m31phy_0 { | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &eud { | ||||
| 	status = "ok"; | ||||
| }; | ||||
|  | ||||
| &pcie_x1 { | ||||
| 	#status = "disabled"; | ||||
| 	#perst-gpio = <&tlmm 18 1>; | ||||
| 	perst-gpio = <&tlmm 18 GPIO_ACTIVE_LOW>; | ||||
| }; | ||||
|  | ||||
| &pcie_x2 { | ||||
| 	#status = "disabled"; | ||||
| 	#perst-gpio = <&tlmm 15 1>; | ||||
| 	perst-gpio = <&tlmm 15 GPIO_ACTIVE_LOW>; | ||||
| }; | ||||
|  | ||||
| &pcie_x1_rp { | ||||
|         status = "disabled"; | ||||
|  | ||||
| 	mhi_0: qcom,mhi@0 { | ||||
| 		reg = <0 0 0 0 0 >; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| &pcie_x2_rp { | ||||
|         status = "disabled"; | ||||
|  | ||||
| 	mhi_1: qcom,mhi@1 { | ||||
| 		reg = <0 0 0 0 0 >; | ||||
|  | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| @@ -151,6 +151,14 @@ | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4F000000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		ramoops: ramoops@4f100000 { | ||||
| 			compatible = "ramoops"; | ||||
| 			reg = <0x0 0x4f100000 0x0 0x80000>; | ||||
| 			record-size = <0x20000>; | ||||
| 			console-size = <0x20000>; | ||||
| 			pmsg-size = <0x20000>; | ||||
| 		}; | ||||
| 	#else | ||||
| 	/*                 512MB/1GB Profiles | ||||
| 	 * +==========+==============+=========================+ | ||||
| @@ -285,6 +293,13 @@ | ||||
| 			reg = <0x0 0x4F800000 0x0 0x500000>; | ||||
| 		}; | ||||
|  | ||||
| 		ramoops: ramoops@4fd00000 { | ||||
| 			compatible = "ramoops"; | ||||
| 			reg = <0x0 0x4fd00000 0x0 0x80000>; | ||||
| 			record-size = <0x20000>; | ||||
| 			console-size = <0x20000>; | ||||
| 			pmsg-size = <0x20000>; | ||||
| 		}; | ||||
| 	#endif | ||||
| 	}; | ||||
|  | ||||
|   | ||||
| @@ -151,6 +151,14 @@ | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4F000000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		ramoops: ramoops@4f100000 { | ||||
| 			compatible = "ramoops"; | ||||
| 			reg = <0x0 0x4f100000 0x0 0x80000>; | ||||
| 			record-size = <0x20000>; | ||||
| 			console-size = <0x20000>; | ||||
| 			pmsg-size = <0x20000>; | ||||
| 		}; | ||||
| 	#else | ||||
| 	/*                 512MB/1GB Profiles | ||||
| 	 * +==========+==============+=========================+ | ||||
| @@ -285,6 +293,13 @@ | ||||
| 			reg = <0x0 0x4F800000 0x0 0x500000>; | ||||
| 		}; | ||||
|  | ||||
| 		ramoops: ramoops@4fd00000 { | ||||
| 			compatible = "ramoops"; | ||||
| 			reg = <0x0 0x4fd00000 0x0 0x80000>; | ||||
| 			record-size = <0x20000>; | ||||
| 			console-size = <0x20000>; | ||||
| 			pmsg-size = <0x20000>; | ||||
| 		}; | ||||
| 	#endif | ||||
| 	}; | ||||
|  | ||||
|   | ||||
| @@ -154,6 +154,14 @@ | ||||
| 			no-map; | ||||
| 			reg = <0x0 0x4F000000 0x0 0x100000>; | ||||
| 		}; | ||||
|  | ||||
| 		ramoops: ramoops@4f100000 { | ||||
| 			compatible = "ramoops"; | ||||
| 			reg = <0x0 0x4f100000 0x0 0x80000>; | ||||
| 			record-size = <0x20000>; | ||||
| 			console-size = <0x20000>; | ||||
| 			pmsg-size = <0x20000>; | ||||
| 		}; | ||||
| 	#else | ||||
| 	/*		 512MB/1GB Profiles | ||||
| 	 * +==========+==============+=========================+ | ||||
| @@ -288,6 +296,13 @@ | ||||
| 			reg = <0x0 0x4F800000 0x0 0x500000>; | ||||
| 		}; | ||||
|  | ||||
| 		ramoops: ramoops@4fd00000 { | ||||
| 			compatible = "ramoops"; | ||||
| 			reg = <0x0 0x4fd00000 0x0 0x80000>; | ||||
| 			record-size = <0x20000>; | ||||
| 			console-size = <0x20000>; | ||||
| 			pmsg-size = <0x20000>; | ||||
| 		}; | ||||
| 	#endif | ||||
| 	}; | ||||
|  | ||||
|   | ||||
| @@ -93,6 +93,42 @@ define Device/edgecore_eap104 | ||||
| endef | ||||
| TARGET_DEVICES += edgecore_eap104 | ||||
|  | ||||
| define Device/indio_um-325ax-v2 | ||||
|   DEVICE_TITLE := Indio UM-325ax-V2 | ||||
|   DEVICE_DTS := qcom-ipq5018-indio-um-325ax-v2 | ||||
|   SUPPORTED_DEVICES := indio,um-325ax-v2 | ||||
|   DEVICE_PACKAGES := ath11k-wifi-indio-um-325ax-v2 ath11k-firmware-ipq50xx-spruce ath11k-firmware-qcn6122 | ||||
|   DEVICE_DTS_CONFIG := config@mp03.5-c1 | ||||
| endef | ||||
| TARGET_DEVICES += indio_um-325ax-v2 | ||||
|  | ||||
| define Device/indio_um-335ax | ||||
|   DEVICE_TITLE := Indio UM-335ax | ||||
|   DEVICE_DTS := qcom-ipq5018-indio-um-335ax | ||||
|   SUPPORTED_DEVICES := indio,um-335ax | ||||
|   DEVICE_PACKAGES := ath11k-wifi-indio-um-335ax ath11k-firmware-qcn9000 ath11k-firmware-ipq50xx-spruce | ||||
|   DEVICE_DTS_CONFIG := config@mp03.1 | ||||
| endef | ||||
| TARGET_DEVICES += indio_um-335ax | ||||
|  | ||||
| define Device/indio_um-525axp | ||||
|   DEVICE_TITLE := Indio UM-525axp | ||||
|   DEVICE_DTS := qcom-ipq5018-indio-um-525axp | ||||
|   SUPPORTED_DEVICES := indio,um-525axp | ||||
|   DEVICE_PACKAGES := ath11k-wifi-indio-um-525axp ath11k-firmware-ipq50xx-spruce ath11k-firmware-qcn6122 | ||||
|   DEVICE_DTS_CONFIG := config@mp03.5-c1 | ||||
| endef | ||||
| TARGET_DEVICES += indio_um-525axp | ||||
|  | ||||
| define Device/indio_um-525axm | ||||
|   DEVICE_TITLE := Indio UM-525axm | ||||
|   DEVICE_DTS := qcom-ipq5018-indio-um-525axm | ||||
|   SUPPORTED_DEVICES := indio,um-525axm | ||||
|   DEVICE_PACKAGES := ath11k-wifi-indio-um-525axm ath11k-firmware-ipq50xx-spruce ath11k-firmware-qcn6122 | ||||
|   DEVICE_DTS_CONFIG := config@mp03.5-c1 | ||||
| endef | ||||
| TARGET_DEVICES += indio_um-525axm | ||||
|  | ||||
| define Device/udaya_a6_id2 | ||||
|   DEVICE_TITLE := Udaya A6 - ID2 | ||||
|   DEVICE_DTS := qcom-ipq5018-udaya-a6-id2 | ||||
|   | ||||
| @@ -0,0 +1,61 @@ | ||||
| --- a/include/init/ssdk_plat.h | ||||
| +++ b/include/init/ssdk_plat.h | ||||
| @@ -330,6 +330,7 @@ struct qca_phy_priv { | ||||
|  	struct mii_bus *miibus; | ||||
|  /*qca808x_end*/ | ||||
|  	u64 *mib_counters; | ||||
| +	a_uint32_t mib_loop_cnt; | ||||
|  	/* dump buf */ | ||||
|  	a_uint8_t  buf[2048]; | ||||
|  	a_uint32_t link_polling_required; | ||||
| --- a/src/ref/ref_mib.c | ||||
| +++ b/src/ref/ref_mib.c | ||||
| @@ -479,39 +479,37 @@ qca_ar8327_sw_get_port_mib(struct switch | ||||
|  #endif | ||||
|  | ||||
|  int | ||||
| -_qca_ar8327_sw_capture_port_tx_counter(struct qca_phy_priv *priv, int port) | ||||
| +_qca_ar8327_sw_capture_port_tx_counter(a_uint32_t dev_id, int port) | ||||
|  { | ||||
|      fal_mib_info_t  mib_Info; | ||||
|  | ||||
|      memset(&mib_Info, 0, sizeof(fal_mib_info_t)); | ||||
| -    fal_get_tx_mib_info(priv->device_id, port, &mib_Info); | ||||
| +    fal_get_tx_mib_info(dev_id, port, &mib_Info); | ||||
|  | ||||
|      return 0; | ||||
|  } | ||||
|  | ||||
|  int | ||||
| -_qca_ar8327_sw_capture_port_rx_counter(struct qca_phy_priv *priv, int port) | ||||
| +_qca_ar8327_sw_capture_port_rx_counter(a_uint32_t dev_id, int port) | ||||
|  { | ||||
|      fal_mib_info_t  mib_Info; | ||||
|  | ||||
|      memset(&mib_Info, 0, sizeof(fal_mib_info_t)); | ||||
| -    fal_get_rx_mib_info(priv->device_id, port, &mib_Info); | ||||
| +    fal_get_rx_mib_info(dev_id, port, &mib_Info); | ||||
|      return 0; | ||||
|  } | ||||
|  | ||||
|  void | ||||
|  qca_ar8327_sw_mib_task(struct qca_phy_priv *priv) | ||||
|  { | ||||
| -	static int loop = 0; | ||||
| - | ||||
|  	mutex_lock(&priv->reg_mutex); | ||||
| -	if ((loop % 2) == 0) | ||||
| -		_qca_ar8327_sw_capture_port_rx_counter(priv, loop/2); | ||||
| +	if ((priv->mib_loop_cnt % 2) == 0) | ||||
| +		_qca_ar8327_sw_capture_port_rx_counter(priv->device_id, priv->mib_loop_cnt/2); | ||||
|  	else | ||||
| -		_qca_ar8327_sw_capture_port_tx_counter(priv, loop/2); | ||||
| +		_qca_ar8327_sw_capture_port_tx_counter(priv->device_id, priv->mib_loop_cnt/2); | ||||
|  | ||||
| -	if(++loop == (2 * (priv->ports))) { | ||||
| -		loop = 0; | ||||
| +	if(++priv->mib_loop_cnt == (2 * (priv->ports))) { | ||||
| +		priv->mib_loop_cnt = 0; | ||||
|  	} | ||||
|  | ||||
|  	mutex_unlock(&priv->reg_mutex); | ||||
| @@ -1,15 +1,15 @@ | ||||
| From 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"); | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
| @@ -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 | ||||
|  | ||||
| @@ -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 | ||||
|  | ||||
| @@ -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 | ||||
|  | ||||
| @@ -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 | ||||
|  | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -200,7 +200,7 @@ | ||||
| 			phy-mode = "sgmii"; | ||||
| 			full-duplex; | ||||
| 			pause; | ||||
| 			airoha,surge = <1>; | ||||
| 			airoha,surge = <0>; | ||||
| 			airoha,polarity = <2>; | ||||
| 		}; | ||||
|  | ||||
|   | ||||
| @@ -169,7 +169,8 @@ | ||||
| 		compatible = "mediatek,eth-mac"; | ||||
| 		reg = <0>; | ||||
| 		phy-mode = "sgmii"; | ||||
| 		phy-handle = <&phy1>;      // add phy handler | ||||
| 		phy-handle = <&phy30>; | ||||
| 		phy-handle2 = <&phy1>; | ||||
| 		mtd-mac-address = <&factory 0x24>; | ||||
| 	}; | ||||
|  | ||||
| @@ -193,6 +194,16 @@ | ||||
| 			nvmem-cell-names = "phy-cal-data"; | ||||
| 		}; | ||||
|  | ||||
| 		phy30: ethernet-phy@30 { // AN8801SB | ||||
| 			compatible = "ethernet-phy-idc0ff.0421"; | ||||
| 			reg = <30>; //0x1e | ||||
| 			phy-mode = "sgmii"; | ||||
| 			full-duplex; | ||||
| 			pause; | ||||
| 			airoha,surge = <0>; | ||||
| 			airoha,polarity = <2>; | ||||
| 		}; | ||||
|  | ||||
| 		phy1: ethernet-phy@1 { | ||||
| 			compatible = "ethernet-phy-id03a2.9471"; | ||||
| 			reg = <24>;            // set phy address to 0x18 | ||||
| @@ -200,9 +211,8 @@ | ||||
| 			reset-assert-us = <600>; | ||||
| 			reset-deassert-us = <20000>; | ||||
| 			phy-mode = "sgmii"; | ||||
|     }; | ||||
|  | ||||
|         }; | ||||
| 		}; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| &hnat { | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
| @@ -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); | ||||
| @@ -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 = ðdma_cg_regs, .shift = _shift,         \ | ||||
| 		.ops = &mtk_clk_gate_ops_no_setclr_inv,           \ | ||||
| 	} | ||||
|  | ||||
| static const struct mtk_gate ethdma_clks[] = { | ||||
| 	GATE_ETHDMA(CK_ETHDMA_FE_EN, "ethdma_fe_en", "netsys_2x_sel", 6), | ||||
| 	GATE_ETHDMA(CK_ETHDMA_GP2_EN, "ethdma_gp2_en", "netsys_500m_sel", 7), | ||||
| 	GATE_ETHDMA(CK_ETHDMA_GP1_EN, "ethdma_gp1_en", "netsys_500m_sel", 8), | ||||
| 	GATE_ETHDMA(CK_ETHDMA_GP3_EN, "ethdma_gp3_en", "netsys_500m_sel", 10), | ||||
| }; | ||||
|  | ||||
| static const struct mtk_gate_regs sgmii_cg_regs = { | ||||
| 	.set_ofs = 0xe4, | ||||
| 	.clr_ofs = 0xe4, | ||||
| 	.sta_ofs = 0xe4, | ||||
| }; | ||||
|  | ||||
| #define GATE_SGMII(_id, _name, _parent, _shift)                   \ | ||||
| 	{                                                         \ | ||||
| 		.id = _id, .name = _name, .parent_name = _parent, \ | ||||
| 		.regs = &sgmii_cg_regs, .shift = _shift,          \ | ||||
| 		.ops = &mtk_clk_gate_ops_no_setclr_inv,           \ | ||||
| 	} | ||||
|  | ||||
| static const struct mtk_gate sgmii0_clks[] = { | ||||
| 	GATE_SGMII(CK_SGM0_TX_EN, "sgm0_tx_en", "clkxtal", 2), | ||||
| 	GATE_SGMII(CK_SGM0_RX_EN, "sgm0_rx_en", "clkxtal", 3), | ||||
| }; | ||||
|  | ||||
| static const struct mtk_gate sgmii1_clks[] = { | ||||
| 	GATE_SGMII(CK_SGM1_TX_EN, "sgm1_tx_en", "clkxtal", 2), | ||||
| 	GATE_SGMII(CK_SGM1_RX_EN, "sgm1_rx_en", "clkxtal", 3), | ||||
| }; | ||||
|  | ||||
| static void __init mtk_sgmiisys_0_init(struct device_node *node) | ||||
| { | ||||
| 	struct clk_onecell_data *clk_data; | ||||
| 	int r; | ||||
|  | ||||
| 	clk_data = mtk_alloc_clk_data(CLK_SGMII0_NR_CLK); | ||||
|  | ||||
| 	mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks), | ||||
| 			       clk_data); | ||||
|  | ||||
| 	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); | ||||
|  | ||||
| 	if (r) | ||||
| 		pr_err("%s(): could not register clock provider: %d\n", | ||||
| 		       __func__, r); | ||||
| } | ||||
| CLK_OF_DECLARE(mtk_sgmiisys_0, "mediatek,mt7987-sgmiisys_0", | ||||
| 	       mtk_sgmiisys_0_init); | ||||
|  | ||||
| static void __init mtk_sgmiisys_1_init(struct device_node *node) | ||||
| { | ||||
| 	struct clk_onecell_data *clk_data; | ||||
| 	int r; | ||||
|  | ||||
| 	clk_data = mtk_alloc_clk_data(CLK_SGMII1_NR_CLK); | ||||
|  | ||||
| 	mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks), | ||||
| 			       clk_data); | ||||
|  | ||||
| 	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); | ||||
|  | ||||
| 	if (r) | ||||
| 		pr_err("%s(): could not register clock provider: %d\n", | ||||
| 		       __func__, r); | ||||
| } | ||||
| CLK_OF_DECLARE(mtk_sgmiisys_1, "mediatek,mt7987-sgmiisys_1", | ||||
| 	       mtk_sgmiisys_1_init); | ||||
|  | ||||
| static void __init mtk_ethdma_init(struct device_node *node) | ||||
| { | ||||
| 	struct clk_onecell_data *clk_data; | ||||
| 	int r; | ||||
|  | ||||
| 	clk_data = mtk_alloc_clk_data(CLK_ETHDMA_NR_CLK); | ||||
|  | ||||
| 	mtk_clk_register_gates(node, ethdma_clks, ARRAY_SIZE(ethdma_clks), | ||||
| 			       clk_data); | ||||
|  | ||||
| 	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); | ||||
|  | ||||
| 	if (r) | ||||
| 		pr_err("%s(): could not register clock provider: %d\n", | ||||
| 		       __func__, r); | ||||
| } | ||||
| CLK_OF_DECLARE(mtk_ethdma, "mediatek,mt7987-ethsys", mtk_ethdma_init); | ||||
| @@ -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); | ||||
| @@ -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); | ||||
| @@ -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); | ||||
| @@ -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", | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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(); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
| @@ -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, ®)) | ||||
| 	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, ®)) | ||||
| 		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; | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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. | ||||
| @@ -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 | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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 */ | ||||
| @@ -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_ */ | ||||
| @@ -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; | ||||
| } | ||||
| @@ -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_ */ | ||||
| @@ -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); | ||||
| @@ -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_ */ | ||||
| @@ -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_ */ | ||||
| @@ -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_ */ | ||||
| @@ -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_ */ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -4,5 +4,5 @@ | ||||
| # | ||||
|  | ||||
| obj-$(CONFIG_NET_MEDIATEK_SOC)			+= mtk_eth.o | ||||
| mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o mtk_eth_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/ | ||||
|   | ||||
							
								
								
									
										1401
									
								
								feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										1401
									
								
								feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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 */ | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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(ð->ptp_info, | ||||
| 					    eth->dev); | ||||
| 	if (IS_ERR(eth->ptp_clock)) { | ||||
| 		eth->ptp_clock = NULL; | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
|  | ||||
| 	for (i = 0; i < MTK_MAX_DEVS; i++) { | ||||
| 		mac = eth->mac[i]; | ||||
| 		if (!mac) | ||||
| 			continue; | ||||
|  | ||||
| 		INIT_WORK(&mac->ptp_tx_work, mtk_ptp_hwtstamp_tx_work); | ||||
| 	} | ||||
|  | ||||
| 	mtk_ptp_enable(ð->ptp_info, NULL, 1); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int mtk_ptp_clock_deinit(struct mtk_eth *eth) | ||||
| { | ||||
| 	struct mtk_mac *mac; | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < MTK_MAX_DEVS; i++) { | ||||
| 		mac = eth->mac[i]; | ||||
| 		if (!mac) | ||||
| 			continue; | ||||
|  | ||||
| 		cancel_work_sync(&mac->ptp_tx_work); | ||||
| 		dev_kfree_skb_any(mac->ptp_tx_skb); | ||||
| 		mac->ptp_tx_skb = NULL; | ||||
| 		mac->ptp_tx_class = 0; | ||||
| 		mac->ptp_tx_start = 0; | ||||
| 	} | ||||
|  | ||||
| 	mtk_ptp_enable(ð->ptp_info, NULL, 0); | ||||
|  | ||||
| 	ptp_clock_unregister(eth->ptp_clock); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -7,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 */ | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -10,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 */ | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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)) | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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); | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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, ®)) | ||||
| 	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, ®)) | ||||
| 		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; | ||||
|  | ||||
|   | ||||
| @@ -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_ */ | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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)); | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user