12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564 |
-
- #include <mii.h>
- #include <stdio.h>
- #include <errno.h>
- #include <unistd.h>
- #include <byteswap.h>
- #include <ipxe/pci.h>
-
- #include "tg3.h"
-
- static void tg3_link_report(struct tg3 *tp);
-
- void tg3_mdio_init(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- if (tg3_flag(tp, 5717_PLUS)) {
- u32 is_serdes;
-
- tp->phy_addr = PCI_FUNC(tp->pdev->busdevfn) + 1;
-
- if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0)
- is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES;
- else
- is_serdes = tr32(TG3_CPMU_PHY_STRAP) &
- TG3_CPMU_PHY_STRAP_IS_SERDES;
- if (is_serdes)
- tp->phy_addr += 7;
- } else
- tp->phy_addr = TG3_PHY_MII_ADDR;
- }
-
- static int tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
- { DBGP("%s\n", __func__);
-
- int i;
- u32 val;
-
- tw32(OTP_CTRL, cmd | OTP_CTRL_OTP_CMD_START);
- tw32(OTP_CTRL, cmd);
-
- /* Wait for up to 1 ms for command to execute. */
- for (i = 0; i < 100; i++) {
- val = tr32(OTP_STATUS);
- if (val & OTP_STATUS_CMD_DONE)
- break;
- udelay(10);
- }
-
- return (val & OTP_STATUS_CMD_DONE) ? 0 : -EBUSY;
- }
-
- /* Read the gphy configuration from the OTP region of the chip. The gphy
- * configuration is a 32-bit value that straddles the alignment boundary.
- * We do two 32-bit reads and then shift and merge the results.
- */
- u32 tg3_read_otp_phycfg(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- u32 bhalf_otp, thalf_otp;
-
- tw32(OTP_MODE, OTP_MODE_OTP_THRU_GRC);
-
- if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_INIT))
- return 0;
-
- tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC1);
-
- if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
- return 0;
-
- thalf_otp = tr32(OTP_READ_DATA);
-
- tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC2);
-
- if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
- return 0;
-
- bhalf_otp = tr32(OTP_READ_DATA);
-
- return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16);
- }
-
- #define PHY_BUSY_LOOPS 5000
-
- int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
- { DBGP("%s\n", __func__);
-
- u32 frame_val;
- unsigned int loops;
- int ret;
-
- if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
- tw32_f(MAC_MI_MODE,
- (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
- udelay(80);
- }
-
- *val = 0x0;
-
- frame_val = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
- MI_COM_PHY_ADDR_MASK);
- frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
- MI_COM_REG_ADDR_MASK);
- frame_val |= (MI_COM_CMD_READ | MI_COM_START);
-
- tw32_f(MAC_MI_COM, frame_val);
-
- loops = PHY_BUSY_LOOPS;
- while (loops != 0) {
- udelay(10);
- frame_val = tr32(MAC_MI_COM);
-
- if ((frame_val & MI_COM_BUSY) == 0) {
- udelay(5);
- frame_val = tr32(MAC_MI_COM);
- break;
- }
- loops -= 1;
- }
-
- ret = -EBUSY;
- if (loops != 0) {
- *val = frame_val & MI_COM_DATA_MASK;
- ret = 0;
- }
-
- if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
- tw32_f(MAC_MI_MODE, tp->mi_mode);
- udelay(80);
- }
-
- return ret;
- }
-
- struct subsys_tbl_ent {
- u16 subsys_vendor, subsys_devid;
- u32 phy_id;
- };
-
- static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
- /* Broadcom boards. */
- { TG3PCI_SUBVENDOR_ID_BROADCOM,
- TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6, TG3_PHY_ID_BCM5401 },
- { TG3PCI_SUBVENDOR_ID_BROADCOM,
- TG3PCI_SUBDEVICE_ID_BROADCOM_95701A5, TG3_PHY_ID_BCM5701 },
- { TG3PCI_SUBVENDOR_ID_BROADCOM,
- TG3PCI_SUBDEVICE_ID_BROADCOM_95700T6, TG3_PHY_ID_BCM8002 },
- { TG3PCI_SUBVENDOR_ID_BROADCOM,
- TG3PCI_SUBDEVICE_ID_BROADCOM_95700A9, 0 },
- { TG3PCI_SUBVENDOR_ID_BROADCOM,
- TG3PCI_SUBDEVICE_ID_BROADCOM_95701T1, TG3_PHY_ID_BCM5701 },
- { TG3PCI_SUBVENDOR_ID_BROADCOM,
- TG3PCI_SUBDEVICE_ID_BROADCOM_95701T8, TG3_PHY_ID_BCM5701 },
- { TG3PCI_SUBVENDOR_ID_BROADCOM,
- TG3PCI_SUBDEVICE_ID_BROADCOM_95701A7, 0 },
- { TG3PCI_SUBVENDOR_ID_BROADCOM,
- TG3PCI_SUBDEVICE_ID_BROADCOM_95701A10, TG3_PHY_ID_BCM5701 },
- { TG3PCI_SUBVENDOR_ID_BROADCOM,
- TG3PCI_SUBDEVICE_ID_BROADCOM_95701A12, TG3_PHY_ID_BCM5701 },
- { TG3PCI_SUBVENDOR_ID_BROADCOM,
- TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX1, TG3_PHY_ID_BCM5703 },
- { TG3PCI_SUBVENDOR_ID_BROADCOM,
- TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX2, TG3_PHY_ID_BCM5703 },
-
- /* 3com boards. */
- { TG3PCI_SUBVENDOR_ID_3COM,
- TG3PCI_SUBDEVICE_ID_3COM_3C996T, TG3_PHY_ID_BCM5401 },
- { TG3PCI_SUBVENDOR_ID_3COM,
- TG3PCI_SUBDEVICE_ID_3COM_3C996BT, TG3_PHY_ID_BCM5701 },
- { TG3PCI_SUBVENDOR_ID_3COM,
- TG3PCI_SUBDEVICE_ID_3COM_3C996SX, 0 },
- { TG3PCI_SUBVENDOR_ID_3COM,
- TG3PCI_SUBDEVICE_ID_3COM_3C1000T, TG3_PHY_ID_BCM5701 },
- { TG3PCI_SUBVENDOR_ID_3COM,
- TG3PCI_SUBDEVICE_ID_3COM_3C940BR01, TG3_PHY_ID_BCM5701 },
-
- /* DELL boards. */
- { TG3PCI_SUBVENDOR_ID_DELL,
- TG3PCI_SUBDEVICE_ID_DELL_VIPER, TG3_PHY_ID_BCM5401 },
- { TG3PCI_SUBVENDOR_ID_DELL,
- TG3PCI_SUBDEVICE_ID_DELL_JAGUAR, TG3_PHY_ID_BCM5401 },
- { TG3PCI_SUBVENDOR_ID_DELL,
- TG3PCI_SUBDEVICE_ID_DELL_MERLOT, TG3_PHY_ID_BCM5411 },
- { TG3PCI_SUBVENDOR_ID_DELL,
- TG3PCI_SUBDEVICE_ID_DELL_SLIM_MERLOT, TG3_PHY_ID_BCM5411 },
-
- /* Compaq boards. */
- { TG3PCI_SUBVENDOR_ID_COMPAQ,
- TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE, TG3_PHY_ID_BCM5701 },
- { TG3PCI_SUBVENDOR_ID_COMPAQ,
- TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE_2, TG3_PHY_ID_BCM5701 },
- { TG3PCI_SUBVENDOR_ID_COMPAQ,
- TG3PCI_SUBDEVICE_ID_COMPAQ_CHANGELING, 0 },
- { TG3PCI_SUBVENDOR_ID_COMPAQ,
- TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780, TG3_PHY_ID_BCM5701 },
- { TG3PCI_SUBVENDOR_ID_COMPAQ,
- TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2, TG3_PHY_ID_BCM5701 },
-
- /* IBM boards. */
- { TG3PCI_SUBVENDOR_ID_IBM,
- TG3PCI_SUBDEVICE_ID_IBM_5703SAX2, 0 }
- };
-
- static struct subsys_tbl_ent *tg3_lookup_by_subsys(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- int i;
-
- DBGC(tp->dev, "Matching with: %x:%x\n", tp->subsystem_vendor, tp->subsystem_device);
-
- for (i = 0; i < (int) ARRAY_SIZE(subsys_id_to_phy_id); i++) {
- if ((subsys_id_to_phy_id[i].subsys_vendor ==
- tp->subsystem_vendor) &&
- (subsys_id_to_phy_id[i].subsys_devid ==
- tp->subsystem_device))
- return &subsys_id_to_phy_id[i];
- }
- return NULL;
- }
-
- int tg3_writephy(struct tg3 *tp, int reg, u32 val)
- { DBGP("%s\n", __func__);
-
- u32 frame_val;
- unsigned int loops;
- int ret;
-
- if ((tp->phy_flags & TG3_PHYFLG_IS_FET) &&
- (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL))
- return 0;
-
- if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
- tw32_f(MAC_MI_MODE,
- (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
- udelay(80);
- }
-
- frame_val = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
- MI_COM_PHY_ADDR_MASK);
- frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
- MI_COM_REG_ADDR_MASK);
- frame_val |= (val & MI_COM_DATA_MASK);
- frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);
-
- tw32_f(MAC_MI_COM, frame_val);
-
- loops = PHY_BUSY_LOOPS;
- while (loops != 0) {
- udelay(10);
- frame_val = tr32(MAC_MI_COM);
- if ((frame_val & MI_COM_BUSY) == 0) {
- udelay(5);
- frame_val = tr32(MAC_MI_COM);
- break;
- }
- loops -= 1;
- }
-
- ret = -EBUSY;
- if (loops != 0)
- ret = 0;
-
- if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
- tw32_f(MAC_MI_MODE, tp->mi_mode);
- udelay(80);
- }
-
- return ret;
- }
-
- static int tg3_bmcr_reset(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- u32 phy_control;
- int limit, err;
-
- /* OK, reset it, and poll the BMCR_RESET bit until it
- * clears or we time out.
- */
- phy_control = BMCR_RESET;
- err = tg3_writephy(tp, MII_BMCR, phy_control);
- if (err != 0)
- return -EBUSY;
-
- limit = 5000;
- while (limit--) {
- err = tg3_readphy(tp, MII_BMCR, &phy_control);
- if (err != 0)
- return -EBUSY;
-
- if ((phy_control & BMCR_RESET) == 0) {
- udelay(40);
- break;
- }
- udelay(10);
- }
- if (limit < 0)
- return -EBUSY;
-
- return 0;
- }
-
- static int tg3_wait_macro_done(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- int limit = 100;
-
- while (limit--) {
- u32 tmp32;
-
- if (!tg3_readphy(tp, MII_TG3_DSP_CONTROL, &tmp32)) {
- if ((tmp32 & 0x1000) == 0)
- break;
- }
- }
- if (limit < 0)
- return -EBUSY;
-
- return 0;
- }
-
- static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp)
- { DBGP("%s\n", __func__);
-
- static const u32 test_pat[4][6] = {
- { 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 },
- { 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 },
- { 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 },
- { 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 }
- };
- int chan;
-
- for (chan = 0; chan < 4; chan++) {
- int i;
-
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
- (chan * 0x2000) | 0x0200);
- tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002);
-
- for (i = 0; i < 6; i++)
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT,
- test_pat[chan][i]);
-
- tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202);
- if (tg3_wait_macro_done(tp)) {
- *resetp = 1;
- return -EBUSY;
- }
-
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
- (chan * 0x2000) | 0x0200);
- tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0082);
- if (tg3_wait_macro_done(tp)) {
- *resetp = 1;
- return -EBUSY;
- }
-
- tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0802);
- if (tg3_wait_macro_done(tp)) {
- *resetp = 1;
- return -EBUSY;
- }
-
- for (i = 0; i < 6; i += 2) {
- u32 low, high;
-
- if (tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low) ||
- tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high) ||
- tg3_wait_macro_done(tp)) {
- *resetp = 1;
- return -EBUSY;
- }
- low &= 0x7fff;
- high &= 0x000f;
- if (low != test_pat[chan][i] ||
- high != test_pat[chan][i+1]) {
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b);
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001);
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005);
-
- return -EBUSY;
- }
- }
- }
-
- return 0;
- }
-
- static int tg3_phy_reset_chanpat(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- int chan;
-
- for (chan = 0; chan < 4; chan++) {
- int i;
-
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
- (chan * 0x2000) | 0x0200);
- tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002);
- for (i = 0; i < 6; i++)
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000);
- tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202);
- if (tg3_wait_macro_done(tp))
- return -EBUSY;
- }
-
- return 0;
- }
-
- static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val)
- { DBGP("%s\n", __func__);
-
- int err;
-
- err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
- if (!err)
- err = tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val);
-
- return err;
- }
-
- static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set)
- { DBGP("%s\n", __func__);
-
- if (reg == MII_TG3_AUXCTL_SHDWSEL_MISC)
- set |= MII_TG3_AUXCTL_MISC_WREN;
-
- return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg);
- }
-
- #define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \
- tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
- MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \
- MII_TG3_AUXCTL_ACTL_TX_6DB)
-
- #define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \
- tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
- MII_TG3_AUXCTL_ACTL_TX_6DB);
-
- static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- u32 reg32, phy9_orig;
- int retries, do_phy_reset, err;
-
- retries = 10;
- do_phy_reset = 1;
- do {
- if (do_phy_reset) {
- err = tg3_bmcr_reset(tp);
- if (err)
- return err;
- do_phy_reset = 0;
- }
-
- /* Disable transmitter and interrupt. */
- if (tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32))
- continue;
-
- reg32 |= 0x3000;
- tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
-
- /* Set full-duplex, 1000 mbps. */
- tg3_writephy(tp, MII_BMCR,
- BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
-
- /* Set to master mode. */
- if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig))
- continue;
-
- tg3_writephy(tp, MII_TG3_CTRL,
- (MII_TG3_CTRL_AS_MASTER |
- MII_TG3_CTRL_ENABLE_AS_MASTER));
-
- err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
- if (err)
- return err;
-
- /* Block the PHY control access. */
- tg3_phydsp_write(tp, 0x8005, 0x0800);
-
- err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset);
- if (!err)
- break;
- } while (--retries);
-
- err = tg3_phy_reset_chanpat(tp);
- if (err)
- return err;
-
- tg3_phydsp_write(tp, 0x8005, 0x0000);
-
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
- tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000);
-
- TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
-
- tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
-
- if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32)) {
- reg32 &= ~0x3000;
- tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
- } else if (!err)
- err = -EBUSY;
-
- return err;
- }
-
- static void tg3_phy_apply_otp(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- u32 otp, phy;
-
- if (!tp->phy_otp)
- return;
-
- otp = tp->phy_otp;
-
- if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp))
- return;
-
- phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT);
- phy |= MII_TG3_DSP_TAP1_AGCTGT_DFLT;
- tg3_phydsp_write(tp, MII_TG3_DSP_TAP1, phy);
-
- phy = ((otp & TG3_OTP_HPFFLTR_MASK) >> TG3_OTP_HPFFLTR_SHIFT) |
- ((otp & TG3_OTP_HPFOVER_MASK) >> TG3_OTP_HPFOVER_SHIFT);
- tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH0, phy);
-
- phy = ((otp & TG3_OTP_LPFDIS_MASK) >> TG3_OTP_LPFDIS_SHIFT);
- phy |= MII_TG3_DSP_AADJ1CH3_ADCCKADJ;
- tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH3, phy);
-
- phy = ((otp & TG3_OTP_VDAC_MASK) >> TG3_OTP_VDAC_SHIFT);
- tg3_phydsp_write(tp, MII_TG3_DSP_EXP75, phy);
-
- phy = ((otp & TG3_OTP_10BTAMP_MASK) >> TG3_OTP_10BTAMP_SHIFT);
- tg3_phydsp_write(tp, MII_TG3_DSP_EXP96, phy);
-
- phy = ((otp & TG3_OTP_ROFF_MASK) >> TG3_OTP_ROFF_SHIFT) |
- ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT);
- tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy);
-
- TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
- }
-
- static int tg3_phy_auxctl_read(struct tg3 *tp, int reg, u32 *val)
- { DBGP("%s\n", __func__);
-
- int err;
-
- err = tg3_writephy(tp, MII_TG3_AUX_CTRL,
- (reg << MII_TG3_AUXCTL_MISC_RDSEL_SHIFT) |
- MII_TG3_AUXCTL_SHDWSEL_MISC);
- if (!err)
- err = tg3_readphy(tp, MII_TG3_AUX_CTRL, val);
-
- return err;
- }
-
- static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
- { DBGP("%s\n", __func__);
-
- u32 phy;
-
- if (!tg3_flag(tp, 5705_PLUS) ||
- (tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
- return;
-
- if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
- u32 ephy;
-
- if (!tg3_readphy(tp, MII_TG3_FET_TEST, &ephy)) {
- u32 reg = MII_TG3_FET_SHDW_MISCCTRL;
-
- tg3_writephy(tp, MII_TG3_FET_TEST,
- ephy | MII_TG3_FET_SHADOW_EN);
- if (!tg3_readphy(tp, reg, &phy)) {
- if (enable)
- phy |= MII_TG3_FET_SHDW_MISCCTRL_MDIX;
- else
- phy &= ~MII_TG3_FET_SHDW_MISCCTRL_MDIX;
- tg3_writephy(tp, reg, phy);
- }
- tg3_writephy(tp, MII_TG3_FET_TEST, ephy);
- }
- } else {
- int ret;
-
- ret = tg3_phy_auxctl_read(tp,
- MII_TG3_AUXCTL_SHDWSEL_MISC, &phy);
- if (!ret) {
- if (enable)
- phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
- else
- phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
- tg3_phy_auxctl_write(tp,
- MII_TG3_AUXCTL_SHDWSEL_MISC, phy);
- }
- }
- }
-
- static void tg3_phy_set_wirespeed(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- int ret;
- u32 val;
-
- if (tp->phy_flags & TG3_PHYFLG_NO_ETH_WIRE_SPEED)
- return;
-
- ret = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_MISC, &val);
- if (!ret)
- tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_MISC,
- val | MII_TG3_AUXCTL_MISC_WIRESPD_EN);
- }
-
- /* This will reset the tigon3 PHY if there is no valid
- * link unless the FORCE argument is non-zero.
- */
- int tg3_phy_reset(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- u32 val, cpmuctrl;
- int err;
-
- DBGCP(&tp->pdev->dev, "%s\n", __func__);
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
- val = tr32(GRC_MISC_CFG);
- tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ);
- udelay(40);
- }
- err = tg3_readphy(tp, MII_BMSR, &val);
- err |= tg3_readphy(tp, MII_BMSR, &val);
- if (err != 0)
- return -EBUSY;
-
- netdev_link_down(tp->dev);
- tg3_link_report(tp);
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
- err = tg3_phy_reset_5703_4_5(tp);
- if (err)
- return err;
- goto out;
- }
-
- cpmuctrl = 0;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
- GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) {
- cpmuctrl = tr32(TG3_CPMU_CTRL);
- if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY)
- tw32(TG3_CPMU_CTRL,
- cpmuctrl & ~CPMU_CTRL_GPHY_10MB_RXONLY);
- }
-
- err = tg3_bmcr_reset(tp);
- if (err)
- return err;
-
- if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) {
- val = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz;
- tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, val);
-
- tw32(TG3_CPMU_CTRL, cpmuctrl);
- }
-
- if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
- GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
- val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
- if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
- CPMU_LSPD_1000MB_MACCLK_12_5) {
- val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
- udelay(40);
- tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
- }
- }
-
- if (tg3_flag(tp, 5717_PLUS) &&
- (tp->phy_flags & TG3_PHYFLG_MII_SERDES))
- return 0;
-
- tg3_phy_apply_otp(tp);
-
- out:
- if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) &&
- !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
- tg3_phydsp_write(tp, 0x201f, 0x2aaa);
- tg3_phydsp_write(tp, 0x000a, 0x0323);
- TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
- }
-
- if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) {
- tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
- tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
- }
-
- if (tp->phy_flags & TG3_PHYFLG_BER_BUG) {
- if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
- tg3_phydsp_write(tp, 0x000a, 0x310b);
- tg3_phydsp_write(tp, 0x201f, 0x9506);
- tg3_phydsp_write(tp, 0x401f, 0x14e2);
- TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
- }
- } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) {
- if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
- if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) {
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b);
- tg3_writephy(tp, MII_TG3_TEST1,
- MII_TG3_TEST1_TRIM_EN | 0x4);
- } else
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
-
- TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
- }
- }
-
- if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
- /* Cannot do read-modify-write on 5401 */
- tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);
- }
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
- /* adjust output voltage */
- tg3_writephy(tp, MII_TG3_FET_PTEST, 0x12);
- }
-
- tg3_phy_toggle_automdix(tp, 1);
- tg3_phy_set_wirespeed(tp);
- return 0;
- }
-
- static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask)
- { DBGP("%s\n", __func__);
-
- u32 adv_reg, all_mask = 0;
-
- if (mask & ADVERTISED_10baseT_Half)
- all_mask |= ADVERTISE_10HALF;
- if (mask & ADVERTISED_10baseT_Full)
- all_mask |= ADVERTISE_10FULL;
- if (mask & ADVERTISED_100baseT_Half)
- all_mask |= ADVERTISE_100HALF;
- if (mask & ADVERTISED_100baseT_Full)
- all_mask |= ADVERTISE_100FULL;
-
- if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg))
- return 0;
-
- if ((adv_reg & all_mask) != all_mask)
- return 0;
- if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
- u32 tg3_ctrl;
-
- all_mask = 0;
- if (mask & ADVERTISED_1000baseT_Half)
- all_mask |= ADVERTISE_1000HALF;
- if (mask & ADVERTISED_1000baseT_Full)
- all_mask |= ADVERTISE_1000FULL;
-
- if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl))
- return 0;
-
- if ((tg3_ctrl & all_mask) != all_mask)
- return 0;
- }
- return 1;
- }
-
- static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl)
- { DBGP("%s\n", __func__);
-
- u16 miireg;
-
- if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
- miireg = ADVERTISE_PAUSE_CAP;
- else if (flow_ctrl & FLOW_CTRL_TX)
- miireg = ADVERTISE_PAUSE_ASYM;
- else if (flow_ctrl & FLOW_CTRL_RX)
- miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
- else
- miireg = 0;
-
- return miireg;
- }
-
- static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
- { DBGP("%s\n", __func__);
-
- int err = 0;
- u32 val __unused, new_adv;
-
- new_adv = ADVERTISE_CSMA;
- if (advertise & ADVERTISED_10baseT_Half)
- new_adv |= ADVERTISE_10HALF;
- if (advertise & ADVERTISED_10baseT_Full)
- new_adv |= ADVERTISE_10FULL;
- if (advertise & ADVERTISED_100baseT_Half)
- new_adv |= ADVERTISE_100HALF;
- if (advertise & ADVERTISED_100baseT_Full)
- new_adv |= ADVERTISE_100FULL;
-
- new_adv |= tg3_advert_flowctrl_1000T(flowctrl);
-
- err = tg3_writephy(tp, MII_ADVERTISE, new_adv);
- if (err)
- goto done;
-
- if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
- goto done;
-
- new_adv = 0;
- if (advertise & ADVERTISED_1000baseT_Half)
- new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
- if (advertise & ADVERTISED_1000baseT_Full)
- new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
-
- if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
- new_adv |= (MII_TG3_CTRL_AS_MASTER |
- MII_TG3_CTRL_ENABLE_AS_MASTER);
-
- err = tg3_writephy(tp, MII_TG3_CTRL, new_adv);
- if (err)
- goto done;
-
- if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
- goto done;
-
- done:
- return err;
- }
-
- static int tg3_init_5401phy_dsp(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- int err;
-
- /* Turn off tap power management. */
- /* Set Extended packet length bit */
- err = tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);
-
- err |= tg3_phydsp_write(tp, 0x0012, 0x1804);
- err |= tg3_phydsp_write(tp, 0x0013, 0x1204);
- err |= tg3_phydsp_write(tp, 0x8006, 0x0132);
- err |= tg3_phydsp_write(tp, 0x8006, 0x0232);
- err |= tg3_phydsp_write(tp, 0x201f, 0x0a20);
-
- udelay(40);
-
- return err;
- }
-
- #define ADVERTISED_Autoneg (1 << 6)
- #define ADVERTISED_Pause (1 << 13)
- #define ADVERTISED_TP (1 << 7)
- #define ADVERTISED_FIBRE (1 << 10)
-
- #define AUTONEG_ENABLE 0x01
-
- static void tg3_phy_init_link_config(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- u32 adv = ADVERTISED_Autoneg |
- ADVERTISED_Pause;
-
-
- if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY))
- adv |= ADVERTISED_1000baseT_Half |
- ADVERTISED_1000baseT_Full;
- if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
- adv |= ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full |
- ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full |
- ADVERTISED_TP;
- else
- adv |= ADVERTISED_FIBRE;
-
- tp->link_config.advertising = adv;
- tp->link_config.speed = SPEED_INVALID;
- tp->link_config.duplex = DUPLEX_INVALID;
- tp->link_config.autoneg = AUTONEG_ENABLE;
- tp->link_config.active_speed = SPEED_INVALID;
- tp->link_config.active_duplex = DUPLEX_INVALID;
- tp->link_config.orig_speed = SPEED_INVALID;
- tp->link_config.orig_duplex = DUPLEX_INVALID;
- tp->link_config.orig_autoneg = AUTONEG_INVALID;
- }
-
- int tg3_phy_probe(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- u32 hw_phy_id_1, hw_phy_id_2;
- u32 hw_phy_id, hw_phy_id_masked;
- int err;
-
- /* flow control autonegotiation is default behavior */
- tg3_flag_set(tp, PAUSE_AUTONEG);
- tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
-
- /* Reading the PHY ID register can conflict with ASF
- * firmware access to the PHY hardware.
- */
- err = 0;
- if (tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE)) {
- hw_phy_id = hw_phy_id_masked = TG3_PHY_ID_INVALID;
- } else {
- /* Now read the physical PHY_ID from the chip and verify
- * that it is sane. If it doesn't look good, we fall back
- * to either the hard-coded table based PHY_ID and failing
- * that the value found in the eeprom area.
- */
- err |= tg3_readphy(tp, MII_PHYSID1, &hw_phy_id_1);
- err |= tg3_readphy(tp, MII_PHYSID2, &hw_phy_id_2);
-
- hw_phy_id = (hw_phy_id_1 & 0xffff) << 10;
- hw_phy_id |= (hw_phy_id_2 & 0xfc00) << 16;
- hw_phy_id |= (hw_phy_id_2 & 0x03ff) << 0;
-
- hw_phy_id_masked = hw_phy_id & TG3_PHY_ID_MASK;
- }
-
- if (!err && TG3_KNOWN_PHY_ID(hw_phy_id_masked)) {
- tp->phy_id = hw_phy_id;
- if (hw_phy_id_masked == TG3_PHY_ID_BCM8002)
- tp->phy_flags |= TG3_PHYFLG_PHY_SERDES;
- else
- tp->phy_flags &= ~TG3_PHYFLG_PHY_SERDES;
- } else {
- if (tp->phy_id != TG3_PHY_ID_INVALID) {
- /* Do nothing, phy ID already set up in
- * tg3_get_eeprom_hw_cfg().
- */
- } else {
- struct subsys_tbl_ent *p;
-
- /* No eeprom signature? Try the hardcoded
- * subsys device table.
- */
- p = tg3_lookup_by_subsys(tp);
- if (!p) {
- DBGC(&tp->pdev->dev, "lookup by subsys failed\n");
- return -ENODEV;
- }
-
- tp->phy_id = p->phy_id;
- if (!tp->phy_id ||
- tp->phy_id == TG3_PHY_ID_BCM8002)
- tp->phy_flags |= TG3_PHYFLG_PHY_SERDES;
- }
- }
-
- if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
- ((tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 &&
- tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
- tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)))
- tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
-
- tg3_phy_init_link_config(tp);
-
- if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
- !tg3_flag(tp, ENABLE_APE) &&
- !tg3_flag(tp, ENABLE_ASF)) {
- u32 bmsr;
- u32 mask;
-
- tg3_readphy(tp, MII_BMSR, &bmsr);
- if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
- (bmsr & BMSR_LSTATUS))
- goto skip_phy_reset;
-
- err = tg3_phy_reset(tp);
- if (err)
- return err;
-
- tg3_phy_set_wirespeed(tp);
-
- mask = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
- ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full);
- if (!tg3_copper_is_advertising_all(tp, mask)) {
- tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
- tp->link_config.flowctrl);
-
- tg3_writephy(tp, MII_BMCR,
- BMCR_ANENABLE | BMCR_ANRESTART);
- }
- }
-
- skip_phy_reset:
- if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
- err = tg3_init_5401phy_dsp(tp);
- if (err)
- return err;
-
- err = tg3_init_5401phy_dsp(tp);
- }
-
- return err;
- }
-
- void tg3_poll_link(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- if (tp->hw_status->status & SD_STATUS_LINK_CHG) {
- DBGC(tp->dev,"link_changed\n");
- tp->hw_status->status &= ~SD_STATUS_LINK_CHG;
- tg3_setup_phy(tp, 0);
- }
- }
-
- static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
- { DBGP("%s\n", __func__);
-
- switch (val & MII_TG3_AUX_STAT_SPDMASK) {
- case MII_TG3_AUX_STAT_10HALF:
- *speed = SPEED_10;
- *duplex = DUPLEX_HALF;
- break;
-
- case MII_TG3_AUX_STAT_10FULL:
- *speed = SPEED_10;
- *duplex = DUPLEX_FULL;
- break;
-
- case MII_TG3_AUX_STAT_100HALF:
- *speed = SPEED_100;
- *duplex = DUPLEX_HALF;
- break;
-
- case MII_TG3_AUX_STAT_100FULL:
- *speed = SPEED_100;
- *duplex = DUPLEX_FULL;
- break;
-
- case MII_TG3_AUX_STAT_1000HALF:
- *speed = SPEED_1000;
- *duplex = DUPLEX_HALF;
- break;
-
- case MII_TG3_AUX_STAT_1000FULL:
- *speed = SPEED_1000;
- *duplex = DUPLEX_FULL;
- break;
-
- default:
- if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
- *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 :
- SPEED_10;
- *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL :
- DUPLEX_HALF;
- break;
- }
- *speed = SPEED_INVALID;
- *duplex = DUPLEX_INVALID;
- break;
- }
- }
-
- static int tg3_adv_1000T_flowctrl_ok(struct tg3 *tp, u32 *lcladv, u32 *rmtadv)
- { DBGP("%s\n", __func__);
-
- u32 curadv, reqadv;
-
- if (tg3_readphy(tp, MII_ADVERTISE, lcladv))
- return 1;
-
- curadv = *lcladv & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
- reqadv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
-
- if (tp->link_config.active_duplex == DUPLEX_FULL) {
- if (curadv != reqadv)
- return 0;
-
- if (tg3_flag(tp, PAUSE_AUTONEG))
- tg3_readphy(tp, MII_LPA, rmtadv);
- } else {
- /* Reprogram the advertisement register, even if it
- * does not affect the current link. If the link
- * gets renegotiated in the future, we can save an
- * additional renegotiation cycle by advertising
- * it correctly in the first place.
- */
- if (curadv != reqadv) {
- *lcladv &= ~(ADVERTISE_PAUSE_CAP |
- ADVERTISE_PAUSE_ASYM);
- tg3_writephy(tp, MII_ADVERTISE, *lcladv | reqadv);
- }
- }
-
- return 1;
- }
-
- static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv)
- { DBGP("%s\n", __func__);
-
- u8 cap = 0;
-
- if (lcladv & ADVERTISE_1000XPAUSE) {
- if (lcladv & ADVERTISE_1000XPSE_ASYM) {
- if (rmtadv & LPA_1000XPAUSE)
- cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
- else if (rmtadv & LPA_1000XPAUSE_ASYM)
- cap = FLOW_CTRL_RX;
- } else {
- if (rmtadv & LPA_1000XPAUSE)
- cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
- }
- } else if (lcladv & ADVERTISE_1000XPSE_ASYM) {
- if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM))
- cap = FLOW_CTRL_TX;
- }
-
- return cap;
- }
-
- static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv)
- { DBGP("%s\n", __func__);
-
- u8 flowctrl = 0;
- u32 old_rx_mode = tp->rx_mode;
- u32 old_tx_mode = tp->tx_mode;
-
- if (tg3_flag(tp, PAUSE_AUTONEG)) {
- if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES)
- flowctrl = tg3_resolve_flowctrl_1000X(lcladv, rmtadv);
- else
- flowctrl = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
- } else
- flowctrl = tp->link_config.flowctrl;
-
- tp->link_config.active_flowctrl = flowctrl;
-
- if (flowctrl & FLOW_CTRL_RX)
- tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
- else
- tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
-
- if (old_rx_mode != tp->rx_mode)
- tw32_f(MAC_RX_MODE, tp->rx_mode);
-
- if (flowctrl & FLOW_CTRL_TX)
- tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
- else
- tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
-
- if (old_tx_mode != tp->tx_mode)
- tw32_f(MAC_TX_MODE, tp->tx_mode);
- }
-
- static void tg3_phy_copper_begin(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- u32 new_adv;
-
- if (tp->link_config.speed == SPEED_INVALID) {
- if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
- tp->link_config.advertising &=
- ~(ADVERTISED_1000baseT_Half |
- ADVERTISED_1000baseT_Full);
-
- tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
- tp->link_config.flowctrl);
- } else {
- /* Asking for a specific link mode. */
- if (tp->link_config.speed == SPEED_1000) {
- if (tp->link_config.duplex == DUPLEX_FULL)
- new_adv = ADVERTISED_1000baseT_Full;
- else
- new_adv = ADVERTISED_1000baseT_Half;
- } else if (tp->link_config.speed == SPEED_100) {
- if (tp->link_config.duplex == DUPLEX_FULL)
- new_adv = ADVERTISED_100baseT_Full;
- else
- new_adv = ADVERTISED_100baseT_Half;
- } else {
- if (tp->link_config.duplex == DUPLEX_FULL)
- new_adv = ADVERTISED_10baseT_Full;
- else
- new_adv = ADVERTISED_10baseT_Half;
- }
-
- tg3_phy_autoneg_cfg(tp, new_adv,
- tp->link_config.flowctrl);
- }
-
- tg3_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
- }
-
- static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
- { DBGP("%s\n", __func__);
-
- if (tp->led_ctrl == LED_CTRL_MODE_PHY_2)
- return 1;
- else if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411) {
- if (speed != SPEED_10)
- return 1;
- } else if (speed == SPEED_10)
- return 1;
-
- return 0;
- }
-
- #if 1
-
- static void tg3_ump_link_report(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- u32 reg;
- u32 val;
-
- if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF))
- return;
-
- tg3_wait_for_event_ack(tp);
-
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE);
-
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14);
-
- val = 0;
- if (!tg3_readphy(tp, MII_BMCR, ®))
- val = reg << 16;
- if (!tg3_readphy(tp, MII_BMSR, ®))
- val |= (reg & 0xffff);
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val);
-
- val = 0;
- if (!tg3_readphy(tp, MII_ADVERTISE, ®))
- val = reg << 16;
- if (!tg3_readphy(tp, MII_LPA, ®))
- val |= (reg & 0xffff);
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val);
-
- val = 0;
- if (!(tp->phy_flags & TG3_PHYFLG_MII_SERDES)) {
- if (!tg3_readphy(tp, MII_CTRL1000, ®))
- val = reg << 16;
- if (!tg3_readphy(tp, MII_STAT1000, ®))
- val |= (reg & 0xffff);
- }
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val);
-
- if (!tg3_readphy(tp, MII_PHYADDR, ®))
- val = reg << 16;
- else
- val = 0;
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);
-
- tg3_generate_fw_event(tp);
- }
-
- /* NOTE: Debugging only code */
- static void tg3_link_report(struct tg3 *tp)
- { DBGP("%s\n", __func__);
-
- if (!netdev_link_ok(tp->dev)) {
- DBGC(tp->dev, "Link is down\n");
- tg3_ump_link_report(tp);
- } else {
- DBGC(tp->dev, "Link is up at %d Mbps, %s duplex\n",
- (tp->link_config.active_speed == SPEED_1000 ?
- 1000 :
- (tp->link_config.active_speed == SPEED_100 ?
- 100 : 10)),
- (tp->link_config.active_duplex == DUPLEX_FULL ?
- "full" : "half"));
-
- DBGC(tp->dev, "Flow control is %s for TX and %s for RX\n",
- (tp->link_config.active_flowctrl & FLOW_CTRL_TX) ?
- "on" : "off",
- (tp->link_config.active_flowctrl & FLOW_CTRL_RX) ?
- "on" : "off");
-
- if (tp->phy_flags & TG3_PHYFLG_EEE_CAP)
- DBGC(tp->dev, "EEE is %s\n",
- tp->setlpicnt ? "enabled" : "disabled");
-
- tg3_ump_link_report(tp);
- }
- }
- #endif
-
- struct tg3_fiber_aneginfo {
- int state;
- #define ANEG_STATE_UNKNOWN 0
- #define ANEG_STATE_AN_ENABLE 1
- #define ANEG_STATE_RESTART_INIT 2
- #define ANEG_STATE_RESTART 3
- #define ANEG_STATE_DISABLE_LINK_OK 4
- #define ANEG_STATE_ABILITY_DETECT_INIT 5
- #define ANEG_STATE_ABILITY_DETECT 6
- #define ANEG_STATE_ACK_DETECT_INIT 7
- #define ANEG_STATE_ACK_DETECT 8
- #define ANEG_STATE_COMPLETE_ACK_INIT 9
- #define ANEG_STATE_COMPLETE_ACK 10
- #define ANEG_STATE_IDLE_DETECT_INIT 11
- #define ANEG_STATE_IDLE_DETECT 12
- #define ANEG_STATE_LINK_OK 13
- #define ANEG_STATE_NEXT_PAGE_WAIT_INIT 14
- #define ANEG_STATE_NEXT_PAGE_WAIT 15
-
- u32 flags;
- #define MR_AN_ENABLE 0x00000001
- #define MR_RESTART_AN 0x00000002
- #define MR_AN_COMPLETE 0x00000004
- #define MR_PAGE_RX 0x00000008
- #define MR_NP_LOADED 0x00000010
- #define MR_TOGGLE_TX 0x00000020
- #define MR_LP_ADV_FULL_DUPLEX 0x00000040
- #define MR_LP_ADV_HALF_DUPLEX 0x00000080
- #define MR_LP_ADV_SYM_PAUSE 0x00000100
- #define MR_LP_ADV_ASYM_PAUSE 0x00000200
- #define MR_LP_ADV_REMOTE_FAULT1 0x00000400
- #define MR_LP_ADV_REMOTE_FAULT2 0x00000800
- #define MR_LP_ADV_NEXT_PAGE 0x00001000
- #define MR_TOGGLE_RX 0x00002000
- #define MR_NP_RX 0x00004000
-
- #define MR_LINK_OK 0x80000000
-
- unsigned long link_time, cur_time;
-
- u32 ability_match_cfg;
- int ability_match_count;
-
- char ability_match, idle_match, ack_match;
-
- u32 txconfig, rxconfig;
- #define ANEG_CFG_NP 0x00000080
- #define ANEG_CFG_ACK 0x00000040
- #define ANEG_CFG_RF2 0x00000020
- #define ANEG_CFG_RF1 0x00000010
- #define ANEG_CFG_PS2 0x00000001
- #define ANEG_CFG_PS1 0x00008000
- #define ANEG_CFG_HD 0x00004000
- #define ANEG_CFG_FD 0x00002000
- #define ANEG_CFG_INVAL 0x00001f06
-
- };
- #define ANEG_OK 0
- #define ANEG_DONE 1
- #define ANEG_TIMER_ENAB 2
- #define ANEG_FAILED -1
-
- #define ANEG_STATE_SETTLE_TIME 10000
-
- static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
- {
- u16 miireg;
-
- if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
- miireg = ADVERTISE_1000XPAUSE;
- else if (flow_ctrl & FLOW_CTRL_TX)
- miireg = ADVERTISE_1000XPSE_ASYM;
- else if (flow_ctrl & FLOW_CTRL_RX)
- miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
- else
- miireg = 0;
-
- return miireg;
- }
-
- static void tg3_init_bcm8002(struct tg3 *tp)
- {
- u32 mac_status = tr32(MAC_STATUS);
- int i;
-
- /* Reset when initting first time or we have a link. */
- if (tg3_flag(tp, INIT_COMPLETE) &&
- !(mac_status & MAC_STATUS_PCS_SYNCED))
- return;
-
- /* Set PLL lock range. */
- tg3_writephy(tp, 0x16, 0x8007);
-
- /* SW reset */
- tg3_writephy(tp, MII_BMCR, BMCR_RESET);
-
- /* Wait for reset to complete. */
- /* XXX schedule_timeout() ... */
- for (i = 0; i < 500; i++)
- udelay(10);
-
- /* Config mode; select PMA/Ch 1 regs. */
- tg3_writephy(tp, 0x10, 0x8411);
-
- /* Enable auto-lock and comdet, select txclk for tx. */
- tg3_writephy(tp, 0x11, 0x0a10);
-
- tg3_writephy(tp, 0x18, 0x00a0);
- tg3_writephy(tp, 0x16, 0x41ff);
-
- /* Assert and deassert POR. */
- tg3_writephy(tp, 0x13, 0x0400);
- udelay(40);
- tg3_writephy(tp, 0x13, 0x0000);
-
- tg3_writephy(tp, 0x11, 0x0a50);
- udelay(40);
- tg3_writephy(tp, 0x11, 0x0a10);
-
- /* Wait for signal to stabilize */
- /* XXX schedule_timeout() ... */
- for (i = 0; i < 15000; i++)
- udelay(10);
-
- /* Deselect the channel register so we can read the PHYID
- * later.
- */
- tg3_writephy(tp, 0x10, 0x8011);
- }
-
- static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
- {
- u16 flowctrl;
- int current_link_up;
- u32 sg_dig_ctrl, sg_dig_status;
- u32 serdes_cfg, expected_sg_dig_ctrl;
- int workaround, port_a;
-
- serdes_cfg = 0;
- expected_sg_dig_ctrl = 0;
- workaround = 0;
- port_a = 1;
- current_link_up = 0;
-
- if (tp->pci_chip_rev_id != CHIPREV_ID_5704_A0 &&
- tp->pci_chip_rev_id != CHIPREV_ID_5704_A1) {
- workaround = 1;
- if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
- port_a = 0;
-
- /* preserve bits 0-11,13,14 for signal pre-emphasis */
- /* preserve bits 20-23 for voltage regulator */
- serdes_cfg = tr32(MAC_SERDES_CFG) & 0x00f06fff;
- }
-
- sg_dig_ctrl = tr32(SG_DIG_CTRL);
-
- if (tp->link_config.autoneg != AUTONEG_ENABLE) {
- if (sg_dig_ctrl & SG_DIG_USING_HW_AUTONEG) {
- if (workaround) {
- u32 val = serdes_cfg;
-
- if (port_a)
- val |= 0xc010000;
- else
- val |= 0x4010000;
- tw32_f(MAC_SERDES_CFG, val);
- }
-
- tw32_f(SG_DIG_CTRL, SG_DIG_COMMON_SETUP);
- }
- if (mac_status & MAC_STATUS_PCS_SYNCED) {
- tg3_setup_flow_control(tp, 0, 0);
- current_link_up = 1;
- }
- goto out;
- }
-
- /* Want auto-negotiation. */
- expected_sg_dig_ctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_COMMON_SETUP;
-
- flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
- if (flowctrl & ADVERTISE_1000XPAUSE)
- expected_sg_dig_ctrl |= SG_DIG_PAUSE_CAP;
- if (flowctrl & ADVERTISE_1000XPSE_ASYM)
- expected_sg_dig_ctrl |= SG_DIG_ASYM_PAUSE;
-
- if (sg_dig_ctrl != expected_sg_dig_ctrl) {
- if ((tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT) &&
- tp->serdes_counter &&
- ((mac_status & (MAC_STATUS_PCS_SYNCED |
- MAC_STATUS_RCVD_CFG)) ==
- MAC_STATUS_PCS_SYNCED)) {
- tp->serdes_counter--;
- current_link_up = 1;
- goto out;
- }
- restart_autoneg:
- if (workaround)
- tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011000);
- tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | SG_DIG_SOFT_RESET);
- udelay(5);
- tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl);
-
- tp->serdes_counter = SERDES_AN_TIMEOUT_5704S;
- tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
- } else if (mac_status & (MAC_STATUS_PCS_SYNCED |
- MAC_STATUS_SIGNAL_DET)) {
- sg_dig_status = tr32(SG_DIG_STATUS);
- mac_status = tr32(MAC_STATUS);
-
- if ((sg_dig_status & SG_DIG_AUTONEG_COMPLETE) &&
- (mac_status & MAC_STATUS_PCS_SYNCED)) {
- u32 local_adv = 0, remote_adv = 0;
-
- if (sg_dig_ctrl & SG_DIG_PAUSE_CAP)
- local_adv |= ADVERTISE_1000XPAUSE;
- if (sg_dig_ctrl & SG_DIG_ASYM_PAUSE)
- local_adv |= ADVERTISE_1000XPSE_ASYM;
-
- if (sg_dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
- remote_adv |= LPA_1000XPAUSE;
- if (sg_dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
- remote_adv |= LPA_1000XPAUSE_ASYM;
-
- tp->link_config.rmt_adv =
- mii_adv_to_ethtool_adv_x(remote_adv);
-
- tg3_setup_flow_control(tp, local_adv, remote_adv);
- current_link_up = 1;
- tp->serdes_counter = 0;
- tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
- } else if (!(sg_dig_status & SG_DIG_AUTONEG_COMPLETE)) {
- if (tp->serdes_counter)
- tp->serdes_counter--;
- else {
- if (workaround) {
- u32 val = serdes_cfg;
-
- if (port_a)
- val |= 0xc010000;
- else
- val |= 0x4010000;
-
- tw32_f(MAC_SERDES_CFG, val);
- }
-
- tw32_f(SG_DIG_CTRL, SG_DIG_COMMON_SETUP);
- udelay(40);
-
- /* Link parallel detection - link is up */
- /* only if we have PCS_SYNC and not */
- /* receiving config code words */
- mac_status = tr32(MAC_STATUS);
- if ((mac_status & MAC_STATUS_PCS_SYNCED) &&
- !(mac_status & MAC_STATUS_RCVD_CFG)) {
- tg3_setup_flow_control(tp, 0, 0);
- current_link_up = 1;
- tp->phy_flags |=
- TG3_PHYFLG_PARALLEL_DETECT;
- tp->serdes_counter =
- SERDES_PARALLEL_DET_TIMEOUT;
- } else
- goto restart_autoneg;
- }
- }
- } else {
- tp->serdes_counter = SERDES_AN_TIMEOUT_5704S;
- tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
- }
-
- out:
- return current_link_up;
- }
-
- static int tg3_fiber_aneg_smachine(struct tg3 *tp,
- struct tg3_fiber_aneginfo *ap)
- {
- u16 flowctrl;
- unsigned long delta;
- u32 rx_cfg_reg;
- int ret;
-
- if (ap->state == ANEG_STATE_UNKNOWN) {
- ap->rxconfig = 0;
- ap->link_time = 0;
- ap->cur_time = 0;
- ap->ability_match_cfg = 0;
- ap->ability_match_count = 0;
- ap->ability_match = 0;
- ap->idle_match = 0;
- ap->ack_match = 0;
- }
- ap->cur_time++;
-
- if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) {
- rx_cfg_reg = tr32(MAC_RX_AUTO_NEG);
-
- if (rx_cfg_reg != ap->ability_match_cfg) {
- ap->ability_match_cfg = rx_cfg_reg;
- ap->ability_match = 0;
- ap->ability_match_count = 0;
- } else {
- if (++ap->ability_match_count > 1) {
- ap->ability_match = 1;
- ap->ability_match_cfg = rx_cfg_reg;
- }
- }
- if (rx_cfg_reg & ANEG_CFG_ACK)
- ap->ack_match = 1;
- else
- ap->ack_match = 0;
-
- ap->idle_match = 0;
- } else {
- ap->idle_match = 1;
- ap->ability_match_cfg = 0;
- ap->ability_match_count = 0;
- ap->ability_match = 0;
- ap->ack_match = 0;
-
- rx_cfg_reg = 0;
- }
-
- ap->rxconfig = rx_cfg_reg;
- ret = ANEG_OK;
-
- switch (ap->state) {
- case ANEG_STATE_UNKNOWN:
- if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN))
- ap->state = ANEG_STATE_AN_ENABLE;
-
- /* fallthru */
- case ANEG_STATE_AN_ENABLE:
- ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX);
- if (ap->flags & MR_AN_ENABLE) {
- ap->link_time = 0;
- ap->cur_time = 0;
- ap->ability_match_cfg = 0;
- ap->ability_match_count = 0;
- ap->ability_match = 0;
- ap->idle_match = 0;
- ap->ack_match = 0;
-
- ap->state = ANEG_STATE_RESTART_INIT;
- } else {
- ap->state = ANEG_STATE_DISABLE_LINK_OK;
- }
- break;
-
- case ANEG_STATE_RESTART_INIT:
- ap->link_time = ap->cur_time;
- ap->flags &= ~(MR_NP_LOADED);
- ap->txconfig = 0;
- tw32(MAC_TX_AUTO_NEG, 0);
- tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
- tw32_f(MAC_MODE, tp->mac_mode);
- udelay(40);
-
- ret = ANEG_TIMER_ENAB;
- ap->state = ANEG_STATE_RESTART;
-
- /* fallthru */
- case ANEG_STATE_RESTART:
- delta = ap->cur_time - ap->link_time;
- if (delta > ANEG_STATE_SETTLE_TIME)
- ap->state = ANEG_STATE_ABILITY_DETECT_INIT;
- else
- ret = ANEG_TIMER_ENAB;
- break;
-
- case ANEG_STATE_DISABLE_LINK_OK:
- ret = ANEG_DONE;
- break;
-
- case ANEG_STATE_ABILITY_DETECT_INIT:
- ap->flags &= ~(MR_TOGGLE_TX);
- ap->txconfig = ANEG_CFG_FD;
- flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
- if (flowctrl & ADVERTISE_1000XPAUSE)
- ap->txconfig |= ANEG_CFG_PS1;
- if (flowctrl & ADVERTISE_1000XPSE_ASYM)
- ap->txconfig |= ANEG_CFG_PS2;
- tw32(MAC_TX_AUTO_NEG, ap->txconfig);
- tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
- tw32_f(MAC_MODE, tp->mac_mode);
- udelay(40);
-
- ap->state = ANEG_STATE_ABILITY_DETECT;
- break;
-
- case ANEG_STATE_ABILITY_DETECT:
- if (ap->ability_match != 0 && ap->rxconfig != 0)
- ap->state = ANEG_STATE_ACK_DETECT_INIT;
- break;
-
- case ANEG_STATE_ACK_DETECT_INIT:
- ap->txconfig |= ANEG_CFG_ACK;
- tw32(MAC_TX_AUTO_NEG, ap->txconfig);
- tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
- tw32_f(MAC_MODE, tp->mac_mode);
- udelay(40);
-
- ap->state = ANEG_STATE_ACK_DETECT;
-
- /* fallthru */
- case ANEG_STATE_ACK_DETECT:
- if (ap->ack_match != 0) {
- if ((ap->rxconfig & ~ANEG_CFG_ACK) ==
- (ap->ability_match_cfg & ~ANEG_CFG_ACK)) {
- ap->state = ANEG_STATE_COMPLETE_ACK_INIT;
- } else {
- ap->state = ANEG_STATE_AN_ENABLE;
- }
- } else if (ap->ability_match != 0 &&
- ap->rxconfig == 0) {
- ap->state = ANEG_STATE_AN_ENABLE;
- }
- break;
-
- case ANEG_STATE_COMPLETE_ACK_INIT:
- if (ap->rxconfig & ANEG_CFG_INVAL) {
- ret = ANEG_FAILED;
- break;
- }
- ap->flags &= ~(MR_LP_ADV_FULL_DUPLEX |
- MR_LP_ADV_HALF_DUPLEX |
- MR_LP_ADV_SYM_PAUSE |
- MR_LP_ADV_ASYM_PAUSE |
- MR_LP_ADV_REMOTE_FAULT1 |
- MR_LP_ADV_REMOTE_FAULT2 |
- MR_LP_ADV_NEXT_PAGE |
- MR_TOGGLE_RX |
- MR_NP_RX);
- if (ap->rxconfig & ANEG_CFG_FD)
- ap->flags |= MR_LP_ADV_FULL_DUPLEX;
- if (ap->rxconfig & ANEG_CFG_HD)
- ap->flags |= MR_LP_ADV_HALF_DUPLEX;
- if (ap->rxconfig & ANEG_CFG_PS1)
- ap->flags |= MR_LP_ADV_SYM_PAUSE;
- if (ap->rxconfig & ANEG_CFG_PS2)
- ap->flags |= MR_LP_ADV_ASYM_PAUSE;
- if (ap->rxconfig & ANEG_CFG_RF1)
- ap->flags |= MR_LP_ADV_REMOTE_FAULT1;
- if (ap->rxconfig & ANEG_CFG_RF2)
- ap->flags |= MR_LP_ADV_REMOTE_FAULT2;
- if (ap->rxconfig & ANEG_CFG_NP)
- ap->flags |= MR_LP_ADV_NEXT_PAGE;
-
- ap->link_time = ap->cur_time;
-
- ap->flags ^= (MR_TOGGLE_TX);
- if (ap->rxconfig & 0x0008)
- ap->flags |= MR_TOGGLE_RX;
- if (ap->rxconfig & ANEG_CFG_NP)
- ap->flags |= MR_NP_RX;
- ap->flags |= MR_PAGE_RX;
-
- ap->state = ANEG_STATE_COMPLETE_ACK;
- ret = ANEG_TIMER_ENAB;
- break;
-
- case ANEG_STATE_COMPLETE_ACK:
- if (ap->ability_match != 0 &&
- ap->rxconfig == 0) {
- ap->state = ANEG_STATE_AN_ENABLE;
- break;
- }
- delta = ap->cur_time - ap->link_time;
- if (delta > ANEG_STATE_SETTLE_TIME) {
- if (!(ap->flags & (MR_LP_ADV_NEXT_PAGE))) {
- ap->state = ANEG_STATE_IDLE_DETECT_INIT;
- } else {
- if ((ap->txconfig & ANEG_CFG_NP) == 0 &&
- !(ap->flags & MR_NP_RX)) {
- ap->state = ANEG_STATE_IDLE_DETECT_INIT;
- } else {
- ret = ANEG_FAILED;
- }
- }
- }
- break;
-
- case ANEG_STATE_IDLE_DETECT_INIT:
- ap->link_time = ap->cur_time;
- tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
- tw32_f(MAC_MODE, tp->mac_mode);
- udelay(40);
-
- ap->state = ANEG_STATE_IDLE_DETECT;
- ret = ANEG_TIMER_ENAB;
- break;
-
- case ANEG_STATE_IDLE_DETECT:
- if (ap->ability_match != 0 &&
- ap->rxconfig == 0) {
- ap->state = ANEG_STATE_AN_ENABLE;
- break;
- }
- delta = ap->cur_time - ap->link_time;
- if (delta > ANEG_STATE_SETTLE_TIME) {
- /* XXX another gem from the Broadcom driver :( */
- ap->state = ANEG_STATE_LINK_OK;
- }
- break;
-
- case ANEG_STATE_LINK_OK:
- ap->flags |= (MR_AN_COMPLETE | MR_LINK_OK);
- ret = ANEG_DONE;
- break;
-
- case ANEG_STATE_NEXT_PAGE_WAIT_INIT:
- /* ??? unimplemented */
- break;
-
- case ANEG_STATE_NEXT_PAGE_WAIT:
- /* ??? unimplemented */
- break;
-
- default:
- ret = ANEG_FAILED;
- break;
- }
-
- return ret;
- }
-
- static int fiber_autoneg(struct tg3 *tp, u32 *txflags, u32 *rxflags)
- {
- int res = 0;
- struct tg3_fiber_aneginfo aninfo;
- int status = ANEG_FAILED;
- unsigned int tick;
- u32 tmp;
-
- tw32_f(MAC_TX_AUTO_NEG, 0);
-
- tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
- tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
- udelay(40);
-
- tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
- udelay(40);
-
- memset(&aninfo, 0, sizeof(aninfo));
- aninfo.flags |= MR_AN_ENABLE;
- aninfo.state = ANEG_STATE_UNKNOWN;
- aninfo.cur_time = 0;
- tick = 0;
- while (++tick < 195000) {
- status = tg3_fiber_aneg_smachine(tp, &aninfo);
- if (status == ANEG_DONE || status == ANEG_FAILED)
- break;
-
- udelay(1);
- }
-
- tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
- tw32_f(MAC_MODE, tp->mac_mode);
- udelay(40);
-
- *txflags = aninfo.txconfig;
- *rxflags = aninfo.flags;
-
- if (status == ANEG_DONE &&
- (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
- MR_LP_ADV_FULL_DUPLEX)))
- res = 1;
-
- return res;
- }
-
- static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
- {
- int current_link_up = 0;
-
- if (!(mac_status & MAC_STATUS_PCS_SYNCED))
- goto out;
-
- if (tp->link_config.autoneg == AUTONEG_ENABLE) {
- u32 txflags, rxflags;
- int i;
-
- if (fiber_autoneg(tp, &txflags, &rxflags)) {
- u32 local_adv = 0, remote_adv = 0;
-
- if (txflags & ANEG_CFG_PS1)
- local_adv |= ADVERTISE_1000XPAUSE;
- if (txflags & ANEG_CFG_PS2)
- local_adv |= ADVERTISE_1000XPSE_ASYM;
-
- if (rxflags & MR_LP_ADV_SYM_PAUSE)
- remote_adv |= LPA_1000XPAUSE;
- if (rxflags & MR_LP_ADV_ASYM_PAUSE)
- remote_adv |= LPA_1000XPAUSE_ASYM;
-
- tp->link_config.rmt_adv =
- mii_adv_to_ethtool_adv_x(remote_adv);
-
- tg3_setup_flow_control(tp, local_adv, remote_adv);
-
- current_link_up = 1;
- }
- for (i = 0; i < 30; i++) {
- udelay(20);
- tw32_f(MAC_STATUS,
- (MAC_STATUS_SYNC_CHANGED |
- MAC_STATUS_CFG_CHANGED));
- udelay(40);
- if ((tr32(MAC_STATUS) &
- (MAC_STATUS_SYNC_CHANGED |
- MAC_STATUS_CFG_CHANGED)) == 0)
- break;
- }
-
- mac_status = tr32(MAC_STATUS);
- if (!current_link_up &&
- (mac_status & MAC_STATUS_PCS_SYNCED) &&
- !(mac_status & MAC_STATUS_RCVD_CFG))
- current_link_up = 1;
- } else {
- tg3_setup_flow_control(tp, 0, 0);
-
- /* Forcing 1000FD link up. */
- current_link_up = 1;
-
- tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
- udelay(40);
-
- tw32_f(MAC_MODE, tp->mac_mode);
- udelay(40);
- }
-
- out:
- return current_link_up;
- }
-
- static int tg3_test_and_report_link_chg(struct tg3 *tp, int curr_link_up)
- {
- if (curr_link_up != tp->link_up) {
- if (curr_link_up) {
- netdev_link_up(tp->dev);
- } else {
- netdev_link_down(tp->dev);
- if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
- tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
- }
-
- tg3_link_report(tp);
- return 1;
- }
-
- return 0;
- }
-
- static void tg3_clear_mac_status(struct tg3 *tp)
- {
- tw32(MAC_EVENT, 0);
-
- tw32_f(MAC_STATUS,
- MAC_STATUS_SYNC_CHANGED |
- MAC_STATUS_CFG_CHANGED |
- MAC_STATUS_MI_COMPLETION |
- MAC_STATUS_LNKSTATE_CHANGED);
- udelay(40);
- }
-
- static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
- {
- u32 orig_pause_cfg;
- u16 orig_active_speed;
- u8 orig_active_duplex;
- u32 mac_status;
- int current_link_up = force_reset;
- int i;
-
- orig_pause_cfg = tp->link_config.active_flowctrl;
- orig_active_speed = tp->link_config.active_speed;
- orig_active_duplex = tp->link_config.active_duplex;
-
- if (!tg3_flag(tp, HW_AUTONEG) &&
- tp->link_up &&
- tg3_flag(tp, INIT_COMPLETE)) {
- mac_status = tr32(MAC_STATUS);
- mac_status &= (MAC_STATUS_PCS_SYNCED |
- MAC_STATUS_SIGNAL_DET |
- MAC_STATUS_CFG_CHANGED |
- MAC_STATUS_RCVD_CFG);
- if (mac_status == (MAC_STATUS_PCS_SYNCED |
- MAC_STATUS_SIGNAL_DET)) {
- tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
- MAC_STATUS_CFG_CHANGED));
- return 0;
- }
- }
-
- tw32_f(MAC_TX_AUTO_NEG, 0);
-
- tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
- tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
- tw32_f(MAC_MODE, tp->mac_mode);
- udelay(40);
-
- if (tp->phy_id == TG3_PHY_ID_BCM8002)
- tg3_init_bcm8002(tp);
-
- /* Enable link change event even when serdes polling. */
- tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
- udelay(40);
-
- current_link_up = 0;
- tp->link_config.rmt_adv = 0;
- mac_status = tr32(MAC_STATUS);
-
- if (tg3_flag(tp, HW_AUTONEG))
- current_link_up = tg3_setup_fiber_hw_autoneg(tp, mac_status);
- else
- current_link_up = tg3_setup_fiber_by_hand(tp, mac_status);
-
- tp->hw_status->status =
- (SD_STATUS_UPDATED |
- (tp->hw_status->status & ~SD_STATUS_LINK_CHG));
-
- for (i = 0; i < 100; i++) {
- tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
- MAC_STATUS_CFG_CHANGED));
- udelay(5);
- if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED |
- MAC_STATUS_CFG_CHANGED |
- MAC_STATUS_LNKSTATE_CHANGED)) == 0)
- break;
- }
-
- mac_status = tr32(MAC_STATUS);
- if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) {
- current_link_up = 0;
- if (tp->link_config.autoneg == AUTONEG_ENABLE &&
- tp->serdes_counter == 0) {
- tw32_f(MAC_MODE, (tp->mac_mode |
- MAC_MODE_SEND_CONFIGS));
- udelay(1);
- tw32_f(MAC_MODE, tp->mac_mode);
- }
- }
-
- if (current_link_up) {
- tp->link_config.active_speed = SPEED_1000;
- tp->link_config.active_duplex = DUPLEX_FULL;
- tw32(MAC_LED_CTRL, (tp->led_ctrl |
- LED_CTRL_LNKLED_OVERRIDE |
- LED_CTRL_1000MBPS_ON));
- } else {
- tp->link_config.active_speed = SPEED_UNKNOWN;
- tp->link_config.active_duplex = DUPLEX_UNKNOWN;
- tw32(MAC_LED_CTRL, (tp->led_ctrl |
- LED_CTRL_LNKLED_OVERRIDE |
- LED_CTRL_TRAFFIC_OVERRIDE));
- }
-
- if (!tg3_test_and_report_link_chg(tp, current_link_up)) {
- u32 now_pause_cfg = tp->link_config.active_flowctrl;
- if (orig_pause_cfg != now_pause_cfg ||
- orig_active_speed != tp->link_config.active_speed ||
- orig_active_duplex != tp->link_config.active_duplex)
- tg3_link_report(tp);
- }
-
- return 0;
- }
-
- static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
- {
- int err = 0;
- u32 bmsr, bmcr;
- u16 current_speed = SPEED_UNKNOWN;
- u8 current_duplex = DUPLEX_UNKNOWN;
- int current_link_up = 0;
- u32 local_adv, remote_adv, sgsr;
-
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) &&
- !tg3_readphy(tp, SERDES_TG3_1000X_STATUS, &sgsr) &&
- (sgsr & SERDES_TG3_SGMII_MODE)) {
-
- if (force_reset)
- tg3_phy_reset(tp);
-
- tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
-
- if (!(sgsr & SERDES_TG3_LINK_UP)) {
- tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
- } else {
- current_link_up = 1;
- if (sgsr & SERDES_TG3_SPEED_1000) {
- current_speed = SPEED_1000;
- tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
- } else if (sgsr & SERDES_TG3_SPEED_100) {
- current_speed = SPEED_100;
- tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
- } else {
- current_speed = SPEED_10;
- tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
- }
-
- if (sgsr & SERDES_TG3_FULL_DUPLEX)
- current_duplex = DUPLEX_FULL;
- else
- current_duplex = DUPLEX_HALF;
- }
-
- tw32_f(MAC_MODE, tp->mac_mode);
- udelay(40);
-
- tg3_clear_mac_status(tp);
-
- goto fiber_setup_done;
- }
-
- tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
- tw32_f(MAC_MODE, tp->mac_mode);
- udelay(40);
-
- tg3_clear_mac_status(tp);
-
- if (force_reset)
- tg3_phy_reset(tp);
-
- tp->link_config.rmt_adv = 0;
-
- err |= tg3_readphy(tp, MII_BMSR, &bmsr);
- err |= tg3_readphy(tp, MII_BMSR, &bmsr);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
- if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
- bmsr |= BMSR_LSTATUS;
- else
- bmsr &= ~BMSR_LSTATUS;
- }
-
- err |= tg3_readphy(tp, MII_BMCR, &bmcr);
-
- if ((tp->link_config.autoneg == AUTONEG_ENABLE) && !force_reset &&
- (tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT)) {
- /* do nothing, just check for link up at the end */
- } else if (tp->link_config.autoneg == AUTONEG_ENABLE) {
- u32 adv, newadv;
-
- err |= tg3_readphy(tp, MII_ADVERTISE, &adv);
- newadv = adv & ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF |
- ADVERTISE_1000XPAUSE |
- ADVERTISE_1000XPSE_ASYM |
- ADVERTISE_SLCT);
-
- newadv |= tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
- newadv |= ethtool_adv_to_mii_adv_x(tp->link_config.advertising);
-
- if ((newadv != adv) || !(bmcr & BMCR_ANENABLE)) {
- tg3_writephy(tp, MII_ADVERTISE, newadv);
- bmcr |= BMCR_ANENABLE | BMCR_ANRESTART;
- tg3_writephy(tp, MII_BMCR, bmcr);
-
- tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
- tp->serdes_counter = SERDES_AN_TIMEOUT_5714S;
- tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
-
- return err;
- }
- } else {
- u32 new_bmcr;
-
- bmcr &= ~BMCR_SPEED1000;
- new_bmcr = bmcr & ~(BMCR_ANENABLE | BMCR_FULLDPLX);
-
- if (tp->link_config.duplex == DUPLEX_FULL)
- new_bmcr |= BMCR_FULLDPLX;
-
- if (new_bmcr != bmcr) {
- /* BMCR_SPEED1000 is a reserved bit that needs
- * to be set on write.
- */
- new_bmcr |= BMCR_SPEED1000;
-
- /* Force a linkdown */
- if (tp->link_up) {
- u32 adv;
-
- err |= tg3_readphy(tp, MII_ADVERTISE, &adv);
- adv &= ~(ADVERTISE_1000XFULL |
- ADVERTISE_1000XHALF |
- ADVERTISE_SLCT);
- tg3_writephy(tp, MII_ADVERTISE, adv);
- tg3_writephy(tp, MII_BMCR, bmcr |
- BMCR_ANRESTART |
- BMCR_ANENABLE);
- udelay(10);
- netdev_link_down(tp->dev);
- }
- tg3_writephy(tp, MII_BMCR, new_bmcr);
- bmcr = new_bmcr;
- err |= tg3_readphy(tp, MII_BMSR, &bmsr);
- err |= tg3_readphy(tp, MII_BMSR, &bmsr);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
- if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
- bmsr |= BMSR_LSTATUS;
- else
- bmsr &= ~BMSR_LSTATUS;
- }
- tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
- }
- }
-
- if (bmsr & BMSR_LSTATUS) {
- current_speed = SPEED_1000;
- current_link_up = 1;
- if (bmcr & BMCR_FULLDPLX)
- current_duplex = DUPLEX_FULL;
- else
- current_duplex = DUPLEX_HALF;
-
- local_adv = 0;
- remote_adv = 0;
-
- if (bmcr & BMCR_ANENABLE) {
- u32 common;
-
- err |= tg3_readphy(tp, MII_ADVERTISE, &local_adv);
- err |= tg3_readphy(tp, MII_LPA, &remote_adv);
- common = local_adv & remote_adv;
- if (common & (ADVERTISE_1000XHALF |
- ADVERTISE_1000XFULL)) {
- if (common & ADVERTISE_1000XFULL)
- current_duplex = DUPLEX_FULL;
- else
- current_duplex = DUPLEX_HALF;
-
- tp->link_config.rmt_adv =
- mii_adv_to_ethtool_adv_x(remote_adv);
- } else if (!tg3_flag(tp, 5780_CLASS)) {
- /* Link is up via parallel detect */
- } else {
- current_link_up = 0;
- }
- }
- }
-
- fiber_setup_done:
- if (current_link_up && current_duplex == DUPLEX_FULL)
- tg3_setup_flow_control(tp, local_adv, remote_adv);
-
- tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
- if (tp->link_config.active_duplex == DUPLEX_HALF)
- tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
-
- tw32_f(MAC_MODE, tp->mac_mode);
- udelay(40);
-
- tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
-
- tp->link_config.active_speed = current_speed;
- tp->link_config.active_duplex = current_duplex;
-
- tg3_test_and_report_link_chg(tp, current_link_up);
- return err;
- }
-
- static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
- { DBGP("%s\n", __func__);
-
- int current_link_up;
- u32 bmsr, val;
- u32 lcl_adv, rmt_adv;
- u16 current_speed;
- u8 current_duplex;
- int i, err;
-
- tw32(MAC_EVENT, 0);
-
- tw32_f(MAC_STATUS,
- (MAC_STATUS_SYNC_CHANGED |
- MAC_STATUS_CFG_CHANGED |
- MAC_STATUS_MI_COMPLETION |
- MAC_STATUS_LNKSTATE_CHANGED));
- udelay(40);
-
- if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
- tw32_f(MAC_MI_MODE,
- (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
- udelay(80);
- }
-
- tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_PWRCTL, 0);
-
- /* Some third-party PHYs need to be reset on link going
- * down.
- */
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
- netdev_link_ok(tp->dev)) {
- tg3_readphy(tp, MII_BMSR, &bmsr);
- if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
- !(bmsr & BMSR_LSTATUS))
- force_reset = 1;
- }
- if (force_reset)
- tg3_phy_reset(tp);
-
- if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
- tg3_readphy(tp, MII_BMSR, &bmsr);
- if (tg3_readphy(tp, MII_BMSR, &bmsr) ||
- !tg3_flag(tp, INIT_COMPLETE))
- bmsr = 0;
-
- if (!(bmsr & BMSR_LSTATUS)) {
- err = tg3_init_5401phy_dsp(tp);
- if (err)
- return err;
-
- tg3_readphy(tp, MII_BMSR, &bmsr);
- for (i = 0; i < 1000; i++) {
- udelay(10);
- if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
- (bmsr & BMSR_LSTATUS)) {
- udelay(40);
- break;
- }
- }
-
- if ((tp->phy_id & TG3_PHY_ID_REV_MASK) ==
- TG3_PHY_REV_BCM5401_B0 &&
- !(bmsr & BMSR_LSTATUS) &&
- tp->link_config.active_speed == SPEED_1000) {
- err = tg3_phy_reset(tp);
- if (!err)
- err = tg3_init_5401phy_dsp(tp);
- if (err)
- return err;
- }
- }
- } else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
- /* 5701 {A0,B0} CRC bug workaround */
- tg3_writephy(tp, 0x15, 0x0a75);
- tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
- tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
- tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
- }
-
- /* Clear pending interrupts... */
- tg3_readphy(tp, MII_TG3_ISTAT, &val);
- tg3_readphy(tp, MII_TG3_ISTAT, &val);
-
- if (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT)
- tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
- else if (!(tp->phy_flags & TG3_PHYFLG_IS_FET))
- tg3_writephy(tp, MII_TG3_IMASK, ~0);
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
- if (tp->led_ctrl == LED_CTRL_MODE_PHY_1)
- tg3_writephy(tp, MII_TG3_EXT_CTRL,
- MII_TG3_EXT_CTRL_LNK3_LED_MODE);
- else
- tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
- }
-
- current_link_up = 0;
- current_speed = SPEED_INVALID;
- current_duplex = DUPLEX_INVALID;
-
- if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) {
- err = tg3_phy_auxctl_read(tp,
- MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
- &val);
- if (!err && !(val & (1 << 10))) {
- tg3_phy_auxctl_write(tp,
- MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
- val | (1 << 10));
- goto relink;
- }
- }
-
- bmsr = 0;
- for (i = 0; i < 100; i++) {
- tg3_readphy(tp, MII_BMSR, &bmsr);
- if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
- (bmsr & BMSR_LSTATUS))
- break;
- udelay(40);
- }
-
- if (bmsr & BMSR_LSTATUS) {
- u32 aux_stat, bmcr;
-
- tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
- for (i = 0; i < 2000; i++) {
- udelay(10);
- if (!tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat) &&
- aux_stat)
- break;
- }
-
- tg3_aux_stat_to_speed_duplex(tp, aux_stat,
- ¤t_speed,
- ¤t_duplex);
-
- bmcr = 0;
- for (i = 0; i < 200; i++) {
- tg3_readphy(tp, MII_BMCR, &bmcr);
- if (tg3_readphy(tp, MII_BMCR, &bmcr))
- continue;
- if (bmcr && bmcr != 0x7fff)
- break;
- udelay(10);
- }
-
- lcl_adv = 0;
- rmt_adv = 0;
-
- tp->link_config.active_speed = current_speed;
- tp->link_config.active_duplex = current_duplex;
-
- if ((bmcr & BMCR_ANENABLE) &&
- tg3_copper_is_advertising_all(tp,
- tp->link_config.advertising)) {
- if (tg3_adv_1000T_flowctrl_ok(tp, &lcl_adv,
- &rmt_adv)) {
- current_link_up = 1;
- }
- }
-
- if (current_link_up == 1 &&
- tp->link_config.active_duplex == DUPLEX_FULL)
- tg3_setup_flow_control(tp, lcl_adv, rmt_adv);
- }
-
- relink:
- if (current_link_up == 0) {
- tg3_phy_copper_begin(tp);
-
- tg3_readphy(tp, MII_BMSR, &bmsr);
- if ((!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) ||
- (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK))
- current_link_up = 1;
- }
-
- tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
- if (current_link_up == 1) {
- if (tp->link_config.active_speed == SPEED_100 ||
- tp->link_config.active_speed == SPEED_10)
- tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
- else
- tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
- } else if (tp->phy_flags & TG3_PHYFLG_IS_FET)
- tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
- else
- tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
-
- tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
- if (tp->link_config.active_duplex == DUPLEX_HALF)
- tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
- if (current_link_up == 1 &&
- tg3_5700_link_polarity(tp, tp->link_config.active_speed))
- tp->mac_mode |= MAC_MODE_LINK_POLARITY;
- else
- tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
- }
-
- /* ??? Without this setting Netgear GA302T PHY does not
- * ??? send/receive packets...
- */
- if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411 &&
- tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
- tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
- tw32_f(MAC_MI_MODE, tp->mi_mode);
- udelay(80);
- }
-
- tw32_f(MAC_MODE, tp->mac_mode);
- udelay(40);
-
- /* Enabled attention when the link has changed state. */
- tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
- udelay(40);
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
- current_link_up == 1 &&
- tp->link_config.active_speed == SPEED_1000 &&
- (tg3_flag(tp, PCIX_MODE) || tg3_flag(tp, PCI_HIGH_SPEED))) {
- udelay(120);
- /* NOTE: this freezes for mdc? */
- tw32_f(MAC_STATUS,
- (MAC_STATUS_SYNC_CHANGED |
- MAC_STATUS_CFG_CHANGED));
- udelay(40);
- tg3_write_mem(tp,
- NIC_SRAM_FIRMWARE_MBOX,
- NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
- }
-
- /* Prevent send BD corruption. */
- if (tg3_flag(tp, CLKREQ_BUG)) {
- u16 oldlnkctl, newlnkctl;
-
- pci_read_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_LNKCTL,
- &oldlnkctl);
- if (tp->link_config.active_speed == SPEED_100 ||
- tp->link_config.active_speed == SPEED_10)
- newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN;
- else
- newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
- if (newlnkctl != oldlnkctl)
- pci_write_config_word(tp->pdev,
- tp->pcie_cap + PCI_EXP_LNKCTL,
- newlnkctl);
- }
-
- if (current_link_up != netdev_link_ok(tp->dev)) {
- if (current_link_up)
- netdev_link_up(tp->dev);
- else
- netdev_link_down(tp->dev);
- tg3_link_report(tp);
- }
-
- return 0;
- }
-
- int tg3_setup_phy(struct tg3 *tp, int force_reset)
- { DBGP("%s\n", __func__);
-
- u32 val;
- int err;
-
- if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)
- err = tg3_setup_fiber_phy(tp, force_reset);
- else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
- err = tg3_setup_fiber_mii_phy(tp, force_reset);
- else
- err = tg3_setup_copper_phy(tp, force_reset);
-
- val = (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
- (6 << TX_LENGTHS_IPG_SHIFT);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
- val |= tr32(MAC_TX_LENGTHS) &
- (TX_LENGTHS_JMB_FRM_LEN_MSK |
- TX_LENGTHS_CNT_DWN_VAL_MSK);
-
- if (tp->link_config.active_speed == SPEED_1000 &&
- tp->link_config.active_duplex == DUPLEX_HALF)
- tw32(MAC_TX_LENGTHS, val |
- (0xff << TX_LENGTHS_SLOT_TIME_SHIFT));
- else
- tw32(MAC_TX_LENGTHS, val |
- (32 << TX_LENGTHS_SLOT_TIME_SHIFT));
-
- if (!tg3_flag(tp, 5705_PLUS)) {
- if (netdev_link_ok(tp->dev)) {
- tw32(HOSTCC_STAT_COAL_TICKS, DEFAULT_STAT_COAL_TICKS);
- } else {
- tw32(HOSTCC_STAT_COAL_TICKS, 0);
- }
- }
-
- val = tr32(PCIE_PWR_MGMT_THRESH);
- if (!netdev_link_ok(tp->dev))
- val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK);
- else
- val |= PCIE_PWR_MGMT_L1_THRESH_MSK;
- tw32(PCIE_PWR_MGMT_THRESH, val);
-
- return err;
- }
|