]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/brcm80211/brcmsmac/wlc_bmac.c
staging: brcm80211: removed 'hnd' from filenames
[mv-sheeva.git] / drivers / staging / brcm80211 / brcmsmac / wlc_bmac.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/pci.h>
21 #include <linux/netdevice.h>
22 #include <linux/etherdevice.h>
23
24 #include <proto/802.11.h>
25 #include <bcmdefs.h>
26 #include <bcmdevs.h>
27 #include <bcmwifi.h>
28 #include <aiutils.h>
29 #include <bcmsrom.h>
30 #include <bcmotp.h>
31 #include <bcmutils.h>
32 #include <bcmnvram.h>
33 #include <sbconfig.h>
34 #include <sbchipc.h>
35 #include <pcicfg.h>
36 #include <sbdma.h>
37 #include <bcmdma.h>
38
39 #include "wlc_types.h"
40 #include "wlc_pmu.h"
41 #include "d11.h"
42 #include "wlc_cfg.h"
43 #include "wlc_rate.h"
44 #include "wlc_scb.h"
45 #include "wlc_pub.h"
46 #include "wlc_key.h"
47 #include "phy/wlc_phy_hal.h"
48 #include "wlc_channel.h"
49 #include "wlc_main.h"
50 #include "wl_export.h"
51 #include "wl_ucode.h"
52 #include "wlc_antsel.h"
53 #include "pcie_core.h"
54 #include "wlc_alloc.h"
55 #include "wl_dbg.h"
56 #include "wlc_bmac.h"
57
58 #define TIMER_INTERVAL_WATCHDOG_BMAC    1000    /* watchdog timer, in unit of ms */
59
60 #define SYNTHPU_DLY_APHY_US     3700    /* a phy synthpu_dly time in us */
61 #define SYNTHPU_DLY_BPHY_US     1050    /* b/g phy synthpu_dly time in us, default */
62 #define SYNTHPU_DLY_NPHY_US     2048    /* n phy REV3 synthpu_dly time in us, default */
63 #define SYNTHPU_DLY_LPPHY_US    300     /* lpphy synthpu_dly time in us */
64
65 #define SYNTHPU_DLY_PHY_US_QT   100     /* QT synthpu_dly time in us */
66
67 #ifndef BMAC_DUP_TO_REMOVE
68 #define WLC_RM_WAIT_TX_SUSPEND          4       /* Wait Tx Suspend */
69
70 #define ANTCNT                  10      /* vanilla M_MAX_ANTCNT value */
71
72 #endif                          /* BMAC_DUP_TO_REMOVE */
73
74 #define DMAREG(wlc_hw, direction, fifonum) \
75         ((direction == DMA_TX) ? \
76                 (void *)&(wlc_hw->regs->fifo64regs[fifonum].dmaxmt) : \
77                 (void *)&(wlc_hw->regs->fifo64regs[fifonum].dmarcv))
78
79 /*
80  * The following table lists the buffer memory allocated to xmt fifos in HW.
81  * the size is in units of 256bytes(one block), total size is HW dependent
82  * ucode has default fifo partition, sw can overwrite if necessary
83  *
84  * This is documented in twiki under the topic UcodeTxFifo. Please ensure
85  * the twiki is updated before making changes.
86  */
87
88 #define XMTFIFOTBL_STARTREV     20      /* Starting corerev for the fifo size table */
89
90 static u16 xmtfifo_sz[][NFIFO] = {
91         {20, 192, 192, 21, 17, 5},      /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */
92         {9, 58, 22, 14, 14, 5}, /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */
93         {20, 192, 192, 21, 17, 5},      /* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */
94         {20, 192, 192, 21, 17, 5},      /* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */
95         {9, 58, 22, 14, 14, 5}, /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */
96 };
97
98 static void wlc_clkctl_clk(struct wlc_hw_info *wlc, uint mode);
99 static void wlc_coreinit(struct wlc_info *wlc);
100
101 /* used by wlc_wakeucode_init() */
102 static void wlc_write_inits(struct wlc_hw_info *wlc_hw,
103                             const struct d11init *inits);
104 static void wlc_ucode_write(struct wlc_hw_info *wlc_hw, const u32 ucode[],
105                             const uint nbytes);
106 static void wlc_ucode_download(struct wlc_hw_info *wlc);
107 static void wlc_ucode_txant_set(struct wlc_hw_info *wlc_hw);
108
109 /* used by wlc_dpc() */
110 static bool wlc_bmac_dotxstatus(struct wlc_hw_info *wlc, tx_status_t *txs,
111                                 u32 s2);
112 static bool wlc_bmac_txstatus(struct wlc_hw_info *wlc, bool bound, bool *fatal);
113 static bool wlc_bmac_recv(struct wlc_hw_info *wlc_hw, uint fifo, bool bound);
114
115 /* used by wlc_down() */
116 static void wlc_flushqueues(struct wlc_info *wlc);
117
118 static void wlc_write_mhf(struct wlc_hw_info *wlc_hw, u16 *mhfs);
119 static void wlc_mctrl_reset(struct wlc_hw_info *wlc_hw);
120 static void wlc_corerev_fifofixup(struct wlc_hw_info *wlc_hw);
121 static bool wlc_bmac_tx_fifo_suspended(struct wlc_hw_info *wlc_hw,
122                                        uint tx_fifo);
123 static void wlc_bmac_tx_fifo_suspend(struct wlc_hw_info *wlc_hw, uint tx_fifo);
124 static void wlc_bmac_tx_fifo_resume(struct wlc_hw_info *wlc_hw, uint tx_fifo);
125
126 /* Low Level Prototypes */
127 static int wlc_bmac_bandtype(struct wlc_hw_info *wlc_hw);
128 static void wlc_bmac_info_init(struct wlc_hw_info *wlc_hw);
129 static void wlc_bmac_xtal(struct wlc_hw_info *wlc_hw, bool want);
130 static u16 wlc_bmac_read_objmem(struct wlc_hw_info *wlc_hw, uint offset,
131                                    u32 sel);
132 static void wlc_bmac_write_objmem(struct wlc_hw_info *wlc_hw, uint offset,
133                                   u16 v, u32 sel);
134 static void wlc_bmac_core_phy_clk(struct wlc_hw_info *wlc_hw, bool clk);
135 static bool wlc_bmac_attach_dmapio(struct wlc_info *wlc, uint j, bool wme);
136 static void wlc_bmac_detach_dmapio(struct wlc_hw_info *wlc_hw);
137 static void wlc_ucode_bsinit(struct wlc_hw_info *wlc_hw);
138 static bool wlc_validboardtype(struct wlc_hw_info *wlc);
139 static bool wlc_isgoodchip(struct wlc_hw_info *wlc_hw);
140 static bool wlc_bmac_validate_chip_access(struct wlc_hw_info *wlc_hw);
141 static char *wlc_get_macaddr(struct wlc_hw_info *wlc_hw);
142 static void wlc_mhfdef(struct wlc_info *wlc, u16 *mhfs, u16 mhf2_init);
143 static void wlc_mctrl_write(struct wlc_hw_info *wlc_hw);
144 static void wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool want, mbool flags);
145 static void wlc_ucode_mute_override_set(struct wlc_hw_info *wlc_hw);
146 static void wlc_ucode_mute_override_clear(struct wlc_hw_info *wlc_hw);
147 static u32 wlc_wlintrsoff(struct wlc_info *wlc);
148 static void wlc_wlintrsrestore(struct wlc_info *wlc, u32 macintmask);
149 static void wlc_gpio_init(struct wlc_info *wlc);
150 static void wlc_write_hw_bcntemplate0(struct wlc_hw_info *wlc_hw, void *bcn,
151                                       int len);
152 static void wlc_write_hw_bcntemplate1(struct wlc_hw_info *wlc_hw, void *bcn,
153                                       int len);
154 static void wlc_bmac_bsinit(struct wlc_info *wlc, chanspec_t chanspec);
155 static u32 wlc_setband_inact(struct wlc_info *wlc, uint bandunit);
156 static void wlc_bmac_setband(struct wlc_hw_info *wlc_hw, uint bandunit,
157                              chanspec_t chanspec);
158 static void wlc_bmac_update_slot_timing(struct wlc_hw_info *wlc_hw,
159                                         bool shortslot);
160 static void wlc_upd_ofdm_pctl1_table(struct wlc_hw_info *wlc_hw);
161 static u16 wlc_bmac_ofdm_ratetable_offset(struct wlc_hw_info *wlc_hw,
162                                              u8 rate);
163
164 /* === Low Level functions === */
165
166 void wlc_bmac_set_shortslot(struct wlc_hw_info *wlc_hw, bool shortslot)
167 {
168         wlc_hw->shortslot = shortslot;
169
170         if (BAND_2G(wlc_bmac_bandtype(wlc_hw)) && wlc_hw->up) {
171                 wlc_suspend_mac_and_wait(wlc_hw->wlc);
172                 wlc_bmac_update_slot_timing(wlc_hw, shortslot);
173                 wlc_enable_mac(wlc_hw->wlc);
174         }
175 }
176
177 /*
178  * Update the slot timing for standard 11b/g (20us slots)
179  * or shortslot 11g (9us slots)
180  * The PSM needs to be suspended for this call.
181  */
182 static void wlc_bmac_update_slot_timing(struct wlc_hw_info *wlc_hw,
183                                         bool shortslot)
184 {
185         d11regs_t *regs;
186
187         regs = wlc_hw->regs;
188
189         if (shortslot) {
190                 /* 11g short slot: 11a timing */
191                 W_REG(&regs->ifs_slot, 0x0207); /* APHY_SLOT_TIME */
192                 wlc_bmac_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME);
193         } else {
194                 /* 11g long slot: 11b timing */
195                 W_REG(&regs->ifs_slot, 0x0212); /* BPHY_SLOT_TIME */
196                 wlc_bmac_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME);
197         }
198 }
199
200 static void WLBANDINITFN(wlc_ucode_bsinit) (struct wlc_hw_info *wlc_hw)
201 {
202         struct wiphy *wiphy = wlc_hw->wlc->wiphy;
203
204         /* init microcode host flags */
205         wlc_write_mhf(wlc_hw, wlc_hw->band->mhfs);
206
207         /* do band-specific ucode IHR, SHM, and SCR inits */
208         if (D11REV_IS(wlc_hw->corerev, 23)) {
209                 if (WLCISNPHY(wlc_hw->band)) {
210                         wlc_write_inits(wlc_hw, d11n0bsinitvals16);
211                 } else {
212                         wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
213                                   " %d\n", __func__, wlc_hw->unit,
214                                   wlc_hw->corerev);
215                 }
216         } else {
217                 if (D11REV_IS(wlc_hw->corerev, 24)) {
218                         if (WLCISLCNPHY(wlc_hw->band)) {
219                                 wlc_write_inits(wlc_hw, d11lcn0bsinitvals24);
220                         } else
221                                 wiphy_err(wiphy, "%s: wl%d: unsupported phy in"
222                                           " core rev %d\n", __func__,
223                                           wlc_hw->unit, wlc_hw->corerev);
224                 } else {
225                         wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
226                                 __func__, wlc_hw->unit, wlc_hw->corerev);
227                 }
228         }
229 }
230
231 /* switch to new band but leave it inactive */
232 static u32 WLBANDINITFN(wlc_setband_inact) (struct wlc_info *wlc, uint bandunit)
233 {
234         struct wlc_hw_info *wlc_hw = wlc->hw;
235         u32 macintmask;
236
237         BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
238
239         WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
240
241         /* disable interrupts */
242         macintmask = wl_intrsoff(wlc->wl);
243
244         /* radio off */
245         wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
246
247         wlc_bmac_core_phy_clk(wlc_hw, OFF);
248
249         wlc_setxband(wlc_hw, bandunit);
250
251         return macintmask;
252 }
253
254 /* Process received frames */
255 /*
256  * Return true if more frames need to be processed. false otherwise.
257  * Param 'bound' indicates max. # frames to process before break out.
258  */
259 static bool
260 wlc_bmac_recv(struct wlc_hw_info *wlc_hw, uint fifo, bool bound)
261 {
262         struct sk_buff *p;
263         struct sk_buff *head = NULL;
264         struct sk_buff *tail = NULL;
265         uint n = 0;
266         uint bound_limit = bound ? wlc_hw->wlc->pub->tunables->rxbnd : -1;
267         wlc_d11rxhdr_t *wlc_rxhdr = NULL;
268
269         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
270         /* gather received frames */
271         while ((p = dma_rx(wlc_hw->di[fifo]))) {
272
273                 if (!tail)
274                         head = tail = p;
275                 else {
276                         tail->prev = p;
277                         tail = p;
278                 }
279
280                 /* !give others some time to run! */
281                 if (++n >= bound_limit)
282                         break;
283         }
284
285         /* post more rbufs */
286         dma_rxfill(wlc_hw->di[fifo]);
287
288         /* process each frame */
289         while ((p = head) != NULL) {
290                 head = head->prev;
291                 p->prev = NULL;
292
293                 wlc_rxhdr = (wlc_d11rxhdr_t *) p->data;
294
295                 /* compute the RSSI from d11rxhdr and record it in wlc_rxd11hr */
296                 wlc_phy_rssi_compute(wlc_hw->band->pi, wlc_rxhdr);
297
298                 wlc_recv(wlc_hw->wlc, p);
299         }
300
301         return n >= bound_limit;
302 }
303
304 /* second-level interrupt processing
305  *   Return true if another dpc needs to be re-scheduled. false otherwise.
306  *   Param 'bounded' indicates if applicable loops should be bounded.
307  */
308 bool wlc_dpc(struct wlc_info *wlc, bool bounded)
309 {
310         u32 macintstatus;
311         struct wlc_hw_info *wlc_hw = wlc->hw;
312         d11regs_t *regs = wlc_hw->regs;
313         bool fatal = false;
314         struct wiphy *wiphy = wlc->wiphy;
315
316         if (DEVICEREMOVED(wlc)) {
317                 wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
318                           __func__);
319                 wl_down(wlc->wl);
320                 return false;
321         }
322
323         /* grab and clear the saved software intstatus bits */
324         macintstatus = wlc->macintstatus;
325         wlc->macintstatus = 0;
326
327         BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n",
328                wlc_hw->unit, macintstatus);
329
330         WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */
331
332         /* BCN template is available */
333         /* ZZZ: Use AP_ACTIVE ? */
334         if (AP_ENAB(wlc->pub) && (!APSTA_ENAB(wlc->pub))
335             && (macintstatus & MI_BCNTPL)) {
336                 wlc_update_beacon(wlc);
337         }
338
339         /* PMQ entry addition */
340         if (macintstatus & MI_PMQ) {
341         }
342
343         /* tx status */
344         if (macintstatus & MI_TFS) {
345                 if (wlc_bmac_txstatus(wlc->hw, bounded, &fatal))
346                         wlc->macintstatus |= MI_TFS;
347                 if (fatal) {
348                         wiphy_err(wiphy, "MI_TFS: fatal\n");
349                         goto fatal;
350                 }
351         }
352
353         if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
354                 wlc_tbtt(wlc, regs);
355
356         /* ATIM window end */
357         if (macintstatus & MI_ATIMWINEND) {
358                 BCMMSG(wlc->wiphy, "end of ATIM window\n");
359                 OR_REG(&regs->maccommand, wlc->qvalid);
360                 wlc->qvalid = 0;
361         }
362
363         /* received data or control frame, MI_DMAINT is indication of RX_FIFO interrupt */
364         if (macintstatus & MI_DMAINT) {
365                 if (wlc_bmac_recv(wlc_hw, RX_FIFO, bounded)) {
366                         wlc->macintstatus |= MI_DMAINT;
367                 }
368         }
369
370         /* TX FIFO suspend/flush completion */
371         if (macintstatus & MI_TXSTOP) {
372                 if (wlc_bmac_tx_fifo_suspended(wlc_hw, TX_DATA_FIFO)) {
373                         /* wiphy_err(wiphy, "dpc: fifo_suspend_comlete\n"); */
374                 }
375         }
376
377         /* noise sample collected */
378         if (macintstatus & MI_BG_NOISE) {
379                 wlc_phy_noise_sample_intr(wlc_hw->band->pi);
380         }
381
382         if (macintstatus & MI_GP0) {
383                 wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d "
384                         "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now);
385
386                 printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
387                                         __func__, wlc_hw->sih->chip,
388                                         wlc_hw->sih->chiprev);
389                 /* big hammer */
390                 wl_init(wlc->wl);
391         }
392
393         /* gptimer timeout */
394         if (macintstatus & MI_TO) {
395                 W_REG(&regs->gptimer, 0);
396         }
397
398         if (macintstatus & MI_RFDISABLE) {
399                 BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the"
400                        " RF Disable Input\n", wlc_hw->unit);
401                 wl_rfkill_set_hw_state(wlc->wl);
402         }
403
404         /* send any enq'd tx packets. Just makes sure to jump start tx */
405         if (!pktq_empty(&wlc->pkt_queue->q))
406                 wlc_send_q(wlc);
407
408         /* it isn't done and needs to be resched if macintstatus is non-zero */
409         return wlc->macintstatus != 0;
410
411  fatal:
412         wl_init(wlc->wl);
413         return wlc->macintstatus != 0;
414 }
415
416 /* common low-level watchdog code */
417 void wlc_bmac_watchdog(void *arg)
418 {
419         struct wlc_info *wlc = (struct wlc_info *) arg;
420         struct wlc_hw_info *wlc_hw = wlc->hw;
421
422         BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
423
424         if (!wlc_hw->up)
425                 return;
426
427         /* increment second count */
428         wlc_hw->now++;
429
430         /* Check for FIFO error interrupts */
431         wlc_bmac_fifoerrors(wlc_hw);
432
433         /* make sure RX dma has buffers */
434         dma_rxfill(wlc->hw->di[RX_FIFO]);
435
436         wlc_phy_watchdog(wlc_hw->band->pi);
437 }
438
439 void
440 wlc_bmac_set_chanspec(struct wlc_hw_info *wlc_hw, chanspec_t chanspec,
441                       bool mute, struct txpwr_limits *txpwr)
442 {
443         uint bandunit;
444
445         BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec);
446
447         wlc_hw->chanspec = chanspec;
448
449         /* Switch bands if necessary */
450         if (NBANDS_HW(wlc_hw) > 1) {
451                 bandunit = CHSPEC_WLCBANDUNIT(chanspec);
452                 if (wlc_hw->band->bandunit != bandunit) {
453                         /* wlc_bmac_setband disables other bandunit,
454                          *  use light band switch if not up yet
455                          */
456                         if (wlc_hw->up) {
457                                 wlc_phy_chanspec_radio_set(wlc_hw->
458                                                            bandstate[bandunit]->
459                                                            pi, chanspec);
460                                 wlc_bmac_setband(wlc_hw, bandunit, chanspec);
461                         } else {
462                                 wlc_setxband(wlc_hw, bandunit);
463                         }
464                 }
465         }
466
467         wlc_phy_initcal_enable(wlc_hw->band->pi, !mute);
468
469         if (!wlc_hw->up) {
470                 if (wlc_hw->clk)
471                         wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr,
472                                                   chanspec);
473                 wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
474         } else {
475                 wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec);
476                 wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec);
477
478                 /* Update muting of the channel */
479                 wlc_bmac_mute(wlc_hw, mute, 0);
480         }
481 }
482
483 int wlc_bmac_state_get(struct wlc_hw_info *wlc_hw, wlc_bmac_state_t *state)
484 {
485         state->machwcap = wlc_hw->machwcap;
486
487         return 0;
488 }
489
490 static bool wlc_bmac_attach_dmapio(struct wlc_info *wlc, uint j, bool wme)
491 {
492         uint i;
493         char name[8];
494         /* ucode host flag 2 needed for pio mode, independent of band and fifo */
495         u16 pio_mhf2 = 0;
496         struct wlc_hw_info *wlc_hw = wlc->hw;
497         uint unit = wlc_hw->unit;
498         wlc_tunables_t *tune = wlc->pub->tunables;
499         struct wiphy *wiphy = wlc->wiphy;
500
501         /* name and offsets for dma_attach */
502         snprintf(name, sizeof(name), "wl%d", unit);
503
504         if (wlc_hw->di[0] == 0) {       /* Init FIFOs */
505                 uint addrwidth;
506                 int dma_attach_err = 0;
507                 /* Find out the DMA addressing capability and let OS know
508                  * All the channels within one DMA core have 'common-minimum' same
509                  * capability
510                  */
511                 addrwidth =
512                     dma_addrwidth(wlc_hw->sih, DMAREG(wlc_hw, DMA_TX, 0));
513
514                 if (!wl_alloc_dma_resources(wlc_hw->wlc->wl, addrwidth)) {
515                         wiphy_err(wiphy, "wl%d: wlc_attach: alloc_dma_"
516                                   "resources failed\n", unit);
517                         return false;
518                 }
519
520                 /*
521                  * FIFO 0
522                  * TX: TX_AC_BK_FIFO (TX AC Background data packets)
523                  * RX: RX_FIFO (RX data packets)
524                  */
525                 wlc_hw->di[0] = dma_attach(name, wlc_hw->sih,
526                                            (wme ? DMAREG(wlc_hw, DMA_TX, 0) :
527                                             NULL), DMAREG(wlc_hw, DMA_RX, 0),
528                                            (wme ? tune->ntxd : 0), tune->nrxd,
529                                            tune->rxbufsz, -1, tune->nrxbufpost,
530                                            WL_HWRXOFF, &wl_msg_level);
531                 dma_attach_err |= (NULL == wlc_hw->di[0]);
532
533                 /*
534                  * FIFO 1
535                  * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets)
536                  *   (legacy) TX_DATA_FIFO (TX data packets)
537                  * RX: UNUSED
538                  */
539                 wlc_hw->di[1] = dma_attach(name, wlc_hw->sih,
540                                            DMAREG(wlc_hw, DMA_TX, 1), NULL,
541                                            tune->ntxd, 0, 0, -1, 0, 0,
542                                            &wl_msg_level);
543                 dma_attach_err |= (NULL == wlc_hw->di[1]);
544
545                 /*
546                  * FIFO 2
547                  * TX: TX_AC_VI_FIFO (TX AC Video data packets)
548                  * RX: UNUSED
549                  */
550                 wlc_hw->di[2] = dma_attach(name, wlc_hw->sih,
551                                            DMAREG(wlc_hw, DMA_TX, 2), NULL,
552                                            tune->ntxd, 0, 0, -1, 0, 0,
553                                            &wl_msg_level);
554                 dma_attach_err |= (NULL == wlc_hw->di[2]);
555                 /*
556                  * FIFO 3
557                  * TX: TX_AC_VO_FIFO (TX AC Voice data packets)
558                  *   (legacy) TX_CTL_FIFO (TX control & mgmt packets)
559                  */
560                 wlc_hw->di[3] = dma_attach(name, wlc_hw->sih,
561                                            DMAREG(wlc_hw, DMA_TX, 3),
562                                            NULL, tune->ntxd, 0, 0, -1,
563                                            0, 0, &wl_msg_level);
564                 dma_attach_err |= (NULL == wlc_hw->di[3]);
565 /* Cleaner to leave this as if with AP defined */
566
567                 if (dma_attach_err) {
568                         wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed"
569                                   "\n", unit);
570                         return false;
571                 }
572
573                 /* get pointer to dma engine tx flow control variable */
574                 for (i = 0; i < NFIFO; i++)
575                         if (wlc_hw->di[i])
576                                 wlc_hw->txavail[i] =
577                                     (uint *) dma_getvar(wlc_hw->di[i],
578                                                         "&txavail");
579         }
580
581         /* initial ucode host flags */
582         wlc_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2);
583
584         return true;
585 }
586
587 static void wlc_bmac_detach_dmapio(struct wlc_hw_info *wlc_hw)
588 {
589         uint j;
590
591         for (j = 0; j < NFIFO; j++) {
592                 if (wlc_hw->di[j]) {
593                         dma_detach(wlc_hw->di[j]);
594                         wlc_hw->di[j] = NULL;
595                 }
596         }
597 }
598
599 /* low level attach
600  *    run backplane attach, init nvram
601  *    run phy attach
602  *    initialize software state for each core and band
603  *    put the whole chip in reset(driver down state), no clock
604  */
605 int wlc_bmac_attach(struct wlc_info *wlc, u16 vendor, u16 device, uint unit,
606                     bool piomode, void *regsva, uint bustype, void *btparam)
607 {
608         struct wlc_hw_info *wlc_hw;
609         d11regs_t *regs;
610         char *macaddr = NULL;
611         char *vars;
612         uint err = 0;
613         uint j;
614         bool wme = false;
615         shared_phy_params_t sha_params;
616         struct wiphy *wiphy = wlc->wiphy;
617
618         BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor,
619                 device);
620
621         wme = true;
622
623         wlc_hw = wlc->hw;
624         wlc_hw->wlc = wlc;
625         wlc_hw->unit = unit;
626         wlc_hw->band = wlc_hw->bandstate[0];
627         wlc_hw->_piomode = piomode;
628
629         /* populate struct wlc_hw_info with default values  */
630         wlc_bmac_info_init(wlc_hw);
631
632         /*
633          * Do the hardware portion of the attach.
634          * Also initialize software state that depends on the particular hardware
635          * we are running.
636          */
637         wlc_hw->sih = ai_attach((uint) device, regsva, bustype, btparam,
638                                 &wlc_hw->vars, &wlc_hw->vars_size);
639         if (wlc_hw->sih == NULL) {
640                 wiphy_err(wiphy, "wl%d: wlc_bmac_attach: si_attach failed\n",
641                           unit);
642                 err = 11;
643                 goto fail;
644         }
645         vars = wlc_hw->vars;
646
647         /*
648          * Get vendid/devid nvram overwrites, which could be different
649          * than those the BIOS recognizes for devices on PCMCIA_BUS,
650          * SDIO_BUS, and SROMless devices on PCI_BUS.
651          */
652 #ifdef BCMBUSTYPE
653         bustype = BCMBUSTYPE;
654 #endif
655         if (bustype != SI_BUS) {
656                 char *var;
657
658                 var = getvar(vars, "vendid");
659                 if (var) {
660                         vendor = (u16) simple_strtoul(var, NULL, 0);
661                         wiphy_err(wiphy, "Overriding vendor id = 0x%x\n",
662                                   vendor);
663                 }
664                 var = getvar(vars, "devid");
665                 if (var) {
666                         u16 devid = (u16) simple_strtoul(var, NULL, 0);
667                         if (devid != 0xffff) {
668                                 device = devid;
669                                 wiphy_err(wiphy, "Overriding device id = 0x%x"
670                                           "\n", device);
671                         }
672                 }
673
674                 /* verify again the device is supported */
675                 if (!wlc_chipmatch(vendor, device)) {
676                         wiphy_err(wiphy, "wl%d: wlc_bmac_attach: Unsupported "
677                                 "vendor/device (0x%x/0x%x)\n",
678                                  unit, vendor, device);
679                         err = 12;
680                         goto fail;
681                 }
682         }
683
684         wlc_hw->vendorid = vendor;
685         wlc_hw->deviceid = device;
686
687         /* set bar0 window to point at D11 core */
688         wlc_hw->regs = (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
689         wlc_hw->corerev = ai_corerev(wlc_hw->sih);
690
691         regs = wlc_hw->regs;
692
693         wlc->regs = wlc_hw->regs;
694
695         /* validate chip, chiprev and corerev */
696         if (!wlc_isgoodchip(wlc_hw)) {
697                 err = 13;
698                 goto fail;
699         }
700
701         /* initialize power control registers */
702         ai_clkctl_init(wlc_hw->sih);
703
704         /* request fastclock and force fastclock for the rest of attach
705          * bring the d11 core out of reset.
706          *   For PMU chips, the first wlc_clkctl_clk is no-op since core-clk is still false;
707          *   But it will be called again inside wlc_corereset, after d11 is out of reset.
708          */
709         wlc_clkctl_clk(wlc_hw, CLK_FAST);
710         wlc_bmac_corereset(wlc_hw, WLC_USE_COREFLAGS);
711
712         if (!wlc_bmac_validate_chip_access(wlc_hw)) {
713                 wiphy_err(wiphy, "wl%d: wlc_bmac_attach: validate_chip_access "
714                         "failed\n", unit);
715                 err = 14;
716                 goto fail;
717         }
718
719         /* get the board rev, used just below */
720         j = getintvar(vars, "boardrev");
721         /* promote srom boardrev of 0xFF to 1 */
722         if (j == BOARDREV_PROMOTABLE)
723                 j = BOARDREV_PROMOTED;
724         wlc_hw->boardrev = (u16) j;
725         if (!wlc_validboardtype(wlc_hw)) {
726                 wiphy_err(wiphy, "wl%d: wlc_bmac_attach: Unsupported Broadcom "
727                         "board type (0x%x)" " or revision level (0x%x)\n",
728                          unit, wlc_hw->sih->boardtype, wlc_hw->boardrev);
729                 err = 15;
730                 goto fail;
731         }
732         wlc_hw->sromrev = (u8) getintvar(vars, "sromrev");
733         wlc_hw->boardflags = (u32) getintvar(vars, "boardflags");
734         wlc_hw->boardflags2 = (u32) getintvar(vars, "boardflags2");
735
736         if (wlc_hw->boardflags & BFL_NOPLLDOWN)
737                 wlc_bmac_pllreq(wlc_hw, true, WLC_PLLREQ_SHARED);
738
739         if ((wlc_hw->sih->bustype == PCI_BUS)
740             && (ai_pci_war16165(wlc_hw->sih)))
741                 wlc->war16165 = true;
742
743         /* check device id(srom, nvram etc.) to set bands */
744         if (wlc_hw->deviceid == BCM43224_D11N_ID ||
745             wlc_hw->deviceid == BCM43224_D11N_ID_VEN1) {
746                 /* Dualband boards */
747                 wlc_hw->_nbands = 2;
748         } else
749                 wlc_hw->_nbands = 1;
750
751         if ((wlc_hw->sih->chip == BCM43225_CHIP_ID))
752                 wlc_hw->_nbands = 1;
753
754         /* BMAC_NOTE: remove init of pub values when wlc_attach() unconditionally does the
755          * init of these values
756          */
757         wlc->vendorid = wlc_hw->vendorid;
758         wlc->deviceid = wlc_hw->deviceid;
759         wlc->pub->sih = wlc_hw->sih;
760         wlc->pub->corerev = wlc_hw->corerev;
761         wlc->pub->sromrev = wlc_hw->sromrev;
762         wlc->pub->boardrev = wlc_hw->boardrev;
763         wlc->pub->boardflags = wlc_hw->boardflags;
764         wlc->pub->boardflags2 = wlc_hw->boardflags2;
765         wlc->pub->_nbands = wlc_hw->_nbands;
766
767         wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc);
768
769         if (wlc_hw->physhim == NULL) {
770                 wiphy_err(wiphy, "wl%d: wlc_bmac_attach: wlc_phy_shim_attach "
771                         "failed\n", unit);
772                 err = 25;
773                 goto fail;
774         }
775
776         /* pass all the parameters to wlc_phy_shared_attach in one struct */
777         sha_params.sih = wlc_hw->sih;
778         sha_params.physhim = wlc_hw->physhim;
779         sha_params.unit = unit;
780         sha_params.corerev = wlc_hw->corerev;
781         sha_params.vars = vars;
782         sha_params.vid = wlc_hw->vendorid;
783         sha_params.did = wlc_hw->deviceid;
784         sha_params.chip = wlc_hw->sih->chip;
785         sha_params.chiprev = wlc_hw->sih->chiprev;
786         sha_params.chippkg = wlc_hw->sih->chippkg;
787         sha_params.sromrev = wlc_hw->sromrev;
788         sha_params.boardtype = wlc_hw->sih->boardtype;
789         sha_params.boardrev = wlc_hw->boardrev;
790         sha_params.boardvendor = wlc_hw->sih->boardvendor;
791         sha_params.boardflags = wlc_hw->boardflags;
792         sha_params.boardflags2 = wlc_hw->boardflags2;
793         sha_params.bustype = wlc_hw->sih->bustype;
794         sha_params.buscorerev = wlc_hw->sih->buscorerev;
795
796         /* alloc and save pointer to shared phy state area */
797         wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params);
798         if (!wlc_hw->phy_sh) {
799                 err = 16;
800                 goto fail;
801         }
802
803         /* initialize software state for each core and band */
804         for (j = 0; j < NBANDS_HW(wlc_hw); j++) {
805                 /*
806                  * band0 is always 2.4Ghz
807                  * band1, if present, is 5Ghz
808                  */
809
810                 /* So if this is a single band 11a card, use band 1 */
811                 if (IS_SINGLEBAND_5G(wlc_hw->deviceid))
812                         j = BAND_5G_INDEX;
813
814                 wlc_setxband(wlc_hw, j);
815
816                 wlc_hw->band->bandunit = j;
817                 wlc_hw->band->bandtype = j ? WLC_BAND_5G : WLC_BAND_2G;
818                 wlc->band->bandunit = j;
819                 wlc->band->bandtype = j ? WLC_BAND_5G : WLC_BAND_2G;
820                 wlc->core->coreidx = ai_coreidx(wlc_hw->sih);
821
822                 wlc_hw->machwcap = R_REG(&regs->machwcap);
823                 wlc_hw->machwcap_backup = wlc_hw->machwcap;
824
825                 /* init tx fifo size */
826                 wlc_hw->xmtfifo_sz =
827                     xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)];
828
829                 /* Get a phy for this band */
830                 wlc_hw->band->pi = wlc_phy_attach(wlc_hw->phy_sh,
831                         (void *)regs, wlc_bmac_bandtype(wlc_hw), vars,
832                         wlc->wiphy);
833                 if (wlc_hw->band->pi == NULL) {
834                         wiphy_err(wiphy, "wl%d: wlc_bmac_attach: wlc_phy_"
835                                   "attach failed\n", unit);
836                         err = 17;
837                         goto fail;
838                 }
839
840                 wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap);
841
842                 wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype,
843                                        &wlc_hw->band->phyrev,
844                                        &wlc_hw->band->radioid,
845                                        &wlc_hw->band->radiorev);
846                 wlc_hw->band->abgphy_encore =
847                     wlc_phy_get_encore(wlc_hw->band->pi);
848                 wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi);
849                 wlc_hw->band->core_flags =
850                     wlc_phy_get_coreflags(wlc_hw->band->pi);
851
852                 /* verify good phy_type & supported phy revision */
853                 if (WLCISNPHY(wlc_hw->band)) {
854                         if (NCONF_HAS(wlc_hw->band->phyrev))
855                                 goto good_phy;
856                         else
857                                 goto bad_phy;
858                 } else if (WLCISLCNPHY(wlc_hw->band)) {
859                         if (LCNCONF_HAS(wlc_hw->band->phyrev))
860                                 goto good_phy;
861                         else
862                                 goto bad_phy;
863                 } else {
864  bad_phy:
865                         wiphy_err(wiphy, "wl%d: wlc_bmac_attach: unsupported "
866                                   "phy type/rev (%d/%d)\n", unit,
867                                   wlc_hw->band->phytype, wlc_hw->band->phyrev);
868                         err = 18;
869                         goto fail;
870                 }
871
872  good_phy:
873                 /* BMAC_NOTE: wlc->band->pi should not be set below and should be done in the
874                  * high level attach. However we can not make that change until all low level access
875                  * is changed to wlc_hw->band->pi. Instead do the wlc->band->pi init below, keeping
876                  * wlc_hw->band->pi as well for incremental update of low level fns, and cut over
877                  * low only init when all fns updated.
878                  */
879                 wlc->band->pi = wlc_hw->band->pi;
880                 wlc->band->phytype = wlc_hw->band->phytype;
881                 wlc->band->phyrev = wlc_hw->band->phyrev;
882                 wlc->band->radioid = wlc_hw->band->radioid;
883                 wlc->band->radiorev = wlc_hw->band->radiorev;
884
885                 /* default contention windows size limits */
886                 wlc_hw->band->CWmin = APHY_CWMIN;
887                 wlc_hw->band->CWmax = PHY_CWMAX;
888
889                 if (!wlc_bmac_attach_dmapio(wlc, j, wme)) {
890                         err = 19;
891                         goto fail;
892                 }
893         }
894
895         /* disable core to match driver "down" state */
896         wlc_coredisable(wlc_hw);
897
898         /* Match driver "down" state */
899         if (wlc_hw->sih->bustype == PCI_BUS)
900                 ai_pci_down(wlc_hw->sih);
901
902         /* register sb interrupt callback functions */
903         ai_register_intr_callback(wlc_hw->sih, (void *)wlc_wlintrsoff,
904                                   (void *)wlc_wlintrsrestore, NULL, wlc);
905
906         /* turn off pll and xtal to match driver "down" state */
907         wlc_bmac_xtal(wlc_hw, OFF);
908
909         /* *********************************************************************
910          * The hardware is in the DOWN state at this point. D11 core
911          * or cores are in reset with clocks off, and the board PLLs
912          * are off if possible.
913          *
914          * Beyond this point, wlc->sbclk == false and chip registers
915          * should not be touched.
916          *********************************************************************
917          */
918
919         /* init etheraddr state variables */
920         macaddr = wlc_get_macaddr(wlc_hw);
921         if (macaddr == NULL) {
922                 wiphy_err(wiphy, "wl%d: wlc_bmac_attach: macaddr not found\n",
923                           unit);
924                 err = 21;
925                 goto fail;
926         }
927         bcm_ether_atoe(macaddr, wlc_hw->etheraddr);
928         if (is_broadcast_ether_addr(wlc_hw->etheraddr) ||
929             is_zero_ether_addr(wlc_hw->etheraddr)) {
930                 wiphy_err(wiphy, "wl%d: wlc_bmac_attach: bad macaddr %s\n",
931                           unit, macaddr);
932                 err = 22;
933                 goto fail;
934         }
935
936         BCMMSG(wlc->wiphy,
937                  "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n",
938                  wlc_hw->deviceid, wlc_hw->_nbands,
939                  wlc_hw->sih->boardtype, macaddr);
940
941         return err;
942
943  fail:
944         wiphy_err(wiphy, "wl%d: wlc_bmac_attach: failed with err %d\n", unit,
945                   err);
946         return err;
947 }
948
949 /*
950  * Initialize wlc_info default values ...
951  * may get overrides later in this function
952  *  BMAC_NOTES, move low out and resolve the dangling ones
953  */
954 static void wlc_bmac_info_init(struct wlc_hw_info *wlc_hw)
955 {
956         struct wlc_info *wlc = wlc_hw->wlc;
957
958         /* set default sw macintmask value */
959         wlc->defmacintmask = DEF_MACINTMASK;
960
961         /* various 802.11g modes */
962         wlc_hw->shortslot = false;
963
964         wlc_hw->SFBL = RETRY_SHORT_FB;
965         wlc_hw->LFBL = RETRY_LONG_FB;
966
967         /* default mac retry limits */
968         wlc_hw->SRL = RETRY_SHORT_DEF;
969         wlc_hw->LRL = RETRY_LONG_DEF;
970         wlc_hw->chanspec = CH20MHZ_CHSPEC(1);
971 }
972
973 /*
974  * low level detach
975  */
976 int wlc_bmac_detach(struct wlc_info *wlc)
977 {
978         uint i;
979         struct wlc_hwband *band;
980         struct wlc_hw_info *wlc_hw = wlc->hw;
981         int callbacks;
982
983         callbacks = 0;
984
985         if (wlc_hw->sih) {
986                 /* detach interrupt sync mechanism since interrupt is disabled and per-port
987                  * interrupt object may has been freed. this must be done before sb core switch
988                  */
989                 ai_deregister_intr_callback(wlc_hw->sih);
990
991                 if (wlc_hw->sih->bustype == PCI_BUS)
992                         ai_pci_sleep(wlc_hw->sih);
993         }
994
995         wlc_bmac_detach_dmapio(wlc_hw);
996
997         band = wlc_hw->band;
998         for (i = 0; i < NBANDS_HW(wlc_hw); i++) {
999                 if (band->pi) {
1000                         /* Detach this band's phy */
1001                         wlc_phy_detach(band->pi);
1002                         band->pi = NULL;
1003                 }
1004                 band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)];
1005         }
1006
1007         /* Free shared phy state */
1008         wlc_phy_shared_detach(wlc_hw->phy_sh);
1009
1010         wlc_phy_shim_detach(wlc_hw->physhim);
1011
1012         /* free vars */
1013         kfree(wlc_hw->vars);
1014         wlc_hw->vars = NULL;
1015
1016         if (wlc_hw->sih) {
1017                 ai_detach(wlc_hw->sih);
1018                 wlc_hw->sih = NULL;
1019         }
1020
1021         return callbacks;
1022
1023 }
1024
1025 void wlc_bmac_reset(struct wlc_hw_info *wlc_hw)
1026 {
1027         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1028
1029         /* reset the core */
1030         if (!DEVICEREMOVED(wlc_hw->wlc))
1031                 wlc_bmac_corereset(wlc_hw, WLC_USE_COREFLAGS);
1032
1033         /* purge the dma rings */
1034         wlc_flushqueues(wlc_hw->wlc);
1035
1036         wlc_reset_bmac_done(wlc_hw->wlc);
1037 }
1038
1039 void
1040 wlc_bmac_init(struct wlc_hw_info *wlc_hw, chanspec_t chanspec,
1041                           bool mute) {
1042         u32 macintmask;
1043         bool fastclk;
1044         struct wlc_info *wlc = wlc_hw->wlc;
1045
1046         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1047
1048         /* request FAST clock if not on */
1049         fastclk = wlc_hw->forcefastclk;
1050         if (!fastclk)
1051                 wlc_clkctl_clk(wlc_hw, CLK_FAST);
1052
1053         /* disable interrupts */
1054         macintmask = wl_intrsoff(wlc->wl);
1055
1056         /* set up the specified band and chanspec */
1057         wlc_setxband(wlc_hw, CHSPEC_WLCBANDUNIT(chanspec));
1058         wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
1059
1060         /* do one-time phy inits and calibration */
1061         wlc_phy_cal_init(wlc_hw->band->pi);
1062
1063         /* core-specific initialization */
1064         wlc_coreinit(wlc);
1065
1066         /* suspend the tx fifos and mute the phy for preism cac time */
1067         if (mute)
1068                 wlc_bmac_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM);
1069
1070         /* band-specific inits */
1071         wlc_bmac_bsinit(wlc, chanspec);
1072
1073         /* restore macintmask */
1074         wl_intrsrestore(wlc->wl, macintmask);
1075
1076         /* seed wake_override with WLC_WAKE_OVERRIDE_MACSUSPEND since the mac is suspended
1077          * and wlc_enable_mac() will clear this override bit.
1078          */
1079         mboolset(wlc_hw->wake_override, WLC_WAKE_OVERRIDE_MACSUSPEND);
1080
1081         /*
1082          * initialize mac_suspend_depth to 1 to match ucode initial suspended state
1083          */
1084         wlc_hw->mac_suspend_depth = 1;
1085
1086         /* restore the clk */
1087         if (!fastclk)
1088                 wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
1089 }
1090
1091 int wlc_bmac_up_prep(struct wlc_hw_info *wlc_hw)
1092 {
1093         uint coremask;
1094
1095         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1096
1097         /*
1098          * Enable pll and xtal, initialize the power control registers,
1099          * and force fastclock for the remainder of wlc_up().
1100          */
1101         wlc_bmac_xtal(wlc_hw, ON);
1102         ai_clkctl_init(wlc_hw->sih);
1103         wlc_clkctl_clk(wlc_hw, CLK_FAST);
1104
1105         /*
1106          * Configure pci/pcmcia here instead of in wlc_attach()
1107          * to allow mfg hotswap:  down, hotswap (chip power cycle), up.
1108          */
1109         coremask = (1 << wlc_hw->wlc->core->coreidx);
1110
1111         if (wlc_hw->sih->bustype == PCI_BUS)
1112                 ai_pci_setup(wlc_hw->sih, coremask);
1113
1114         /*
1115          * Need to read the hwradio status here to cover the case where the system
1116          * is loaded with the hw radio disabled. We do not want to bring the driver up in this case.
1117          */
1118         if (wlc_bmac_radio_read_hwdisabled(wlc_hw)) {
1119                 /* put SB PCI in down state again */
1120                 if (wlc_hw->sih->bustype == PCI_BUS)
1121                         ai_pci_down(wlc_hw->sih);
1122                 wlc_bmac_xtal(wlc_hw, OFF);
1123                 return -ENOMEDIUM;
1124         }
1125
1126         if (wlc_hw->sih->bustype == PCI_BUS)
1127                 ai_pci_up(wlc_hw->sih);
1128
1129         /* reset the d11 core */
1130         wlc_bmac_corereset(wlc_hw, WLC_USE_COREFLAGS);
1131
1132         return 0;
1133 }
1134
1135 int wlc_bmac_up_finish(struct wlc_hw_info *wlc_hw)
1136 {
1137         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1138
1139         wlc_hw->up = true;
1140         wlc_phy_hw_state_upd(wlc_hw->band->pi, true);
1141
1142         /* FULLY enable dynamic power control and d11 core interrupt */
1143         wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
1144         wl_intrson(wlc_hw->wlc->wl);
1145         return 0;
1146 }
1147
1148 int wlc_bmac_down_prep(struct wlc_hw_info *wlc_hw)
1149 {
1150         bool dev_gone;
1151         uint callbacks = 0;
1152
1153         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1154
1155         if (!wlc_hw->up)
1156                 return callbacks;
1157
1158         dev_gone = DEVICEREMOVED(wlc_hw->wlc);
1159
1160         /* disable interrupts */
1161         if (dev_gone)
1162                 wlc_hw->wlc->macintmask = 0;
1163         else {
1164                 /* now disable interrupts */
1165                 wl_intrsoff(wlc_hw->wlc->wl);
1166
1167                 /* ensure we're running on the pll clock again */
1168                 wlc_clkctl_clk(wlc_hw, CLK_FAST);
1169         }
1170         /* down phy at the last of this stage */
1171         callbacks += wlc_phy_down(wlc_hw->band->pi);
1172
1173         return callbacks;
1174 }
1175
1176 int wlc_bmac_down_finish(struct wlc_hw_info *wlc_hw)
1177 {
1178         uint callbacks = 0;
1179         bool dev_gone;
1180
1181         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1182
1183         if (!wlc_hw->up)
1184                 return callbacks;
1185
1186         wlc_hw->up = false;
1187         wlc_phy_hw_state_upd(wlc_hw->band->pi, false);
1188
1189         dev_gone = DEVICEREMOVED(wlc_hw->wlc);
1190
1191         if (dev_gone) {
1192                 wlc_hw->sbclk = false;
1193                 wlc_hw->clk = false;
1194                 wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
1195
1196                 /* reclaim any posted packets */
1197                 wlc_flushqueues(wlc_hw->wlc);
1198         } else {
1199
1200                 /* Reset and disable the core */
1201                 if (ai_iscoreup(wlc_hw->sih)) {
1202                         if (R_REG(&wlc_hw->regs->maccontrol) &
1203                             MCTL_EN_MAC)
1204                                 wlc_suspend_mac_and_wait(wlc_hw->wlc);
1205                         callbacks += wl_reset(wlc_hw->wlc->wl);
1206                         wlc_coredisable(wlc_hw);
1207                 }
1208
1209                 /* turn off primary xtal and pll */
1210                 if (!wlc_hw->noreset) {
1211                         if (wlc_hw->sih->bustype == PCI_BUS)
1212                                 ai_pci_down(wlc_hw->sih);
1213                         wlc_bmac_xtal(wlc_hw, OFF);
1214                 }
1215         }
1216
1217         return callbacks;
1218 }
1219
1220 void wlc_bmac_wait_for_wake(struct wlc_hw_info *wlc_hw)
1221 {
1222         /* delay before first read of ucode state */
1223         udelay(40);
1224
1225         /* wait until ucode is no longer asleep */
1226         SPINWAIT((wlc_bmac_read_shm(wlc_hw, M_UCODE_DBGST) ==
1227                   DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly);
1228 }
1229
1230 void wlc_bmac_hw_etheraddr(struct wlc_hw_info *wlc_hw, u8 *ea)
1231 {
1232         memcpy(ea, wlc_hw->etheraddr, ETH_ALEN);
1233 }
1234
1235 static int wlc_bmac_bandtype(struct wlc_hw_info *wlc_hw)
1236 {
1237         return wlc_hw->band->bandtype;
1238 }
1239
1240 /* control chip clock to save power, enable dynamic clock or force fast clock */
1241 static void wlc_clkctl_clk(struct wlc_hw_info *wlc_hw, uint mode)
1242 {
1243         if (PMUCTL_ENAB(wlc_hw->sih)) {
1244                 /* new chips with PMU, CCS_FORCEHT will distribute the HT clock on backplane,
1245                  *  but mac core will still run on ALP(not HT) when it enters powersave mode,
1246                  *      which means the FCA bit may not be set.
1247                  *      should wakeup mac if driver wants it to run on HT.
1248                  */
1249
1250                 if (wlc_hw->clk) {
1251                         if (mode == CLK_FAST) {
1252                                 OR_REG(&wlc_hw->regs->clk_ctl_st,
1253                                        CCS_FORCEHT);
1254
1255                                 udelay(64);
1256
1257                                 SPINWAIT(((R_REG
1258                                            (&wlc_hw->regs->
1259                                             clk_ctl_st) & CCS_HTAVAIL) == 0),
1260                                          PMU_MAX_TRANSITION_DLY);
1261                                 WARN_ON(!(R_REG
1262                                           (&wlc_hw->regs->
1263                                            clk_ctl_st) & CCS_HTAVAIL));
1264                         } else {
1265                                 if ((wlc_hw->sih->pmurev == 0) &&
1266                                     (R_REG
1267                                      (&wlc_hw->regs->
1268                                       clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ)))
1269                                         SPINWAIT(((R_REG
1270                                                    (&wlc_hw->regs->
1271                                                     clk_ctl_st) & CCS_HTAVAIL)
1272                                                   == 0),
1273                                                  PMU_MAX_TRANSITION_DLY);
1274                                 AND_REG(&wlc_hw->regs->clk_ctl_st,
1275                                         ~CCS_FORCEHT);
1276                         }
1277                 }
1278                 wlc_hw->forcefastclk = (mode == CLK_FAST);
1279         } else {
1280
1281                 /* old chips w/o PMU, force HT through cc,
1282                  * then use FCA to verify mac is running fast clock
1283                  */
1284
1285                 wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode);
1286
1287                 /* check fast clock is available (if core is not in reset) */
1288                 if (wlc_hw->forcefastclk && wlc_hw->clk)
1289                         WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) &
1290                                   SISF_FCLKA));
1291
1292                 /* keep the ucode wake bit on if forcefastclk is on
1293                  * since we do not want ucode to put us back to slow clock
1294                  * when it dozes for PM mode.
1295                  * Code below matches the wake override bit with current forcefastclk state
1296                  * Only setting bit in wake_override instead of waking ucode immediately
1297                  * since old code (wlc.c 1.4499) had this behavior. Older code set
1298                  * wlc->forcefastclk but only had the wake happen if the wakup_ucode work
1299                  * (protected by an up check) was executed just below.
1300                  */
1301                 if (wlc_hw->forcefastclk)
1302                         mboolset(wlc_hw->wake_override,
1303                                  WLC_WAKE_OVERRIDE_FORCEFAST);
1304                 else
1305                         mboolclr(wlc_hw->wake_override,
1306                                  WLC_WAKE_OVERRIDE_FORCEFAST);
1307         }
1308 }
1309
1310 /* set initial host flags value */
1311 static void
1312 wlc_mhfdef(struct wlc_info *wlc, u16 *mhfs, u16 mhf2_init)
1313 {
1314         struct wlc_hw_info *wlc_hw = wlc->hw;
1315
1316         memset(mhfs, 0, MHFMAX * sizeof(u16));
1317
1318         mhfs[MHF2] |= mhf2_init;
1319
1320         /* prohibit use of slowclock on multifunction boards */
1321         if (wlc_hw->boardflags & BFL_NOPLLDOWN)
1322                 mhfs[MHF1] |= MHF1_FORCEFASTCLK;
1323
1324         if (WLCISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) {
1325                 mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR;
1326                 mhfs[MHF1] |= MHF1_IQSWAP_WAR;
1327         }
1328 }
1329
1330 /* set or clear ucode host flag bits
1331  * it has an optimization for no-change write
1332  * it only writes through shared memory when the core has clock;
1333  * pre-CLK changes should use wlc_write_mhf to get around the optimization
1334  *
1335  *
1336  * bands values are: WLC_BAND_AUTO <--- Current band only
1337  *                   WLC_BAND_5G   <--- 5G band only
1338  *                   WLC_BAND_2G   <--- 2G band only
1339  *                   WLC_BAND_ALL  <--- All bands
1340  */
1341 void
1342 wlc_bmac_mhf(struct wlc_hw_info *wlc_hw, u8 idx, u16 mask, u16 val,
1343              int bands)
1344 {
1345         u16 save;
1346         u16 addr[MHFMAX] = {
1347                 M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
1348                 M_HOST_FLAGS5
1349         };
1350         struct wlc_hwband *band;
1351
1352         if ((val & ~mask) || idx >= MHFMAX)
1353                 return; /* error condition */
1354
1355         switch (bands) {
1356                 /* Current band only or all bands,
1357                  * then set the band to current band
1358                  */
1359         case WLC_BAND_AUTO:
1360         case WLC_BAND_ALL:
1361                 band = wlc_hw->band;
1362                 break;
1363         case WLC_BAND_5G:
1364                 band = wlc_hw->bandstate[BAND_5G_INDEX];
1365                 break;
1366         case WLC_BAND_2G:
1367                 band = wlc_hw->bandstate[BAND_2G_INDEX];
1368                 break;
1369         default:
1370                 band = NULL;    /* error condition */
1371         }
1372
1373         if (band) {
1374                 save = band->mhfs[idx];
1375                 band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val;
1376
1377                 /* optimization: only write through if changed, and
1378                  * changed band is the current band
1379                  */
1380                 if (wlc_hw->clk && (band->mhfs[idx] != save)
1381                     && (band == wlc_hw->band))
1382                         wlc_bmac_write_shm(wlc_hw, addr[idx],
1383                                            (u16) band->mhfs[idx]);
1384         }
1385
1386         if (bands == WLC_BAND_ALL) {
1387                 wlc_hw->bandstate[0]->mhfs[idx] =
1388                     (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val;
1389                 wlc_hw->bandstate[1]->mhfs[idx] =
1390                     (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val;
1391         }
1392 }
1393
1394 u16 wlc_bmac_mhf_get(struct wlc_hw_info *wlc_hw, u8 idx, int bands)
1395 {
1396         struct wlc_hwband *band;
1397
1398         if (idx >= MHFMAX)
1399                 return 0; /* error condition */
1400         switch (bands) {
1401         case WLC_BAND_AUTO:
1402                 band = wlc_hw->band;
1403                 break;
1404         case WLC_BAND_5G:
1405                 band = wlc_hw->bandstate[BAND_5G_INDEX];
1406                 break;
1407         case WLC_BAND_2G:
1408                 band = wlc_hw->bandstate[BAND_2G_INDEX];
1409                 break;
1410         default:
1411                 band = NULL;            /* error condition */
1412         }
1413
1414         if (!band)
1415                 return 0;
1416
1417         return band->mhfs[idx];
1418 }
1419
1420 static void wlc_write_mhf(struct wlc_hw_info *wlc_hw, u16 *mhfs)
1421 {
1422         u8 idx;
1423         u16 addr[] = {
1424                 M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
1425                 M_HOST_FLAGS5
1426         };
1427
1428         for (idx = 0; idx < MHFMAX; idx++) {
1429                 wlc_bmac_write_shm(wlc_hw, addr[idx], mhfs[idx]);
1430         }
1431 }
1432
1433 /* set the maccontrol register to desired reset state and
1434  * initialize the sw cache of the register
1435  */
1436 static void wlc_mctrl_reset(struct wlc_hw_info *wlc_hw)
1437 {
1438         /* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */
1439         wlc_hw->maccontrol = 0;
1440         wlc_hw->suspended_fifos = 0;
1441         wlc_hw->wake_override = 0;
1442         wlc_hw->mute_override = 0;
1443         wlc_bmac_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE);
1444 }
1445
1446 /* set or clear maccontrol bits */
1447 void wlc_bmac_mctrl(struct wlc_hw_info *wlc_hw, u32 mask, u32 val)
1448 {
1449         u32 maccontrol;
1450         u32 new_maccontrol;
1451
1452         if (val & ~mask)
1453                 return; /* error condition */
1454         maccontrol = wlc_hw->maccontrol;
1455         new_maccontrol = (maccontrol & ~mask) | val;
1456
1457         /* if the new maccontrol value is the same as the old, nothing to do */
1458         if (new_maccontrol == maccontrol)
1459                 return;
1460
1461         /* something changed, cache the new value */
1462         wlc_hw->maccontrol = new_maccontrol;
1463
1464         /* write the new values with overrides applied */
1465         wlc_mctrl_write(wlc_hw);
1466 }
1467
1468 /* write the software state of maccontrol and overrides to the maccontrol register */
1469 static void wlc_mctrl_write(struct wlc_hw_info *wlc_hw)
1470 {
1471         u32 maccontrol = wlc_hw->maccontrol;
1472
1473         /* OR in the wake bit if overridden */
1474         if (wlc_hw->wake_override)
1475                 maccontrol |= MCTL_WAKE;
1476
1477         /* set AP and INFRA bits for mute if needed */
1478         if (wlc_hw->mute_override) {
1479                 maccontrol &= ~(MCTL_AP);
1480                 maccontrol |= MCTL_INFRA;
1481         }
1482
1483         W_REG(&wlc_hw->regs->maccontrol, maccontrol);
1484 }
1485
1486 void wlc_ucode_wake_override_set(struct wlc_hw_info *wlc_hw, u32 override_bit)
1487 {
1488         if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) {
1489                 mboolset(wlc_hw->wake_override, override_bit);
1490                 return;
1491         }
1492
1493         mboolset(wlc_hw->wake_override, override_bit);
1494
1495         wlc_mctrl_write(wlc_hw);
1496         wlc_bmac_wait_for_wake(wlc_hw);
1497
1498         return;
1499 }
1500
1501 void wlc_ucode_wake_override_clear(struct wlc_hw_info *wlc_hw, u32 override_bit)
1502 {
1503         mboolclr(wlc_hw->wake_override, override_bit);
1504
1505         if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE))
1506                 return;
1507
1508         wlc_mctrl_write(wlc_hw);
1509
1510         return;
1511 }
1512
1513 /* When driver needs ucode to stop beaconing, it has to make sure that
1514  * MCTL_AP is clear and MCTL_INFRA is set
1515  * Mode           MCTL_AP        MCTL_INFRA
1516  * AP                1              1
1517  * STA               0              1 <--- This will ensure no beacons
1518  * IBSS              0              0
1519  */
1520 static void wlc_ucode_mute_override_set(struct wlc_hw_info *wlc_hw)
1521 {
1522         wlc_hw->mute_override = 1;
1523
1524         /* if maccontrol already has AP == 0 and INFRA == 1 without this
1525          * override, then there is no change to write
1526          */
1527         if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
1528                 return;
1529
1530         wlc_mctrl_write(wlc_hw);
1531
1532         return;
1533 }
1534
1535 /* Clear the override on AP and INFRA bits */
1536 static void wlc_ucode_mute_override_clear(struct wlc_hw_info *wlc_hw)
1537 {
1538         if (wlc_hw->mute_override == 0)
1539                 return;
1540
1541         wlc_hw->mute_override = 0;
1542
1543         /* if maccontrol already has AP == 0 and INFRA == 1 without this
1544          * override, then there is no change to write
1545          */
1546         if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
1547                 return;
1548
1549         wlc_mctrl_write(wlc_hw);
1550 }
1551
1552 /*
1553  * Write a MAC address to the given match reg offset in the RXE match engine.
1554  */
1555 void
1556 wlc_bmac_set_addrmatch(struct wlc_hw_info *wlc_hw, int match_reg_offset,
1557                        const u8 *addr)
1558 {
1559         d11regs_t *regs;
1560         u16 mac_l;
1561         u16 mac_m;
1562         u16 mac_h;
1563
1564         BCMMSG(wlc_hw->wlc->wiphy, "wl%d: wlc_bmac_set_addrmatch\n",
1565                  wlc_hw->unit);
1566
1567         regs = wlc_hw->regs;
1568         mac_l = addr[0] | (addr[1] << 8);
1569         mac_m = addr[2] | (addr[3] << 8);
1570         mac_h = addr[4] | (addr[5] << 8);
1571
1572         /* enter the MAC addr into the RXE match registers */
1573         W_REG(&regs->rcm_ctl, RCM_INC_DATA | match_reg_offset);
1574         W_REG(&regs->rcm_mat_data, mac_l);
1575         W_REG(&regs->rcm_mat_data, mac_m);
1576         W_REG(&regs->rcm_mat_data, mac_h);
1577
1578 }
1579
1580 void
1581 wlc_bmac_write_template_ram(struct wlc_hw_info *wlc_hw, int offset, int len,
1582                             void *buf)
1583 {
1584         d11regs_t *regs;
1585         u32 word;
1586         bool be_bit;
1587         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1588
1589         regs = wlc_hw->regs;
1590         W_REG(&regs->tplatewrptr, offset);
1591
1592         /* if MCTL_BIGEND bit set in mac control register,
1593          * the chip swaps data in fifo, as well as data in
1594          * template ram
1595          */
1596         be_bit = (R_REG(&regs->maccontrol) & MCTL_BIGEND) != 0;
1597
1598         while (len > 0) {
1599                 memcpy(&word, buf, sizeof(u32));
1600
1601                 if (be_bit)
1602                         word = cpu_to_be32(word);
1603                 else
1604                         word = cpu_to_le32(word);
1605
1606                 W_REG(&regs->tplatewrdata, word);
1607
1608                 buf = (u8 *) buf + sizeof(u32);
1609                 len -= sizeof(u32);
1610         }
1611 }
1612
1613 void wlc_bmac_set_cwmin(struct wlc_hw_info *wlc_hw, u16 newmin)
1614 {
1615         wlc_hw->band->CWmin = newmin;
1616
1617         W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN);
1618         (void)R_REG(&wlc_hw->regs->objaddr);
1619         W_REG(&wlc_hw->regs->objdata, newmin);
1620 }
1621
1622 void wlc_bmac_set_cwmax(struct wlc_hw_info *wlc_hw, u16 newmax)
1623 {
1624         wlc_hw->band->CWmax = newmax;
1625
1626         W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX);
1627         (void)R_REG(&wlc_hw->regs->objaddr);
1628         W_REG(&wlc_hw->regs->objdata, newmax);
1629 }
1630
1631 void wlc_bmac_bw_set(struct wlc_hw_info *wlc_hw, u16 bw)
1632 {
1633         bool fastclk;
1634
1635         /* request FAST clock if not on */
1636         fastclk = wlc_hw->forcefastclk;
1637         if (!fastclk)
1638                 wlc_clkctl_clk(wlc_hw, CLK_FAST);
1639
1640         wlc_phy_bw_state_set(wlc_hw->band->pi, bw);
1641
1642         wlc_bmac_phy_reset(wlc_hw);
1643         wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi));
1644
1645         /* restore the clk */
1646         if (!fastclk)
1647                 wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
1648 }
1649
1650 static void
1651 wlc_write_hw_bcntemplate0(struct wlc_hw_info *wlc_hw, void *bcn, int len)
1652 {
1653         d11regs_t *regs = wlc_hw->regs;
1654
1655         wlc_bmac_write_template_ram(wlc_hw, T_BCN0_TPL_BASE, (len + 3) & ~3,
1656                                     bcn);
1657         /* write beacon length to SCR */
1658         wlc_bmac_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len);
1659         /* mark beacon0 valid */
1660         OR_REG(&regs->maccommand, MCMD_BCN0VLD);
1661 }
1662
1663 static void
1664 wlc_write_hw_bcntemplate1(struct wlc_hw_info *wlc_hw, void *bcn, int len)
1665 {
1666         d11regs_t *regs = wlc_hw->regs;
1667
1668         wlc_bmac_write_template_ram(wlc_hw, T_BCN1_TPL_BASE, (len + 3) & ~3,
1669                                     bcn);
1670         /* write beacon length to SCR */
1671         wlc_bmac_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len);
1672         /* mark beacon1 valid */
1673         OR_REG(&regs->maccommand, MCMD_BCN1VLD);
1674 }
1675
1676 /* mac is assumed to be suspended at this point */
1677 void
1678 wlc_bmac_write_hw_bcntemplates(struct wlc_hw_info *wlc_hw, void *bcn, int len,
1679                                bool both)
1680 {
1681         d11regs_t *regs = wlc_hw->regs;
1682
1683         if (both) {
1684                 wlc_write_hw_bcntemplate0(wlc_hw, bcn, len);
1685                 wlc_write_hw_bcntemplate1(wlc_hw, bcn, len);
1686         } else {
1687                 /* bcn 0 */
1688                 if (!(R_REG(&regs->maccommand) & MCMD_BCN0VLD))
1689                         wlc_write_hw_bcntemplate0(wlc_hw, bcn, len);
1690                 /* bcn 1 */
1691                 else if (!
1692                          (R_REG(&regs->maccommand) & MCMD_BCN1VLD))
1693                         wlc_write_hw_bcntemplate1(wlc_hw, bcn, len);
1694         }
1695 }
1696
1697 static void WLBANDINITFN(wlc_bmac_upd_synthpu) (struct wlc_hw_info *wlc_hw)
1698 {
1699         u16 v;
1700         struct wlc_info *wlc = wlc_hw->wlc;
1701         /* update SYNTHPU_DLY */
1702
1703         if (WLCISLCNPHY(wlc->band)) {
1704                 v = SYNTHPU_DLY_LPPHY_US;
1705         } else if (WLCISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3))) {
1706                 v = SYNTHPU_DLY_NPHY_US;
1707         } else {
1708                 v = SYNTHPU_DLY_BPHY_US;
1709         }
1710
1711         wlc_bmac_write_shm(wlc_hw, M_SYNTHPU_DLY, v);
1712 }
1713
1714 /* band-specific init */
1715 static void
1716 WLBANDINITFN(wlc_bmac_bsinit) (struct wlc_info *wlc, chanspec_t chanspec)
1717 {
1718         struct wlc_hw_info *wlc_hw = wlc->hw;
1719
1720         BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
1721                 wlc_hw->band->bandunit);
1722
1723         wlc_ucode_bsinit(wlc_hw);
1724
1725         wlc_phy_init(wlc_hw->band->pi, chanspec);
1726
1727         wlc_ucode_txant_set(wlc_hw);
1728
1729         /* cwmin is band-specific, update hardware with value for current band */
1730         wlc_bmac_set_cwmin(wlc_hw, wlc_hw->band->CWmin);
1731         wlc_bmac_set_cwmax(wlc_hw, wlc_hw->band->CWmax);
1732
1733         wlc_bmac_update_slot_timing(wlc_hw,
1734                                     BAND_5G(wlc_hw->band->
1735                                             bandtype) ? true : wlc_hw->
1736                                     shortslot);
1737
1738         /* write phytype and phyvers */
1739         wlc_bmac_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype);
1740         wlc_bmac_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev);
1741
1742         /* initialize the txphyctl1 rate table since shmem is shared between bands */
1743         wlc_upd_ofdm_pctl1_table(wlc_hw);
1744
1745         wlc_bmac_upd_synthpu(wlc_hw);
1746 }
1747
1748 static void wlc_bmac_core_phy_clk(struct wlc_hw_info *wlc_hw, bool clk)
1749 {
1750         BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk);
1751
1752         wlc_hw->phyclk = clk;
1753
1754         if (OFF == clk) {       /* clear gmode bit, put phy into reset */
1755
1756                 ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE),
1757                                (SICF_PRST | SICF_FGC));
1758                 udelay(1);
1759                 ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST);
1760                 udelay(1);
1761
1762         } else {                /* take phy out of reset */
1763
1764                 ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC);
1765                 udelay(1);
1766                 ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0);
1767                 udelay(1);
1768
1769         }
1770 }
1771
1772 /* Perform a soft reset of the PHY PLL */
1773 void wlc_bmac_core_phypll_reset(struct wlc_hw_info *wlc_hw)
1774 {
1775         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1776
1777         ai_corereg(wlc_hw->sih, SI_CC_IDX,
1778                    offsetof(chipcregs_t, chipcontrol_addr), ~0, 0);
1779         udelay(1);
1780         ai_corereg(wlc_hw->sih, SI_CC_IDX,
1781                    offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
1782         udelay(1);
1783         ai_corereg(wlc_hw->sih, SI_CC_IDX,
1784                    offsetof(chipcregs_t, chipcontrol_data), 0x4, 4);
1785         udelay(1);
1786         ai_corereg(wlc_hw->sih, SI_CC_IDX,
1787                    offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
1788         udelay(1);
1789 }
1790
1791 /* light way to turn on phy clock without reset for NPHY only
1792  *  refer to wlc_bmac_core_phy_clk for full version
1793  */
1794 void wlc_bmac_phyclk_fgc(struct wlc_hw_info *wlc_hw, bool clk)
1795 {
1796         /* support(necessary for NPHY and HYPHY) only */
1797         if (!WLCISNPHY(wlc_hw->band))
1798                 return;
1799
1800         if (ON == clk)
1801                 ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC);
1802         else
1803                 ai_core_cflags(wlc_hw->sih, SICF_FGC, 0);
1804
1805 }
1806
1807 void wlc_bmac_macphyclk_set(struct wlc_hw_info *wlc_hw, bool clk)
1808 {
1809         if (ON == clk)
1810                 ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE);
1811         else
1812                 ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0);
1813 }
1814
1815 void wlc_bmac_phy_reset(struct wlc_hw_info *wlc_hw)
1816 {
1817         wlc_phy_t *pih = wlc_hw->band->pi;
1818         u32 phy_bw_clkbits;
1819         bool phy_in_reset = false;
1820
1821         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1822
1823         if (pih == NULL)
1824                 return;
1825
1826         phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi);
1827
1828         /* Specific reset sequence required for NPHY rev 3 and 4 */
1829         if (WLCISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) &&
1830             NREV_LE(wlc_hw->band->phyrev, 4)) {
1831                 /* Set the PHY bandwidth */
1832                 ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits);
1833
1834                 udelay(1);
1835
1836                 /* Perform a soft reset of the PHY PLL */
1837                 wlc_bmac_core_phypll_reset(wlc_hw);
1838
1839                 /* reset the PHY */
1840                 ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE),
1841                                (SICF_PRST | SICF_PCLKE));
1842                 phy_in_reset = true;
1843         } else {
1844
1845                 ai_core_cflags(wlc_hw->sih,
1846                                (SICF_PRST | SICF_PCLKE | SICF_BWMASK),
1847                                (SICF_PRST | SICF_PCLKE | phy_bw_clkbits));
1848         }
1849
1850         udelay(2);
1851         wlc_bmac_core_phy_clk(wlc_hw, ON);
1852
1853         if (pih)
1854                 wlc_phy_anacore(pih, ON);
1855 }
1856
1857 /* switch to and initialize new band */
1858 static void
1859 WLBANDINITFN(wlc_bmac_setband) (struct wlc_hw_info *wlc_hw, uint bandunit,
1860                                 chanspec_t chanspec) {
1861         struct wlc_info *wlc = wlc_hw->wlc;
1862         u32 macintmask;
1863
1864         /* Enable the d11 core before accessing it */
1865         if (!ai_iscoreup(wlc_hw->sih)) {
1866                 ai_core_reset(wlc_hw->sih, 0, 0);
1867                 wlc_mctrl_reset(wlc_hw);
1868         }
1869
1870         macintmask = wlc_setband_inact(wlc, bandunit);
1871
1872         if (!wlc_hw->up)
1873                 return;
1874
1875         wlc_bmac_core_phy_clk(wlc_hw, ON);
1876
1877         /* band-specific initializations */
1878         wlc_bmac_bsinit(wlc, chanspec);
1879
1880         /*
1881          * If there are any pending software interrupt bits,
1882          * then replace these with a harmless nonzero value
1883          * so wlc_dpc() will re-enable interrupts when done.
1884          */
1885         if (wlc->macintstatus)
1886                 wlc->macintstatus = MI_DMAINT;
1887
1888         /* restore macintmask */
1889         wl_intrsrestore(wlc->wl, macintmask);
1890
1891         /* ucode should still be suspended.. */
1892         WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
1893 }
1894
1895 /* low-level band switch utility routine */
1896 void WLBANDINITFN(wlc_setxband) (struct wlc_hw_info *wlc_hw, uint bandunit)
1897 {
1898         BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
1899                 bandunit);
1900
1901         wlc_hw->band = wlc_hw->bandstate[bandunit];
1902
1903         /* BMAC_NOTE: until we eliminate need for wlc->band refs in low level code */
1904         wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
1905
1906         /* set gmode core flag */
1907         if (wlc_hw->sbclk && !wlc_hw->noreset) {
1908                 ai_core_cflags(wlc_hw->sih, SICF_GMODE,
1909                                ((bandunit == 0) ? SICF_GMODE : 0));
1910         }
1911 }
1912
1913 static bool wlc_isgoodchip(struct wlc_hw_info *wlc_hw)
1914 {
1915
1916         /* reject unsupported corerev */
1917         if (!VALID_COREREV(wlc_hw->corerev)) {
1918                 wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n",
1919                           wlc_hw->corerev);
1920                 return false;
1921         }
1922
1923         return true;
1924 }
1925
1926 static bool wlc_validboardtype(struct wlc_hw_info *wlc_hw)
1927 {
1928         bool goodboard = true;
1929         uint boardrev = wlc_hw->boardrev;
1930
1931         if (boardrev == 0)
1932                 goodboard = false;
1933         else if (boardrev > 0xff) {
1934                 uint brt = (boardrev & 0xf000) >> 12;
1935                 uint b0 = (boardrev & 0xf00) >> 8;
1936                 uint b1 = (boardrev & 0xf0) >> 4;
1937                 uint b2 = boardrev & 0xf;
1938
1939                 if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9)
1940                     || (b2 > 9))
1941                         goodboard = false;
1942         }
1943
1944         if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM)
1945                 return goodboard;
1946
1947         return goodboard;
1948 }
1949
1950 static char *wlc_get_macaddr(struct wlc_hw_info *wlc_hw)
1951 {
1952         const char *varname = "macaddr";
1953         char *macaddr;
1954
1955         /* If macaddr exists, use it (Sromrev4, CIS, ...). */
1956         macaddr = getvar(wlc_hw->vars, varname);
1957         if (macaddr != NULL)
1958                 return macaddr;
1959
1960         if (NBANDS_HW(wlc_hw) > 1)
1961                 varname = "et1macaddr";
1962         else
1963                 varname = "il0macaddr";
1964
1965         macaddr = getvar(wlc_hw->vars, varname);
1966         if (macaddr == NULL) {
1967                 wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr "
1968                           "getvar(%s) not found\n", wlc_hw->unit, varname);
1969         }
1970
1971         return macaddr;
1972 }
1973
1974 /*
1975  * Return true if radio is disabled, otherwise false.
1976  * hw radio disable signal is an external pin, users activate it asynchronously
1977  * this function could be called when driver is down and w/o clock
1978  * it operates on different registers depending on corerev and boardflag.
1979  */
1980 bool wlc_bmac_radio_read_hwdisabled(struct wlc_hw_info *wlc_hw)
1981 {
1982         bool v, clk, xtal;
1983         u32 resetbits = 0, flags = 0;
1984
1985         xtal = wlc_hw->sbclk;
1986         if (!xtal)
1987                 wlc_bmac_xtal(wlc_hw, ON);
1988
1989         /* may need to take core out of reset first */
1990         clk = wlc_hw->clk;
1991         if (!clk) {
1992                 /*
1993                  * mac no longer enables phyclk automatically when driver
1994                  * accesses phyreg throughput mac. This can be skipped since
1995                  * only mac reg is accessed below
1996                  */
1997                 flags |= SICF_PCLKE;
1998
1999                 /* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
2000                 if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
2001                     (wlc_hw->sih->chip == BCM43225_CHIP_ID) ||
2002                     (wlc_hw->sih->chip == BCM43421_CHIP_ID))
2003                         wlc_hw->regs =
2004                             (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID,
2005                                                      0);
2006                 ai_core_reset(wlc_hw->sih, flags, resetbits);
2007                 wlc_mctrl_reset(wlc_hw);
2008         }
2009
2010         v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0);
2011
2012         /* put core back into reset */
2013         if (!clk)
2014                 ai_core_disable(wlc_hw->sih, 0);
2015
2016         if (!xtal)
2017                 wlc_bmac_xtal(wlc_hw, OFF);
2018
2019         return v;
2020 }
2021
2022 /* Initialize just the hardware when coming out of POR or S3/S5 system states */
2023 void wlc_bmac_hw_up(struct wlc_hw_info *wlc_hw)
2024 {
2025         if (wlc_hw->wlc->pub->hw_up)
2026                 return;
2027
2028         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
2029
2030         /*
2031          * Enable pll and xtal, initialize the power control registers,
2032          * and force fastclock for the remainder of wlc_up().
2033          */
2034         wlc_bmac_xtal(wlc_hw, ON);
2035         ai_clkctl_init(wlc_hw->sih);
2036         wlc_clkctl_clk(wlc_hw, CLK_FAST);
2037
2038         if (wlc_hw->sih->bustype == PCI_BUS) {
2039                 ai_pci_fixcfg(wlc_hw->sih);
2040
2041                 /* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
2042                 if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
2043                     (wlc_hw->sih->chip == BCM43225_CHIP_ID) ||
2044                     (wlc_hw->sih->chip == BCM43421_CHIP_ID))
2045                         wlc_hw->regs =
2046                             (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID,
2047                                                      0);
2048         }
2049
2050         /* Inform phy that a POR reset has occurred so it does a complete phy init */
2051         wlc_phy_por_inform(wlc_hw->band->pi);
2052
2053         wlc_hw->ucode_loaded = false;
2054         wlc_hw->wlc->pub->hw_up = true;
2055
2056         if ((wlc_hw->boardflags & BFL_FEM)
2057             && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
2058                 if (!
2059                     (wlc_hw->boardrev >= 0x1250
2060                      && (wlc_hw->boardflags & BFL_FEM_BT)))
2061                         ai_epa_4313war(wlc_hw->sih);
2062         }
2063 }
2064
2065 static bool wlc_dma_rxreset(struct wlc_hw_info *wlc_hw, uint fifo)
2066 {
2067         struct hnddma_pub *di = wlc_hw->di[fifo];
2068         return dma_rxreset(di);
2069 }
2070
2071 /* d11 core reset
2072  *   ensure fask clock during reset
2073  *   reset dma
2074  *   reset d11(out of reset)
2075  *   reset phy(out of reset)
2076  *   clear software macintstatus for fresh new start
2077  * one testing hack wlc_hw->noreset will bypass the d11/phy reset
2078  */
2079 void wlc_bmac_corereset(struct wlc_hw_info *wlc_hw, u32 flags)
2080 {
2081         d11regs_t *regs;
2082         uint i;
2083         bool fastclk;
2084         u32 resetbits = 0;
2085
2086         if (flags == WLC_USE_COREFLAGS)
2087                 flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0);
2088
2089         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
2090
2091         regs = wlc_hw->regs;
2092
2093         /* request FAST clock if not on  */
2094         fastclk = wlc_hw->forcefastclk;
2095         if (!fastclk)
2096                 wlc_clkctl_clk(wlc_hw, CLK_FAST);
2097
2098         /* reset the dma engines except first time thru */
2099         if (ai_iscoreup(wlc_hw->sih)) {
2100                 for (i = 0; i < NFIFO; i++)
2101                         if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) {
2102                                 wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: "
2103                                           "dma_txreset[%d]: cannot stop dma\n",
2104                                            wlc_hw->unit, __func__, i);
2105                         }
2106
2107                 if ((wlc_hw->di[RX_FIFO])
2108                     && (!wlc_dma_rxreset(wlc_hw, RX_FIFO))) {
2109                         wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset"
2110                                   "[%d]: cannot stop dma\n",
2111                                   wlc_hw->unit, __func__, RX_FIFO);
2112                 }
2113         }
2114         /* if noreset, just stop the psm and return */
2115         if (wlc_hw->noreset) {
2116                 wlc_hw->wlc->macintstatus = 0;  /* skip wl_dpc after down */
2117                 wlc_bmac_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0);
2118                 return;
2119         }
2120
2121         /*
2122          * mac no longer enables phyclk automatically when driver accesses
2123          * phyreg throughput mac, AND phy_reset is skipped at early stage when
2124          * band->pi is invalid. need to enable PHY CLK
2125          */
2126         flags |= SICF_PCLKE;
2127
2128         /* reset the core
2129          * In chips with PMU, the fastclk request goes through d11 core reg 0x1e0, which
2130          *  is cleared by the core_reset. have to re-request it.
2131          *  This adds some delay and we can optimize it by also requesting fastclk through
2132          *  chipcommon during this period if necessary. But that has to work coordinate
2133          *  with other driver like mips/arm since they may touch chipcommon as well.
2134          */
2135         wlc_hw->clk = false;
2136         ai_core_reset(wlc_hw->sih, flags, resetbits);
2137         wlc_hw->clk = true;
2138         if (wlc_hw->band && wlc_hw->band->pi)
2139                 wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true);
2140
2141         wlc_mctrl_reset(wlc_hw);
2142
2143         if (PMUCTL_ENAB(wlc_hw->sih))
2144                 wlc_clkctl_clk(wlc_hw, CLK_FAST);
2145
2146         wlc_bmac_phy_reset(wlc_hw);
2147
2148         /* turn on PHY_PLL */
2149         wlc_bmac_core_phypll_ctl(wlc_hw, true);
2150
2151         /* clear sw intstatus */
2152         wlc_hw->wlc->macintstatus = 0;
2153
2154         /* restore the clk setting */
2155         if (!fastclk)
2156                 wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
2157 }
2158
2159 /* txfifo sizes needs to be modified(increased) since the newer cores
2160  * have more memory.
2161  */
2162 static void wlc_corerev_fifofixup(struct wlc_hw_info *wlc_hw)
2163 {
2164         d11regs_t *regs = wlc_hw->regs;
2165         u16 fifo_nu;
2166         u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk;
2167         u16 txfifo_def, txfifo_def1;
2168         u16 txfifo_cmd;
2169
2170         /* tx fifos start at TXFIFO_START_BLK from the Base address */
2171         txfifo_startblk = TXFIFO_START_BLK;
2172
2173         /* sequence of operations:  reset fifo, set fifo size, reset fifo */
2174         for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) {
2175
2176                 txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu];
2177                 txfifo_def = (txfifo_startblk & 0xff) |
2178                     (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT);
2179                 txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) |
2180                     ((((txfifo_endblk -
2181                         1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT);
2182                 txfifo_cmd =
2183                     TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT);
2184
2185                 W_REG(&regs->xmtfifocmd, txfifo_cmd);
2186                 W_REG(&regs->xmtfifodef, txfifo_def);
2187                 W_REG(&regs->xmtfifodef1, txfifo_def1);
2188
2189                 W_REG(&regs->xmtfifocmd, txfifo_cmd);
2190
2191                 txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu];
2192         }
2193         /*
2194          * need to propagate to shm location to be in sync since ucode/hw won't
2195          * do this
2196          */
2197         wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE0,
2198                            wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]);
2199         wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE1,
2200                            wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]);
2201         wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE2,
2202                            ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw->
2203                             xmtfifo_sz[TX_AC_BK_FIFO]));
2204         wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE3,
2205                            ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw->
2206                             xmtfifo_sz[TX_BCMC_FIFO]));
2207 }
2208
2209 /* d11 core init
2210  *   reset PSM
2211  *   download ucode/PCM
2212  *   let ucode run to suspended
2213  *   download ucode inits
2214  *   config other core registers
2215  *   init dma
2216  */
2217 static void wlc_coreinit(struct wlc_info *wlc)
2218 {
2219         struct wlc_hw_info *wlc_hw = wlc->hw;
2220         d11regs_t *regs;
2221         u32 sflags;
2222         uint bcnint_us;
2223         uint i = 0;
2224         bool fifosz_fixup = false;
2225         int err = 0;
2226         u16 buf[NFIFO];
2227         struct wiphy *wiphy = wlc->wiphy;
2228
2229         regs = wlc_hw->regs;
2230
2231         BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
2232
2233         /* reset PSM */
2234         wlc_bmac_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE));
2235
2236         wlc_ucode_download(wlc_hw);
2237         /*
2238          * FIFOSZ fixup. driver wants to controls the fifo allocation.
2239          */
2240         fifosz_fixup = true;
2241
2242         /* let the PSM run to the suspended state, set mode to BSS STA */
2243         W_REG(&regs->macintstatus, -1);
2244         wlc_bmac_mctrl(wlc_hw, ~0,
2245                        (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE));
2246
2247         /* wait for ucode to self-suspend after auto-init */
2248         SPINWAIT(((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0),
2249                  1000 * 1000);
2250         if ((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0)
2251                 wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-"
2252                           "suspend!\n", wlc_hw->unit);
2253
2254         wlc_gpio_init(wlc);
2255
2256         sflags = ai_core_sflags(wlc_hw->sih, 0, 0);
2257
2258         if (D11REV_IS(wlc_hw->corerev, 23)) {
2259                 if (WLCISNPHY(wlc_hw->band))
2260                         wlc_write_inits(wlc_hw, d11n0initvals16);
2261                 else
2262                         wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
2263                                   " %d\n", __func__, wlc_hw->unit,
2264                                   wlc_hw->corerev);
2265         } else if (D11REV_IS(wlc_hw->corerev, 24)) {
2266                 if (WLCISLCNPHY(wlc_hw->band)) {
2267                         wlc_write_inits(wlc_hw, d11lcn0initvals24);
2268                 } else {
2269                         wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
2270                                   " %d\n", __func__, wlc_hw->unit,
2271                                   wlc_hw->corerev);
2272                 }
2273         } else {
2274                 wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
2275                           __func__, wlc_hw->unit, wlc_hw->corerev);
2276         }
2277
2278         /* For old ucode, txfifo sizes needs to be modified(increased) */
2279         if (fifosz_fixup == true) {
2280                 wlc_corerev_fifofixup(wlc_hw);
2281         }
2282
2283         /* check txfifo allocations match between ucode and driver */
2284         buf[TX_AC_BE_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE0);
2285         if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) {
2286                 i = TX_AC_BE_FIFO;
2287                 err = -1;
2288         }
2289         buf[TX_AC_VI_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE1);
2290         if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) {
2291                 i = TX_AC_VI_FIFO;
2292                 err = -1;
2293         }
2294         buf[TX_AC_BK_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE2);
2295         buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff;
2296         buf[TX_AC_BK_FIFO] &= 0xff;
2297         if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) {
2298                 i = TX_AC_BK_FIFO;
2299                 err = -1;
2300         }
2301         if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) {
2302                 i = TX_AC_VO_FIFO;
2303                 err = -1;
2304         }
2305         buf[TX_BCMC_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE3);
2306         buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff;
2307         buf[TX_BCMC_FIFO] &= 0xff;
2308         if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) {
2309                 i = TX_BCMC_FIFO;
2310                 err = -1;
2311         }
2312         if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) {
2313                 i = TX_ATIM_FIFO;
2314                 err = -1;
2315         }
2316         if (err != 0) {
2317                 wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d"
2318                           " driver size %d index %d\n", buf[i],
2319                           wlc_hw->xmtfifo_sz[i], i);
2320         }
2321
2322         /* make sure we can still talk to the mac */
2323         WARN_ON(R_REG(&regs->maccontrol) == 0xffffffff);
2324
2325         /* band-specific inits done by wlc_bsinit() */
2326
2327         /* Set up frame burst size and antenna swap threshold init values */
2328         wlc_bmac_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST);
2329         wlc_bmac_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT);
2330
2331         /* enable one rx interrupt per received frame */
2332         W_REG(&regs->intrcvlazy[0], (1 << IRL_FC_SHIFT));
2333
2334         /* set the station mode (BSS STA) */
2335         wlc_bmac_mctrl(wlc_hw,
2336                        (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP),
2337                        (MCTL_INFRA | MCTL_DISCARD_PMQ));
2338
2339         /* set up Beacon interval */
2340         bcnint_us = 0x8000 << 10;
2341         W_REG(&regs->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT));
2342         W_REG(&regs->tsf_cfpstart, bcnint_us);
2343         W_REG(&regs->macintstatus, MI_GP1);
2344
2345         /* write interrupt mask */
2346         W_REG(&regs->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK);
2347
2348         /* allow the MAC to control the PHY clock (dynamic on/off) */
2349         wlc_bmac_macphyclk_set(wlc_hw, ON);
2350
2351         /* program dynamic clock control fast powerup delay register */
2352         wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih);
2353         W_REG(&regs->scc_fastpwrup_dly, wlc->fastpwrup_dly);
2354
2355         /* tell the ucode the corerev */
2356         wlc_bmac_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev);
2357
2358         /* tell the ucode MAC capabilities */
2359         wlc_bmac_write_shm(wlc_hw, M_MACHW_CAP_L,
2360                            (u16) (wlc_hw->machwcap & 0xffff));
2361         wlc_bmac_write_shm(wlc_hw, M_MACHW_CAP_H,
2362                            (u16) ((wlc_hw->
2363                                       machwcap >> 16) & 0xffff));
2364
2365         /* write retry limits to SCR, this done after PSM init */
2366         W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
2367         (void)R_REG(&regs->objaddr);
2368         W_REG(&regs->objdata, wlc_hw->SRL);
2369         W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
2370         (void)R_REG(&regs->objaddr);
2371         W_REG(&regs->objdata, wlc_hw->LRL);
2372
2373         /* write rate fallback retry limits */
2374         wlc_bmac_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL);
2375         wlc_bmac_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL);
2376
2377         AND_REG(&regs->ifs_ctl, 0x0FFF);
2378         W_REG(&regs->ifs_aifsn, EDCF_AIFSN_MIN);
2379
2380         /* dma initializations */
2381         wlc->txpend16165war = 0;
2382
2383         /* init the tx dma engines */
2384         for (i = 0; i < NFIFO; i++) {
2385                 if (wlc_hw->di[i])
2386                         dma_txinit(wlc_hw->di[i]);
2387         }
2388
2389         /* init the rx dma engine(s) and post receive buffers */
2390         dma_rxinit(wlc_hw->di[RX_FIFO]);
2391         dma_rxfill(wlc_hw->di[RX_FIFO]);
2392 }
2393
2394 /* This function is used for changing the tsf frac register
2395  * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz
2396  * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz
2397  * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz
2398  * HTPHY Formula is 2^26/freq(MHz) e.g.
2399  * For spuron2 - 126MHz -> 2^26/126 = 532610.0
2400  *  - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082
2401  * For spuron: 123MHz -> 2^26/123    = 545600.5
2402  *  - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341
2403  * For spur off: 120MHz -> 2^26/120    = 559240.5
2404  *  - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889
2405  */
2406
2407 void wlc_bmac_switch_macfreq(struct wlc_hw_info *wlc_hw, u8 spurmode)
2408 {
2409         d11regs_t *regs;
2410         regs = wlc_hw->regs;
2411
2412         if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
2413             (wlc_hw->sih->chip == BCM43225_CHIP_ID)) {
2414                 if (spurmode == WL_SPURAVOID_ON2) {     /* 126Mhz */
2415                         W_REG(&regs->tsf_clk_frac_l, 0x2082);
2416                         W_REG(&regs->tsf_clk_frac_h, 0x8);
2417                 } else if (spurmode == WL_SPURAVOID_ON1) {      /* 123Mhz */
2418                         W_REG(&regs->tsf_clk_frac_l, 0x5341);
2419                         W_REG(&regs->tsf_clk_frac_h, 0x8);
2420                 } else {        /* 120Mhz */
2421                         W_REG(&regs->tsf_clk_frac_l, 0x8889);
2422                         W_REG(&regs->tsf_clk_frac_h, 0x8);
2423                 }
2424         } else if (WLCISLCNPHY(wlc_hw->band)) {
2425                 if (spurmode == WL_SPURAVOID_ON1) {     /* 82Mhz */
2426                         W_REG(&regs->tsf_clk_frac_l, 0x7CE0);
2427                         W_REG(&regs->tsf_clk_frac_h, 0xC);
2428                 } else {        /* 80Mhz */
2429                         W_REG(&regs->tsf_clk_frac_l, 0xCCCD);
2430                         W_REG(&regs->tsf_clk_frac_h, 0xC);
2431                 }
2432         }
2433 }
2434
2435 /* Initialize GPIOs that are controlled by D11 core */
2436 static void wlc_gpio_init(struct wlc_info *wlc)
2437 {
2438         struct wlc_hw_info *wlc_hw = wlc->hw;
2439         d11regs_t *regs;
2440         u32 gc, gm;
2441
2442         regs = wlc_hw->regs;
2443
2444         /* use GPIO select 0 to get all gpio signals from the gpio out reg */
2445         wlc_bmac_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0);
2446
2447         /*
2448          * Common GPIO setup:
2449          *      G0 = LED 0 = WLAN Activity
2450          *      G1 = LED 1 = WLAN 2.4 GHz Radio State
2451          *      G2 = LED 2 = WLAN 5 GHz Radio State
2452          *      G4 = radio disable input (HI enabled, LO disabled)
2453          */
2454
2455         gc = gm = 0;
2456
2457         /* Allocate GPIOs for mimo antenna diversity feature */
2458         if (wlc_hw->antsel_type == ANTSEL_2x3) {
2459                 /* Enable antenna diversity, use 2x3 mode */
2460                 wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
2461                              MHF3_ANTSEL_EN, WLC_BAND_ALL);
2462                 wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE,
2463                              MHF3_ANTSEL_MODE, WLC_BAND_ALL);
2464
2465                 /* init superswitch control */
2466                 wlc_phy_antsel_init(wlc_hw->band->pi, false);
2467
2468         } else if (wlc_hw->antsel_type == ANTSEL_2x4) {
2469                 gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13);
2470                 /*
2471                  * The board itself is powered by these GPIOs
2472                  * (when not sending pattern) so set them high
2473                  */
2474                 OR_REG(&regs->psm_gpio_oe,
2475                        (BOARD_GPIO_12 | BOARD_GPIO_13));
2476                 OR_REG(&regs->psm_gpio_out,
2477                        (BOARD_GPIO_12 | BOARD_GPIO_13));
2478
2479                 /* Enable antenna diversity, use 2x4 mode */
2480                 wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
2481                              MHF3_ANTSEL_EN, WLC_BAND_ALL);
2482                 wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0,
2483                              WLC_BAND_ALL);
2484
2485                 /* Configure the desired clock to be 4Mhz */
2486                 wlc_bmac_write_shm(wlc_hw, M_ANTSEL_CLKDIV,
2487                                    ANTSEL_CLKDIV_4MHZ);
2488         }
2489
2490         /* gpio 9 controls the PA.  ucode is responsible for wiggling out and oe */
2491         if (wlc_hw->boardflags & BFL_PACTRL)
2492                 gm |= gc |= BOARD_GPIO_PACTRL;
2493
2494         /* apply to gpiocontrol register */
2495         ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY);
2496 }
2497
2498 static void wlc_ucode_download(struct wlc_hw_info *wlc_hw)
2499 {
2500         struct wlc_info *wlc;
2501         wlc = wlc_hw->wlc;
2502
2503         if (wlc_hw->ucode_loaded)
2504                 return;
2505
2506         if (D11REV_IS(wlc_hw->corerev, 23)) {
2507                 if (WLCISNPHY(wlc_hw->band)) {
2508                         wlc_ucode_write(wlc_hw, bcm43xx_16_mimo,
2509                                         bcm43xx_16_mimosz);
2510                         wlc_hw->ucode_loaded = true;
2511                 } else
2512                         wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
2513                                   "corerev %d\n",
2514                                   __func__, wlc_hw->unit, wlc_hw->corerev);
2515         } else if (D11REV_IS(wlc_hw->corerev, 24)) {
2516                 if (WLCISLCNPHY(wlc_hw->band)) {
2517                         wlc_ucode_write(wlc_hw, bcm43xx_24_lcn,
2518                                         bcm43xx_24_lcnsz);
2519                         wlc_hw->ucode_loaded = true;
2520                 } else {
2521                         wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
2522                                   "corerev %d\n",
2523                                   __func__, wlc_hw->unit, wlc_hw->corerev);
2524                 }
2525         }
2526 }
2527
2528 static void wlc_ucode_write(struct wlc_hw_info *wlc_hw, const u32 ucode[],
2529                               const uint nbytes) {
2530         d11regs_t *regs = wlc_hw->regs;
2531         uint i;
2532         uint count;
2533
2534         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
2535
2536         count = (nbytes / sizeof(u32));
2537
2538         W_REG(&regs->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL));
2539         (void)R_REG(&regs->objaddr);
2540         for (i = 0; i < count; i++)
2541                 W_REG(&regs->objdata, ucode[i]);
2542 }
2543
2544 static void wlc_write_inits(struct wlc_hw_info *wlc_hw,
2545                             const struct d11init *inits)
2546 {
2547         int i;
2548         volatile u8 *base;
2549
2550         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
2551
2552         base = (volatile u8 *)wlc_hw->regs;
2553
2554         for (i = 0; inits[i].addr != 0xffff; i++) {
2555                 if (inits[i].size == 2)
2556                         W_REG((u16 *)(base + inits[i].addr),
2557                               inits[i].value);
2558                 else if (inits[i].size == 4)
2559                         W_REG((u32 *)(base + inits[i].addr),
2560                               inits[i].value);
2561         }
2562 }
2563
2564 static void wlc_ucode_txant_set(struct wlc_hw_info *wlc_hw)
2565 {
2566         u16 phyctl;
2567         u16 phytxant = wlc_hw->bmac_phytxant;
2568         u16 mask = PHY_TXC_ANT_MASK;
2569
2570         /* set the Probe Response frame phy control word */
2571         phyctl = wlc_bmac_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS);
2572         phyctl = (phyctl & ~mask) | phytxant;
2573         wlc_bmac_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl);
2574
2575         /* set the Response (ACK/CTS) frame phy control word */
2576         phyctl = wlc_bmac_read_shm(wlc_hw, M_RSP_PCTLWD);
2577         phyctl = (phyctl & ~mask) | phytxant;
2578         wlc_bmac_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl);
2579 }
2580
2581 void wlc_bmac_txant_set(struct wlc_hw_info *wlc_hw, u16 phytxant)
2582 {
2583         /* update sw state */
2584         wlc_hw->bmac_phytxant = phytxant;
2585
2586         /* push to ucode if up */
2587         if (!wlc_hw->up)
2588                 return;
2589         wlc_ucode_txant_set(wlc_hw);
2590
2591 }
2592
2593 u16 wlc_bmac_get_txant(struct wlc_hw_info *wlc_hw)
2594 {
2595         return (u16) wlc_hw->wlc->stf->txant;
2596 }
2597
2598 void wlc_bmac_antsel_type_set(struct wlc_hw_info *wlc_hw, u8 antsel_type)
2599 {
2600         wlc_hw->antsel_type = antsel_type;
2601
2602         /* Update the antsel type for phy module to use */
2603         wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type);
2604 }
2605
2606 void wlc_bmac_fifoerrors(struct wlc_hw_info *wlc_hw)
2607 {
2608         bool fatal = false;
2609         uint unit;
2610         uint intstatus, idx;
2611         d11regs_t *regs = wlc_hw->regs;
2612         struct wiphy *wiphy = wlc_hw->wlc->wiphy;
2613
2614         unit = wlc_hw->unit;
2615
2616         for (idx = 0; idx < NFIFO; idx++) {
2617                 /* read intstatus register and ignore any non-error bits */
2618                 intstatus =
2619                     R_REG(&regs->intctrlregs[idx].intstatus) & I_ERRORS;
2620                 if (!intstatus)
2621                         continue;
2622
2623                 BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n",
2624                         unit, idx, intstatus);
2625
2626                 if (intstatus & I_RO) {
2627                         wiphy_err(wiphy, "wl%d: fifo %d: receive fifo "
2628                                   "overflow\n", unit, idx);
2629                         fatal = true;
2630                 }
2631
2632                 if (intstatus & I_PC) {
2633                         wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n",
2634                                  unit, idx);
2635                         fatal = true;
2636                 }
2637
2638                 if (intstatus & I_PD) {
2639                         wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit,
2640                                   idx);
2641                         fatal = true;
2642                 }
2643
2644                 if (intstatus & I_DE) {
2645                         wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol "
2646                                   "error\n", unit, idx);
2647                         fatal = true;
2648                 }
2649
2650                 if (intstatus & I_RU) {
2651                         wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor "
2652                                   "underflow\n", idx, unit);
2653                 }
2654
2655                 if (intstatus & I_XU) {
2656                         wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo "
2657                                   "underflow\n", idx, unit);
2658                         fatal = true;
2659                 }
2660
2661                 if (fatal) {
2662                         wlc_fatal_error(wlc_hw->wlc);   /* big hammer */
2663                         break;
2664                 } else
2665                         W_REG(&regs->intctrlregs[idx].intstatus,
2666                               intstatus);
2667         }
2668 }
2669
2670 void wlc_intrson(struct wlc_info *wlc)
2671 {
2672         struct wlc_hw_info *wlc_hw = wlc->hw;
2673         wlc->macintmask = wlc->defmacintmask;
2674         W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
2675 }
2676
2677 /* callback for siutils.c, which has only wlc handler, no wl
2678  * they both check up, not only because there is no need to off/restore d11 interrupt
2679  *  but also because per-port code may require sync with valid interrupt.
2680  */
2681
2682 static u32 wlc_wlintrsoff(struct wlc_info *wlc)
2683 {
2684         if (!wlc->hw->up)
2685                 return 0;
2686
2687         return wl_intrsoff(wlc->wl);
2688 }
2689
2690 static void wlc_wlintrsrestore(struct wlc_info *wlc, u32 macintmask)
2691 {
2692         if (!wlc->hw->up)
2693                 return;
2694
2695         wl_intrsrestore(wlc->wl, macintmask);
2696 }
2697
2698 u32 wlc_intrsoff(struct wlc_info *wlc)
2699 {
2700         struct wlc_hw_info *wlc_hw = wlc->hw;
2701         u32 macintmask;
2702
2703         if (!wlc_hw->clk)
2704                 return 0;
2705
2706         macintmask = wlc->macintmask;   /* isr can still happen */
2707
2708         W_REG(&wlc_hw->regs->macintmask, 0);
2709         (void)R_REG(&wlc_hw->regs->macintmask); /* sync readback */
2710         udelay(1);              /* ensure int line is no longer driven */
2711         wlc->macintmask = 0;
2712
2713         /* return previous macintmask; resolve race between us and our isr */
2714         return wlc->macintstatus ? 0 : macintmask;
2715 }
2716
2717 void wlc_intrsrestore(struct wlc_info *wlc, u32 macintmask)
2718 {
2719         struct wlc_hw_info *wlc_hw = wlc->hw;
2720         if (!wlc_hw->clk)
2721                 return;
2722
2723         wlc->macintmask = macintmask;
2724         W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
2725 }
2726
2727 static void wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool on, mbool flags)
2728 {
2729         u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
2730
2731         if (on) {
2732                 /* suspend tx fifos */
2733                 wlc_bmac_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO);
2734                 wlc_bmac_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO);
2735                 wlc_bmac_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO);
2736                 wlc_bmac_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO);
2737
2738                 /* zero the address match register so we do not send ACKs */
2739                 wlc_bmac_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
2740                                        null_ether_addr);
2741         } else {
2742                 /* resume tx fifos */
2743                 if (!wlc_hw->wlc->tx_suspended) {
2744                         wlc_bmac_tx_fifo_resume(wlc_hw, TX_DATA_FIFO);
2745                 }
2746                 wlc_bmac_tx_fifo_resume(wlc_hw, TX_CTL_FIFO);
2747                 wlc_bmac_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO);
2748                 wlc_bmac_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO);
2749
2750                 /* Restore address */
2751                 wlc_bmac_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
2752                                        wlc_hw->etheraddr);
2753         }
2754
2755         wlc_phy_mute_upd(wlc_hw->band->pi, on, flags);
2756
2757         if (on)
2758                 wlc_ucode_mute_override_set(wlc_hw);
2759         else
2760                 wlc_ucode_mute_override_clear(wlc_hw);
2761 }
2762
2763 int wlc_bmac_xmtfifo_sz_get(struct wlc_hw_info *wlc_hw, uint fifo, uint *blocks)
2764 {
2765         if (fifo >= NFIFO)
2766                 return -EINVAL;
2767
2768         *blocks = wlc_hw->xmtfifo_sz[fifo];
2769
2770         return 0;
2771 }
2772
2773 /* wlc_bmac_tx_fifo_suspended:
2774  * Check the MAC's tx suspend status for a tx fifo.
2775  *
2776  * When the MAC acknowledges a tx suspend, it indicates that no more
2777  * packets will be transmitted out the radio. This is independent of
2778  * DMA channel suspension---the DMA may have finished suspending, or may still
2779  * be pulling data into a tx fifo, by the time the MAC acks the suspend
2780  * request.
2781  */
2782 static bool wlc_bmac_tx_fifo_suspended(struct wlc_hw_info *wlc_hw, uint tx_fifo)
2783 {
2784         /* check that a suspend has been requested and is no longer pending */
2785
2786         /*
2787          * for DMA mode, the suspend request is set in xmtcontrol of the DMA engine,
2788          * and the tx fifo suspend at the lower end of the MAC is acknowledged in the
2789          * chnstatus register.
2790          * The tx fifo suspend completion is independent of the DMA suspend completion and
2791          *   may be acked before or after the DMA is suspended.
2792          */
2793         if (dma_txsuspended(wlc_hw->di[tx_fifo]) &&
2794             (R_REG(&wlc_hw->regs->chnstatus) &
2795              (1 << tx_fifo)) == 0)
2796                 return true;
2797
2798         return false;
2799 }
2800
2801 static void wlc_bmac_tx_fifo_suspend(struct wlc_hw_info *wlc_hw, uint tx_fifo)
2802 {
2803         u8 fifo = 1 << tx_fifo;
2804
2805         /* Two clients of this code, 11h Quiet period and scanning. */
2806
2807         /* only suspend if not already suspended */
2808         if ((wlc_hw->suspended_fifos & fifo) == fifo)
2809                 return;
2810
2811         /* force the core awake only if not already */
2812         if (wlc_hw->suspended_fifos == 0)
2813                 wlc_ucode_wake_override_set(wlc_hw, WLC_WAKE_OVERRIDE_TXFIFO);
2814
2815         wlc_hw->suspended_fifos |= fifo;
2816
2817         if (wlc_hw->di[tx_fifo]) {
2818                 /* Suspending AMPDU transmissions in the middle can cause underflow
2819                  * which may result in mismatch between ucode and driver
2820                  * so suspend the mac before suspending the FIFO
2821                  */
2822                 if (WLC_PHY_11N_CAP(wlc_hw->band))
2823                         wlc_suspend_mac_and_wait(wlc_hw->wlc);
2824
2825                 dma_txsuspend(wlc_hw->di[tx_fifo]);
2826
2827                 if (WLC_PHY_11N_CAP(wlc_hw->band))
2828                         wlc_enable_mac(wlc_hw->wlc);
2829         }
2830 }
2831
2832 static void wlc_bmac_tx_fifo_resume(struct wlc_hw_info *wlc_hw, uint tx_fifo)
2833 {
2834         /* BMAC_NOTE: WLC_TX_FIFO_ENAB is done in wlc_dpc() for DMA case but need to be done
2835          * here for PIO otherwise the watchdog will catch the inconsistency and fire
2836          */
2837         /* Two clients of this code, 11h Quiet period and scanning. */
2838         if (wlc_hw->di[tx_fifo])
2839                 dma_txresume(wlc_hw->di[tx_fifo]);
2840
2841         /* allow core to sleep again */
2842         if (wlc_hw->suspended_fifos == 0)
2843                 return;
2844         else {
2845                 wlc_hw->suspended_fifos &= ~(1 << tx_fifo);
2846                 if (wlc_hw->suspended_fifos == 0)
2847                         wlc_ucode_wake_override_clear(wlc_hw,
2848                                                       WLC_WAKE_OVERRIDE_TXFIFO);
2849         }
2850 }
2851
2852 /*
2853  * Read and clear macintmask and macintstatus and intstatus registers.
2854  * This routine should be called with interrupts off
2855  * Return:
2856  *   -1 if DEVICEREMOVED(wlc) evaluates to true;
2857  *   0 if the interrupt is not for us, or we are in some special cases;
2858  *   device interrupt status bits otherwise.
2859  */
2860 static inline u32 wlc_intstatus(struct wlc_info *wlc, bool in_isr)
2861 {
2862         struct wlc_hw_info *wlc_hw = wlc->hw;
2863         d11regs_t *regs = wlc_hw->regs;
2864         u32 macintstatus;
2865
2866         /* macintstatus includes a DMA interrupt summary bit */
2867         macintstatus = R_REG(&regs->macintstatus);
2868
2869         BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit,
2870                  macintstatus);
2871
2872         /* detect cardbus removed, in power down(suspend) and in reset */
2873         if (DEVICEREMOVED(wlc))
2874                 return -1;
2875
2876         /* DEVICEREMOVED succeeds even when the core is still resetting,
2877          * handle that case here.
2878          */
2879         if (macintstatus == 0xffffffff)
2880                 return 0;
2881
2882         /* defer unsolicited interrupts */
2883         macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask);
2884
2885         /* if not for us */
2886         if (macintstatus == 0)
2887                 return 0;
2888
2889         /* interrupts are already turned off for CFE build
2890          * Caution: For CFE Turning off the interrupts again has some undesired
2891          * consequences
2892          */
2893         /* turn off the interrupts */
2894         W_REG(&regs->macintmask, 0);
2895         (void)R_REG(&regs->macintmask); /* sync readback */
2896         wlc->macintmask = 0;
2897
2898         /* clear device interrupts */
2899         W_REG(&regs->macintstatus, macintstatus);
2900
2901         /* MI_DMAINT is indication of non-zero intstatus */
2902         if (macintstatus & MI_DMAINT) {
2903                 /*
2904                  * only fifo interrupt enabled is I_RI in
2905                  * RX_FIFO. If MI_DMAINT is set, assume it
2906                  * is set and clear the interrupt.
2907                  */
2908                 W_REG(&regs->intctrlregs[RX_FIFO].intstatus,
2909                       DEF_RXINTMASK);
2910         }
2911
2912         return macintstatus;
2913 }
2914
2915 /* Update wlc->macintstatus and wlc->intstatus[]. */
2916 /* Return true if they are updated successfully. false otherwise */
2917 bool wlc_intrsupd(struct wlc_info *wlc)
2918 {
2919         u32 macintstatus;
2920
2921         /* read and clear macintstatus and intstatus registers */
2922         macintstatus = wlc_intstatus(wlc, false);
2923
2924         /* device is removed */
2925         if (macintstatus == 0xffffffff)
2926                 return false;
2927
2928         /* update interrupt status in software */
2929         wlc->macintstatus |= macintstatus;
2930
2931         return true;
2932 }
2933
2934 /*
2935  * First-level interrupt processing.
2936  * Return true if this was our interrupt, false otherwise.
2937  * *wantdpc will be set to true if further wlc_dpc() processing is required,
2938  * false otherwise.
2939  */
2940 bool wlc_isr(struct wlc_info *wlc, bool *wantdpc)
2941 {
2942         struct wlc_hw_info *wlc_hw = wlc->hw;
2943         u32 macintstatus;
2944
2945         *wantdpc = false;
2946
2947         if (!wlc_hw->up || !wlc->macintmask)
2948                 return false;
2949
2950         /* read and clear macintstatus and intstatus registers */
2951         macintstatus = wlc_intstatus(wlc, true);
2952
2953         if (macintstatus == 0xffffffff)
2954                 wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code"
2955                           " path\n");
2956
2957         /* it is not for us */
2958         if (macintstatus == 0)
2959                 return false;
2960
2961         *wantdpc = true;
2962
2963         /* save interrupt status bits */
2964         wlc->macintstatus = macintstatus;
2965
2966         return true;
2967
2968 }
2969
2970 static bool
2971 wlc_bmac_dotxstatus(struct wlc_hw_info *wlc_hw, tx_status_t *txs, u32 s2)
2972 {
2973         /* discard intermediate indications for ucode with one legitimate case:
2974          *   e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent
2975          *   tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts
2976          *   transmission count)
2977          */
2978         if (!(txs->status & TX_STATUS_AMPDU)
2979             && (txs->status & TX_STATUS_INTERMEDIATE)) {
2980                 return false;
2981         }
2982
2983         return wlc_dotxstatus(wlc_hw->wlc, txs, s2);
2984 }
2985
2986 /* process tx completion events in BMAC
2987  * Return true if more tx status need to be processed. false otherwise.
2988  */
2989 static bool
2990 wlc_bmac_txstatus(struct wlc_hw_info *wlc_hw, bool bound, bool *fatal)
2991 {
2992         bool morepending = false;
2993         struct wlc_info *wlc = wlc_hw->wlc;
2994         d11regs_t *regs;
2995         tx_status_t txstatus, *txs;
2996         u32 s1, s2;
2997         uint n = 0;
2998         /*
2999          * Param 'max_tx_num' indicates max. # tx status to process before
3000          * break out.
3001          */
3002         uint max_tx_num = bound ? wlc->pub->tunables->txsbnd : -1;
3003
3004         BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
3005
3006         txs = &txstatus;
3007         regs = wlc_hw->regs;
3008         while (!(*fatal)
3009                && (s1 = R_REG(&regs->frmtxstatus)) & TXS_V) {
3010
3011                 if (s1 == 0xffffffff) {
3012                         wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n",
3013                                 wlc_hw->unit, __func__);
3014                         return morepending;
3015                 }
3016
3017                         s2 = R_REG(&regs->frmtxstatus2);
3018
3019                 txs->status = s1 & TXS_STATUS_MASK;
3020                 txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
3021                 txs->sequence = s2 & TXS_SEQ_MASK;
3022                 txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT;
3023                 txs->lasttxtime = 0;
3024
3025                 *fatal = wlc_bmac_dotxstatus(wlc_hw, txs, s2);
3026
3027                 /* !give others some time to run! */
3028                 if (++n >= max_tx_num)
3029                         break;
3030         }
3031
3032         if (*fatal)
3033                 return 0;
3034
3035         if (n >= max_tx_num)
3036                 morepending = true;
3037
3038         if (!pktq_empty(&wlc->pkt_queue->q))
3039                 wlc_send_q(wlc);
3040
3041         return morepending;
3042 }
3043
3044 void wlc_suspend_mac_and_wait(struct wlc_info *wlc)
3045 {
3046         struct wlc_hw_info *wlc_hw = wlc->hw;
3047         d11regs_t *regs = wlc_hw->regs;
3048         u32 mc, mi;
3049         struct wiphy *wiphy = wlc->wiphy;
3050
3051         BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
3052                 wlc_hw->band->bandunit);
3053
3054         /*
3055          * Track overlapping suspend requests
3056          */
3057         wlc_hw->mac_suspend_depth++;
3058         if (wlc_hw->mac_suspend_depth > 1)
3059                 return;
3060
3061         /* force the core awake */
3062         wlc_ucode_wake_override_set(wlc_hw, WLC_WAKE_OVERRIDE_MACSUSPEND);
3063
3064         mc = R_REG(&regs->maccontrol);
3065
3066         if (mc == 0xffffffff) {
3067                 wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
3068                           __func__);
3069                 wl_down(wlc->wl);
3070                 return;
3071         }
3072         WARN_ON(mc & MCTL_PSM_JMP_0);
3073         WARN_ON(!(mc & MCTL_PSM_RUN));
3074         WARN_ON(!(mc & MCTL_EN_MAC));
3075
3076         mi = R_REG(&regs->macintstatus);
3077         if (mi == 0xffffffff) {
3078                 wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
3079                           __func__);
3080                 wl_down(wlc->wl);
3081                 return;
3082         }
3083         WARN_ON(mi & MI_MACSSPNDD);
3084
3085         wlc_bmac_mctrl(wlc_hw, MCTL_EN_MAC, 0);
3086
3087         SPINWAIT(!(R_REG(&regs->macintstatus) & MI_MACSSPNDD),
3088                  WLC_MAX_MAC_SUSPEND);
3089
3090         if (!(R_REG(&regs->macintstatus) & MI_MACSSPNDD)) {
3091                 wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS"
3092                           " and MI_MACSSPNDD is still not on.\n",
3093                           wlc_hw->unit, WLC_MAX_MAC_SUSPEND);
3094                 wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, "
3095                           "psm_brc 0x%04x\n", wlc_hw->unit,
3096                           R_REG(&regs->psmdebug),
3097                           R_REG(&regs->phydebug),
3098                           R_REG(&regs->psm_brc));
3099         }
3100
3101         mc = R_REG(&regs->maccontrol);
3102         if (mc == 0xffffffff) {
3103                 wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
3104                           __func__);
3105                 wl_down(wlc->wl);
3106                 return;
3107         }
3108         WARN_ON(mc & MCTL_PSM_JMP_0);
3109         WARN_ON(!(mc & MCTL_PSM_RUN));
3110         WARN_ON(mc & MCTL_EN_MAC);
3111 }
3112
3113 void wlc_enable_mac(struct wlc_info *wlc)
3114 {
3115         struct wlc_hw_info *wlc_hw = wlc->hw;
3116         d11regs_t *regs = wlc_hw->regs;
3117         u32 mc, mi;
3118
3119         BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
3120                 wlc->band->bandunit);
3121
3122         /*
3123          * Track overlapping suspend requests
3124          */
3125         wlc_hw->mac_suspend_depth--;
3126         if (wlc_hw->mac_suspend_depth > 0)
3127                 return;
3128
3129         mc = R_REG(&regs->maccontrol);
3130         WARN_ON(mc & MCTL_PSM_JMP_0);
3131         WARN_ON(mc & MCTL_EN_MAC);
3132         WARN_ON(!(mc & MCTL_PSM_RUN));
3133
3134         wlc_bmac_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC);
3135         W_REG(&regs->macintstatus, MI_MACSSPNDD);
3136
3137         mc = R_REG(&regs->maccontrol);
3138         WARN_ON(mc & MCTL_PSM_JMP_0);
3139         WARN_ON(!(mc & MCTL_EN_MAC));
3140         WARN_ON(!(mc & MCTL_PSM_RUN));
3141
3142         mi = R_REG(&regs->macintstatus);
3143         WARN_ON(mi & MI_MACSSPNDD);
3144
3145         wlc_ucode_wake_override_clear(wlc_hw, WLC_WAKE_OVERRIDE_MACSUSPEND);
3146 }
3147
3148 static void wlc_upd_ofdm_pctl1_table(struct wlc_hw_info *wlc_hw)
3149 {
3150         u8 rate;
3151         u8 rates[8] = {
3152                 WLC_RATE_6M, WLC_RATE_9M, WLC_RATE_12M, WLC_RATE_18M,
3153                 WLC_RATE_24M, WLC_RATE_36M, WLC_RATE_48M, WLC_RATE_54M
3154         };
3155         u16 entry_ptr;
3156         u16 pctl1;
3157         uint i;
3158
3159         if (!WLC_PHY_11N_CAP(wlc_hw->band))
3160                 return;
3161
3162         /* walk the phy rate table and update the entries */
3163         for (i = 0; i < ARRAY_SIZE(rates); i++) {
3164                 rate = rates[i];
3165
3166                 entry_ptr = wlc_bmac_ofdm_ratetable_offset(wlc_hw, rate);
3167
3168                 /* read the SHM Rate Table entry OFDM PCTL1 values */
3169                 pctl1 =
3170                     wlc_bmac_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS);
3171
3172                 /* modify the value */
3173                 pctl1 &= ~PHY_TXC1_MODE_MASK;
3174                 pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT);
3175
3176                 /* Update the SHM Rate Table entry OFDM PCTL1 values */
3177                 wlc_bmac_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS,
3178                                    pctl1);
3179         }
3180 }
3181
3182 static u16 wlc_bmac_ofdm_ratetable_offset(struct wlc_hw_info *wlc_hw, u8 rate)
3183 {
3184         uint i;
3185         u8 plcp_rate = 0;
3186         struct plcp_signal_rate_lookup {
3187                 u8 rate;
3188                 u8 signal_rate;
3189         };
3190         /* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */
3191         const struct plcp_signal_rate_lookup rate_lookup[] = {
3192                 {WLC_RATE_6M, 0xB},
3193                 {WLC_RATE_9M, 0xF},
3194                 {WLC_RATE_12M, 0xA},
3195                 {WLC_RATE_18M, 0xE},
3196                 {WLC_RATE_24M, 0x9},
3197                 {WLC_RATE_36M, 0xD},
3198                 {WLC_RATE_48M, 0x8},
3199                 {WLC_RATE_54M, 0xC}
3200         };
3201
3202         for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) {
3203                 if (rate == rate_lookup[i].rate) {
3204                         plcp_rate = rate_lookup[i].signal_rate;
3205                         break;
3206                 }
3207         }
3208
3209         /* Find the SHM pointer to the rate table entry by looking in the
3210          * Direct-map Table
3211          */
3212         return 2 * wlc_bmac_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2));
3213 }
3214
3215 void wlc_bmac_band_stf_ss_set(struct wlc_hw_info *wlc_hw, u8 stf_mode)
3216 {
3217         wlc_hw->hw_stf_ss_opmode = stf_mode;
3218
3219         if (wlc_hw->clk)
3220                 wlc_upd_ofdm_pctl1_table(wlc_hw);
3221 }
3222
3223 void
3224 wlc_bmac_read_tsf(struct wlc_hw_info *wlc_hw, u32 *tsf_l_ptr,
3225                   u32 *tsf_h_ptr)
3226 {
3227         d11regs_t *regs = wlc_hw->regs;
3228
3229         /* read the tsf timer low, then high to get an atomic read */
3230         *tsf_l_ptr = R_REG(&regs->tsf_timerlow);
3231         *tsf_h_ptr = R_REG(&regs->tsf_timerhigh);
3232
3233         return;
3234 }
3235
3236 static bool wlc_bmac_validate_chip_access(struct wlc_hw_info *wlc_hw)
3237 {
3238         d11regs_t *regs;
3239         u32 w, val;
3240         struct wiphy *wiphy = wlc_hw->wlc->wiphy;
3241
3242         BCMMSG(wiphy, "wl%d\n", wlc_hw->unit);
3243
3244         regs = wlc_hw->regs;
3245
3246         /* Validate dchip register access */
3247
3248         W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
3249         (void)R_REG(&regs->objaddr);
3250         w = R_REG(&regs->objdata);
3251
3252         /* Can we write and read back a 32bit register? */
3253         W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
3254         (void)R_REG(&regs->objaddr);
3255         W_REG(&regs->objdata, (u32) 0xaa5555aa);
3256
3257         W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
3258         (void)R_REG(&regs->objaddr);
3259         val = R_REG(&regs->objdata);
3260         if (val != (u32) 0xaa5555aa) {
3261                 wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
3262                           "expected 0xaa5555aa\n", wlc_hw->unit, val);
3263                 return false;
3264         }
3265
3266         W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
3267         (void)R_REG(&regs->objaddr);
3268         W_REG(&regs->objdata, (u32) 0x55aaaa55);
3269
3270         W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
3271         (void)R_REG(&regs->objaddr);
3272         val = R_REG(&regs->objdata);
3273         if (val != (u32) 0x55aaaa55) {
3274                 wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
3275                           "expected 0x55aaaa55\n", wlc_hw->unit, val);
3276                 return false;
3277         }
3278
3279         W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
3280         (void)R_REG(&regs->objaddr);
3281         W_REG(&regs->objdata, w);
3282
3283         /* clear CFPStart */
3284         W_REG(&regs->tsf_cfpstart, 0);
3285
3286         w = R_REG(&regs->maccontrol);
3287         if ((w != (MCTL_IHR_EN | MCTL_WAKE)) &&
3288             (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) {
3289                 wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = "
3290                           "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w,
3291                           (MCTL_IHR_EN | MCTL_WAKE),
3292                           (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE));
3293                 return false;
3294         }
3295
3296         return true;
3297 }
3298
3299 #define PHYPLL_WAIT_US  100000
3300
3301 void wlc_bmac_core_phypll_ctl(struct wlc_hw_info *wlc_hw, bool on)
3302 {
3303         d11regs_t *regs;
3304         u32 tmp;
3305
3306         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
3307
3308         tmp = 0;
3309         regs = wlc_hw->regs;
3310
3311         if (on) {
3312                 if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
3313                         OR_REG(&regs->clk_ctl_st,
3314                                (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL |
3315                                 CCS_ERSRC_REQ_PHYPLL));
3316                         SPINWAIT((R_REG(&regs->clk_ctl_st) &
3317                                   (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT),
3318                                  PHYPLL_WAIT_US);
3319
3320                         tmp = R_REG(&regs->clk_ctl_st);
3321                         if ((tmp & (CCS_ERSRC_AVAIL_HT)) !=
3322                             (CCS_ERSRC_AVAIL_HT)) {
3323                                 wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY"
3324                                           " PLL failed\n", __func__);
3325                         }
3326                 } else {
3327                         OR_REG(&regs->clk_ctl_st,
3328                                (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL));
3329                         SPINWAIT((R_REG(&regs->clk_ctl_st) &
3330                                   (CCS_ERSRC_AVAIL_D11PLL |
3331                                    CCS_ERSRC_AVAIL_PHYPLL)) !=
3332                                  (CCS_ERSRC_AVAIL_D11PLL |
3333                                   CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US);
3334
3335                         tmp = R_REG(&regs->clk_ctl_st);
3336                         if ((tmp &
3337                              (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
3338                             !=
3339                             (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) {
3340                                 wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on "
3341                                           "PHY PLL failed\n", __func__);
3342                         }
3343                 }
3344         } else {
3345                 /* Since the PLL may be shared, other cores can still be requesting it;
3346                  * so we'll deassert the request but not wait for status to comply.
3347                  */
3348                 AND_REG(&regs->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL);
3349                 tmp = R_REG(&regs->clk_ctl_st);
3350         }
3351 }
3352
3353 void wlc_coredisable(struct wlc_hw_info *wlc_hw)
3354 {
3355         bool dev_gone;
3356
3357         BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
3358
3359         dev_gone = DEVICEREMOVED(wlc_hw->wlc);
3360
3361         if (dev_gone)
3362                 return;
3363
3364         if (wlc_hw->noreset)
3365                 return;
3366
3367         /* radio off */
3368         wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
3369
3370         /* turn off analog core */
3371         wlc_phy_anacore(wlc_hw->band->pi, OFF);
3372
3373         /* turn off PHYPLL to save power */
3374         wlc_bmac_core_phypll_ctl(wlc_hw, false);
3375
3376         /* No need to set wlc->pub->radio_active = OFF
3377          * because this function needs down capability and
3378          * radio_active is designed for BCMNODOWN.
3379          */
3380
3381         /* remove gpio controls */
3382         if (wlc_hw->ucode_dbgsel)
3383                 ai_gpiocontrol(wlc_hw->sih, ~0, 0, GPIO_DRV_PRIORITY);
3384
3385         wlc_hw->clk = false;
3386         ai_core_disable(wlc_hw->sih, 0);
3387         wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
3388 }
3389
3390 /* power both the pll and external oscillator on/off */
3391 static void wlc_bmac_xtal(struct wlc_hw_info *wlc_hw, bool want)
3392 {
3393         BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want);
3394
3395         /* dont power down if plldown is false or we must poll hw radio disable */
3396         if (!want && wlc_hw->pllreq)
3397                 return;
3398
3399         if (wlc_hw->sih)
3400                 ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want);
3401
3402         wlc_hw->sbclk = want;
3403         if (!wlc_hw->sbclk) {
3404                 wlc_hw->clk = false;
3405                 if (wlc_hw->band && wlc_hw->band->pi)
3406                         wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
3407         }
3408 }
3409
3410 static void wlc_flushqueues(struct wlc_info *wlc)
3411 {
3412         struct wlc_hw_info *wlc_hw = wlc->hw;
3413         uint i;
3414
3415         wlc->txpend16165war = 0;
3416
3417         /* free any posted tx packets */
3418         for (i = 0; i < NFIFO; i++)
3419                 if (wlc_hw->di[i]) {
3420                         dma_txreclaim(wlc_hw->di[i], HNDDMA_RANGE_ALL);
3421                         TXPKTPENDCLR(wlc, i);
3422                         BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i);
3423                 }
3424
3425         /* free any posted rx packets */
3426         dma_rxreclaim(wlc_hw->di[RX_FIFO]);
3427 }
3428
3429 u16 wlc_bmac_read_shm(struct wlc_hw_info *wlc_hw, uint offset)
3430 {
3431         return wlc_bmac_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL);
3432 }
3433
3434 void wlc_bmac_write_shm(struct wlc_hw_info *wlc_hw, uint offset, u16 v)
3435 {
3436         wlc_bmac_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL);
3437 }
3438
3439 static u16
3440 wlc_bmac_read_objmem(struct wlc_hw_info *wlc_hw, uint offset, u32 sel)
3441 {
3442         d11regs_t *regs = wlc_hw->regs;
3443         volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
3444         volatile u16 *objdata_hi = objdata_lo + 1;
3445         u16 v;
3446
3447         W_REG(&regs->objaddr, sel | (offset >> 2));
3448         (void)R_REG(&regs->objaddr);
3449         if (offset & 2) {
3450                 v = R_REG(objdata_hi);
3451         } else {
3452                 v = R_REG(objdata_lo);
3453         }
3454
3455         return v;
3456 }
3457
3458 static void
3459 wlc_bmac_write_objmem(struct wlc_hw_info *wlc_hw, uint offset, u16 v, u32 sel)
3460 {
3461         d11regs_t *regs = wlc_hw->regs;
3462         volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
3463         volatile u16 *objdata_hi = objdata_lo + 1;
3464
3465         W_REG(&regs->objaddr, sel | (offset >> 2));
3466         (void)R_REG(&regs->objaddr);
3467         if (offset & 2) {
3468                 W_REG(objdata_hi, v);
3469         } else {
3470                 W_REG(objdata_lo, v);
3471         }
3472 }
3473
3474 /* Copy a buffer to shared memory of specified type .
3475  * SHM 'offset' needs to be an even address and
3476  * Buffer length 'len' must be an even number of bytes
3477  * 'sel' selects the type of memory
3478  */
3479 void
3480 wlc_bmac_copyto_objmem(struct wlc_hw_info *wlc_hw, uint offset, const void *buf,
3481                        int len, u32 sel)
3482 {
3483         u16 v;
3484         const u8 *p = (const u8 *)buf;
3485         int i;
3486
3487         if (len <= 0 || (offset & 1) || (len & 1))
3488                 return;
3489
3490         for (i = 0; i < len; i += 2) {
3491                 v = p[i] | (p[i + 1] << 8);
3492                 wlc_bmac_write_objmem(wlc_hw, offset + i, v, sel);
3493         }
3494 }
3495
3496 /* Copy a piece of shared memory of specified type to a buffer .
3497  * SHM 'offset' needs to be an even address and
3498  * Buffer length 'len' must be an even number of bytes
3499  * 'sel' selects the type of memory
3500  */
3501 void
3502 wlc_bmac_copyfrom_objmem(struct wlc_hw_info *wlc_hw, uint offset, void *buf,
3503                          int len, u32 sel)
3504 {
3505         u16 v;
3506         u8 *p = (u8 *) buf;
3507         int i;
3508
3509         if (len <= 0 || (offset & 1) || (len & 1))
3510                 return;
3511
3512         for (i = 0; i < len; i += 2) {
3513                 v = wlc_bmac_read_objmem(wlc_hw, offset + i, sel);
3514                 p[i] = v & 0xFF;
3515                 p[i + 1] = (v >> 8) & 0xFF;
3516         }
3517 }
3518
3519 void wlc_bmac_copyfrom_vars(struct wlc_hw_info *wlc_hw, char **buf, uint *len)
3520 {
3521         BCMMSG(wlc_hw->wlc->wiphy, "nvram vars totlen=%d\n",
3522                 wlc_hw->vars_size);
3523
3524         *buf = wlc_hw->vars;
3525         *len = wlc_hw->vars_size;
3526 }
3527
3528 void wlc_bmac_retrylimit_upd(struct wlc_hw_info *wlc_hw, u16 SRL, u16 LRL)
3529 {
3530         wlc_hw->SRL = SRL;
3531         wlc_hw->LRL = LRL;
3532
3533         /* write retry limit to SCR, shouldn't need to suspend */
3534         if (wlc_hw->up) {
3535                 W_REG(&wlc_hw->regs->objaddr,
3536                       OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
3537                 (void)R_REG(&wlc_hw->regs->objaddr);
3538                 W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL);
3539                 W_REG(&wlc_hw->regs->objaddr,
3540                       OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
3541                 (void)R_REG(&wlc_hw->regs->objaddr);
3542                 W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL);
3543         }
3544 }
3545
3546 void wlc_bmac_pllreq(struct wlc_hw_info *wlc_hw, bool set, mbool req_bit)
3547 {
3548         if (set) {
3549                 if (mboolisset(wlc_hw->pllreq, req_bit))
3550                         return;
3551
3552                 mboolset(wlc_hw->pllreq, req_bit);
3553
3554                 if (mboolisset(wlc_hw->pllreq, WLC_PLLREQ_FLIP)) {
3555                         if (!wlc_hw->sbclk) {
3556                                 wlc_bmac_xtal(wlc_hw, ON);
3557                         }
3558                 }
3559         } else {
3560                 if (!mboolisset(wlc_hw->pllreq, req_bit))
3561                         return;
3562
3563                 mboolclr(wlc_hw->pllreq, req_bit);
3564
3565                 if (mboolisset(wlc_hw->pllreq, WLC_PLLREQ_FLIP)) {
3566                         if (wlc_hw->sbclk) {
3567                                 wlc_bmac_xtal(wlc_hw, OFF);
3568                         }
3569                 }
3570         }
3571
3572         return;
3573 }
3574
3575 u16 wlc_bmac_rate_shm_offset(struct wlc_hw_info *wlc_hw, u8 rate)
3576 {
3577         u16 table_ptr;
3578         u8 phy_rate, index;
3579
3580         /* get the phy specific rate encoding for the PLCP SIGNAL field */
3581         /* XXX4321 fixup needed ? */
3582         if (IS_OFDM(rate))
3583                 table_ptr = M_RT_DIRMAP_A;
3584         else
3585                 table_ptr = M_RT_DIRMAP_B;
3586
3587         /* for a given rate, the LS-nibble of the PLCP SIGNAL field is
3588          * the index into the rate table.
3589          */
3590         phy_rate = rate_info[rate] & WLC_RATE_MASK;
3591         index = phy_rate & 0xf;
3592
3593         /* Find the SHM pointer to the rate table entry by looking in the
3594          * Direct-map Table
3595          */
3596         return 2 * wlc_bmac_read_shm(wlc_hw, table_ptr + (index * 2));
3597 }
3598
3599 void wlc_bmac_antsel_set(struct wlc_hw_info *wlc_hw, u32 antsel_avail)
3600 {
3601         wlc_hw->antsel_avail = antsel_avail;
3602 }