From cf632b7b86e7e281f04d158a00e4b14dca79343b Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Sat, 22 Aug 2015 02:00:41 +0200
Subject: [PATCH] WIP Sync ral(4) with FreeBSD.

---
 share/man/man4/ral.4              |  21 +-
 sys/bus/pci/pcidevs               |   3 +
 sys/contrib/dev/ral/LICENSE       |   2 +-
 sys/contrib/dev/ral/rt2561.fw.uu  |   2 +-
 sys/contrib/dev/ral/rt2561s.fw.uu |   2 +-
 sys/contrib/dev/ral/rt2661.fw.uu  |   2 +-
 sys/contrib/dev/ral/rt2860.fw.uu  | 194 +++++++++---------
 sys/dev/netif/ral/if_ral_pci.c    |  48 +++--
 sys/dev/netif/ral/rt2860.c        | 419 ++++++++++++++++++++++++++++++++------
 sys/dev/netif/ral/rt2860reg.h     | 246 +++++++++++++++-------
 sys/dev/netif/ral/rt2860var.h     |   2 +-
 11 files changed, 680 insertions(+), 261 deletions(-)

diff --git a/share/man/man4/ral.4 b/share/man/man4/ral.4
index 84880d1..d1942c4 100644
--- a/share/man/man4/ral.4
+++ b/share/man/man4/ral.4
@@ -14,7 +14,7 @@
 .\"
 .\" $FreeBSD: src/share/man/man4/ral.4,v 1.25 2012/11/17 01:50:46 svnexp Exp $
 .\"
-.Dd May 15, 2014
+.Dd August 22, 2015
 .Dt RAL 4
 .Os
 .Sh NAME
@@ -41,7 +41,7 @@ if_ral_load="YES"
 The
 .Nm
 driver supports PCI/PCIe/CardBus wireless adapters based on the Ralink RT2500,
-RT2501, RT2600, RT2700, RT2800 and RT3090 chipsets.
+RT2501, RT2600, RT2700, RT2800, RT3090 and RT3900E chipsets.
 .Pp
 The RT2500 chipset is the first generation of 802.11b/g adapters from Ralink.
 It consists of two integrated chips, an RT2560 MAC/BBP and an RT2525 radio
@@ -102,10 +102,23 @@ interfaces may be operated together with a
 .Cm hostap
 interface to construct a wireless repeater device.
 .Pp
+The RT3900E chipset is a single-chip 802.11n adapters from Ralink.
+The MAC/Baseband Processor can be an RT5390 or RT5392.
+The RT5390 chip operates in the 2GHz spectrum and supports 1 transmit path
+and 1 receiver path (1T1R).
+The RT5392 chip operates in the 2GHz spectrum and supports up to 2 transmit
+paths and 2 receiver paths (2T2R).
+.Pp
 The transmit speed is user-selectable or can be adapted automatically by the
 driver depending on the number of hardware transmission retries.
 For more information on configuring this device, see
 .Xr ifconfig 8 .
+.Sh LOADER TUNABLES
+.Bl -tag -width indent
+.It Va hw.ral.msi.enable
+By default, the driver will use MSI if it is supported.
+This behavior can be turned off by setting this tunable to 0.
+.El
 .Sh HARDWARE
 The
 .Nm
@@ -140,6 +153,7 @@ chipsets, including:
 .It "Compex WLP54G" Ta RT2560 Ta PCI
 .It "Conceptronic C54RC" Ta RT2560 Ta CardBus
 .It "Conceptronic C54Ri" Ta RT2560 Ta PCI
+.It "D-Link DWA-525 rev A2" Ta RT5392 Ta PCI
 .It "Digitus DN-7001G-RA" Ta RT2560 Ta CardBus
 .It "Digitus DN-7006G-RA" Ta RT2560 Ta PCI
 .It "E-Tech WGPC02" Ta RT2560 Ta CardBus
@@ -174,6 +188,7 @@ chipsets, including:
 .It "MSI PC54G2" Ta RT2560 Ta PCI
 .It "OvisLink EVO-W54PCI" Ta RT2560 Ta PCI
 .It "PheeNet HWL-PCIG/RA" Ta RT2560 Ta PCI
+.It "Planex GW-NS300N" Ta RT2860 Ta CardBus
 .It "Pro-Nets CB80211G" Ta RT2560 Ta CardBus
 .It "Pro-Nets PC80211G" Ta RT2560 Ta PCI
 .It "Repotec RP-WB7108" Ta RT2560 Ta CardBus
@@ -271,7 +286,7 @@ Support for the RT3090 chipset was added in
 The original
 .Nm
 driver was written by
-.An Damien Bergamini Aq Mt damien@FreeBSD.org .
+.An Damien Bergamini Aq Mt damien@openbsd.org .
 .Sh CAVEATS
 The
 .Nm
diff --git a/sys/bus/pci/pcidevs b/sys/bus/pci/pcidevs
index f22c89c..277f263 100644
--- a/sys/bus/pci/pcidevs
+++ b/sys/bus/pci/pcidevs
@@ -510,6 +510,9 @@ product RALINK	RT3593		0x3593	RT3593
 product RALINK	RT5390_1	0x5390	RT5390
 product RALINK	RT5390_2	0x539a	RT5390
 product RALINK	RT5390_3	0x539f	RT5390
+product RALINK	RT5390_4	0x5360	RT5390
+product RALINK	RT5392_1	0x5362	RT5390
+product RALINK	RT5392_2	0x5392	RT5390
 
 /* Realtek (Creative Labs?) products */
 product REALTEK	RT8029		0x8029	8029 Ethernet
diff --git a/sys/contrib/dev/ral/LICENSE b/sys/contrib/dev/ral/LICENSE
index 5acf6db..0e2c69a 100644
--- a/sys/contrib/dev/ral/LICENSE
+++ b/sys/contrib/dev/ral/LICENSE
@@ -1,4 +1,4 @@
-$FreeBSD$
+$FreeBSD: head/sys/contrib/dev/ral/LICENSE 178354 2008-04-20 20:35:46Z sam $
 
 Copyright (c) 2005-2008, Ralink Technology Corp.
 	Paul Lin <paul_lin@ralinktech.com.tw>
diff --git a/sys/contrib/dev/ral/rt2561.fw.uu b/sys/contrib/dev/ral/rt2561.fw.uu
index 87ef667..cfbfad9 100644
--- a/sys/contrib/dev/ral/rt2561.fw.uu
+++ b/sys/contrib/dev/ral/rt2561.fw.uu
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/contrib/dev/ral/rt2561.fw.uu 178354 2008-04-20 20:35:46Z sam $
 #
 # Copyright (c) 2005-2008, Ralink Technology Corp.
 # 	Paul Lin <paul_lin@ralinktech.com.tw>
diff --git a/sys/contrib/dev/ral/rt2561s.fw.uu b/sys/contrib/dev/ral/rt2561s.fw.uu
index bce9bc5..36558fe 100644
--- a/sys/contrib/dev/ral/rt2561s.fw.uu
+++ b/sys/contrib/dev/ral/rt2561s.fw.uu
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/contrib/dev/ral/rt2561s.fw.uu 178354 2008-04-20 20:35:46Z sam $
 #
 # Copyright (c) 2005-2008, Ralink Technology Corp.
 # 	Paul Lin <paul_lin@ralinktech.com.tw>
diff --git a/sys/contrib/dev/ral/rt2661.fw.uu b/sys/contrib/dev/ral/rt2661.fw.uu
index ee4698a..d644c72 100644
--- a/sys/contrib/dev/ral/rt2661.fw.uu
+++ b/sys/contrib/dev/ral/rt2661.fw.uu
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/contrib/dev/ral/rt2661.fw.uu 178354 2008-04-20 20:35:46Z sam $
 #
 # Copyright (c) 2005-2008, Ralink Technology Corp.
 # 	Paul Lin <paul_lin@ralinktech.com.tw>
diff --git a/sys/contrib/dev/ral/rt2860.fw.uu b/sys/contrib/dev/ral/rt2860.fw.uu
index ce4fb9f..501c953 100644
--- a/sys/contrib/dev/ral/rt2860.fw.uu
+++ b/sys/contrib/dev/ral/rt2860.fw.uu
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/contrib/dev/ral/rt2860.fw.uu 232946 2012-03-13 21:25:25Z bschmidt $
+# $FreeBSD: head/sys/contrib/dev/ral/rt2860.fw.uu 278551 2015-02-11 05:25:23Z kevlo $
 #
 # Copyright (c) 2005-2008, Ralink Technology Corp.
 # 	Paul Lin <paul_lin@ralinktech.com.tw>
