]> Pileus Git - ~andy/linux/blob - drivers/staging/rt2860/pci_main_dev.c
Staging: rt28x0: run *.c files through Lindent
[~andy/linux] / drivers / staging / rt2860 / pci_main_dev.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26
27     Module Name:
28     pci_main_dev.c
29
30     Abstract:
31     Create and register network interface for PCI based chipsets in Linux platform.
32
33     Revision History:
34     Who         When            What
35     --------    ----------      ----------------------------------------------
36 */
37
38 #include "rt_config.h"
39 #include <linux/pci.h>
40
41 // Following information will be show when you run 'modinfo'
42 // *** If you have a solution for the bug in current version of driver, please mail to me.
43 // Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. ***
44 MODULE_AUTHOR("Jett Chen <jett_chen@ralinktech.com>");
45 MODULE_DESCRIPTION("RT2860/RT3090 Wireless Lan Linux Driver");
46 MODULE_LICENSE("GPL");
47 MODULE_ALIAS("rt3090sta");
48
49 //
50 // Function declarations
51 //
52 extern int rt28xx_close(IN struct net_device *net_dev);
53 extern int rt28xx_open(struct net_device *net_dev);
54
55 static VOID __devexit rt2860_remove_one(struct pci_dev *pci_dev);
56 static INT __devinit rt2860_probe(struct pci_dev *pci_dev,
57                                   const struct pci_device_id *ent);
58 static void __exit rt2860_cleanup_module(void);
59 static int __init rt2860_init_module(void);
60
61 static VOID RTMPInitPCIeDevice(IN struct pci_dev *pci_dev,
62                                IN PRTMP_ADAPTER pAd);
63
64 #ifdef CONFIG_PM
65 static int rt2860_suspend(struct pci_dev *pci_dev, pm_message_t state);
66 static int rt2860_resume(struct pci_dev *pci_dev);
67 #endif // CONFIG_PM //
68
69 //
70 // Ralink PCI device table, include all supported chipsets
71 //
72 static struct pci_device_id rt2860_pci_tbl[] __devinitdata = {
73 #ifdef RT2860
74         {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCI_DEVICE_ID)}, //RT28602.4G
75         {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCIe_DEVICE_ID)},
76         {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2760_PCI_DEVICE_ID)},
77         {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2790_PCIe_DEVICE_ID)},
78         {PCI_DEVICE(VEN_AWT_PCI_VENDOR_ID, VEN_AWT_PCIe_DEVICE_ID)},
79         {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7708)},
80         {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7728)},
81         {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7758)},
82         {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7727)},
83         {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7738)},
84         {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7748)},
85         {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7768)},
86 #endif
87 #ifdef RT3090
88         {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3090_PCIe_DEVICE_ID)},
89         {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3091_PCIe_DEVICE_ID)},
90         {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3092_PCIe_DEVICE_ID)},
91 #endif // RT3090 //
92 #ifdef RT3390
93         {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3390_PCIe_DEVICE_ID)},
94         {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3391_PCIe_DEVICE_ID)},
95         {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC3392_PCIe_DEVICE_ID)},
96 #endif // RT3390 //
97         {0,}                    // terminate list
98 };
99
100 MODULE_DEVICE_TABLE(pci, rt2860_pci_tbl);
101 #ifdef MODULE_VERSION
102 MODULE_VERSION(STA_DRIVER_VERSION);
103 #endif
104
105 //
106 // Our PCI driver structure
107 //
108 static struct pci_driver rt2860_driver = {
109 name:   "rt2860",
110 id_table:rt2860_pci_tbl,
111 probe:  rt2860_probe,
112 remove:__devexit_p(rt2860_remove_one),
113 #ifdef CONFIG_PM
114 suspend:rt2860_suspend,
115 resume:rt2860_resume,
116 #endif
117 };
118
119 /***************************************************************************
120  *
121  *      PCI device initialization related procedures.
122  *
123  ***************************************************************************/
124 #ifdef CONFIG_PM
125
126 VOID RT2860RejectPendingPackets(IN PRTMP_ADAPTER pAd)
127 {
128         // clear PS packets
129         // clear TxSw packets
130 }
131
132 static int rt2860_suspend(struct pci_dev *pci_dev, pm_message_t state)
133 {
134         struct net_device *net_dev = pci_get_drvdata(pci_dev);
135         PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) NULL;
136         INT32 retval = 0;
137
138         DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_suspend()\n"));
139
140         if (net_dev == NULL) {
141                 DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n"));
142         } else {
143                 GET_PAD_FROM_NET_DEV(pAd, net_dev);
144
145                 /* we can not use IFF_UP because ra0 down but ra1 up */
146                 /* and 1 suspend/resume function for 1 module, not for each interface */
147                 /* so Linux will call suspend/resume function once */
148                 if (VIRTUAL_IF_NUM(pAd) > 0) {
149                         // avoid users do suspend after interface is down
150
151                         // stop interface
152                         netif_carrier_off(net_dev);
153                         netif_stop_queue(net_dev);
154
155                         // mark device as removed from system and therefore no longer available
156                         netif_device_detach(net_dev);
157
158                         // mark halt flag
159                         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
160                         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
161
162                         // take down the device
163                         rt28xx_close((PNET_DEV) net_dev);
164
165                         RT_MOD_DEC_USE_COUNT();
166                 }
167         }
168
169         // reference to http://vovo2000.com/type-lab/linux/kernel-api/linux-kernel-api.html
170         // enable device to generate PME# when suspended
171         // pci_choose_state(): Choose the power state of a PCI device to be suspended
172         retval = pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1);
173         // save the PCI configuration space of a device before suspending
174         pci_save_state(pci_dev);
175         // disable PCI device after use
176         pci_disable_device(pci_dev);
177
178         retval = pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
179
180         DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_suspend()\n"));
181         return retval;
182 }
183
184 static int rt2860_resume(struct pci_dev *pci_dev)
185 {
186         struct net_device *net_dev = pci_get_drvdata(pci_dev);
187         PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) NULL;
188         INT32 retval;
189
190         // set the power state of a PCI device
191         // PCI has 4 power states, DO (normal) ~ D3(less power)
192         // in include/linux/pci.h, you can find that
193         // #define PCI_D0          ((pci_power_t __force) 0)
194         // #define PCI_D1          ((pci_power_t __force) 1)
195         // #define PCI_D2          ((pci_power_t __force) 2)
196         // #define PCI_D3hot       ((pci_power_t __force) 3)
197         // #define PCI_D3cold      ((pci_power_t __force) 4)
198         // #define PCI_UNKNOWN     ((pci_power_t __force) 5)
199         // #define PCI_POWER_ERROR ((pci_power_t __force) -1)
200         retval = pci_set_power_state(pci_dev, PCI_D0);
201
202         // restore the saved state of a PCI device
203         pci_restore_state(pci_dev);
204
205         // initialize device before it's used by a driver
206         if (pci_enable_device(pci_dev)) {
207                 printk("pci enable fail!\n");
208                 return 0;
209         }
210
211         DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_resume()\n"));
212
213         if (net_dev == NULL) {
214                 DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n"));
215         } else
216                 GET_PAD_FROM_NET_DEV(pAd, net_dev);
217
218         if (pAd != NULL) {
219                 /* we can not use IFF_UP because ra0 down but ra1 up */
220                 /* and 1 suspend/resume function for 1 module, not for each interface */
221                 /* so Linux will call suspend/resume function once */
222                 if (VIRTUAL_IF_NUM(pAd) > 0) {
223                         // mark device as attached from system and restart if needed
224                         netif_device_attach(net_dev);
225
226                         if (rt28xx_open((PNET_DEV) net_dev) != 0) {
227                                 // open fail
228                                 DBGPRINT(RT_DEBUG_TRACE,
229                                          ("<=== rt2860_resume()\n"));
230                                 return 0;
231                         }
232                         // increase MODULE use count
233                         RT_MOD_INC_USE_COUNT();
234
235                         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
236                         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
237
238                         netif_start_queue(net_dev);
239                         netif_carrier_on(net_dev);
240                         netif_wake_queue(net_dev);
241                 }
242         }
243
244         DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_resume()\n"));
245         return 0;
246 }
247 #endif // CONFIG_PM //
248
249 static INT __init rt2860_init_module(VOID)
250 {
251         return pci_register_driver(&rt2860_driver);
252 }
253
254 //
255 // Driver module unload function
256 //
257 static VOID __exit rt2860_cleanup_module(VOID)
258 {
259         pci_unregister_driver(&rt2860_driver);
260 }
261
262 module_init(rt2860_init_module);
263 module_exit(rt2860_cleanup_module);
264
265 //
266 // PCI device probe & initialization function
267 //
268 static INT __devinit rt2860_probe(IN struct pci_dev *pci_dev,
269                                   IN const struct pci_device_id *pci_id)
270 {
271         PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) NULL;
272         struct net_device *net_dev;
273         PVOID handle;
274         PSTRING print_name;
275         ULONG csr_addr;
276         INT rv = 0;
277         RTMP_OS_NETDEV_OP_HOOK netDevHook;
278
279         DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_probe\n"));
280
281 //PCIDevInit==============================================
282         // wake up and enable device
283         if ((rv = pci_enable_device(pci_dev)) != 0) {
284                 DBGPRINT(RT_DEBUG_ERROR,
285                          ("Enable PCI device failed, errno=%d!\n", rv));
286                 return rv;
287         }
288
289         print_name = (PSTRING) pci_name(pci_dev);
290
291         if ((rv = pci_request_regions(pci_dev, print_name)) != 0) {
292                 DBGPRINT(RT_DEBUG_ERROR,
293                          ("Request PCI resource failed, errno=%d!\n", rv));
294                 goto err_out;
295         }
296         // map physical address to virtual address for accessing register
297         csr_addr =
298             (unsigned long)ioremap(pci_resource_start(pci_dev, 0),
299                                    pci_resource_len(pci_dev, 0));
300         if (!csr_addr) {
301                 DBGPRINT(RT_DEBUG_ERROR,
302                          ("ioremap failed for device %s, region 0x%lX @ 0x%lX\n",
303                           print_name, (ULONG) pci_resource_len(pci_dev, 0),
304                           (ULONG) pci_resource_start(pci_dev, 0)));
305                 goto err_out_free_res;
306         } else {
307                 DBGPRINT(RT_DEBUG_TRACE,
308                          ("%s: at 0x%lx, VA 0x%lx, IRQ %d. \n", print_name,
309                           (ULONG) pci_resource_start(pci_dev, 0),
310                           (ULONG) csr_addr, pci_dev->irq));
311         }
312
313         // Set DMA master
314         pci_set_master(pci_dev);
315
316 //RtmpDevInit==============================================
317         // Allocate RTMP_ADAPTER adapter structure
318         handle = kmalloc(sizeof(struct os_cookie), GFP_KERNEL);
319         if (handle == NULL) {
320                 DBGPRINT(RT_DEBUG_ERROR,
321                          ("%s(): Allocate memory for os handle failed!\n",
322                           __func__));
323                 goto err_out_iounmap;
324         }
325
326         ((POS_COOKIE) handle)->pci_dev = pci_dev;
327
328         rv = RTMPAllocAdapterBlock(handle, &pAd);       //shiang: we may need the pci_dev for allocate structure of "RTMP_ADAPTER"
329         if (rv != NDIS_STATUS_SUCCESS)
330                 goto err_out_iounmap;
331         // Here are the RTMP_ADAPTER structure with pci-bus specific parameters.
332         pAd->CSRBaseAddress = (PUCHAR) csr_addr;
333         DBGPRINT(RT_DEBUG_ERROR,
334                  ("pAd->CSRBaseAddress =0x%lx, csr_addr=0x%lx!\n",
335                   (ULONG) pAd->CSRBaseAddress, csr_addr));
336         RtmpRaDevCtrlInit(pAd, RTMP_DEV_INF_PCI);
337
338 //NetDevInit==============================================
339         net_dev = RtmpPhyNetDevInit(pAd, &netDevHook);
340         if (net_dev == NULL)
341                 goto err_out_free_radev;
342
343         // Here are the net_device structure with pci-bus specific parameters.
344         net_dev->irq = pci_dev->irq;    // Interrupt IRQ number
345         net_dev->base_addr = csr_addr;  // Save CSR virtual address and irq to device structure
346         pci_set_drvdata(pci_dev, net_dev);      // Set driver data
347
348 /* for supporting Network Manager */
349         /* Set the sysfs physical device reference for the network logical device
350          * if set prior to registration will cause a symlink during initialization.
351          */
352         SET_NETDEV_DEV(net_dev, &(pci_dev->dev));
353
354 //All done, it's time to register the net device to linux kernel.
355         // Register this device
356         rv = RtmpOSNetDevAttach(net_dev, &netDevHook);
357         if (rv)
358                 goto err_out_free_netdev;
359
360         pAd->StaCfg.OriDevType = net_dev->type;
361         RTMPInitPCIeDevice(pci_dev, pAd);
362
363         DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_probe\n"));
364
365         return 0;               // probe ok
366
367         /* --------------------------- ERROR HANDLE --------------------------- */
368 err_out_free_netdev:
369         RtmpOSNetDevFree(net_dev);
370
371 err_out_free_radev:
372         /* free RTMP_ADAPTER strcuture and os_cookie */
373         RTMPFreeAdapter(pAd);
374
375 err_out_iounmap:
376         iounmap((void *)(csr_addr));
377         release_mem_region(pci_resource_start(pci_dev, 0),
378                            pci_resource_len(pci_dev, 0));
379
380 err_out_free_res:
381         pci_release_regions(pci_dev);
382
383 err_out:
384         pci_disable_device(pci_dev);
385
386         DBGPRINT(RT_DEBUG_ERROR,
387                  ("<=== rt2860_probe failed with rv = %d!\n", rv));
388
389         return -ENODEV;         /* probe fail */
390 }
391
392 static VOID __devexit rt2860_remove_one(IN struct pci_dev *pci_dev)
393 {
394         PNET_DEV net_dev = pci_get_drvdata(pci_dev);
395         RTMP_ADAPTER *pAd = NULL;
396         ULONG csr_addr = net_dev->base_addr;    // pAd->CSRBaseAddress;
397
398         GET_PAD_FROM_NET_DEV(pAd, net_dev);
399
400         DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_remove_one\n"));
401
402         if (pAd != NULL) {
403                 // Unregister/Free all allocated net_device.
404                 RtmpPhyNetDevExit(pAd, net_dev);
405
406                 // Unmap CSR base address
407                 iounmap((char *)(csr_addr));
408
409                 // release memory region
410                 release_mem_region(pci_resource_start(pci_dev, 0),
411                                    pci_resource_len(pci_dev, 0));
412
413                 // Free RTMP_ADAPTER related structures.
414                 RtmpRaDevCtrlExit(pAd);
415
416         } else {
417                 // Unregister network device
418                 RtmpOSNetDevDetach(net_dev);
419
420                 // Unmap CSR base address
421                 iounmap((char *)(net_dev->base_addr));
422
423                 // release memory region
424                 release_mem_region(pci_resource_start(pci_dev, 0),
425                                    pci_resource_len(pci_dev, 0));
426         }
427
428         // Free the root net_device
429         RtmpOSNetDevFree(net_dev);
430
431 }
432
433 /*
434 ========================================================================
435 Routine Description:
436     Check the chipset vendor/product ID.
437
438 Arguments:
439     _dev_p                              Point to the PCI or USB device
440
441 Return Value:
442     TRUE                                Check ok
443         FALSE                           Check fail
444
445 Note:
446 ========================================================================
447 */
448 BOOLEAN RT28XXChipsetCheck(IN void *_dev_p)
449 {
450         /* always TRUE */
451         return TRUE;
452 }
453
454 /***************************************************************************
455  *
456  *      PCIe device initialization related procedures.
457  *
458  ***************************************************************************/
459 static VOID RTMPInitPCIeDevice(IN struct pci_dev *pci_dev, IN PRTMP_ADAPTER pAd)
460 {
461         USHORT device_id;
462         POS_COOKIE pObj;
463
464         pObj = (POS_COOKIE) pAd->OS_Cookie;
465         pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id);
466         device_id = le2cpu16(device_id);
467         pObj->DeviceID = device_id;
468         if (
469 #ifdef RT2860
470                    (device_id == NIC2860_PCIe_DEVICE_ID) ||
471                    (device_id == NIC2790_PCIe_DEVICE_ID) ||
472                    (device_id == VEN_AWT_PCIe_DEVICE_ID) ||
473 #endif
474 #ifdef RT3090
475                    (device_id == NIC3090_PCIe_DEVICE_ID) ||
476                    (device_id == NIC3091_PCIe_DEVICE_ID) ||
477                    (device_id == NIC3092_PCIe_DEVICE_ID) ||
478 #endif // RT3090 //
479                    0) {
480                 UINT32 MacCsr0 = 0, Index = 0;
481                 do {
482                         RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0);
483
484                         if ((MacCsr0 != 0x00) && (MacCsr0 != 0xFFFFFFFF))
485                                 break;
486
487                         RTMPusecDelay(10);
488                 } while (Index++ < 100);
489
490                 // Support advanced power save after 2892/2790.
491                 // MAC version at offset 0x1000 is 0x2872XXXX/0x2870XXXX(PCIe, USB, SDIO).
492                 if ((MacCsr0 & 0xffff0000) != 0x28600000) {
493                         OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PCIE_DEVICE);
494                 }
495         }
496 }
497
498 VOID RTMPInitPCIeLinkCtrlValue(IN PRTMP_ADAPTER pAd)
499 {
500         INT pos;
501         USHORT reg16, data2, PCIePowerSaveLevel, Configuration;
502         UINT32 MacValue;
503         BOOLEAN bFindIntel = FALSE;
504         POS_COOKIE pObj;
505
506         pObj = (POS_COOKIE) pAd->OS_Cookie;
507
508         if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
509                 return;
510
511         DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __func__));
512         // Init EEPROM, and save settings
513         if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) {
514                 RT28xx_EEPROM_READ16(pAd, 0x22, PCIePowerSaveLevel);
515                 pAd->PCIePowerSaveLevel = PCIePowerSaveLevel & 0xff;
516
517                 pAd->LnkCtrlBitMask = 0;
518                 if ((PCIePowerSaveLevel & 0xff) == 0xff) {
519                         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_PCIE_DEVICE);
520                         DBGPRINT(RT_DEBUG_TRACE,
521                                  ("====> PCIePowerSaveLevel = 0x%x.\n",
522                                   PCIePowerSaveLevel));
523                         return;
524                 } else {
525                         PCIePowerSaveLevel &= 0x3;
526                         RT28xx_EEPROM_READ16(pAd, 0x24, data2);
527
528                         if (!
529                             (((data2 & 0xff00) == 0x9200)
530                              && ((data2 & 0x80) != 0))) {
531                                 if (PCIePowerSaveLevel > 1)
532                                         PCIePowerSaveLevel = 1;
533                         }
534
535                         DBGPRINT(RT_DEBUG_TRACE,
536                                  ("====> Write 0x83 = 0x%x.\n",
537                                   PCIePowerSaveLevel));
538                         AsicSendCommandToMcu(pAd, 0x83, 0xff,
539                                              (UCHAR) PCIePowerSaveLevel, 0x00);
540                         RT28xx_EEPROM_READ16(pAd, 0x22, PCIePowerSaveLevel);
541                         PCIePowerSaveLevel &= 0xff;
542                         PCIePowerSaveLevel = PCIePowerSaveLevel >> 6;
543                         switch (PCIePowerSaveLevel) {
544                         case 0: // Only support L0
545                                 pAd->LnkCtrlBitMask = 0;
546                                 break;
547                         case 1: // Only enable L0s
548                                 pAd->LnkCtrlBitMask = 1;
549                                 break;
550                         case 2: // enable L1, L0s
551                                 pAd->LnkCtrlBitMask = 3;
552                                 break;
553                         case 3: // sync with host clk and enable L1, L0s
554                                 pAd->LnkCtrlBitMask = 0x103;
555                                 break;
556                         }
557                         RT28xx_EEPROM_READ16(pAd, 0x24, data2);
558                         if ((PCIePowerSaveLevel & 0xff) != 0xff) {
559                                 PCIePowerSaveLevel &= 0x3;
560
561                                 if (!
562                                     (((data2 & 0xff00) == 0x9200)
563                                      && ((data2 & 0x80) != 0))) {
564                                         if (PCIePowerSaveLevel > 1)
565                                                 PCIePowerSaveLevel = 1;
566                                 }
567
568                                 DBGPRINT(RT_DEBUG_TRACE,
569                                          ("====> rt28xx Write 0x83 Command = 0x%x.\n",
570                                           PCIePowerSaveLevel));
571
572                                 AsicSendCommandToMcu(pAd, 0x83, 0xff,
573                                                      (UCHAR) PCIePowerSaveLevel,
574                                                      0x00);
575                         }
576                         DBGPRINT(RT_DEBUG_TRACE,
577                                  ("====> LnkCtrlBitMask = 0x%x.\n",
578                                   pAd->LnkCtrlBitMask));
579                 }
580         } else if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) {
581                 UCHAR LinkCtrlSetting = 0;
582
583                 // Check 3090E special setting chip.
584                 RT28xx_EEPROM_READ16(pAd, 0x24, data2);
585                 if ((data2 == 0x9280) && ((pAd->MACVersion & 0xffff) == 0x0211)) {
586                         pAd->b3090ESpecialChip = TRUE;
587                         DBGPRINT_RAW(RT_DEBUG_ERROR, ("Special 3090E chip \n"));
588                 }
589
590                 RTMP_IO_READ32(pAd, AUX_CTRL, &MacValue);
591                 //enable WAKE_PCIE function, which forces to enable PCIE clock when mpu interrupt asserting.
592                 //Force PCIE 125MHz CLK to toggle
593                 MacValue |= 0x402;
594                 RTMP_IO_WRITE32(pAd, AUX_CTRL, MacValue);
595                 DBGPRINT_RAW(RT_DEBUG_ERROR,
596                              (" AUX_CTRL = 0x%32x\n", MacValue));
597
598                 // for RT30xx F and after, PCIe infterface, and for power solution 3
599                 if ((IS_VERSION_AFTER_F(pAd))
600                     && (pAd->StaCfg.PSControl.field.rt30xxPowerMode >= 2)
601                     && (pAd->StaCfg.PSControl.field.rt30xxPowerMode <= 3)) {
602                         RTMP_IO_READ32(pAd, AUX_CTRL, &MacValue);
603                         DBGPRINT_RAW(RT_DEBUG_ERROR,
604                                      (" Read AUX_CTRL = 0x%x\n", MacValue));
605                         // turn on bit 12.
606                         //enable 32KHz clock mode for power saving
607                         MacValue |= 0x1000;
608                         if (MacValue != 0xffffffff) {
609                                 RTMP_IO_WRITE32(pAd, AUX_CTRL, MacValue);
610                                 DBGPRINT_RAW(RT_DEBUG_ERROR,
611                                              (" Write AUX_CTRL = 0x%x\n",
612                                               MacValue));
613                                 // 1. if use PCIePowerSetting is 2 or 3, need to program OSC_CTRL to 0x3ff11.
614                                 MacValue = 0x3ff11;
615                                 RTMP_IO_WRITE32(pAd, OSC_CTRL, MacValue);
616                                 DBGPRINT_RAW(RT_DEBUG_ERROR,
617                                              (" OSC_CTRL = 0x%x\n", MacValue));
618                                 // 2. Write PCI register Clk ref bit
619                                 RTMPrt3xSetPCIePowerLinkCtrl(pAd);
620                         } else {
621                                 // Error read Aux_Ctrl value.  Force to use solution 1
622                                 DBGPRINT(RT_DEBUG_ERROR,
623                                          (" Error Value in AUX_CTRL = 0x%x\n",
624                                           MacValue));
625                                 pAd->StaCfg.PSControl.field.rt30xxPowerMode = 1;
626                                 DBGPRINT(RT_DEBUG_ERROR,
627                                          (" Force to use power solution1 \n"));
628                         }
629                 }
630                 // 1. read setting from inf file.
631
632                 PCIePowerSaveLevel =
633                     (USHORT) pAd->StaCfg.PSControl.field.rt30xxPowerMode;
634                 DBGPRINT(RT_DEBUG_ERROR,
635                          ("====> rt30xx Read PowerLevelMode =  0x%x.\n",
636                           PCIePowerSaveLevel));
637                 // 2. Check EnableNewPS.
638                 if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE)
639                         PCIePowerSaveLevel = 1;
640
641                 if (IS_VERSION_BEFORE_F(pAd)
642                     && (pAd->b3090ESpecialChip == FALSE)) {
643                         // Chip Version E only allow 1, So force set 1.
644                         PCIePowerSaveLevel &= 0x1;
645                         pAd->PCIePowerSaveLevel = (USHORT) PCIePowerSaveLevel;
646                         DBGPRINT(RT_DEBUG_TRACE,
647                                  ("====> rt30xx E Write 0x83 Command = 0x%x.\n",
648                                   PCIePowerSaveLevel));
649
650                         AsicSendCommandToMcu(pAd, 0x83, 0xff,
651                                              (UCHAR) PCIePowerSaveLevel, 0x00);
652                 } else {
653                         // Chip Version F and after only allow 1 or 2 or 3. This might be modified after new chip version come out.
654                         if (!
655                             ((PCIePowerSaveLevel == 1)
656                              || (PCIePowerSaveLevel == 3)))
657                                 PCIePowerSaveLevel = 1;
658                         DBGPRINT(RT_DEBUG_ERROR,
659                                  ("====> rt30xx F Write 0x83 Command = 0x%x.\n",
660                                   PCIePowerSaveLevel));
661                         pAd->PCIePowerSaveLevel = (USHORT) PCIePowerSaveLevel;
662                         // for 3090F , we need to add high-byte arg for 0x83 command to indicate the link control setting in
663                         // PCI Configuration Space. Because firmware can't read PCI Configuration Space
664                         if ((pAd->Rt3xxRalinkLinkCtrl & 0x2)
665                             && (pAd->Rt3xxHostLinkCtrl & 0x2)) {
666                                 LinkCtrlSetting = 1;
667                         }
668                         DBGPRINT(RT_DEBUG_TRACE,
669                                  ("====> rt30xxF LinkCtrlSetting = 0x%x.\n",
670                                   LinkCtrlSetting));
671                         AsicSendCommandToMcu(pAd, 0x83, 0xff,
672                                              (UCHAR) PCIePowerSaveLevel,
673                                              LinkCtrlSetting);
674                 }
675         }
676         // Find Ralink PCIe Device's Express Capability Offset
677         pos = pci_find_capability(pObj->pci_dev, PCI_CAP_ID_EXP);
678
679         if (pos != 0) {
680                 // Ralink PCIe Device's Link Control Register Offset
681                 pAd->RLnkCtrlOffset = pos + PCI_EXP_LNKCTL;
682                 pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset,
683                                      &reg16);
684                 Configuration = le2cpu16(reg16);
685                 DBGPRINT(RT_DEBUG_TRACE,
686                          ("Read (Ralink PCIe Link Control Register) offset 0x%x = 0x%x\n",
687                           pAd->RLnkCtrlOffset, Configuration));
688                 pAd->RLnkCtrlConfiguration = (Configuration & 0x103);
689                 Configuration &= 0xfefc;
690                 Configuration |= (0x0);
691 #ifdef RT2860
692                 if ((pObj->DeviceID == NIC2860_PCIe_DEVICE_ID)
693                     || (pObj->DeviceID == NIC2790_PCIe_DEVICE_ID)) {
694                         reg16 = cpu2le16(Configuration);
695                         pci_write_config_word(pObj->pci_dev,
696                                               pAd->RLnkCtrlOffset, reg16);
697                         DBGPRINT(RT_DEBUG_TRACE,
698                                  ("Write (Ralink PCIe Link Control Register)  offset 0x%x = 0x%x\n",
699                                   pos + PCI_EXP_LNKCTL, Configuration));
700                 }
701 #endif // RT2860 //
702
703                 RTMPFindHostPCIDev(pAd);
704                 if (pObj->parent_pci_dev) {
705                         USHORT vendor_id;
706
707                         pci_read_config_word(pObj->parent_pci_dev,
708                                              PCI_VENDOR_ID, &vendor_id);
709                         vendor_id = le2cpu16(vendor_id);
710                         if (vendor_id == PCIBUS_INTEL_VENDOR) {
711                                 bFindIntel = TRUE;
712                                 RTMP_SET_PSFLAG(pAd, fRTMP_PS_TOGGLE_L1);
713                         }
714                         // Find PCI-to-PCI Bridge Express Capability Offset
715                         pos =
716                             pci_find_capability(pObj->parent_pci_dev,
717                                                 PCI_CAP_ID_EXP);
718
719                         if (pos != 0) {
720                                 BOOLEAN bChange = FALSE;
721                                 // PCI-to-PCI Bridge Link Control Register Offset
722                                 pAd->HostLnkCtrlOffset = pos + PCI_EXP_LNKCTL;
723                                 pci_read_config_word(pObj->parent_pci_dev,
724                                                      pAd->HostLnkCtrlOffset,
725                                                      &reg16);
726                                 Configuration = le2cpu16(reg16);
727                                 DBGPRINT(RT_DEBUG_TRACE,
728                                          ("Read (Host PCI-to-PCI Bridge Link Control Register) offset 0x%x = 0x%x\n",
729                                           pAd->HostLnkCtrlOffset,
730                                           Configuration));
731                                 pAd->HostLnkCtrlConfiguration =
732                                     (Configuration & 0x103);
733                                 Configuration &= 0xfefc;
734                                 Configuration |= (0x0);
735
736                                 switch (pObj->DeviceID) {
737 #ifdef RT2860
738                                 case NIC2860_PCIe_DEVICE_ID:
739                                 case NIC2790_PCIe_DEVICE_ID:
740                                         bChange = TRUE;
741                                         break;
742 #endif // RT2860 //
743 #ifdef RT3090
744                                 case NIC3090_PCIe_DEVICE_ID:
745                                 case NIC3091_PCIe_DEVICE_ID:
746                                 case NIC3092_PCIe_DEVICE_ID:
747                                         if (bFindIntel == FALSE)
748                                                 bChange = TRUE;
749                                         break;
750 #endif // RT3090 //
751                                 default:
752                                         break;
753                                 }
754
755                                 if (bChange) {
756                                         reg16 = cpu2le16(Configuration);
757                                         pci_write_config_word(pObj->
758                                                               parent_pci_dev,
759                                                               pAd->
760                                                               HostLnkCtrlOffset,
761                                                               reg16);
762                                         DBGPRINT(RT_DEBUG_TRACE,
763                                                  ("Write (Host PCI-to-PCI Bridge Link Control Register) offset 0x%x = 0x%x\n",
764                                                   pAd->HostLnkCtrlOffset,
765                                                   Configuration));
766                                 }
767                         } else {
768                                 pAd->HostLnkCtrlOffset = 0;
769                                 DBGPRINT(RT_DEBUG_ERROR,
770                                          ("%s: cannot find PCI-to-PCI Bridge PCI Express Capability!\n",
771                                           __func__));
772                         }
773                 }
774         } else {
775                 pAd->RLnkCtrlOffset = 0;
776                 pAd->HostLnkCtrlOffset = 0;
777                 DBGPRINT(RT_DEBUG_ERROR,
778                          ("%s: cannot find Ralink PCIe Device's PCI Express Capability!\n",
779                           __func__));
780         }
781
782         if (bFindIntel == FALSE) {
783                 DBGPRINT(RT_DEBUG_TRACE,
784                          ("Doesn't find Intel PCI host controller. \n"));
785                 // Doesn't switch L0, L1, So set PCIePowerSaveLevel to 0xff
786                 pAd->PCIePowerSaveLevel = 0xff;
787                 if ((pAd->RLnkCtrlOffset != 0)
788 #ifdef RT3090
789                     && ((pObj->DeviceID == NIC3090_PCIe_DEVICE_ID)
790                         || (pObj->DeviceID == NIC3091_PCIe_DEVICE_ID)
791                         || (pObj->DeviceID == NIC3092_PCIe_DEVICE_ID))
792 #endif // RT3090 //
793                     ) {
794                         pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset,
795                                              &reg16);
796                         Configuration = le2cpu16(reg16);
797                         DBGPRINT(RT_DEBUG_TRACE,
798                                  ("Read (Ralink 30xx PCIe Link Control Register) offset 0x%x = 0x%x\n",
799                                   pAd->RLnkCtrlOffset, Configuration));
800                         pAd->RLnkCtrlConfiguration = (Configuration & 0x103);
801                         Configuration &= 0xfefc;
802                         Configuration |= (0x0);
803                         reg16 = cpu2le16(Configuration);
804                         pci_write_config_word(pObj->pci_dev,
805                                               pAd->RLnkCtrlOffset, reg16);
806                         DBGPRINT(RT_DEBUG_TRACE,
807                                  ("Write (Ralink PCIe Link Control Register)  offset 0x%x = 0x%x\n",
808                                   pos + PCI_EXP_LNKCTL, Configuration));
809                 }
810         }
811 }
812
813 VOID RTMPFindHostPCIDev(IN PRTMP_ADAPTER pAd)
814 {
815         USHORT reg16;
816         UCHAR reg8;
817         UINT DevFn;
818         PPCI_DEV pPci_dev;
819         POS_COOKIE pObj;
820
821         pObj = (POS_COOKIE) pAd->OS_Cookie;
822
823         if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
824                 return;
825
826         DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __func__));
827
828         pObj->parent_pci_dev = NULL;
829         if (pObj->pci_dev->bus->parent) {
830                 for (DevFn = 0; DevFn < 255; DevFn++) {
831                         pPci_dev =
832                             pci_get_slot(pObj->pci_dev->bus->parent, DevFn);
833                         if (pPci_dev) {
834                                 pci_read_config_word(pPci_dev, PCI_CLASS_DEVICE,
835                                                      &reg16);
836                                 reg16 = le2cpu16(reg16);
837                                 pci_read_config_byte(pPci_dev, PCI_CB_CARD_BUS,
838                                                      &reg8);
839                                 if ((reg16 == PCI_CLASS_BRIDGE_PCI)
840                                     && (reg8 == pObj->pci_dev->bus->number)) {
841                                         pObj->parent_pci_dev = pPci_dev;
842                                 }
843                         }
844                 }
845         }
846 }
847
848 /*
849         ========================================================================
850
851         Routine Description:
852
853         Arguments:
854                 Level = RESTORE_HALT : Restore PCI host and Ralink PCIe Link Control field to its default value.
855                 Level = Other Value : Restore from dot11 power save or radio off status. And force PCI host Link Control fields to 0x1
856
857         ========================================================================
858 */
859 VOID RTMPPCIeLinkCtrlValueRestore(IN PRTMP_ADAPTER pAd, IN UCHAR Level)
860 {
861         USHORT PCIePowerSaveLevel, reg16;
862         USHORT Configuration;
863         POS_COOKIE pObj;
864
865         pObj = (POS_COOKIE) pAd->OS_Cookie;
866
867         if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
868                 return;
869
870 #ifdef RT2860
871         if (!((pObj->DeviceID == NIC2860_PCIe_DEVICE_ID)
872               || (pObj->DeviceID == NIC2790_PCIe_DEVICE_ID)))
873                 return;
874 #endif // RT2860 //
875         // Check PSControl Configuration
876         if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE)
877                 return;
878
879         //3090 will not execute the following codes.
880         // Check interface : If not PCIe interface, return.
881
882 #ifdef RT3090
883         if ((pObj->DeviceID == NIC3090_PCIe_DEVICE_ID)
884             || (pObj->DeviceID == NIC3091_PCIe_DEVICE_ID)
885             || (pObj->DeviceID == NIC3092_PCIe_DEVICE_ID))
886                 return;
887 #endif // RT3090 //
888
889         DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __func__));
890         PCIePowerSaveLevel = pAd->PCIePowerSaveLevel;
891         if ((PCIePowerSaveLevel & 0xff) == 0xff) {
892                 DBGPRINT(RT_DEBUG_TRACE, ("return  \n"));
893                 return;
894         }
895
896         if (pObj->parent_pci_dev && (pAd->HostLnkCtrlOffset != 0)) {
897                 PCI_REG_READ_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset,
898                                   Configuration);
899                 if ((Configuration != 0) && (Configuration != 0xFFFF)) {
900                         Configuration &= 0xfefc;
901                         // If call from interface down, restore to orginial setting.
902                         if (Level == RESTORE_CLOSE) {
903                                 Configuration |= pAd->HostLnkCtrlConfiguration;
904                         } else
905                                 Configuration |= 0x0;
906                         PCI_REG_WIRTE_WORD(pObj->parent_pci_dev,
907                                            pAd->HostLnkCtrlOffset,
908                                            Configuration);
909                         DBGPRINT(RT_DEBUG_TRACE,
910                                  ("Restore PCI host : offset 0x%x = 0x%x\n",
911                                   pAd->HostLnkCtrlOffset, Configuration));
912                 } else
913                         DBGPRINT(RT_DEBUG_ERROR,
914                                  ("Restore PCI host : PCI_REG_READ_WORD failed (Configuration = 0x%x)\n",
915                                   Configuration));
916         }
917
918         if (pObj->pci_dev && (pAd->RLnkCtrlOffset != 0)) {
919                 PCI_REG_READ_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset,
920                                   Configuration);
921                 if ((Configuration != 0) && (Configuration != 0xFFFF)) {
922                         Configuration &= 0xfefc;
923                         // If call from interface down, restore to orginial setting.
924                         if (Level == RESTORE_CLOSE)
925                                 Configuration |= pAd->RLnkCtrlConfiguration;
926                         else
927                                 Configuration |= 0x0;
928                         PCI_REG_WIRTE_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset,
929                                            Configuration);
930                         DBGPRINT(RT_DEBUG_TRACE,
931                                  ("Restore Ralink : offset 0x%x = 0x%x\n",
932                                   pAd->RLnkCtrlOffset, Configuration));
933                 } else
934                         DBGPRINT(RT_DEBUG_ERROR,
935                                  ("Restore Ralink : PCI_REG_READ_WORD failed (Configuration = 0x%x)\n",
936                                   Configuration));
937         }
938
939         DBGPRINT(RT_DEBUG_TRACE, ("%s <===\n", __func__));
940 }
941
942 /*
943         ========================================================================
944
945         Routine Description:
946
947         Arguments:
948                 Max : limit Host PCI and Ralink PCIe device's LINK CONTROL field's value.
949                 Because now frequently set our device to mode 1 or mode 3 will cause problem.
950
951         ========================================================================
952 */
953 VOID RTMPPCIeLinkCtrlSetting(IN PRTMP_ADAPTER pAd, IN USHORT Max)
954 {
955         USHORT PCIePowerSaveLevel, reg16;
956         USHORT Configuration;
957         POS_COOKIE pObj;
958
959         pObj = (POS_COOKIE) pAd->OS_Cookie;
960
961         if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
962                 return;
963
964 #ifdef RT2860
965         if (!((pObj->DeviceID == NIC2860_PCIe_DEVICE_ID)
966               || (pObj->DeviceID == NIC2790_PCIe_DEVICE_ID)))
967                 return;
968 #endif // RT2860 //
969         // Check PSControl Configuration
970         if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE)
971                 return;
972
973         // Check interface : If not PCIe interface, return.
974         //Block 3090 to enter the following function
975
976 #ifdef RT3090
977         if ((pObj->DeviceID == NIC3090_PCIe_DEVICE_ID)
978             || (pObj->DeviceID == NIC3091_PCIe_DEVICE_ID)
979             || (pObj->DeviceID == NIC3092_PCIe_DEVICE_ID))
980                 return;
981 #endif // RT3090 //
982         if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)) {
983                 DBGPRINT(RT_DEBUG_INFO,
984                          ("RTMPPCIePowerLinkCtrl return on fRTMP_PS_CAN_GO_SLEEP flag\n"));
985                 return;
986         }
987
988         DBGPRINT(RT_DEBUG_TRACE, ("%s===>\n", __func__));
989         PCIePowerSaveLevel = pAd->PCIePowerSaveLevel;
990         if ((PCIePowerSaveLevel & 0xff) == 0xff) {
991                 DBGPRINT(RT_DEBUG_TRACE, ("return  \n"));
992                 return;
993         }
994         PCIePowerSaveLevel = PCIePowerSaveLevel >> 6;
995
996         // Skip non-exist deice right away
997         if (pObj->parent_pci_dev && (pAd->HostLnkCtrlOffset != 0)) {
998                 PCI_REG_READ_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset,
999                                   Configuration);
1000                 switch (PCIePowerSaveLevel) {
1001                 case 0:
1002                         // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 00
1003                         Configuration &= 0xfefc;
1004                         break;
1005                 case 1:
1006                         // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 01
1007                         Configuration &= 0xfefc;
1008                         Configuration |= 0x1;
1009                         break;
1010                 case 2:
1011                         //  Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11
1012                         Configuration &= 0xfefc;
1013                         Configuration |= 0x3;
1014                         break;
1015                 case 3:
1016                         // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 and bit 8 of LinkControl of 2892 to 1
1017                         Configuration &= 0xfefc;
1018                         Configuration |= 0x103;
1019                         break;
1020                 }
1021                 PCI_REG_WIRTE_WORD(pObj->parent_pci_dev, pAd->HostLnkCtrlOffset,
1022                                    Configuration);
1023                 DBGPRINT(RT_DEBUG_TRACE,
1024                          ("Write PCI host offset 0x%x = 0x%x\n",
1025                           pAd->HostLnkCtrlOffset, Configuration));
1026         }
1027
1028         if (pObj->pci_dev && (pAd->RLnkCtrlOffset != 0)) {
1029                 // first 2892 chip not allow to frequently set mode 3. will cause hang problem.
1030                 if (PCIePowerSaveLevel > Max)
1031                         PCIePowerSaveLevel = Max;
1032
1033                 PCI_REG_READ_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset,
1034                                   Configuration);
1035                 switch (PCIePowerSaveLevel) {
1036                 case 0:
1037                         // No PCI power safe
1038                         // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 00 .
1039                         Configuration &= 0xfefc;
1040                         break;
1041                 case 1:
1042                         //  L0
1043                         // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 01 .
1044                         Configuration &= 0xfefc;
1045                         Configuration |= 0x1;
1046                         break;
1047                 case 2:
1048                         // L0 and L1
1049                         //  Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11
1050                         Configuration &= 0xfefc;
1051                         Configuration |= 0x3;
1052                         break;
1053                 case 3:
1054                         // L0 , L1 and clock management.
1055                         // Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 and bit 8 of LinkControl of 2892 to 1
1056                         Configuration &= 0xfefc;
1057                         Configuration |= 0x103;
1058                         pAd->bPCIclkOff = TRUE;
1059                         break;
1060                 }
1061                 PCI_REG_WIRTE_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset,
1062                                    Configuration);
1063                 DBGPRINT(RT_DEBUG_TRACE,
1064                          ("Write Ralink device : offset 0x%x = 0x%x\n",
1065                           pAd->RLnkCtrlOffset, Configuration));
1066         }
1067
1068         DBGPRINT(RT_DEBUG_TRACE, ("RTMPPCIePowerLinkCtrl <==============\n"));
1069 }
1070
1071 /*
1072         ========================================================================
1073
1074         Routine Description:
1075                 1. Write a PCI register for rt30xx power solution 3
1076
1077         ========================================================================
1078 */
1079 VOID RTMPrt3xSetPCIePowerLinkCtrl(IN PRTMP_ADAPTER pAd)
1080 {
1081
1082         ULONG HostConfiguration = 0;
1083         ULONG Configuration;
1084         POS_COOKIE pObj;
1085         INT pos;
1086         USHORT reg16;
1087
1088         pObj = (POS_COOKIE) pAd->OS_Cookie;
1089
1090         DBGPRINT(RT_DEBUG_INFO,
1091                  ("RTMPrt3xSetPCIePowerLinkCtrl.===> %lx\n",
1092                   pAd->StaCfg.PSControl.word));
1093
1094         // Check PSControl Configuration
1095         if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE)
1096                 return;
1097         RTMPFindHostPCIDev(pAd);
1098         if (pObj->parent_pci_dev) {
1099                 // Find PCI-to-PCI Bridge Express Capability Offset
1100                 pos = pci_find_capability(pObj->parent_pci_dev, PCI_CAP_ID_EXP);
1101
1102                 if (pos != 0) {
1103                         pAd->HostLnkCtrlOffset = pos + PCI_EXP_LNKCTL;
1104                 }
1105                 // If configurared to turn on L1.
1106                 HostConfiguration = 0;
1107                 if (pAd->StaCfg.PSControl.field.rt30xxForceASPMTest == 1) {
1108                         DBGPRINT(RT_DEBUG_TRACE, ("Enter,PSM : Force ASPM \n"));
1109
1110                         // Skip non-exist deice right away
1111                         if ((pAd->HostLnkCtrlOffset != 0)) {
1112                                 PCI_REG_READ_WORD(pObj->parent_pci_dev,
1113                                                   pAd->HostLnkCtrlOffset,
1114                                                   HostConfiguration);
1115                                 // Prepare Configuration to write to Host
1116                                 HostConfiguration |= 0x3;
1117                                 PCI_REG_WIRTE_WORD(pObj->parent_pci_dev,
1118                                                    pAd->HostLnkCtrlOffset,
1119                                                    HostConfiguration);
1120                                 pAd->Rt3xxHostLinkCtrl = HostConfiguration;
1121                                 // Because in rt30xxForceASPMTest Mode, Force turn on L0s, L1.
1122                                 // Fix HostConfiguration bit0:1 = 0x3 for later use.
1123                                 HostConfiguration = 0x3;
1124                                 DBGPRINT(RT_DEBUG_TRACE,
1125                                          ("PSM : Force ASPM : "
1126                                           "Host device L1/L0s Value =  0x%lx\n",
1127                                           HostConfiguration));
1128                         }
1129                 } else if (pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM ==
1130                            1) {
1131
1132                         // Skip non-exist deice right away
1133                         if ((pAd->HostLnkCtrlOffset != 0)) {
1134                                 PCI_REG_READ_WORD(pObj->parent_pci_dev,
1135                                                   pAd->HostLnkCtrlOffset,
1136                                                   HostConfiguration);
1137                                 pAd->Rt3xxHostLinkCtrl = HostConfiguration;
1138                                 HostConfiguration &= 0x3;
1139                                 DBGPRINT(RT_DEBUG_TRACE,
1140                                          ("PSM : Follow Host ASPM : "
1141                                           "Host device L1/L0s Value =  0x%lx\n",
1142                                           HostConfiguration));
1143                         }
1144                 }
1145         }
1146         // Prepare to write Ralink setting.
1147         // Find Ralink PCIe Device's Express Capability Offset
1148         pos = pci_find_capability(pObj->pci_dev, PCI_CAP_ID_EXP);
1149
1150         if (pos != 0) {
1151                 // Ralink PCIe Device's Link Control Register Offset
1152                 pAd->RLnkCtrlOffset = pos + PCI_EXP_LNKCTL;
1153                 pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset,
1154                                      &reg16);
1155                 Configuration = le2cpu16(reg16);
1156                 DBGPRINT(RT_DEBUG_TRACE,
1157                          ("Read (Ralink PCIe Link Control Register) "
1158                           "offset 0x%x = 0x%lx\n",
1159                           pAd->RLnkCtrlOffset, Configuration));
1160                 Configuration |= 0x100;
1161                 if ((pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM == 1)
1162                     || (pAd->StaCfg.PSControl.field.rt30xxForceASPMTest == 1)) {
1163                         switch (HostConfiguration) {
1164                         case 0:
1165                                 Configuration &= 0xffffffc;
1166                                 break;
1167                         case 1:
1168                                 Configuration &= 0xffffffc;
1169                                 Configuration |= 0x1;
1170                                 break;
1171                         case 2:
1172                                 Configuration &= 0xffffffc;
1173                                 Configuration |= 0x2;
1174                                 break;
1175                         case 3:
1176                                 Configuration |= 0x3;
1177                                 break;
1178                         }
1179                 }
1180                 reg16 = cpu2le16(Configuration);
1181                 pci_write_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset,
1182                                       reg16);
1183                 pAd->Rt3xxRalinkLinkCtrl = Configuration;
1184                 DBGPRINT(RT_DEBUG_TRACE,
1185                          ("PSM :Write Ralink device L1/L0s Value =  0x%lx\n",
1186                           Configuration));
1187         }
1188         DBGPRINT(RT_DEBUG_INFO,
1189                  ("PSM :RTMPrt3xSetPCIePowerLinkCtrl <==============\n"));
1190 }