]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/rt2860/pci_main_dev.c
Staging: rt28x0: remove typedefs (part one)
[net-next-2.6.git] / drivers / staging / rt2860 / pci_main_dev.c
CommitLineData
ca97b838
BZ
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
9f548a2a
BZ
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. *** */
e44fd1cf
BZ
44MODULE_AUTHOR("Jett Chen <jett_chen@ralinktech.com>");
45MODULE_DESCRIPTION("RT2860/RT3090 Wireless Lan Linux Driver");
46MODULE_LICENSE("GPL");
e20aea64 47MODULE_ALIAS("rt3090sta");
e44fd1cf 48
9f548a2a
BZ
49/* */
50/* Function declarations */
51/* */
ca97b838
BZ
52extern int rt28xx_close(IN struct net_device *net_dev);
53extern int rt28xx_open(struct net_device *net_dev);
54
51126deb
BZ
55static void __devexit rt2860_remove_one(struct pci_dev *pci_dev);
56static int __devinit rt2860_probe(struct pci_dev *pci_dev,
66cd8d6e 57 const struct pci_device_id *ent);
ca97b838
BZ
58static void __exit rt2860_cleanup_module(void);
59static int __init rt2860_init_module(void);
60
51126deb 61static void RTMPInitPCIeDevice(IN struct pci_dev *pci_dev,
66cd8d6e 62 IN PRTMP_ADAPTER pAd);
ca97b838
BZ
63
64#ifdef CONFIG_PM
65static int rt2860_suspend(struct pci_dev *pci_dev, pm_message_t state);
66static int rt2860_resume(struct pci_dev *pci_dev);
9f548a2a 67#endif /* CONFIG_PM // */
ca97b838 68
9f548a2a
BZ
69/* */
70/* Ralink PCI device table, include all supported chipsets */
71/* */
66cd8d6e 72static struct pci_device_id rt2860_pci_tbl[] __devinitdata = {
e44fd1cf 73#ifdef RT2860
9f548a2a 74 {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCI_DEVICE_ID)}, /*RT28602.4G */
ca97b838
BZ
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)},
e44fd1cf
BZ
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)},
9f548a2a 91#endif /* RT3090 // */
e44fd1cf
BZ
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)},
9f548a2a
BZ
96#endif /* RT3390 // */
97 {0,} /* terminate list */
ca97b838
BZ
98};
99
100MODULE_DEVICE_TABLE(pci, rt2860_pci_tbl);
ca97b838
BZ
101#ifdef MODULE_VERSION
102MODULE_VERSION(STA_DRIVER_VERSION);
103#endif
104
9f548a2a
BZ
105/* */
106/* Our PCI driver structure */
107/* */
66cd8d6e
BZ
108static struct pci_driver rt2860_driver = {
109name: "rt2860",
110id_table:rt2860_pci_tbl,
111probe: rt2860_probe,
112remove:__devexit_p(rt2860_remove_one),
ca97b838 113#ifdef CONFIG_PM
66cd8d6e
BZ
114suspend:rt2860_suspend,
115resume:rt2860_resume,
ca97b838
BZ
116#endif
117};
118
ca97b838
BZ
119/***************************************************************************
120 *
121 * PCI device initialization related procedures.
122 *
123 ***************************************************************************/
124#ifdef CONFIG_PM
125
51126deb 126void RT2860RejectPendingPackets(IN PRTMP_ADAPTER pAd)
ca97b838 127{
9f548a2a
BZ
128 /* clear PS packets */
129 /* clear TxSw packets */
ca97b838
BZ
130}
131
66cd8d6e 132static int rt2860_suspend(struct pci_dev *pci_dev, pm_message_t state)
ca97b838
BZ
133{
134 struct net_device *net_dev = pci_get_drvdata(pci_dev);
66cd8d6e 135 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) NULL;
51126deb 136 int retval = 0;
ca97b838 137
ca97b838
BZ
138 DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_suspend()\n"));
139
66cd8d6e 140 if (net_dev == NULL) {
ca97b838 141 DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n"));
66cd8d6e 142 } else {
ca97b838
BZ
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 */
66cd8d6e 148 if (VIRTUAL_IF_NUM(pAd) > 0) {
9f548a2a 149 /* avoid users do suspend after interface is down */
ca97b838 150
9f548a2a 151 /* stop interface */
ca97b838
BZ
152 netif_carrier_off(net_dev);
153 netif_stop_queue(net_dev);
154
9f548a2a 155 /* mark device as removed from system and therefore no longer available */
ca97b838
BZ
156 netif_device_detach(net_dev);
157
9f548a2a 158 /* mark halt flag */
ca97b838
BZ
159 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
160 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
161
9f548a2a 162 /* take down the device */
66cd8d6e 163 rt28xx_close((PNET_DEV) net_dev);
ca97b838
BZ
164
165 RT_MOD_DEC_USE_COUNT();
166 }
167 }
168
9f548a2a
BZ
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 */
ca97b838 172 retval = pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1);
9f548a2a 173 /* save the PCI configuration space of a device before suspending */
ca97b838 174 pci_save_state(pci_dev);
9f548a2a 175 /* disable PCI device after use */
ca97b838
BZ
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
66cd8d6e 184static int rt2860_resume(struct pci_dev *pci_dev)
ca97b838
BZ
185{
186 struct net_device *net_dev = pci_get_drvdata(pci_dev);
66cd8d6e 187 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) NULL;
51126deb 188 int retval;
ca97b838 189
9f548a2a
BZ
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) */
ca97b838
BZ
200 retval = pci_set_power_state(pci_dev, PCI_D0);
201
9f548a2a 202 /* restore the saved state of a PCI device */
ca97b838
BZ
203 pci_restore_state(pci_dev);
204
9f548a2a 205 /* initialize device before it's used by a driver */
66cd8d6e 206 if (pci_enable_device(pci_dev)) {
ca97b838
BZ
207 printk("pci enable fail!\n");
208 return 0;
209 }
210
211 DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_resume()\n"));
212
66cd8d6e 213 if (net_dev == NULL) {
ca97b838 214 DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n"));
66cd8d6e 215 } else
ca97b838
BZ
216 GET_PAD_FROM_NET_DEV(pAd, net_dev);
217
66cd8d6e 218 if (pAd != NULL) {
ca97b838
BZ
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 */
66cd8d6e 222 if (VIRTUAL_IF_NUM(pAd) > 0) {
9f548a2a 223 /* mark device as attached from system and restart if needed */
ca97b838
BZ
224 netif_device_attach(net_dev);
225
66cd8d6e 226 if (rt28xx_open((PNET_DEV) net_dev) != 0) {
9f548a2a 227 /* open fail */
66cd8d6e
BZ
228 DBGPRINT(RT_DEBUG_TRACE,
229 ("<=== rt2860_resume()\n"));
ca97b838
BZ
230 return 0;
231 }
9f548a2a 232 /* increase MODULE use count */
ca97b838
BZ
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}
9f548a2a 247#endif /* CONFIG_PM // */
ca97b838 248
51126deb 249static int __init rt2860_init_module(void)
ca97b838
BZ
250{
251 return pci_register_driver(&rt2860_driver);
252}
253
9f548a2a
BZ
254/* */
255/* Driver module unload function */
256/* */
51126deb 257static void __exit rt2860_cleanup_module(void)
ca97b838 258{
66cd8d6e 259 pci_unregister_driver(&rt2860_driver);
ca97b838
BZ
260}
261
262module_init(rt2860_init_module);
263module_exit(rt2860_cleanup_module);
264
9f548a2a
BZ
265/* */
266/* PCI device probe & initialization function */
267/* */
51126deb 268static int __devinit rt2860_probe(IN struct pci_dev *pci_dev,
66cd8d6e 269 IN const struct pci_device_id *pci_id)
ca97b838 270{
66cd8d6e
BZ
271 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) NULL;
272 struct net_device *net_dev;
51126deb
BZ
273 void *handle;
274 char *print_name;
275 unsigned long csr_addr;
276 int rv = 0;
66cd8d6e 277 RTMP_OS_NETDEV_OP_HOOK netDevHook;
ca97b838
BZ
278
279 DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_probe\n"));
280
9f548a2a
BZ
281/*PCIDevInit============================================== */
282 /* wake up and enable device */
66cd8d6e
BZ
283 if ((rv = pci_enable_device(pci_dev)) != 0) {
284 DBGPRINT(RT_DEBUG_ERROR,
285 ("Enable PCI device failed, errno=%d!\n", rv));
ca97b838
BZ
286 return rv;
287 }
288
51126deb 289 print_name = (char *)pci_name(pci_dev);
ca97b838 290
66cd8d6e
BZ
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));
ca97b838
BZ
294 goto err_out;
295 }
9f548a2a 296 /* map physical address to virtual address for accessing register */
66cd8d6e
BZ
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",
51126deb
BZ
303 print_name, (unsigned long)pci_resource_len(pci_dev, 0),
304 (unsigned long)pci_resource_start(pci_dev, 0)));
ca97b838 305 goto err_out_free_res;
66cd8d6e
BZ
306 } else {
307 DBGPRINT(RT_DEBUG_TRACE,
308 ("%s: at 0x%lx, VA 0x%lx, IRQ %d. \n", print_name,
51126deb
BZ
309 (unsigned long)pci_resource_start(pci_dev, 0),
310 (unsigned long)csr_addr, pci_dev->irq));
ca97b838
BZ
311 }
312
9f548a2a 313 /* Set DMA master */
ca97b838
BZ
314 pci_set_master(pci_dev);
315
9f548a2a
BZ
316/*RtmpDevInit============================================== */
317 /* Allocate RTMP_ADAPTER adapter structure */
ca97b838 318 handle = kmalloc(sizeof(struct os_cookie), GFP_KERNEL);
66cd8d6e
BZ
319 if (handle == NULL) {
320 DBGPRINT(RT_DEBUG_ERROR,
321 ("%s(): Allocate memory for os handle failed!\n",
322 __func__));
ca97b838
BZ
323 goto err_out_iounmap;
324 }
325
66cd8d6e 326 ((POS_COOKIE) handle)->pci_dev = pci_dev;
ca97b838 327
9f548a2a 328 rv = RTMPAllocAdapterBlock(handle, &pAd); /*shiang: we may need the pci_dev for allocate structure of "RTMP_ADAPTER" */
ca97b838
BZ
329 if (rv != NDIS_STATUS_SUCCESS)
330 goto err_out_iounmap;
9f548a2a 331 /* Here are the RTMP_ADAPTER structure with pci-bus specific parameters. */
51126deb 332 pAd->CSRBaseAddress = (u8 *)csr_addr;
66cd8d6e
BZ
333 DBGPRINT(RT_DEBUG_ERROR,
334 ("pAd->CSRBaseAddress =0x%lx, csr_addr=0x%lx!\n",
51126deb 335 (unsigned long)pAd->CSRBaseAddress, csr_addr));
ca97b838
BZ
336 RtmpRaDevCtrlInit(pAd, RTMP_DEV_INF_PCI);
337
9f548a2a 338/*NetDevInit============================================== */
ca97b838
BZ
339 net_dev = RtmpPhyNetDevInit(pAd, &netDevHook);
340 if (net_dev == NULL)
341 goto err_out_free_radev;
342
9f548a2a
BZ
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 */
ca97b838
BZ
347
348/* for supporting Network Manager */
349 /* Set the sysfs physical device reference for the network logical device
66cd8d6e 350 * if set prior to registration will cause a symlink during initialization.
ca97b838
BZ
351 */
352 SET_NETDEV_DEV(net_dev, &(pci_dev->dev));
353
9f548a2a
BZ
354/*All done, it's time to register the net device to linux kernel. */
355 /* Register this device */
ca97b838
BZ
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
ca97b838
BZ
363 DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_probe\n"));
364
9f548a2a 365 return 0; /* probe ok */
ca97b838
BZ
366
367 /* --------------------------- ERROR HANDLE --------------------------- */
368err_out_free_netdev:
369 RtmpOSNetDevFree(net_dev);
370
371err_out_free_radev:
66cd8d6e 372 /* free RTMP_ADAPTER strcuture and os_cookie */
ca97b838
BZ
373 RTMPFreeAdapter(pAd);
374
375err_out_iounmap:
376 iounmap((void *)(csr_addr));
66cd8d6e
BZ
377 release_mem_region(pci_resource_start(pci_dev, 0),
378 pci_resource_len(pci_dev, 0));
ca97b838
BZ
379
380err_out_free_res:
381 pci_release_regions(pci_dev);
382
383err_out:
384 pci_disable_device(pci_dev);
385
66cd8d6e
BZ
386 DBGPRINT(RT_DEBUG_ERROR,
387 ("<=== rt2860_probe failed with rv = %d!\n", rv));
ca97b838 388
66cd8d6e 389 return -ENODEV; /* probe fail */
ca97b838
BZ
390}
391
51126deb 392static void __devexit rt2860_remove_one(IN struct pci_dev *pci_dev)
ca97b838 393{
66cd8d6e
BZ
394 PNET_DEV net_dev = pci_get_drvdata(pci_dev);
395 RTMP_ADAPTER *pAd = NULL;
51126deb 396 unsigned long csr_addr = net_dev->base_addr; /* pAd->CSRBaseAddress; */
ca97b838
BZ
397
398 GET_PAD_FROM_NET_DEV(pAd, net_dev);
399
66cd8d6e 400 DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_remove_one\n"));
ca97b838 401
66cd8d6e 402 if (pAd != NULL) {
9f548a2a 403 /* Unregister/Free all allocated net_device. */
ca97b838
BZ
404 RtmpPhyNetDevExit(pAd, net_dev);
405
9f548a2a 406 /* Unmap CSR base address */
ca97b838
BZ
407 iounmap((char *)(csr_addr));
408
9f548a2a 409 /* release memory region */
66cd8d6e
BZ
410 release_mem_region(pci_resource_start(pci_dev, 0),
411 pci_resource_len(pci_dev, 0));
ca97b838 412
9f548a2a 413 /* Free RTMP_ADAPTER related structures. */
ca97b838
BZ
414 RtmpRaDevCtrlExit(pAd);
415
66cd8d6e 416 } else {
9f548a2a 417 /* Unregister network device */
ca97b838
BZ
418 RtmpOSNetDevDetach(net_dev);
419
9f548a2a 420 /* Unmap CSR base address */
ca97b838
BZ
421 iounmap((char *)(net_dev->base_addr));
422
9f548a2a 423 /* release memory region */
66cd8d6e
BZ
424 release_mem_region(pci_resource_start(pci_dev, 0),
425 pci_resource_len(pci_dev, 0));
ca97b838
BZ
426 }
427
9f548a2a 428 /* Free the root net_device */
ca97b838
BZ
429 RtmpOSNetDevFree(net_dev);
430
431}
432
ca97b838
BZ
433/*
434========================================================================
435Routine Description:
436 Check the chipset vendor/product ID.
437
438Arguments:
439 _dev_p Point to the PCI or USB device
440
441Return Value:
442 TRUE Check ok
443 FALSE Check fail
444
445Note:
446========================================================================
447*/
66cd8d6e 448BOOLEAN RT28XXChipsetCheck(IN void *_dev_p)
ca97b838
BZ
449{
450 /* always TRUE */
451 return TRUE;
452}
453
ca97b838
BZ
454/***************************************************************************
455 *
456 * PCIe device initialization related procedures.
457 *
458 ***************************************************************************/
51126deb 459static void RTMPInitPCIeDevice(IN struct pci_dev *pci_dev, IN PRTMP_ADAPTER pAd)
ca97b838 460{
51126deb 461 u16 device_id;
ca97b838
BZ
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;
ca97b838 468 if (
e44fd1cf 469#ifdef RT2860
66cd8d6e
BZ
470 (device_id == NIC2860_PCIe_DEVICE_ID) ||
471 (device_id == NIC2790_PCIe_DEVICE_ID) ||
472 (device_id == VEN_AWT_PCIe_DEVICE_ID) ||
e44fd1cf
BZ
473#endif
474#ifdef RT3090
66cd8d6e
BZ
475 (device_id == NIC3090_PCIe_DEVICE_ID) ||
476 (device_id == NIC3091_PCIe_DEVICE_ID) ||
477 (device_id == NIC3092_PCIe_DEVICE_ID) ||
9f548a2a 478#endif /* RT3090 // */
66cd8d6e 479 0) {
51126deb 480 u32 MacCsr0 = 0, Index = 0;
66cd8d6e 481 do {
ca97b838
BZ
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
9f548a2a
BZ
490 /* Support advanced power save after 2892/2790. */
491 /* MAC version at offset 0x1000 is 0x2872XXXX/0x2870XXXX(PCIe, USB, SDIO). */
66cd8d6e 492 if ((MacCsr0 & 0xffff0000) != 0x28600000) {
e44fd1cf 493 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PCIE_DEVICE);
ca97b838
BZ
494 }
495 }
496}
497
51126deb 498void RTMPInitPCIeLinkCtrlValue(IN PRTMP_ADAPTER pAd)
ca97b838 499{
51126deb
BZ
500 int pos;
501 u16 reg16, data2, PCIePowerSaveLevel, Configuration;
502 u32 MacValue;
66cd8d6e 503 BOOLEAN bFindIntel = FALSE;
ca97b838
BZ
504 POS_COOKIE pObj;
505
506 pObj = (POS_COOKIE) pAd->OS_Cookie;
507
e44fd1cf 508 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
ca97b838
BZ
509 return;
510
66cd8d6e 511 DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __func__));
9f548a2a 512 /* Init EEPROM, and save settings */
66cd8d6e 513 if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) {
ca97b838
BZ
514 RT28xx_EEPROM_READ16(pAd, 0x22, PCIePowerSaveLevel);
515 pAd->PCIePowerSaveLevel = PCIePowerSaveLevel & 0xff;
516
e44fd1cf 517 pAd->LnkCtrlBitMask = 0;
66cd8d6e 518 if ((PCIePowerSaveLevel & 0xff) == 0xff) {
e44fd1cf 519 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_PCIE_DEVICE);
66cd8d6e
BZ
520 DBGPRINT(RT_DEBUG_TRACE,
521 ("====> PCIePowerSaveLevel = 0x%x.\n",
522 PCIePowerSaveLevel));
ca97b838 523 return;
66cd8d6e
BZ
524 } else {
525 PCIePowerSaveLevel &= 0x3;
526 RT28xx_EEPROM_READ16(pAd, 0x24, data2);
ca97b838 527
66cd8d6e
BZ
528 if (!
529 (((data2 & 0xff00) == 0x9200)
530 && ((data2 & 0x80) != 0))) {
531 if (PCIePowerSaveLevel > 1)
532 PCIePowerSaveLevel = 1;
533 }
ca97b838 534
66cd8d6e
BZ
535 DBGPRINT(RT_DEBUG_TRACE,
536 ("====> Write 0x83 = 0x%x.\n",
537 PCIePowerSaveLevel));
538 AsicSendCommandToMcu(pAd, 0x83, 0xff,
51126deb 539 (u8)PCIePowerSaveLevel, 0x00);
66cd8d6e
BZ
540 RT28xx_EEPROM_READ16(pAd, 0x22, PCIePowerSaveLevel);
541 PCIePowerSaveLevel &= 0xff;
542 PCIePowerSaveLevel = PCIePowerSaveLevel >> 6;
543 switch (PCIePowerSaveLevel) {
9f548a2a 544 case 0: /* Only support L0 */
66cd8d6e 545 pAd->LnkCtrlBitMask = 0;
ca97b838 546 break;
9f548a2a 547 case 1: /* Only enable L0s */
66cd8d6e 548 pAd->LnkCtrlBitMask = 1;
ca97b838 549 break;
9f548a2a 550 case 2: /* enable L1, L0s */
66cd8d6e 551 pAd->LnkCtrlBitMask = 3;
ca97b838 552 break;
9f548a2a 553 case 3: /* sync with host clk and enable L1, L0s */
ca97b838
BZ
554 pAd->LnkCtrlBitMask = 0x103;
555 break;
66cd8d6e 556 }
e44fd1cf 557 RT28xx_EEPROM_READ16(pAd, 0x24, data2);
66cd8d6e 558 if ((PCIePowerSaveLevel & 0xff) != 0xff) {
e44fd1cf
BZ
559 PCIePowerSaveLevel &= 0x3;
560
66cd8d6e
BZ
561 if (!
562 (((data2 & 0xff00) == 0x9200)
563 && ((data2 & 0x80) != 0))) {
564 if (PCIePowerSaveLevel > 1)
e44fd1cf
BZ
565 PCIePowerSaveLevel = 1;
566 }
567
66cd8d6e
BZ
568 DBGPRINT(RT_DEBUG_TRACE,
569 ("====> rt28xx Write 0x83 Command = 0x%x.\n",
570 PCIePowerSaveLevel));
e44fd1cf 571
66cd8d6e 572 AsicSendCommandToMcu(pAd, 0x83, 0xff,
51126deb 573 (u8)PCIePowerSaveLevel,
66cd8d6e 574 0x00);
e44fd1cf 575 }
66cd8d6e
BZ
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)) {
51126deb 581 u8 LinkCtrlSetting = 0;
e44fd1cf 582
9f548a2a 583 /* Check 3090E special setting chip. */
66cd8d6e
BZ
584 RT28xx_EEPROM_READ16(pAd, 0x24, data2);
585 if ((data2 == 0x9280) && ((pAd->MACVersion & 0xffff) == 0x0211)) {
e44fd1cf 586 pAd->b3090ESpecialChip = TRUE;
66cd8d6e 587 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Special 3090E chip \n"));
e44fd1cf
BZ
588 }
589
590 RTMP_IO_READ32(pAd, AUX_CTRL, &MacValue);
9f548a2a
BZ
591 /*enable WAKE_PCIE function, which forces to enable PCIE clock when mpu interrupt asserting. */
592 /*Force PCIE 125MHz CLK to toggle */
e44fd1cf
BZ
593 MacValue |= 0x402;
594 RTMP_IO_WRITE32(pAd, AUX_CTRL, MacValue);
66cd8d6e
BZ
595 DBGPRINT_RAW(RT_DEBUG_ERROR,
596 (" AUX_CTRL = 0x%32x\n", MacValue));
e44fd1cf 597
9f548a2a 598 /* for RT30xx F and after, PCIe infterface, and for power solution 3 */
e44fd1cf 599 if ((IS_VERSION_AFTER_F(pAd))
66cd8d6e
BZ
600 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode >= 2)
601 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode <= 3)) {
e44fd1cf 602 RTMP_IO_READ32(pAd, AUX_CTRL, &MacValue);
66cd8d6e
BZ
603 DBGPRINT_RAW(RT_DEBUG_ERROR,
604 (" Read AUX_CTRL = 0x%x\n", MacValue));
9f548a2a
BZ
605 /* turn on bit 12. */
606 /*enable 32KHz clock mode for power saving */
e44fd1cf 607 MacValue |= 0x1000;
66cd8d6e 608 if (MacValue != 0xffffffff) {
e44fd1cf 609 RTMP_IO_WRITE32(pAd, AUX_CTRL, MacValue);
66cd8d6e
BZ
610 DBGPRINT_RAW(RT_DEBUG_ERROR,
611 (" Write AUX_CTRL = 0x%x\n",
612 MacValue));
9f548a2a 613 /* 1. if use PCIePowerSetting is 2 or 3, need to program OSC_CTRL to 0x3ff11. */
e44fd1cf
BZ
614 MacValue = 0x3ff11;
615 RTMP_IO_WRITE32(pAd, OSC_CTRL, MacValue);
66cd8d6e
BZ
616 DBGPRINT_RAW(RT_DEBUG_ERROR,
617 (" OSC_CTRL = 0x%x\n", MacValue));
9f548a2a 618 /* 2. Write PCI register Clk ref bit */
e44fd1cf 619 RTMPrt3xSetPCIePowerLinkCtrl(pAd);
66cd8d6e 620 } else {
9f548a2a 621 /* Error read Aux_Ctrl value. Force to use solution 1 */
66cd8d6e
BZ
622 DBGPRINT(RT_DEBUG_ERROR,
623 (" Error Value in AUX_CTRL = 0x%x\n",
624 MacValue));
e44fd1cf 625 pAd->StaCfg.PSControl.field.rt30xxPowerMode = 1;
66cd8d6e
BZ
626 DBGPRINT(RT_DEBUG_ERROR,
627 (" Force to use power solution1 \n"));
e44fd1cf
BZ
628 }
629 }
9f548a2a 630 /* 1. read setting from inf file. */
e44fd1cf 631
66cd8d6e 632 PCIePowerSaveLevel =
51126deb 633 (u16)pAd->StaCfg.PSControl.field.rt30xxPowerMode;
66cd8d6e
BZ
634 DBGPRINT(RT_DEBUG_ERROR,
635 ("====> rt30xx Read PowerLevelMode = 0x%x.\n",
636 PCIePowerSaveLevel));
9f548a2a 637 /* 2. Check EnableNewPS. */
ca97b838 638 if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE)
e44fd1cf 639 PCIePowerSaveLevel = 1;
ca97b838 640
66cd8d6e
BZ
641 if (IS_VERSION_BEFORE_F(pAd)
642 && (pAd->b3090ESpecialChip == FALSE)) {
9f548a2a 643 /* Chip Version E only allow 1, So force set 1. */
e44fd1cf 644 PCIePowerSaveLevel &= 0x1;
51126deb 645 pAd->PCIePowerSaveLevel = (u16)PCIePowerSaveLevel;
66cd8d6e
BZ
646 DBGPRINT(RT_DEBUG_TRACE,
647 ("====> rt30xx E Write 0x83 Command = 0x%x.\n",
648 PCIePowerSaveLevel));
649
650 AsicSendCommandToMcu(pAd, 0x83, 0xff,
51126deb 651 (u8)PCIePowerSaveLevel, 0x00);
66cd8d6e 652 } else {
9f548a2a 653 /* Chip Version F and after only allow 1 or 2 or 3. This might be modified after new chip version come out. */
66cd8d6e
BZ
654 if (!
655 ((PCIePowerSaveLevel == 1)
656 || (PCIePowerSaveLevel == 3)))
e44fd1cf 657 PCIePowerSaveLevel = 1;
66cd8d6e
BZ
658 DBGPRINT(RT_DEBUG_ERROR,
659 ("====> rt30xx F Write 0x83 Command = 0x%x.\n",
660 PCIePowerSaveLevel));
51126deb 661 pAd->PCIePowerSaveLevel = (u16)PCIePowerSaveLevel;
9f548a2a
BZ
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 */
66cd8d6e
BZ
664 if ((pAd->Rt3xxRalinkLinkCtrl & 0x2)
665 && (pAd->Rt3xxHostLinkCtrl & 0x2)) {
e44fd1cf
BZ
666 LinkCtrlSetting = 1;
667 }
66cd8d6e
BZ
668 DBGPRINT(RT_DEBUG_TRACE,
669 ("====> rt30xxF LinkCtrlSetting = 0x%x.\n",
670 LinkCtrlSetting));
671 AsicSendCommandToMcu(pAd, 0x83, 0xff,
51126deb 672 (u8)PCIePowerSaveLevel,
66cd8d6e 673 LinkCtrlSetting);
ca97b838 674 }
ca97b838 675 }
9f548a2a 676 /* Find Ralink PCIe Device's Express Capability Offset */
ca97b838
BZ
677 pos = pci_find_capability(pObj->pci_dev, PCI_CAP_ID_EXP);
678
66cd8d6e 679 if (pos != 0) {
9f548a2a 680 /* Ralink PCIe Device's Link Control Register Offset */
66cd8d6e
BZ
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);
e44fd1cf 691#ifdef RT2860
ca97b838 692 if ((pObj->DeviceID == NIC2860_PCIe_DEVICE_ID)
66cd8d6e 693 || (pObj->DeviceID == NIC2790_PCIe_DEVICE_ID)) {
ca97b838 694 reg16 = cpu2le16(Configuration);
66cd8d6e
BZ
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));
ca97b838 700 }
9f548a2a 701#endif /* RT2860 // */
ca97b838 702
66cd8d6e
BZ
703 RTMPFindHostPCIDev(pAd);
704 if (pObj->parent_pci_dev) {
51126deb 705 u16 vendor_id;
ca97b838 706
66cd8d6e
BZ
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 }
9f548a2a 714 /* Find PCI-to-PCI Bridge Express Capability Offset */
66cd8d6e
BZ
715 pos =
716 pci_find_capability(pObj->parent_pci_dev,
717 PCI_CAP_ID_EXP);
718
719 if (pos != 0) {
720 BOOLEAN bChange = FALSE;
9f548a2a 721 /* PCI-to-PCI Bridge Link Control Register Offset */
66cd8d6e
BZ
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);
ca97b838 735
66cd8d6e 736 switch (pObj->DeviceID) {
e44fd1cf 737#ifdef RT2860
ca97b838
BZ
738 case NIC2860_PCIe_DEVICE_ID:
739 case NIC2790_PCIe_DEVICE_ID:
740 bChange = TRUE;
741 break;
9f548a2a 742#endif /* RT2860 // */
e44fd1cf
BZ
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)
66cd8d6e 748 bChange = TRUE;
e44fd1cf 749 break;
9f548a2a 750#endif /* RT3090 // */
ca97b838
BZ
751 default:
752 break;
66cd8d6e 753 }
ca97b838 754
66cd8d6e
BZ
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__));
ca97b838
BZ
772 }
773 }
66cd8d6e
BZ
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"));
9f548a2a 785 /* Doesn't switch L0, L1, So set PCIePowerSaveLevel to 0xff */
ca97b838
BZ
786 pAd->PCIePowerSaveLevel = 0xff;
787 if ((pAd->RLnkCtrlOffset != 0)
e44fd1cf 788#ifdef RT3090
66cd8d6e
BZ
789 && ((pObj->DeviceID == NIC3090_PCIe_DEVICE_ID)
790 || (pObj->DeviceID == NIC3091_PCIe_DEVICE_ID)
791 || (pObj->DeviceID == NIC3092_PCIe_DEVICE_ID))
9f548a2a 792#endif /* RT3090 // */
66cd8d6e
BZ
793 ) {
794 pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset,
795 &reg16);
ca97b838 796 Configuration = le2cpu16(reg16);
66cd8d6e
BZ
797 DBGPRINT(RT_DEBUG_TRACE,
798 ("Read (Ralink 30xx PCIe Link Control Register) offset 0x%x = 0x%x\n",
799 pAd->RLnkCtrlOffset, Configuration));
ca97b838
BZ
800 pAd->RLnkCtrlConfiguration = (Configuration & 0x103);
801 Configuration &= 0xfefc;
802 Configuration |= (0x0);
803 reg16 = cpu2le16(Configuration);
66cd8d6e
BZ
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));
ca97b838
BZ
809 }
810 }
811}
812
51126deb 813void RTMPFindHostPCIDev(IN PRTMP_ADAPTER pAd)
ca97b838 814{
51126deb
BZ
815 u16 reg16;
816 u8 reg8;
817 u32 DevFn;
66cd8d6e
BZ
818 PPCI_DEV pPci_dev;
819 POS_COOKIE pObj;
ca97b838
BZ
820
821 pObj = (POS_COOKIE) pAd->OS_Cookie;
822
e44fd1cf 823 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
ca97b838
BZ
824 return;
825
66cd8d6e
BZ
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 }
ca97b838
BZ
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*/
51126deb 859void RTMPPCIeLinkCtrlValueRestore(IN PRTMP_ADAPTER pAd, u8 Level)
ca97b838 860{
51126deb
BZ
861 u16 PCIePowerSaveLevel, reg16;
862 u16 Configuration;
66cd8d6e 863 POS_COOKIE pObj;
ca97b838
BZ
864
865 pObj = (POS_COOKIE) pAd->OS_Cookie;
866
e44fd1cf 867 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
ca97b838
BZ
868 return;
869
e44fd1cf 870#ifdef RT2860
ca97b838 871 if (!((pObj->DeviceID == NIC2860_PCIe_DEVICE_ID)
66cd8d6e 872 || (pObj->DeviceID == NIC2790_PCIe_DEVICE_ID)))
ca97b838 873 return;
9f548a2a
BZ
874#endif /* RT2860 // */
875 /* Check PSControl Configuration */
e44fd1cf 876 if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE)
ca58fb30 877 return;
e44fd1cf 878
9f548a2a
BZ
879 /*3090 will not execute the following codes. */
880 /* Check interface : If not PCIe interface, return. */
e44fd1cf
BZ
881
882#ifdef RT3090
883 if ((pObj->DeviceID == NIC3090_PCIe_DEVICE_ID)
66cd8d6e
BZ
884 || (pObj->DeviceID == NIC3091_PCIe_DEVICE_ID)
885 || (pObj->DeviceID == NIC3092_PCIe_DEVICE_ID))
e44fd1cf 886 return;
9f548a2a 887#endif /* RT3090 // */
ca97b838
BZ
888
889 DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __func__));
890 PCIePowerSaveLevel = pAd->PCIePowerSaveLevel;
66cd8d6e
BZ
891 if ((PCIePowerSaveLevel & 0xff) == 0xff) {
892 DBGPRINT(RT_DEBUG_TRACE, ("return \n"));
ca97b838
BZ
893 return;
894 }
895
66cd8d6e
BZ
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;
9f548a2a 901 /* If call from interface down, restore to orginial setting. */
66cd8d6e
BZ
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;
9f548a2a 923 /* If call from interface down, restore to orginial setting. */
ca97b838 924 if (Level == RESTORE_CLOSE)
66cd8d6e 925 Configuration |= pAd->RLnkCtrlConfiguration;
ca97b838
BZ
926 else
927 Configuration |= 0x0;
66cd8d6e
BZ
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));
ca97b838
BZ
937 }
938
66cd8d6e 939 DBGPRINT(RT_DEBUG_TRACE, ("%s <===\n", __func__));
ca97b838
BZ
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*/
51126deb 953void RTMPPCIeLinkCtrlSetting(IN PRTMP_ADAPTER pAd, u16 Max)
ca97b838 954{
51126deb
BZ
955 u16 PCIePowerSaveLevel, reg16;
956 u16 Configuration;
66cd8d6e 957 POS_COOKIE pObj;
ca97b838
BZ
958
959 pObj = (POS_COOKIE) pAd->OS_Cookie;
960
e44fd1cf 961 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
ca97b838
BZ
962 return;
963
e44fd1cf 964#ifdef RT2860
ca97b838 965 if (!((pObj->DeviceID == NIC2860_PCIe_DEVICE_ID)
66cd8d6e 966 || (pObj->DeviceID == NIC2790_PCIe_DEVICE_ID)))
ca97b838 967 return;
9f548a2a
BZ
968#endif /* RT2860 // */
969 /* Check PSControl Configuration */
e44fd1cf 970 if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE)
ca58fb30 971 return;
e44fd1cf 972
9f548a2a
BZ
973 /* Check interface : If not PCIe interface, return. */
974 /*Block 3090 to enter the following function */
e44fd1cf
BZ
975
976#ifdef RT3090
977 if ((pObj->DeviceID == NIC3090_PCIe_DEVICE_ID)
66cd8d6e
BZ
978 || (pObj->DeviceID == NIC3091_PCIe_DEVICE_ID)
979 || (pObj->DeviceID == NIC3092_PCIe_DEVICE_ID))
e44fd1cf 980 return;
9f548a2a 981#endif /* RT3090 // */
66cd8d6e
BZ
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"));
e44fd1cf
BZ
985 return;
986 }
ca97b838 987
66cd8d6e 988 DBGPRINT(RT_DEBUG_TRACE, ("%s===>\n", __func__));
ca97b838 989 PCIePowerSaveLevel = pAd->PCIePowerSaveLevel;
66cd8d6e
BZ
990 if ((PCIePowerSaveLevel & 0xff) == 0xff) {
991 DBGPRINT(RT_DEBUG_TRACE, ("return \n"));
ca97b838
BZ
992 return;
993 }
66cd8d6e
BZ
994 PCIePowerSaveLevel = PCIePowerSaveLevel >> 6;
995
9f548a2a 996 /* Skip non-exist deice right away */
66cd8d6e
BZ
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:
9f548a2a 1002 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 00 */
66cd8d6e
BZ
1003 Configuration &= 0xfefc;
1004 break;
1005 case 1:
9f548a2a 1006 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 01 */
66cd8d6e
BZ
1007 Configuration &= 0xfefc;
1008 Configuration |= 0x1;
1009 break;
1010 case 2:
9f548a2a 1011 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 */
66cd8d6e
BZ
1012 Configuration &= 0xfefc;
1013 Configuration |= 0x3;
1014 break;
1015 case 3:
9f548a2a 1016 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 and bit 8 of LinkControl of 2892 to 1 */
66cd8d6e
BZ
1017 Configuration &= 0xfefc;
1018 Configuration |= 0x103;
1019 break;
e44fd1cf 1020 }
66cd8d6e
BZ
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));
e44fd1cf 1026 }
ca97b838 1027
66cd8d6e 1028 if (pObj->pci_dev && (pAd->RLnkCtrlOffset != 0)) {
9f548a2a 1029 /* first 2892 chip not allow to frequently set mode 3. will cause hang problem. */
ca97b838
BZ
1030 if (PCIePowerSaveLevel > Max)
1031 PCIePowerSaveLevel = Max;
1032
66cd8d6e
BZ
1033 PCI_REG_READ_WORD(pObj->pci_dev, pAd->RLnkCtrlOffset,
1034 Configuration);
1035 switch (PCIePowerSaveLevel) {
1036 case 0:
9f548a2a
BZ
1037 /* No PCI power safe */
1038 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 00 . */
66cd8d6e
BZ
1039 Configuration &= 0xfefc;
1040 break;
1041 case 1:
9f548a2a
BZ
1042 /* L0 */
1043 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 01 . */
66cd8d6e
BZ
1044 Configuration &= 0xfefc;
1045 Configuration |= 0x1;
1046 break;
1047 case 2:
9f548a2a
BZ
1048 /* L0 and L1 */
1049 /* Set b0 and b1 of LinkControl (both 2892 and PCIe bridge) to 11 */
66cd8d6e
BZ
1050 Configuration &= 0xfefc;
1051 Configuration |= 0x3;
1052 break;
1053 case 3:
9f548a2a
BZ
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 */
66cd8d6e
BZ
1056 Configuration &= 0xfefc;
1057 Configuration |= 0x103;
1058 pAd->bPCIclkOff = TRUE;
1059 break;
e44fd1cf 1060 }
66cd8d6e
BZ
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));
ca97b838
BZ
1066 }
1067
66cd8d6e 1068 DBGPRINT(RT_DEBUG_TRACE, ("RTMPPCIePowerLinkCtrl <==============\n"));
ca97b838 1069}
e44fd1cf
BZ
1070
1071/*
1072 ========================================================================
1073
1074 Routine Description:
1075 1. Write a PCI register for rt30xx power solution 3
1076
1077 ========================================================================
1078*/
51126deb 1079void RTMPrt3xSetPCIePowerLinkCtrl(IN PRTMP_ADAPTER pAd)
e44fd1cf
BZ
1080{
1081
51126deb
BZ
1082 unsigned long HostConfiguration = 0;
1083 unsigned long Configuration;
66cd8d6e 1084 POS_COOKIE pObj;
51126deb
BZ
1085 int pos;
1086 u16 reg16;
e44fd1cf
BZ
1087
1088 pObj = (POS_COOKIE) pAd->OS_Cookie;
1089
ca58fb30
BZ
1090 DBGPRINT(RT_DEBUG_INFO,
1091 ("RTMPrt3xSetPCIePowerLinkCtrl.===> %lx\n",
1092 pAd->StaCfg.PSControl.word));
e44fd1cf 1093
9f548a2a 1094 /* Check PSControl Configuration */
e44fd1cf
BZ
1095 if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE)
1096 return;
1097 RTMPFindHostPCIDev(pAd);
66cd8d6e 1098 if (pObj->parent_pci_dev) {
9f548a2a 1099 /* Find PCI-to-PCI Bridge Express Capability Offset */
e44fd1cf
BZ
1100 pos = pci_find_capability(pObj->parent_pci_dev, PCI_CAP_ID_EXP);
1101
66cd8d6e 1102 if (pos != 0) {
e44fd1cf
BZ
1103 pAd->HostLnkCtrlOffset = pos + PCI_EXP_LNKCTL;
1104 }
9f548a2a 1105 /* If configurared to turn on L1. */
66cd8d6e
BZ
1106 HostConfiguration = 0;
1107 if (pAd->StaCfg.PSControl.field.rt30xxForceASPMTest == 1) {
1108 DBGPRINT(RT_DEBUG_TRACE, ("Enter,PSM : Force ASPM \n"));
e44fd1cf 1109
9f548a2a 1110 /* Skip non-exist deice right away */
66cd8d6e
BZ
1111 if ((pAd->HostLnkCtrlOffset != 0)) {
1112 PCI_REG_READ_WORD(pObj->parent_pci_dev,
1113 pAd->HostLnkCtrlOffset,
1114 HostConfiguration);
9f548a2a 1115 /* Prepare Configuration to write to Host */
e44fd1cf 1116 HostConfiguration |= 0x3;
66cd8d6e
BZ
1117 PCI_REG_WIRTE_WORD(pObj->parent_pci_dev,
1118 pAd->HostLnkCtrlOffset,
1119 HostConfiguration);
e44fd1cf 1120 pAd->Rt3xxHostLinkCtrl = HostConfiguration;
9f548a2a
BZ
1121 /* Because in rt30xxForceASPMTest Mode, Force turn on L0s, L1. */
1122 /* Fix HostConfiguration bit0:1 = 0x3 for later use. */
e44fd1cf 1123 HostConfiguration = 0x3;
ca58fb30
BZ
1124 DBGPRINT(RT_DEBUG_TRACE,
1125 ("PSM : Force ASPM : "
1126 "Host device L1/L0s Value = 0x%lx\n",
1127 HostConfiguration));
e44fd1cf 1128 }
66cd8d6e
BZ
1129 } else if (pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM ==
1130 1) {
e44fd1cf 1131
9f548a2a 1132 /* Skip non-exist deice right away */
66cd8d6e
BZ
1133 if ((pAd->HostLnkCtrlOffset != 0)) {
1134 PCI_REG_READ_WORD(pObj->parent_pci_dev,
1135 pAd->HostLnkCtrlOffset,
1136 HostConfiguration);
e44fd1cf
BZ
1137 pAd->Rt3xxHostLinkCtrl = HostConfiguration;
1138 HostConfiguration &= 0x3;
ca58fb30
BZ
1139 DBGPRINT(RT_DEBUG_TRACE,
1140 ("PSM : Follow Host ASPM : "
1141 "Host device L1/L0s Value = 0x%lx\n",
1142 HostConfiguration));
e44fd1cf
BZ
1143 }
1144 }
66cd8d6e 1145 }
9f548a2a
BZ
1146 /* Prepare to write Ralink setting. */
1147 /* Find Ralink PCIe Device's Express Capability Offset */
e44fd1cf
BZ
1148 pos = pci_find_capability(pObj->pci_dev, PCI_CAP_ID_EXP);
1149
66cd8d6e 1150 if (pos != 0) {
9f548a2a 1151 /* Ralink PCIe Device's Link Control Register Offset */
66cd8d6e
BZ
1152 pAd->RLnkCtrlOffset = pos + PCI_EXP_LNKCTL;
1153 pci_read_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset,
1154 &reg16);
1155 Configuration = le2cpu16(reg16);
ca58fb30
BZ
1156 DBGPRINT(RT_DEBUG_TRACE,
1157 ("Read (Ralink PCIe Link Control Register) "
1158 "offset 0x%x = 0x%lx\n",
1159 pAd->RLnkCtrlOffset, Configuration));
e44fd1cf
BZ
1160 Configuration |= 0x100;
1161 if ((pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM == 1)
66cd8d6e
BZ
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;
e44fd1cf
BZ
1178 }
1179 }
1180 reg16 = cpu2le16(Configuration);
66cd8d6e
BZ
1181 pci_write_config_word(pObj->pci_dev, pAd->RLnkCtrlOffset,
1182 reg16);
e44fd1cf 1183 pAd->Rt3xxRalinkLinkCtrl = Configuration;
ca58fb30
BZ
1184 DBGPRINT(RT_DEBUG_TRACE,
1185 ("PSM :Write Ralink device L1/L0s Value = 0x%lx\n",
1186 Configuration));
e44fd1cf 1187 }
66cd8d6e
BZ
1188 DBGPRINT(RT_DEBUG_INFO,
1189 ("PSM :RTMPrt3xSetPCIePowerLinkCtrl <==============\n"));
e44fd1cf 1190}