@@ -15,27 +15,24 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 begin 644 rt2860.fw
-M`@-;`@*F(B+___\"`2S______P(`'O______`@#=P.#`\,"#P(+`T'70&,*O
-M,$4#$A`)D`06X##C`W0(\)`$%.`@YP,"`,MT@/"0<!+@]3:0!`3@),]@,!1@
-M0B3B8$<48%4D(7!@Y54D_F`'%&`()`)P"'T!@"A]`H`DD'`0X/50A39`T@&`
-M/N559`-@!.55<`1]`H`)A39!T@*`*:U5KS82`H*`()!P$.#U1Y!P$>#U1!(0
-M)8`&D'`0X/5%Y/VO-A("@M($D'`3Y/"0<!/D\-*OT-#0@M"#T/#0X#+`X,#P
+M`@*C`@(N(O____\"`2S______P(`'O______`@#=P.#`\,"#P(+`T'70&,*O
+M,$4#$A`)D`06X##C`W0(\)`$%.`@YP,"`,MT@/"0<!+@]220!`3@),]@,!1@
+M0B3B8$<48%4D(7!@Y54D_F`'%&`()`)P"'T!@"A]`H`DD'`0X/50A21`T@&`
+M/N559`-@!.55<`1]`H`)A21!T@*`*:U5KR02`@J`()!P$.#U1Y!P$>#U1!(0
+M)8`&D'`0X/5%Y/VO)!(""M($D'`3Y/"0<!/D\-*OT-#0@M"#T/#0X#+`X,#P
 MP(/`@L#0Z,#@Z<#@ZL#@Z\#@[,#@[<#@[L#@[\#@PJ\P10,2$!+2K]#@_]#@
 M_M#@_=#@_-#@^]#@^M#@^=#@^-#0T(+0@]#PT.`RP.#`\,"#P(+`T'70$,*O
 M,$4#$A`,,%@*Y51@!!54@`+"6#!9"N508`054(`"PEG54P<P8`051M($,$4#
-M$A`/PHW2K]#0T(+0@]#PT.`RD'`JX##A0\*OD'`HX)`0'/"0<"G@D!`=\)!P
-M*N"0$![PD!`<X/4WD!`>X"#A\Y`0'."0<"CPD!`=X)!P*?"0$![@D'`J\,(%
-MTJ\B$@+(,$4#$A`#,`$&(`D#$A`<,`(&(`H#$A`?,`,&(`L#$A`?,`0&(`P#
-M$A`B(!,)(!$&Y2M%+&`#TX`!PY*I$@,<@+_"0])%Y/4@]2'U4_5&]2OU+,)"
-M]5'U4O55D`08=(#PD`0:=`CPPAK"&,(;(LCOR.;Z".9*8`S([\@(YA88<`$6
-MPR+M)/_][#3_R._(]@C&[<;3(M"#T(+XY)-P$G0!DW`-HZ.3^'0!D_6"B(/D
-M<W0"DVA@[Z.CHX#?[_1@'^3^$@-GX+3_$A(#9^_P=!PN]8+D-'#U@^WP(@Z^
-M!.,BP.#`\,"#P(+`T'70",*O,$4#$A`&TJ_0T-""T(/0\-#@,L*O$@`&$@()
-M$@+AY/4B]4>0!`!T@/#2KR)UB0+D]8SUBO6(];CUZ'60&-*,=:@%(N]@`Q^`
-M^B+_P"9T`\#@P(+`@W4F"B+`)G0#P.#`@L"#=288(C!%`Q(0%>4@<`,@$`,P
-M$0-#AP$BSN_.[F`(?_\2`O@>@/4BR._(YF`#%L,B[13VTR+([\CF8`86YB3_
-MLR+#(GA_Y/;8_76!7P(!Q704+O6"Y#1P]8,B[Y`#>Y.0`P!S"AC_________
+M$A`/PHW2K]#0T(+0@]#PT.`R$@)0,$4#$A`#,`$&(`D#$A`<,`(&(`H#$A`?
+M,`,&(`L#$A`?,`0&(`P#$A`B(!,)(!$&Y2M%+&`#TX`!PY*I$@*`@+_"0])%
+MY/4@]2'U4_5&]2OU+,)"]5'U4O55D`08=(#PD`0:=`CP(M"#T(+XY)-P$G0!
+MDW`-HZ.3^'0!D_6"B(/D<W0"DVA@[Z.CHX#?[_1@'^3^$@*OX+3_$A("K^_P
+M=!PN]8+D-'#U@^WP(@Z^!.,BP.#`\,"#P(+`T'70",*O,$4#$A`&TJ_0T-""
+MT(/0\-#@,L*O$@`&$@&^$@)IY/4B]4>0!`!T@/#2KR)UB0+D]8SUBO6(];CU
+MZ'60&-*,=:@%(C!%`Q(0%>4@<`,@$`,P$0-#AP$BSN_.[F`(?_\2`L4>@/4B
+M>'_D]MC]=8%?`@%Z=!0N]8+D-'#U@R+OD`+#DY`#`',*&.]@`Q^`^B+_____
 M____________________________________________________________
+M____P"9T`\#@P(+`@W4F"B+`)G0#P.#`@L"#=288(O__________________
 M____________________________________________________________
 M____________________________________________________________
 M____________________________________________________________
@@ -106,83 +103,86 @@ M____________________________________________________________
 M____________________________________________________________
 M____________________________________________________________
 M____________________________________________________________
-M_____P(0*`(0.P(0/`(3O`(3O0(4<@(4<\,B__\"&4H"&O0"%6P"%*<P!08@
-M#0,2`7HP!@8@#@,2'"XB(I`$%.`@YP,"$[N0<!+@]5:0!`3@$@)<$/LP$-(Q
-M$),S$*$T$+0U$*LV$0E0$4Y1$5=2$5=3$5=4$9-5$?!6$D-P$FEQ$I)R$SYS
-M$V&`$XB#$Z"$```3N](8TF%U-2IU,@MU,[@BPAB0`13@5/WP(I!P$>#U/`(3
-MM>55M`(/Y5@PX`:0`0UT"/!]`8`"?0*O5A("@@(3M2`"`S`#"GT"KU82`H("
-M$[7E--.4`4`,D`$,X$0"\*/@1`3PA59!T@(BD'`1X/1P`P(3N^#U,"+E--.4
-M`4`'Y55@`P(3NY!P$.!4?_^_"@V0<!'@M`@&=4X!=4^$D'`0X%1__[\"$I!P
-M$>!D"&`$X+0@!G5.`W5/(.3U)R*0<!'@)/^21R+E--.4`4`'Y55@`P(329`$
-M!.`EX"1=]5>0<!#@_W1')5?XQN_&D'`1X/]T2"57^,;OQN3]KU82`H("$[7E
-M--.4`4`'Y55@`P(32>5'9`=@'>5'9`A@%^5'9`E@$>5'9`I@"^5'9`M@!>5'
-MM`P(D'`1X%0/]3KE1[0)".4ZM`,#Y/5&Y4>T"@CE.K0!`^3U1N3]KU82`H+2
-M!"*0<!'@]/^0<!#@7_^0<!'@52=/D'`8\)!P$>"0<!GPY/VO5A("@C`5`](4
-M(I!P&.#U)Y`"*>#_D'`9X/[O7I`"*?`P1P2O)X`$Y2?T_Y`"*._P(N4TTY0!
-M0`?E56`#`A-)D'`0X/Z0<!'@_>WXYO57_:]6$@*"`A.UY333E`%`!^558`,"
-M$TF0<!#@_I!P$>#][?6"CH/@]5?]KU82`H("$[60$`#@]5?D]5CU69`0`^"T
-M*`5U6`&`/)`0`^"T,`5U6`*`,)`0`^"T,P5U6`2`))`0`^"T-0R0$`+@M'(%
-M=5@(@!&0$`/@M#4*D!`"X+23`W58$.58,.$9D`4(X$0!\/V0!07@5/OP1`3P
-M[53^D`4(\.3U3O5/=3K_PAK"&,(;]320!:1T$?"C=/_PHW0#\.3U,,(9D`$-
-MX$1`\'4\_ZU7KU82`H+DD'`R\(!WY333E`%`"^558`=]`Z]6`@*"D'`0X"3_
-MDI/D_:]6$@*"@%3E--.4`4`-Y55@"7T#KU82`H*`0)!P$.`D_Y)*T@6M5Z]6
-M$@*"@"WD]33U,)!P$.#T8`/@]32M5Z]6$@*"@!72&04OY2^T&@/D]2_2!*U7
-MKU82`H*0!!1T@/`B(N4TPY0#0!?E5;0"$N4P8`XP8`MT_25&]4;2!.3U4^53
-M8`,"%'$P8"&R33!-'.4TPY0#0!'E5;0"#.4P8`AT`R5&]4:``@5&P@3E3T5.
-M8`CE3Q5/<`(53C`:27\R?;A\"Q("-5`&D`00=$#P?S5],A(#/U`)D!`$X%3W
-M\-(&Y373E"U`,#`;+<(;HAB2&B`:))`$">!4W?"0$`3@1`CPPF'2`R+D]36B
-M&)(:,!H'D`0)X$0B\"(B,!0PD'`9X%4G_Y!P&.!/]2>0`BG@_Y!P&>#^[UZ0
-M`BGP,$<$KR>`!.4G]/^0`BCO\,(4(L)+PDSE1!("7!3)`!57!!53"!4S$!3=
-M(!3]8!4.H```%5F%2$.%2D*%3%[E1V0&8`,"%5F`&^5(Q%0/]4/E2L14#_5"
-MY4S$5`_U7N5'9`9P85-##X!<A4E#A4M"A4U>Y4=D!G!-@!OE2<14#_5#Y4O$
-M5`_U0N5-Q%0/]5[E1V0&<##E0U0/1!#U0X`FY4=D!&`%Y4>T!09#7@1U0@GE
-M1[0&$.5#5`]$,/5#@`;22X`"TDSD]2KE0L14\/_E0U0/3_5?TF`BTA7E1R3U
-M8`LDRV`')$!P!L(5(A(9%1(5CL(5PJ_"!-*O(L*OD`04X%0.8`32'(`(Y4Y%
-M3R3_DAS2KY`$%."BY)(==![PY5]4#_4MY2IP$S`<!>5?(.4+,!TIY5]4,&0P
-M<"'E*G`5Y33#E`-`">4P8`5U*@6`!W4J#(`"%2K2;-)M@`_E7S#F!L)LTFV`
-M!-)LPFWE1V0#<"$P2P;";-)M@!CE*G`#,$P1PDSE*G`%=2H'@`(5*M)LTFWE
-M1[0)%.5$(.,+Y3ID`F`%Y3JT`P3";-)MY4>T"A/E.K0!!L)LTFV`".4Z<`32
-M;,)M(&D'Y5X@X`*R:"!K!^5>(.$"LFH@;0?E7B#B`K)L=2Y`(&D$HFB`13!H
-M!N5&HN*`/#`9'.5>(.`$?P&``G\`Y2^T&01^`8`"?@#N;R3_@!WE7B#@!'\!
-M@`)_`.5&5/#^OO`$?@&``GX`[F\D_Y)SDG(@:P2B:H!%,&H&Y4:BXH`\,!D<
-MY5X@X01_`8`"?P#E+[09!'X!@`)^`.YO)/^`'>5>(.$$?P&``G\`Y494\/Z^
-M\`1^`8`"?@#N;R3_DG62="!M!*)L@";E1V0*<"(P;`;E1J+C@!?E.K0!!N5&
-MHN.`4^5&(.0#,.4#TX`!PX!%,&P&Y4:BXH`\,!D<Y5X@X@1_`8`"?P#E+[09
-M!'X!@`)^`.YO)/^`'>5>(.($?P&``G\`Y494\/Z^\`1^`8`"?@#N;R3_DG&2
-M<)`0`."0$"SPD!`#X,.4,$`4HG&2=Z)PDG;E+A,35#_U+L)WTG:0$"_E+O#E
-M1V0&<#F0`BG@5/[PY4/$5`\48`PD_F`,)`-P$\(X@`_2.(`+Y48PX@/3@`'#
-MDC@P1P6O)P(9#^4G]/\"&0_E1V0'8`_E1V0(8`GE1V0)8`,"&(Z0`BG@5/SP
-MY3H48"(48"448"TD_&!))/E@%"0.<%#E1A,35#]U\`.$Y?`D_X`ZTCG".(`^
-MY48PX@/3@!W#@!KE1C#B#50XPY0P4`9^`'\!@`1^`'\`[D\D_Y(XPCF`$^5&
-M,.(#TX`!PY(YPCB`!,(XPCDP1P2O)X`$Y2?T_P(9#^5'9`Q@!N5'9`MP>I`"
-M*>!4_?#E.A1@(!1@(11@*R3\8$4D^6`2)`YP2N5&$Q-4/W7P`X3E\(`ITCF`
-M.N5&,.(#TX`!PY(Y@"WE1C#B#50XPY0P4`9^`'\!@`1^`'\`[D\D_Y(Y@`_E
-M1C#B`].``<.2.8`"PCDP1P2O)X`$Y2?T_Y`"*._P(N5'M`L0D`(IX%3K\.4G
-M5.M%1?4G(N20`BGP,$<$KT6`!.5%]/^0`BCO\"*/4-)9(H]4TE@BY/4WPJ_E
-M411@2A1@:R0"8`,"&M726755`2`:')`"".!4_O#@(.$CD`0TX+0"'*/@M`(7
-MH^"T`A)_(!(90)`0!.!4\_!U40$"&M7E4'`&=3<#`AK5D!(`X%0#<!5_(!(9
-M0"`:!Y`"".!4^_!U40("&M7E4'`#`AK0(!H5D`((X##C`P(:S)`$-^!D(F`#
-M`AK,D!($=`KPY5@PXQ7DD`4`\*-T"/"C=`'P=`/P?P$2`S"0$RC@D'`:\)`3
-M*>"0<!OPD!,KX)!P(O"0$RC@5/#PH^!4\/"0$RO@5,SPY5@PXQ?E-'`3Y3ST
-MD!,J8`7@5/.`$>!4^_"`%.4\])`3*F`(X%3R13SP@`3@5/KP(!H'D`0!X$00
-M\.4TTY0!0`GE,'`%=8Q`@`-UC("0!`'@5/WP(!H'D!($X$0$\.58,.`&D`$-
-MX/4QY333E`%`+)`!#>!$`?#E6"#C#.4TM`,'D!($X%3]\"`"$2`##I`!#>!4
-M^_"0`0S@5/WP=3<!=54"Y/51@`GE4'`%=3<#]5'E-V`8P@'D]5'"62`:#JTW
-MKT`2&_KE-[0#`M(#TJ\BPJ\P`0[D]5'"6<(!?0*O0!(;^N52%&!6%&`S)`)@
-M`P(;]^4TTY0!0!^0`0S@1`+PH^!$!/"0$@3@1`+P?S(2`S"0`0W@5/[P=5("
-M=54#Y5@PX`:0`0WE,?"0$@3@5/OP?R`2&45U4@%U50,"&_?E5&`#`AOWD`0!
-MX$0.\"`:!.!4[_#D]8SE6%088!Z0<!K@D!,H\)!P&^"0$RGPHW0%\)!P(N"0
-M$ROP@!&0$RC@1`_PH^!$#_"CX$0%\)`2!'0#\.58,.,6D`4`=.+PHW0(\*-T
-M`?!T`_!_`1(#,"`:!Y`"".!$!?"0$`3@1`SPY/52]54P`@G"`GT!KT$2&_HP
-M`P+"`]*O(N_T8"WD_G04+O6"Y#1P]8/@M/\9=!0N]8+D-'#U@^_P=!PN]8+D
-M-'#U@^WP(@Z^!-4B(B(P&G>0!#?@(.5LD`0HX/4XH^#U-_4YY/4EY3EU\("D
-M)`#_Y?`T@/[E-V4Y<`7\?2B`!'P`?0#O+?_N//X2'*E0!Y`!%.!$`O#E.64X
-M8!#D)3G_Y#2`CX+U@^#U.8"[D`00=`'PD`0HY3CPH^4W\)`$$70!\("-P@;2
-M&R+E)<.4!E`9CX*.@^"T_P<%)>3U)(`NY/4ECX*.@_"`).4D=?`&A'0()?#U
-M@N0T$/6#X/V/@HZ#X&UP!@4E!22``^3U)0^_``$.[U1_8`?E)<.4*D"KY26T
-M*@/3@`'#(@``````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+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
+MD'`J\,(%TJ\B(@``````````````````````````````````````````````
 M````````````````````````````````````````````````````````````
 M````````````````````````````````````````````````````````````
 M````````````````````````````````````````````````````````````
@@ -196,7 +196,7 @@ M````````````````````````````````````````````````````````````
 M````````````````````````````````````````````````````````````
 M````````````````````````````````````````````````````````````
 M````````````````````````````````````````````````````````````
-M```````````````````````````````````````````````````````````:
-"4X@`
+M```````````````````````````````````````````````````````````F
+"6](`
 `
 end
diff --git a/sys/dev/netif/ral/if_ral_pci.c b/sys/dev/netif/ral/if_ral_pci.c
index c7614b0..749e9fd 100644
--- a/sys/dev/netif/ral/if_ral_pci.c
+++ b/sys/dev/netif/ral/if_ral_pci.c
@@ -1,5 +1,3 @@
-/*	$FreeBSD: src/sys/dev/ral/if_ral_pci.c,v 1.10 2012/05/10 17:41:16 bschmidt Exp $	*/
-
 /*-
  * Copyright (c) 2005, 2006
  *	Damien Bergamini <damien.bergamini@free.fr>
@@ -15,6 +13,8 @@
  * 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.
+ *
+ * $FreeBSD: head/sys/dev/ral/if_ral_pci.c 286437 2015-08-08 01:10:17Z adrian $
  */
 
 
@@ -60,6 +60,9 @@ MODULE_DEPEND(ral, firmware, 1, 1, 1);
 MODULE_DEPEND(ral, wlan, 1, 1, 1);
 MODULE_DEPEND(ral, wlan_amrr, 1, 1, 1);
 
+static int	ral_msi_enable = 1;
+TUNABLE_INT("hw.ral.msi.enable", &ral_msi_enable);
+
 struct ral_pci_ident {
 	uint16_t	vendor;
 	uint16_t	device;
@@ -129,11 +132,17 @@ static const struct ral_pci_ident ral_pci_ids[] = {
 		"Ralink Technology RT5390" },
 	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT5390_3,
 		"Ralink Technology RT5390" },
+	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT5390_4,
+		"Ralink Technology RT5390" },
+	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT5392_1,
+		"Ralink Technology RT5392" },
+	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT5392_2,
+		"Ralink Technology RT5392" },
 
 	{ 0, 0, NULL }
 };
 
-static struct ral_opns {
+static const struct ral_opns {
 	int	(*attach)(device_t, int);
 	int	(*detach)(void *);
 	void	(*shutdown)(void *);
@@ -172,8 +181,9 @@ struct ral_pci_softc {
 		struct rt2860_softc sc_rt2860;
 	} u;
 
-	struct ral_opns		*sc_opns;
+	const struct ral_opns	*sc_opns;
 	int			irq_rid;
+	int			irq_type;
 	int			mem_rid;
 	struct resource		*irq;
 	struct resource		*mem;
@@ -221,31 +231,22 @@ ral_pci_probe(device_t dev)
 		    pci_get_device(dev) == ident->device) {
 			device_set_desc(dev, ident->name);
 			wlan_serialize_exit();
-			return 0;
+			return (BUS_PROBE_DEFAULT);
 		}
 	}
 	wlan_serialize_exit();
 	return ENXIO;
 }
 
-/* Base Address Register */
-#define RAL_PCI_BAR0	0x10
-
 static int
 ral_pci_attach(device_t dev)
 {
 	struct ral_pci_softc *psc = device_get_softc(dev);
 	struct rt2560_softc *sc = &psc->u.sc_rt2560;
+	u_int irq_flags;
 	int error;
 
 	wlan_serialize_enter();
-	if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
-		device_printf(dev, "chip is in D%d power mode "
-		    "-- setting to D0\n", pci_get_powerstate(dev));
-		pci_set_powerstate(dev, PCI_POWERSTATE_D0);
-	}
-
-	/* enable bus-mastering */
 	pci_enable_busmaster(dev);
 
 	switch (pci_get_device(dev)) {
@@ -262,7 +263,7 @@ ral_pci_attach(device_t dev)
 		break;
 	}
 
-	psc->mem_rid = RAL_PCI_BAR0;
+	psc->mem_rid = PCIR_BAR(0);
 	psc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &psc->mem_rid,
 	    RF_ACTIVE);
 	if (psc->mem == NULL) {
@@ -276,10 +277,15 @@ ral_pci_attach(device_t dev)
 	sc->sc_invalid = 1;
 	
 	psc->irq_rid = 0;
+	psc->irq_type = pci_alloc_1intr(dev, ral_msi_enable, &psc->irq_rid,
+	    &irq_flags);
 	psc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &psc->irq_rid,
-	    RF_ACTIVE | RF_SHAREABLE);
+	    irq_flags);
 	if (psc->irq == NULL) {
 		device_printf(dev, "could not allocate interrupt resource\n");
+		pci_release_msi(dev);
+		bus_release_resource(dev, SYS_RES_MEMORY, psc->mem_rid,
+		    psc->mem);
 		wlan_serialize_exit();
 		return ENXIO;
 	}
@@ -315,13 +321,15 @@ ral_pci_detach(device_t dev)
 	wlan_serialize_enter();
 	/* check if device was removed */
 	sc->sc_invalid = !bus_child_present(dev);
-	
+
+	if (psc->sc_ih != NULL)
+		bus_teardown_intr(dev, psc->irq, psc->sc_ih);
 	(*psc->sc_opns->detach)(psc);
 
 	bus_generic_detach(dev);
-	bus_teardown_intr(dev, psc->irq, psc->sc_ih);
 	bus_release_resource(dev, SYS_RES_IRQ, psc->irq_rid, psc->irq);
-
+	if (psc->irq_type == PCI_INTR_TYPE_MSI)
+		pci_release_msi(dev);
 	bus_release_resource(dev, SYS_RES_MEMORY, psc->mem_rid, psc->mem);
 
 	wlan_serialize_exit();
diff --git a/sys/dev/netif/ral/rt2860.c b/sys/dev/netif/ral/rt2860.c
index c431bbb..be1df22 100644
--- a/sys/dev/netif/ral/rt2860.c
+++ b/sys/dev/netif/ral/rt2860.c
@@ -15,11 +15,11 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
  * $OpenBSD: rt2860.c,v 1.65 2010/10/23 14:24:54 damien Exp $
- * $FreeBSD: src/sys/dev/ral/rt2860.c,v 1.3 2012/12/04 11:18:52 svnexp Exp $
+ * $FreeBSD: head/sys/dev/ral/rt2860.c 278551 2015-02-11 05:25:23Z kevlo $
  */
 
 /*-
- * Ralink Technology RT2860/RT3090/RT3390/RT3562 chipset driver
+ * Ralink Technology RT2860/RT3090/RT3390/RT3562/RT5390/RT5392 chipset driver
  * http://www.ralinktech.com/
  */
 
@@ -40,6 +40,7 @@
 
 #include <net/bpf.h>
 #include <net/if.h>
+#include <net/if_var.h>
 #include <net/if_arp.h>
 #include <net/ethernet.h>
 #include <net/if_dl.h>
@@ -139,8 +140,11 @@ static void	rt2860_set_channel(struct ieee80211com *);
 static void	rt2860_select_chan_group(struct rt2860_softc *, int);
 static void	rt2860_set_chan(struct rt2860_softc *, u_int);
 static void	rt3090_set_chan(struct rt2860_softc *, u_int);
+static void	rt5390_set_chan(struct rt2860_softc *, u_int);
 static int	rt3090_rf_init(struct rt2860_softc *);
+static void	rt5390_rf_init(struct rt2860_softc *);
 static void	rt3090_rf_wakeup(struct rt2860_softc *);
+static void	rt5390_rf_wakeup(struct rt2860_softc *);
 static int	rt3090_filter_calib(struct rt2860_softc *, uint8_t, uint8_t,
 		    uint8_t *);
 static void	rt3090_rf_setup(struct rt2860_softc *);
@@ -163,6 +167,7 @@ static const char *rt2860_get_rf(uint8_t);
 static int	rt2860_read_eeprom(struct rt2860_softc *,
 		    uint8_t macaddr[IEEE80211_ADDR_LEN]);
 static int	rt2860_bbp_init(struct rt2860_softc *);
+static void	rt5390_bbp_init(struct rt2860_softc *);
 static int	rt2860_txrx_enable(struct rt2860_softc *);
 static void	rt2860_init(void *);
 static void	rt2860_init_locked(struct rt2860_softc *);
@@ -191,6 +196,8 @@ static const struct {
 	uint8_t	val;
 } rt2860_def_bbp[] = {
 	RT2860_DEF_BBP
+}, rt5390_def_bbp[] = {
+	RT5390_DEF_BBP
 };
 
 static const struct rfprog {
@@ -209,8 +216,12 @@ struct {
 static const struct {
 	uint8_t	reg;
 	uint8_t	val;
-}  rt3090_def_rf[] = {
+} rt3090_def_rf[] = {
 	RT3070_DEF_RF
+}, rt5390_def_rf[] = {
+	RT5390_DEF_RF
+}, rt5392_def_rf[] = {
+	RT5392_DEF_RF
 };
 
 int
@@ -225,6 +236,7 @@ rt2860_attach(device_t dev, int id)
 	uint8_t macaddr[IEEE80211_ADDR_LEN];
 	struct sysctl_ctx_list *ctx;
 	struct sysctl_oid *tree;
+	char ethstr[ETHER_ADDRSTRLEN + 1];
 
 	sc->sc_dev = dev;
 	sc->sc_debug = 0;
@@ -260,15 +272,10 @@ rt2860_attach(device_t dev, int id)
 
 	/* retrieve RF rev. no and various other things from EEPROM */
 	rt2860_read_eeprom(sc, macaddr);
-	if (bootverbose) {
-		char ethstr[ETHER_ADDRSTRLEN + 1];
-
-		device_printf(sc->sc_dev, "MAC/BBP RT%X (rev 0x%04X), "
-		    "RF %s (MIMO %dT%dR), address %s\n",
-		    sc->mac_ver, sc->mac_rev, rt2860_get_rf(sc->rf_rev),
-		    sc->ntxchains, sc->nrxchains,
-		    kether_ntoa(macaddr, ethstr));
-	}
+	device_printf(sc->sc_dev, "MAC/BBP RT%X (rev 0x%04X), "
+	    "RF %s (MIMO %dT%dR), address %s\n",
+	    sc->mac_ver, sc->mac_rev, rt2860_get_rf(sc->rf_rev),
+	    sc->ntxchains, sc->nrxchains, kether_ntoa(macaddr, ethstr));
 
 	/*
 	 * Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings.
@@ -1518,7 +1525,7 @@ rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
 		tid = 0;
 	}
 	ring = &sc->txq[qid];
-	ridx = ic->ic_rt->rateCodeToIndex[rate];
+	ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, rate);
 
 	/* get MCS code from rate index */
 	mcs = rt2860_rates[ridx].mcs;
@@ -1770,7 +1777,8 @@ rt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m,
 
 	/* Choose a TX rate index. */
 	rate = params->ibp_rate0;
-	ridx = ic->ic_rt->rateCodeToIndex[rate];
+	ridx = ieee80211_legacy_rate_lookup(ic->ic_rt,
+	    rate & IEEE80211_RATE_VAL);
 	if (ridx == (uint8_t)-1) {
 		/* XXX fall back to mcast/mgmt rate? */
 		m_freem(m);
@@ -2062,7 +2070,7 @@ rt2860_mcu_bbp_write(struct rt2860_softc *sc, uint8_t reg, uint8_t val)
 	}
 	if (ntries == 100) {
 		device_printf(sc->sc_dev,
-		    "could not write to BBP through MCU\n");
+			"could not write to BBP through MCU\n");
 		return;
 	}
 
@@ -2293,7 +2301,7 @@ rt2860_set_basicrates(struct rt2860_softc *sc,
 		if (!(rate & IEEE80211_RATE_BASIC))
 			continue;
 
-		mask |= 1 << ic->ic_rt->rateCodeToIndex[RV(rate)];
+		mask |= 1 << ieee80211_legacy_rate_lookup(ic->ic_rt, RV(rate));
 	}
 
 	RAL_WRITE(sc, RT2860_LEGACY_BASIC_RATE, mask);
@@ -2540,10 +2548,110 @@ rt3090_set_chan(struct rt2860_softc *sc, u_int chan)
 	rt3090_rf_write(sc, 7, rf | RT3070_TUNE);
 }
 
+static void
+rt5390_set_chan(struct rt2860_softc *sc, u_int chan)
+{
+	uint8_t h20mhz, rf, tmp;
+	int8_t txpow1, txpow2;
+	int i;
+
+	/* RT5390 is 2GHz only */
+	KASSERT(chan >= 1 && chan <= 14, ("chan %d not support", chan));
+
+	/* find the settings for this channel (we know it exists) */
+	for (i = 0; rt2860_rf2850[i].chan != chan; i++);
+
+	/* use Tx power values from EEPROM */
+	txpow1 = sc->txpow1[i];
+	txpow2 = sc->txpow2[i];
+
+	rt3090_rf_write(sc, 8, rt3090_freqs[i].n);
+	rt3090_rf_write(sc, 9, rt3090_freqs[i].k & 0x0f);
+	rf = rt3090_rf_read(sc, 11);
+	rf = (rf & ~0x03) | (rt3090_freqs[i].r & 0x03);
+	rt3090_rf_write(sc, 11, rf);
+
+	rf = rt3090_rf_read(sc, 49);
+	rf = (rf & ~0x3f) | (txpow1 & 0x3f);
+	/* the valid range of the RF R49 is 0x00~0x27 */
+	if ((rf & 0x3f) > 0x27)
+		rf = (rf & ~0x3f) | 0x27;
+	rt3090_rf_write(sc, 49, rf);
+	if (sc->mac_ver == 0x5392) {
+		rf = rt3090_rf_read(sc, 50);
+		rf = (rf & ~0x3f) | (txpow2 & 0x3f);
+		/* the valid range of the RF R50 is 0x00~0x27 */
+		if ((rf & 0x3f) > 0x27)
+			rf = (rf & ~0x3f) | 0x27;
+		rt3090_rf_write(sc, 50, rf);
+	}
+
+	rf = rt3090_rf_read(sc, 1);
+	rf |= RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD;
+	if (sc->mac_ver == 0x5392)
+		rf |= RT3070_RX1_PD | RT3070_TX1_PD;
+	rt3090_rf_write(sc, 1, rf);
+
+	rf = rt3090_rf_read(sc, 2);
+	rt3090_rf_write(sc, 2, rf | RT3593_RESCAL);
+	DELAY(1000);
+	rt3090_rf_write(sc, 2, rf & ~RT3593_RESCAL);
+
+	rf = rt3090_rf_read(sc, 17);
+	tmp = rf;
+	rf = (rf & ~0x7f) | (sc->freq & 0x7f);
+	rf = MIN(rf, 0x5f);
+	if (tmp != rf)
+		rt2860_mcu_cmd(sc, 0x74, (tmp << 8 ) | rf, 0);
+	
+	if (sc->mac_ver == 0x5390) {
+		if (chan <= 4)
+			rf = 0x73;
+		else if (chan >= 5 && chan <= 6)
+			rf = 0x63;
+		else if (chan >= 7 && chan <= 10)
+			rf = 0x53;
+		else
+			rf = 43;
+		rt3090_rf_write(sc, 55, rf);
+
+		if (chan == 1)
+			rf = 0x0c;
+		else if (chan == 2)
+			rf = 0x0b;
+		else if (chan == 3)
+			rf = 0x0a;
+		else if (chan >= 4 && chan <= 6)
+			rf = 0x09;
+		else if (chan >= 7 && chan <= 12)
+			rf = 0x08;
+		else if (chan == 13)
+			rf = 0x07;
+		else
+			rf = 0x06;
+		rt3090_rf_write(sc, 59, rf);
+	}
+
+	/* Tx/Rx h20M */
+	h20mhz = (sc->rf24_20mhz & 0x20) >> 5;
+	rf = rt3090_rf_read(sc, 30);
+	rf = (rf & ~0x06) | (h20mhz << 1) | (h20mhz << 2);
+	rt3090_rf_write(sc, 30, rf);
+
+	/* Rx BB filter VCM */
+	rf = rt3090_rf_read(sc, 30);
+	rf = (rf & ~0x18) | 0x10;
+	rt3090_rf_write(sc, 30, rf);
+
+	/* Initiate VCO calibration. */
+	rf = rt3090_rf_read(sc, 3);
+	rf |= RT3593_VCOCAL;
+	rt3090_rf_write(sc, 3, rf);
+}
+
 static int
 rt3090_rf_init(struct rt2860_softc *sc)
 {
-#define N(a)	(sizeof (a) / sizeof ((a)[0]))
 	uint32_t tmp;
 	uint8_t rf, bbp;
 	int i;
@@ -2567,7 +2675,7 @@ rt3090_rf_init(struct rt2860_softc *sc)
 	RAL_WRITE(sc, RT3070_GPIO_SWITCH, tmp & ~0x20);
 
 	/* initialize RF registers to default value */
-	for (i = 0; i < N(rt3090_def_rf); i++) {
+	for (i = 0; i < nitems(rt3090_def_rf); i++) {
 		rt3090_rf_write(sc, rt3090_def_rf[i].reg,
 		    rt3090_def_rf[i].val);
 	}
@@ -2646,11 +2754,79 @@ rt3090_rf_init(struct rt2860_softc *sc)
 	rf = rt3090_rf_read(sc, 21);
 	rt3090_rf_write(sc, 21, rf & ~RT3070_RX_LO2);
 
-	return 0;
-#undef N
+	return (0);
 }
 
-void
+static void
+rt5390_rf_init(struct rt2860_softc *sc)
+{
+	uint8_t rf, bbp;
+	int i;
+
+	rf = rt3090_rf_read(sc, 2);
+	/* Toggle RF R2 bit 7. */
+	rt3090_rf_write(sc, 2, rf | RT3593_RESCAL);
+	DELAY(1000);
+	rt3090_rf_write(sc, 2, rf & ~RT3593_RESCAL);
+
+	/* Initialize RF registers to default value. */
+	if (sc->mac_ver == 0x5392) {
+		for (i = 0; i < nitems(rt5392_def_rf); i++) {
+			rt3090_rf_write(sc, rt5392_def_rf[i].reg,
+			    rt5392_def_rf[i].val);
+		}
+	} else {
+		for (i = 0; i < nitems(rt5390_def_rf); i++) {
+			rt3090_rf_write(sc, rt5390_def_rf[i].reg,
+			    rt5390_def_rf[i].val);
+		}
+	}
+
+	sc->rf24_20mhz = 0x1f;
+	sc->rf24_40mhz = 0x2f;
+
+	if (sc->mac_rev < 0x0211)
+		rt3090_rf_write(sc, 27, 0x03);
+
+	/* Set led open drain enable. */
+	RAL_WRITE(sc, RT3070_OPT_14, RAL_READ(sc, RT3070_OPT_14) | 1);
+
+	RAL_WRITE(sc, RT2860_TX_SW_CFG1, 0);
+	RAL_WRITE(sc, RT2860_TX_SW_CFG2, 0);
+
+	if (sc->mac_ver == 0x5390)
+		rt3090_set_rx_antenna(sc, 0);
+
+	/* Patch RSSI inaccurate issue. */
+	rt2860_mcu_bbp_write(sc, 79, 0x13);
+	rt2860_mcu_bbp_write(sc, 80, 0x05);
+	rt2860_mcu_bbp_write(sc, 81, 0x33);
+
+	/* Enable DC filter. */
+	if (sc->mac_rev >= 0x0211)
+		rt2860_mcu_bbp_write(sc, 103, 0xc0);
+
+	bbp = rt2860_mcu_bbp_read(sc, 138);
+	if (sc->ntxchains == 1)
+		bbp |= 0x20;	/* Turn off DAC1. */
+	if (sc->nrxchains == 1)
+		bbp &= ~0x02;	/* Turn off ADC1. */
+	rt2860_mcu_bbp_write(sc, 138, bbp);
+
+	/* Enable RX LO1 and LO2. */
+	rt3090_rf_write(sc, 38, rt3090_rf_read(sc, 38) & ~RT5390_RX_LO1);
+	rt3090_rf_write(sc, 39, rt3090_rf_read(sc, 39) & ~RT5390_RX_LO2);
+
+	/* Avoid data lost and CRC error. */
+	rt2860_mcu_bbp_write(sc, 4,
+	    rt2860_mcu_bbp_read(sc, 4) | RT5390_MAC_IF_CTRL);
+
+	rf = rt3090_rf_read(sc, 30);
+	rf = (rf & ~0x18) | 0x10;
+	rt3090_rf_write(sc, 30, rf);
+}
+
+static void
 rt3090_rf_wakeup(struct rt2860_softc *sc)
 {
 	uint32_t tmp;
@@ -2716,7 +2892,43 @@ rt3090_rf_wakeup(struct rt2860_softc *sc)
 	}
 }
 
-int
+static void
+rt5390_rf_wakeup(struct rt2860_softc *sc)
+{
+	uint32_t tmp;
+	uint8_t rf;
+
+	rf = rt3090_rf_read(sc, 1);
+	rf |= RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | 
+	    RT3070_TX0_PD;
+	if (sc->mac_ver == 0x5392)
+		rf |= RT3070_RX1_PD | RT3070_TX1_PD;
+	rt3090_rf_write(sc, 1, rf);
+
+	rf = rt3090_rf_read(sc, 6);
+	rf |= RT3593_VCO_IC | RT3593_VCOCAL;
+	if (sc->mac_ver == 0x5390)
+		rf &= ~RT3593_VCO_IC;
+	rt3090_rf_write(sc, 6, rf);
+
+	rt3090_rf_write(sc, 2, rt3090_rf_read(sc, 2) | RT3593_RESCAL);
+
+	rf = rt3090_rf_read(sc, 22);
+	rf = (rf & ~0xe0) | 0x20;
+	rt3090_rf_write(sc, 22, rf);
+
+	rt3090_rf_write(sc, 42, rt3090_rf_read(sc, 42) | RT5390_RX_CTB);
+	rt3090_rf_write(sc, 20, rt3090_rf_read(sc, 20) & ~0x77);
+	rt3090_rf_write(sc, 3, rt3090_rf_read(sc, 3) | RT3593_VCOCAL);
+
+	if (sc->patch_dac && sc->mac_rev < 0x0211) {
+		tmp = RAL_READ(sc, RT3070_LDO_CFG0);
+		tmp = (tmp & ~0x1f000000) | 0x0d000000;
+		RAL_WRITE(sc, RT3070_LDO_CFG0, tmp);
+	}
+}
+
+static int
 rt3090_filter_calib(struct rt2860_softc *sc, uint8_t init, uint8_t target,
     uint8_t *val)
 {
@@ -2745,7 +2957,7 @@ rt3090_filter_calib(struct rt2860_softc *sc, uint8_t init, uint8_t target,
 			break;
 	}
 	if (ntries == 100)
-		return ETIMEDOUT;
+		return (ETIMEDOUT);
 
 	/* set power and frequency of stopband test tone */
 	rt2860_mcu_bbp_write(sc, 24, 0x06);
@@ -2778,7 +2990,7 @@ rt3090_filter_calib(struct rt2860_softc *sc, uint8_t init, uint8_t target,
 	rf22 = rt3090_rf_read(sc, 22);
 	rt3090_rf_write(sc, 22, rf22 & ~RT3070_BB_LOOPBACK);
 
-	return 0;
+	return (0);
 }
 
 static void
@@ -2804,10 +3016,12 @@ rt3090_rf_setup(struct rt2860_softc *sc)
 		RAL_WRITE(sc, RT2860_TX_SW_CFG2, 0);
 
 	/* initialize RF registers from ROM */
-	for (i = 0; i < 10; i++) {
-		if (sc->rf[i].reg == 0 || sc->rf[i].reg == 0xff)
-			continue;
-		rt3090_rf_write(sc, sc->rf[i].reg, sc->rf[i].val);
+	if (sc->mac_ver < 0x5390) {
+		for (i = 0; i < 10; i++) {
+			if (sc->rf[i].reg == 0 || sc->rf[i].reg == 0xff)
+				continue;
+			rt3090_rf_write(sc, sc->rf[i].reg, sc->rf[i].val);
+		}
 	}
 }
 
@@ -3146,6 +3360,7 @@ rt2860_get_rf(uint8_t rev)
 	case RT3070_RF_3052:	return "RT3052";
 	case RT3070_RF_3320:	return "RT3320";
 	case RT3070_RF_3053:	return "RT3053";
+	case RT5390_RF_5390:	return "RT5390";
 	default:		return "unknown";
 	}
 }
@@ -3228,7 +3443,12 @@ rt2860_read_eeprom(struct rt2860_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN])
 	val = rt2860_srom_read(sc, RT2860_EEPROM_ANTENNA);
 	if (val == 0xffff) {
 		DPRINTF(("invalid EEPROM antenna info, using default\n"));
-		if (sc->mac_ver == 0x3593) {
+		if (sc->mac_ver >= 0x5390) {
+			/* default to RF5390 */
+			sc->rf_rev = RT5390_RF_5390;
+			sc->ntxchains = (sc->mac_ver == 0x5392) ? 2 : 1;
+			sc->nrxchains = (sc->mac_ver == 0x5392) ? 2 : 1;
+		} else if (sc->mac_ver == 0x3593) {
 			/* default to RF3053 3T3R */
 			sc->rf_rev = RT3070_RF_3053;
 			sc->ntxchains = 3;
@@ -3246,8 +3466,13 @@ rt2860_read_eeprom(struct rt2860_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN])
 		}
 	} else {
 		sc->rf_rev = (val >> 8) & 0xf;
-		sc->ntxchains = (val >> 4) & 0xf;
-		sc->nrxchains = val & 0xf;
+		if (sc->mac_ver >= 0x5390) {
+			sc->ntxchains = (sc->mac_ver == 0x5392) ? 2 : 1;
+			sc->nrxchains = (sc->mac_ver == 0x5392) ? 2 : 1;
+		} else {
+			sc->ntxchains = (val >> 4) & 0xf;
+			sc->nrxchains = val & 0xf;
+		}
 	}
 	DPRINTF(("EEPROM RF rev=0x%02x chains=%dT%dR\n",
 	    sc->rf_rev, sc->ntxchains, sc->nrxchains));
@@ -3285,17 +3510,23 @@ rt2860_read_eeprom(struct rt2860_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN])
 		sc->txpow1[i + 0] = (int8_t)(val & 0xff);
 		sc->txpow1[i + 1] = (int8_t)(val >> 8);
 
-		val = rt2860_srom_read(sc,
-		    RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2);
-		sc->txpow2[i + 0] = (int8_t)(val & 0xff);
-		sc->txpow2[i + 1] = (int8_t)(val >> 8);
+		if (sc->mac_ver != 0x5390) {
+			val = rt2860_srom_read(sc,
+			    RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2);
+			sc->txpow2[i + 0] = (int8_t)(val & 0xff);
+			sc->txpow2[i + 1] = (int8_t)(val >> 8);
+		}
 	}
 	/* fix broken Tx power entries */
 	for (i = 0; i < 14; i++) {
-		if (sc->txpow1[i] < 0 || sc->txpow1[i] > 31)
+		if (sc->txpow1[i] < 0 ||
+		    sc->txpow1[i] > ((sc->mac_ver >= 0x5390) ? 39 : 31))
 			sc->txpow1[i] = 5;
-		if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31)
-			sc->txpow2[i] = 5;
+		if (sc->mac_ver != 0x5390) {
+			if (sc->txpow2[i] < 0 ||
+			    sc->txpow2[i] > ((sc->mac_ver == 0x5392) ? 39 : 31))
+				sc->txpow2[i] = 5;
+		}
 		DPRINTF(("chan %d: power1=%d, power2=%d\n",
 		    rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]));
 	}
@@ -3463,10 +3694,9 @@ rt2860_read_eeprom(struct rt2860_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN])
 	return 0;
 }
 
-int
+static int
 rt2860_bbp_init(struct rt2860_softc *sc)
 {
-#define N(a)	(sizeof (a) / sizeof ((a)[0]))
 	int i, ntries;
 
 	/* wait for BBP to wake up */
@@ -3478,13 +3708,17 @@ rt2860_bbp_init(struct rt2860_softc *sc)
 	if (ntries == 20) {
 		device_printf(sc->sc_dev,
 		    "timeout waiting for BBP to wake up\n");
-		return ETIMEDOUT;
+		return (ETIMEDOUT);
 	}
 
 	/* initialize BBP registers to default values */
-	for (i = 0; i < N(rt2860_def_bbp); i++) {
-		rt2860_mcu_bbp_write(sc, rt2860_def_bbp[i].reg,
-		    rt2860_def_bbp[i].val);
+	if (sc->mac_ver >= 0x5390)
+		rt5390_bbp_init(sc);
+	else {
+		for (i = 0; i < nitems(rt2860_def_bbp); i++) {
+			rt2860_mcu_bbp_write(sc, rt2860_def_bbp[i].reg,
+			    rt2860_def_bbp[i].val);
+		}
 	}
 
 	/* fix BBP84 for RT2860E */
@@ -3501,7 +3735,44 @@ rt2860_bbp_init(struct rt2860_softc *sc)
 	}
 
 	return 0;
-#undef N
+}
+
+static void
+rt5390_bbp_init(struct rt2860_softc *sc)
+{
+	uint8_t bbp;
+	int i;
+
+	/* Apply maximum likelihood detection for 2 stream case. */
+	if (sc->nrxchains > 1) {
+		bbp = rt2860_mcu_bbp_read(sc, 105);
+		rt2860_mcu_bbp_write(sc, 105, bbp | RT5390_MLD);
+	}
+
+	/* Avoid data lost and CRC error. */
+	bbp = rt2860_mcu_bbp_read(sc, 4);
+	rt2860_mcu_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL);
+
+	for (i = 0; i < nitems(rt5390_def_bbp); i++) {
+		rt2860_mcu_bbp_write(sc, rt5390_def_bbp[i].reg,
+		    rt5390_def_bbp[i].val);
+	}
+
+	if (sc->mac_ver == 0x5392) {
+		rt2860_mcu_bbp_write(sc, 84, 0x9a);
+		rt2860_mcu_bbp_write(sc, 95, 0x9a);
+		rt2860_mcu_bbp_write(sc, 98, 0x12);
+		rt2860_mcu_bbp_write(sc, 106, 0x05);
+		rt2860_mcu_bbp_write(sc, 134, 0xd0);
+		rt2860_mcu_bbp_write(sc, 135, 0xf6);
+	}
+
+	bbp = rt2860_mcu_bbp_read(sc, 152);
+	rt2860_mcu_bbp_write(sc, 152, bbp | 0x80);
+
+	/* Disable hardware antenna diversity. */
+	if (sc->mac_ver == 0x5390)
+		rt2860_mcu_bbp_write(sc, 154, 0);
 }
 
 static int
@@ -3566,7 +3837,6 @@ rt2860_init(void *arg)
 static void
 rt2860_init_locked(struct rt2860_softc *sc)
 {
-#define N(a)	(sizeof (a) / sizeof ((a)[0]))
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
 	uint32_t tmp;
@@ -3639,9 +3909,11 @@ rt2860_init_locked(struct rt2860_softc *sc)
 	RAL_BARRIER_WRITE(sc);
 	RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, 0);
 
-	for (i = 0; i < N(rt2860_def_mac); i++)
+	for (i = 0; i < nitems(rt2860_def_mac); i++)
 		RAL_WRITE(sc, rt2860_def_mac[i].reg, rt2860_def_mac[i].val);
-	if (sc->mac_ver >= 0x3071) {
+	if (sc->mac_ver >= 0x5390)
+		RAL_WRITE(sc, RT2860_TX_SW_CFG0, 0x00000404);
+	else if (sc->mac_ver >= 0x3071) {
 		/* set delay of PA_PE assertion to 1us (unit of 0.25us) */
 		RAL_WRITE(sc, RT2860_TX_SW_CFG0,
 		    4 << RT2860_DLY_PAPE_EN_SHIFT);
@@ -3736,7 +4008,8 @@ rt2860_init_locked(struct rt2860_softc *sc)
 	/* select Main antenna for 1T1R devices */
 	if (sc->rf_rev == RT3070_RF_2020 ||
 	    sc->rf_rev == RT3070_RF_3020 ||
-	    sc->rf_rev == RT3070_RF_3320)
+	    sc->rf_rev == RT3070_RF_3320 ||
+	    sc->mac_ver == 0x5390)
 		rt3090_set_rx_antenna(sc, 0);
 
 	/* send LEDs operating mode to microcontroller */
@@ -3744,13 +4017,21 @@ rt2860_init_locked(struct rt2860_softc *sc)
 	rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED2, sc->led[1], 0);
 	rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED3, sc->led[2], 0);
 
-	if (sc->mac_ver >= 0x3071)
-		rt3090_rf_init(sc);
+	if (sc->mac_ver >= 0x5390)
+		rt5390_rf_init(sc);
+	else if (sc->mac_ver >= 0x3071) {
+		if ((error = rt3090_rf_init(sc)) != 0) {
+			rt2860_stop_locked(sc);
+			return;
+		}
+	}
 
 	rt2860_mcu_cmd(sc, RT2860_MCU_CMD_SLEEP, 0x02ff, 1);
 	rt2860_mcu_cmd(sc, RT2860_MCU_CMD_WAKEUP, 0, 1);
 
-	if (sc->mac_ver >= 0x3071)
+	if (sc->mac_ver >= 0x5390)
+		rt5390_rf_wakeup(sc);
+	else if (sc->mac_ver >= 0x3071)
 		rt3090_rf_wakeup(sc);
 
 	/* disable non-existing Rx chains */
@@ -3811,7 +4092,6 @@ rt2860_init_locked(struct rt2860_softc *sc)
 	ifp->if_flags |= IFF_RUNNING;
 
 	callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc);
-#undef N
 }
 
 static void
@@ -3961,15 +4241,25 @@ rt3090_set_rx_antenna(struct rt2860_softc *sc, int aux)
 	uint32_t tmp;
 
 	if (aux) {
-		tmp = RAL_READ(sc, RT2860_PCI_EECTRL);
-		RAL_WRITE(sc, RT2860_PCI_EECTRL, tmp & ~RT2860_C);
-		tmp = RAL_READ(sc, RT2860_GPIO_CTRL);
-		RAL_WRITE(sc, RT2860_GPIO_CTRL, (tmp & ~0x0808) | 0x08);
+		if (sc->mac_ver == 0x5390) {
+			rt2860_mcu_bbp_write(sc, 152, 
+			    rt2860_mcu_bbp_read(sc, 152) & ~0x80);
+		} else {
+			tmp = RAL_READ(sc, RT2860_PCI_EECTRL);
+			RAL_WRITE(sc, RT2860_PCI_EECTRL, tmp & ~RT2860_C);
+			tmp = RAL_READ(sc, RT2860_GPIO_CTRL);
+			RAL_WRITE(sc, RT2860_GPIO_CTRL, (tmp & ~0x0808) | 0x08);
+		}
 	} else {
-		tmp = RAL_READ(sc, RT2860_PCI_EECTRL);
-		RAL_WRITE(sc, RT2860_PCI_EECTRL, tmp | RT2860_C);
-		tmp = RAL_READ(sc, RT2860_GPIO_CTRL);
-		RAL_WRITE(sc, RT2860_GPIO_CTRL, tmp & ~0x0808);
+		if (sc->mac_ver == 0x5390) {
+			rt2860_mcu_bbp_write(sc, 152, 
+			    rt2860_mcu_bbp_read(sc, 152) | 0x80);
+		} else {
+			tmp = RAL_READ(sc, RT2860_PCI_EECTRL);
+			RAL_WRITE(sc, RT2860_PCI_EECTRL, tmp | RT2860_C);
+			tmp = RAL_READ(sc, RT2860_GPIO_CTRL);
+			RAL_WRITE(sc, RT2860_GPIO_CTRL, tmp & ~0x0808);
+		}
 	}
 }
 
@@ -3984,7 +4274,9 @@ rt2860_switch_chan(struct rt2860_softc *sc, struct ieee80211_channel *c)
 	if (chan == 0 || chan == IEEE80211_CHAN_ANY)
 		return;
 
-	if (sc->mac_ver >= 0x3071)
+	if (sc->mac_ver >= 0x5390)
+		rt5390_set_chan(sc, chan);
+	else if (sc->mac_ver >= 0x3071)
 		rt3090_set_chan(sc, chan);
 	else
 		rt2860_set_chan(sc, chan);
@@ -4000,7 +4292,8 @@ rt2860_switch_chan(struct rt2860_softc *sc, struct ieee80211_channel *c)
 		group = 3;
 
 	/* XXX necessary only when group has changed! */
-	rt2860_select_chan_group(sc, group);
+	if (sc->mac_ver < 0x5390)
+		rt2860_select_chan_group(sc, group);
 
 	DELAY(1000);
 }
diff --git a/sys/dev/netif/ral/rt2860reg.h b/sys/dev/netif/ral/rt2860reg.h
index c0c9ceb..6f07c7f 100644
--- a/sys/dev/netif/ral/rt2860reg.h
+++ b/sys/dev/netif/ral/rt2860reg.h
@@ -15,7 +15,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
  * $OpenBSD: rt2860reg.h,v 1.30 2010/05/10 18:17:10 damien Exp $
- * $FreeBSD: src/sys/dev/ral/rt2860reg.h,v 1.2 2012/11/17 01:52:11 svnexp Exp $
+ * $FreeBSD: head/sys/dev/ral/rt2860reg.h 278551 2015-02-11 05:25:23Z kevlo $
  */
 
 #define RT2860_NOISE_FLOOR		-95
@@ -258,7 +258,7 @@
 #define RT2860_TX_DMA_EN		(1 << 0)
 
 /* possible flags for register DELAY_INT_CFG */
-#define RT2860_TXDLY_INT_EN		(1 << 31)
+#define RT2860_TXDLY_INT_EN		(1U << 31)
 #define RT2860_TXMAX_PINT_SHIFT		24
 #define RT2860_TXMAX_PTIME_SHIFT	16
 #define RT2860_RXDLY_INT_EN		(1 << 15)
@@ -270,7 +270,7 @@
 #define RT2860_GPIO_O_SHIFT	0
 
 /* possible flags for register USB_DMA_CFG */
-#define RT2860_USB_TX_BUSY		(1 << 31)
+#define RT2860_USB_TX_BUSY		(1U << 31)
 #define RT2860_USB_RX_BUSY		(1 << 30)
 #define RT2860_USB_EPOUT_VLD_SHIFT	24
 #define RT2860_USB_TX_EN		(1 << 23)
@@ -370,7 +370,7 @@
 #define RT2860_TX0Q_PCNT_MASK	0x000000ff
 
 /* possible flags for register CAP_CTRL */
-#define RT2860_CAP_ADC_FEQ		(1 << 31)
+#define RT2860_CAP_ADC_FEQ		(1U << 31)
 #define RT2860_CAP_START		(1 << 30)
 #define RT2860_MAN_TRIG			(1 << 29)
 #define RT2860_TRIG_OFFSET_SHIFT	16
@@ -381,7 +381,7 @@
 #define RT3070_RF_WRITE		(1 << 16)
 
 /* possible flags for register EFUSE_CTRL */
-#define RT3070_SEL_EFUSE	(1 << 31)
+#define RT3070_SEL_EFUSE	(1U << 31)
 #define RT3070_EFSROM_KICK	(1 << 30)
 #define RT3070_EFSROM_AIN_MASK	0x03ff0000
 #define RT3070_EFSROM_AIN_SHIFT	16
@@ -420,7 +420,7 @@
 #define RT2860_BBP_DATA_SHIFT		0
 
 /* possible flags for register RF_CSR_CFG0 */
-#define RT2860_RF_REG_CTRL		(1 << 31)
+#define RT2860_RF_REG_CTRL		(1U << 31)
 #define RT2860_RF_LE_SEL1		(1 << 30)
 #define RT2860_RF_LE_STBY		(1 << 29)
 #define RT2860_RF_REG_WIDTH_SHIFT	24
@@ -455,7 +455,7 @@
 #define RT2860_SLOT_TIME		0
 
 /* possible flags for register NAV_TIME_CFG */
-#define RT2860_NAV_UPD			(1 << 31)
+#define RT2860_NAV_UPD			(1U << 31)
 #define RT2860_NAV_UPD_VAL_SHIFT	16
 #define RT2860_NAV_CLR_EN		(1 << 15)
 #define RT2860_NAV_TIMER_SHIFT		0
@@ -509,7 +509,7 @@
 #define RT2860_WAKEUP_LEAD_TIME_SHIFT	0
 
 /* possible flags for register TX_PIN_CFG */
-#define RT3593_LNA_PE_G2_POL	(1 << 31)
+#define RT3593_LNA_PE_G2_POL	(1U << 31)
 #define RT3593_LNA_PE_A2_POL	(1 << 30)
 #define RT3593_LNA_PE_G2_EN	(1 << 29)
 #define RT3593_LNA_PE_A2_EN	(1 << 28)
@@ -699,6 +699,7 @@
 
 /* possible flags for RT3020 RF register 1 */
 #define RT3070_RF_BLOCK	(1 << 0)
+#define RT3070_PLL_PD	(1 << 1)
 #define RT3070_RX0_PD	(1 << 2)
 #define RT3070_TX0_PD	(1 << 3)
 #define RT3070_RX1_PD	(1 << 4)
@@ -750,6 +751,22 @@
 
 #define RT3090_DEF_LNA	10
 
+/* possible flags for RT5390 RF register 38 */
+#define RT5390_RX_LO1	(1 << 5)
+
+/* possible flags for RT5390 RF register 39 */
+#define RT5390_RX_LO2	(1 << 7)
+
+/* possible flags for RT5390 RF register 42 */
+#define RT5390_RX_CTB	(1 << 6)
+
+/* possible flags for RT5390 BBP register 4 */
+#define RT5390_MAC_IF_CTRL	(1 << 6)
+
+/* possible flags for RT5390 BBP register 105 */
+#define RT5390_MLD		(1 << 2)
+#define	RT5390_SIG_MODULATION	(1 << 3)
+
 /* RT2860 TX descriptor */
 struct rt2860_txd {
 	uint32_t	sdp0;		/* Segment Data Pointer 0 */
@@ -894,6 +911,7 @@ struct rt2860_rxwi {
 #define RT3070_RF_3052	9	/* dual-band 2T2R */
 #define RT3070_RF_3320	11	/* 1T1R */
 #define RT3070_RF_3053	13	/* dual-band 3T3R */
+#define RT5390_RF_5390	15	/* b/g/n */
 
 /* USB commands for RT2870 only */
 #define RT2870_RESET		1
@@ -1006,14 +1024,17 @@ static const struct rt2860_rate {
  */
 #define RT2860_DEF_MAC					\
 	{ RT2860_BCN_OFFSET0,		0xf8f0e8e0 },	\
+	{ RT2860_BCN_OFFSET1,		0x6f77d0c8 },	\
 	{ RT2860_LEGACY_BASIC_RATE,	0x0000013f },	\
 	{ RT2860_HT_BASIC_RATE,		0x00008003 },	\
 	{ RT2860_MAC_SYS_CTRL,		0x00000000 },	\
+	{ RT2860_RX_FILTR_CFG,		0x00017f97 },	\
 	{ RT2860_BKOFF_SLOT_CFG,	0x00000209 },	\
 	{ RT2860_TX_SW_CFG0,		0x00000000 },	\
 	{ RT2860_TX_SW_CFG1,		0x00080606 },	\
 	{ RT2860_TX_LINK_CFG,		0x00001020 },	\
 	{ RT2860_TX_TIMEOUT_CFG,	0x000a2090 },	\
+	{ RT2860_MAX_LEN_CFG,		0x00001f00 },	\
 	{ RT2860_LED_CFG,		0x7f031e46 },	\
 	{ RT2860_WMM_AIFSN_CFG,		0x00002273 },	\
 	{ RT2860_WMM_CWMIN_CFG,		0x00002344 },	\
@@ -1028,42 +1049,9 @@ static const struct rt2860_rate {
 	{ RT2860_MM20_PROT_CFG,		0x01744004 },	\
 	{ RT2860_MM40_PROT_CFG,		0x03f54084 },	\
 	{ RT2860_TXOP_CTRL_CFG,		0x0000583f },	\
-	{ RT2860_TXOP_HLDR_ET,		0x00000002 },	\
 	{ RT2860_TX_RTS_CFG,		0x00092b20 },	\
 	{ RT2860_EXP_ACK_TIME,		0x002400ca },	\
-	{ RT2860_XIFS_TIME_CFG,		0x33a41010 },	\
-	{ RT2860_PWR_PIN_CFG,		0x00000003 }
-
-/* XXX only a few registers differ from above, try to merge? */
-#define RT2870_DEF_MAC					\
-	{ RT2860_BCN_OFFSET0,		0xf8f0e8e0 },	\
-	{ RT2860_LEGACY_BASIC_RATE,	0x0000013f },	\
-	{ RT2860_HT_BASIC_RATE,		0x00008003 },	\
-	{ RT2860_MAC_SYS_CTRL,		0x00000000 },	\
-	{ RT2860_BKOFF_SLOT_CFG,	0x00000209 },	\
-	{ RT2860_TX_SW_CFG0,		0x00000000 },	\
-	{ RT2860_TX_SW_CFG1,		0x00080606 },	\
-	{ RT2860_TX_LINK_CFG,		0x00001020 },	\
-	{ RT2860_TX_TIMEOUT_CFG,	0x000a2090 },	\
-	{ RT2860_LED_CFG,		0x7f031e46 },	\
-	{ RT2860_WMM_AIFSN_CFG,		0x00002273 },	\
-	{ RT2860_WMM_CWMIN_CFG,		0x00002344 },	\
-	{ RT2860_WMM_CWMAX_CFG,		0x000034aa },	\
-	{ RT2860_MAX_PCNT,		0x1f3fbf9f },	\
-	{ RT2860_TX_RTY_CFG,		0x47d01f0f },	\
-	{ RT2860_AUTO_RSP_CFG,		0x00000013 },	\
-	{ RT2860_CCK_PROT_CFG,		0x05740003 },	\
-	{ RT2860_OFDM_PROT_CFG,		0x05740003 },	\
-	{ RT2860_PBF_CFG,		0x00f40006 },	\
-	{ RT2860_WPDMA_GLO_CFG,		0x00000030 },	\
-	{ RT2860_GF20_PROT_CFG,		0x01744004 },	\
-	{ RT2860_GF40_PROT_CFG,		0x03f44084 },	\
-	{ RT2860_MM20_PROT_CFG,		0x01744004 },	\
-	{ RT2860_MM40_PROT_CFG,		0x03f44084 },	\
-	{ RT2860_TXOP_CTRL_CFG,		0x0000583f },	\
 	{ RT2860_TXOP_HLDR_ET,		0x00000002 },	\
-	{ RT2860_TX_RTS_CFG,		0x00092b20 },	\
-	{ RT2860_EXP_ACK_TIME,		0x002400ca },	\
 	{ RT2860_XIFS_TIME_CFG,		0x33a41010 },	\
 	{ RT2860_PWR_PIN_CFG,		0x00000003 }
 
@@ -1073,6 +1061,7 @@ static const struct rt2860_rate {
 #define RT2860_DEF_BBP	\
 	{  65, 0x2c },	\
 	{  66, 0x38 },	\
+	{  68, 0x0b },	\
 	{  69, 0x12 },	\
 	{  70, 0x0a },	\
 	{  73, 0x10 },	\
@@ -1087,6 +1076,30 @@ static const struct rt2860_rate {
 	{ 105, 0x05 },	\
 	{ 106, 0x35 }
 
+#define RT5390_DEF_BBP	\
+	{  31, 0x08 },	\
+	{  65, 0x2c },	\
+	{  66, 0x38 },	\
+	{  68, 0x0b },	\
+	{  69, 0x12 },	\
+	{  70, 0x0a },	\
+	{  73, 0x13 },	\
+	{  75, 0x46 },	\
+	{  76, 0x28 },	\
+	{  77, 0x59 },	\
+	{  81, 0x37 },	\
+	{  82, 0x62 },	\
+	{  83, 0x7a },	\
+	{  84, 0x19 },	\
+	{  86, 0x38 },	\
+	{  91, 0x04 },	\
+	{  92, 0x02 },	\
+	{ 103, 0xc0 },	\
+	{ 104, 0x92 },	\
+	{ 105, 0x3c },	\
+	{ 106, 0x03 },	\
+	{ 128, 0x12 },	\
+
 /*
  * Default settings for RF registers; values derived from the reference driver.
  */
@@ -1204,7 +1217,7 @@ static const struct rt2860_rate {
 	{  4, 0x40 },	\
 	{  5, 0x03 },	\
 	{  6, 0x02 },	\
-	{  7, 0x70 },	\
+	{  7, 0x60 },	\
 	{  9, 0x0f },	\
 	{ 10, 0x41 },	\
 	{ 11, 0x21 },	\
@@ -1221,35 +1234,122 @@ static const struct rt2860_rate {
 	{ 25, 0x01 },	\
 	{ 29, 0x1f }
 
-#define RT3572_DEF_RF	\
-	{  0, 0x70 },	\
-	{  1, 0x81 },	\
-	{  2, 0xf1 },	\
-	{  3, 0x02 },	\
-	{  4, 0x4c },	\
-	{  5, 0x05 },	\
-	{  6, 0x4a },	\
-	{  7, 0xd8 },	\
-	{  9, 0xc3 },	\
-	{ 10, 0xf1 },	\
-	{ 11, 0xb9 },	\
-	{ 12, 0x70 },	\
-	{ 13, 0x65 },	\
-	{ 14, 0xa0 },	\
-	{ 15, 0x53 },	\
-	{ 16, 0x4c },	\
-	{ 17, 0x23 },	\
-	{ 18, 0xac },	\
-	{ 19, 0x93 },	\
-	{ 20, 0xb3 },	\
-	{ 21, 0xd0 },	\
-	{ 22, 0x00 },  	\
-	{ 23, 0x3c },	\
-	{ 24, 0x16 },	\
-	{ 25, 0x15 },	\
-	{ 26, 0x85 },	\
-	{ 27, 0x00 },	\
+#define RT5390_DEF_RF	\
+	{  1, 0x0f },	\
+	{  2, 0x80 },	\
+	{  3, 0x88 },	\
+	{  5, 0x10 },	\
+	{  6, 0xe0 },	\
+	{  7, 0x00 },	\
+	{ 10, 0x53 },	\
+	{ 11, 0x4a },	\
+	{ 12, 0x46 },	\
+	{ 13, 0x9f },	\
+	{ 14, 0x00 },	\
+	{ 15, 0x00 },	\
+	{ 16, 0x00 },	\
+	{ 18, 0x03 },	\
+	{ 19, 0x00 },	\
+	{ 20, 0x00 },	\
+	{ 21, 0x00 },	\
+	{ 22, 0x20 },	\
+	{ 23, 0x00 },	\
+	{ 24, 0x00 },	\
+	{ 25, 0x80 },	\
+	{ 26, 0x00 },	\
+	{ 27, 0x09 },	\
+	{ 28, 0x00 },	\
+	{ 29, 0x10 },	\
+	{ 30, 0x10 },	\
+	{ 31, 0x80 },	\
+	{ 32, 0x80 },	\
+	{ 33, 0x00 },	\
+	{ 34, 0x07 },	\
+	{ 35, 0x12 },	\
+	{ 36, 0x00 },	\
+	{ 37, 0x08 },	\
+	{ 38, 0x85 },	\
+	{ 39, 0x1b },	\
+	{ 40, 0x0b },	\
+	{ 41, 0xbb },	\
+	{ 42, 0xd2 },	\
+	{ 43, 0x9a },	\
+	{ 44, 0x0e },	\
+	{ 45, 0xa2 },	\
+	{ 46, 0x73 },	\
+	{ 47, 0x00 },	\
+	{ 48, 0x10 },	\
+	{ 49, 0x94 },	\
+	{ 52, 0x38 },	\
+	{ 53, 0x00 },	\
+	{ 54, 0x78 },	\
+	{ 55, 0x23 },	\
+	{ 56, 0x22 },	\
+	{ 57, 0x80 },	\
+	{ 58, 0x7f },	\
+	{ 59, 0x07 },	\
+	{ 60, 0x45 },	\
+	{ 61, 0xd1 },	\
+	{ 62, 0x00 },	\
+	{ 63, 0x00 }
+
+#define RT5392_DEF_RF	\
+	{  1, 0x17 },	\
+	{  2, 0x80 },	\
+	{  3, 0x88 },	\
+	{  5, 0x10 },	\
+	{  6, 0xe0 },	\
+	{  7, 0x00 },	\
+	{ 10, 0x53 },	\
+	{ 11, 0x4a },	\
+	{ 12, 0x46 },	\
+	{ 13, 0x9f },	\
+	{ 14, 0x00 },	\
+	{ 15, 0x00 },	\
+	{ 16, 0x00 },	\
+	{ 18, 0x03 },	\
+	{ 19, 0x4d },	\
+	{ 20, 0x00 },	\
+	{ 21, 0x8d },	\
+	{ 22, 0x20 },	\
+	{ 23, 0x0b },	\
+	{ 24, 0x44 },	\
+	{ 25, 0x80 },	\
+	{ 26, 0x82 },	\
+	{ 27, 0x09 },	\
 	{ 28, 0x00 },	\
-	{ 29, 0x9b },	\
-	{ 30, 0x09 },	\
-	{ 31, 0x10 }
+	{ 29, 0x10 },	\
+	{ 30, 0x10 },	\
+	{ 31, 0x80 },	\
+	{ 32, 0x80 },	\
+	{ 33, 0xc0 },	\
+	{ 34, 0x07 },	\
+	{ 35, 0x12 },	\
+	{ 36, 0x00 },	\
+	{ 37, 0x08 },	\
+	{ 38, 0x89 },	\
+	{ 39, 0x1b },	\
+	{ 40, 0x0f },	\
+	{ 41, 0xbb },	\
+	{ 42, 0xd5 },	\
+	{ 43, 0x9b },	\
+	{ 44, 0x0e },	\
+	{ 45, 0xa2 },	\
+	{ 46, 0x73 },	\
+	{ 47, 0x0c },	\
+	{ 48, 0x10 },	\
+	{ 49, 0x94 },	\
+	{ 50, 0x94 },	\
+	{ 51, 0x3a },	\
+	{ 52, 0x48 },	\
+	{ 53, 0x44 },	\
+	{ 54, 0x38 },	\
+	{ 55, 0x43 },	\
+	{ 56, 0xa1 },	\
+	{ 57, 0x00 },	\
+	{ 58, 0x39 },	\
+	{ 59, 0x07 },	\
+	{ 60, 0x45 },	\
+	{ 61, 0x91 },	\
+	{ 62, 0x39 },	\
+	{ 63, 0x00 }
diff --git a/sys/dev/netif/ral/rt2860var.h b/sys/dev/netif/ral/rt2860var.h
index 5e993c4..8e26b8b 100644
--- a/sys/dev/netif/ral/rt2860var.h
+++ b/sys/dev/netif/ral/rt2860var.h
@@ -15,7 +15,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
  * $OpenBSD: rt2860var.h,v 1.20 2010/09/07 16:21:42 deraadt Exp $
- * $FreeBSD: src/sys/dev/ral/rt2860var.h,v 1.2 2012/11/17 01:52:11 svnexp Exp $
+ * $FreeBSD: head/sys/dev/ral/rt2860var.h 286437 2015-08-08 01:10:17Z adrian $
  */
 
 #define RT2860_TX_RING_COUNT	64
-- 
2.4.5

