00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 FILE_LICENCE ( MIT );
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <unistd.h>
00040
00041 #include "ath5k.h"
00042 #include "reg.h"
00043 #include "base.h"
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
00055 {
00056 ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
00057 ath5k_hw_reg_read(ah, AR5K_CR);
00058 }
00059
00060
00061
00062
00063
00064
00065 int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
00066 {
00067 unsigned int i;
00068
00069 ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
00070
00071
00072
00073
00074 for (i = 1000; i > 0 &&
00075 (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
00076 i--)
00077 udelay(10);
00078
00079 return i ? 0 : -EBUSY;
00080 }
00081
00082
00083
00084
00085
00086
00087
00088
00089 u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
00090 {
00091 return ath5k_hw_reg_read(ah, AR5K_RXDP);
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
00103 {
00104 ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
00128 {
00129 u32 tx_queue;
00130
00131
00132 if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE)
00133 return -EIO;
00134
00135 if (ah->ah_version == AR5K_AR5210) {
00136 tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
00137
00138
00139 tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0;
00140
00141
00142 ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
00143 ath5k_hw_reg_read(ah, AR5K_CR);
00144 } else {
00145
00146 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
00147 return -EIO;
00148
00149
00150 AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue);
00151 }
00152
00153 return 0;
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
00168 {
00169 unsigned int i = 40;
00170 u32 tx_queue, pending;
00171
00172
00173 if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE)
00174 return -EIO;
00175
00176 if (ah->ah_version == AR5K_AR5210) {
00177 tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
00178
00179
00180 tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0;
00181
00182
00183 ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
00184 ath5k_hw_reg_read(ah, AR5K_CR);
00185 } else {
00186
00187
00188
00189 AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
00190
00191
00192 do {
00193 pending = ath5k_hw_reg_read(ah,
00194 AR5K_QUEUE_STATUS(queue)) &
00195 AR5K_QCU_STS_FRMPENDCNT;
00196 udelay(100);
00197 } while (--i && pending);
00198
00199
00200
00201 if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) && pending) {
00202
00203 ath5k_hw_reg_write(ah,
00204 AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)|
00205 AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR),
00206 AR5K_QUIET_CTL2);
00207
00208
00209 ath5k_hw_reg_write(ah,
00210 AR5K_QUIET_CTL1_QT_EN |
00211 AR5K_REG_SM(ath5k_hw_reg_read(ah,
00212 AR5K_TSF_L32_5211) >> 10,
00213 AR5K_QUIET_CTL1_NEXT_QT_TSF),
00214 AR5K_QUIET_CTL1);
00215
00216
00217 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
00218 AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
00219
00220
00221 udelay(200);
00222 AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1,
00223 AR5K_QUIET_CTL1_QT_EN);
00224
00225
00226 i = 40;
00227 do {
00228 pending = ath5k_hw_reg_read(ah,
00229 AR5K_QUEUE_STATUS(queue)) &
00230 AR5K_QCU_STS_FRMPENDCNT;
00231 udelay(100);
00232 } while (--i && pending);
00233
00234 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
00235 AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
00236 }
00237
00238
00239 ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
00240 if (pending)
00241 return -EBUSY;
00242 }
00243
00244
00245 return 0;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
00262 {
00263 u16 tx_reg;
00264
00265
00266
00267
00268
00269 if (ah->ah_version == AR5K_AR5210) {
00270
00271 tx_reg = AR5K_NOQCU_TXDP0;
00272 } else {
00273 tx_reg = AR5K_QUEUE_TXDP(queue);
00274 }
00275
00276 return ath5k_hw_reg_read(ah, tx_reg);
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
00293 {
00294 u16 tx_reg;
00295
00296
00297
00298
00299
00300 if (ah->ah_version == AR5K_AR5210) {
00301
00302 tx_reg = AR5K_NOQCU_TXDP0;
00303 } else {
00304
00305
00306
00307
00308
00309 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
00310 return -EIO;
00311
00312 tx_reg = AR5K_QUEUE_TXDP(queue);
00313 }
00314
00315
00316 ath5k_hw_reg_write(ah, phys_addr, tx_reg);
00317
00318 return 0;
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, int increase)
00340 {
00341 u32 trigger_level, imr;
00342 int ret = -EIO;
00343
00344
00345
00346
00347 imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL);
00348
00349 trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
00350 AR5K_TXCFG_TXFULL);
00351
00352 if (!increase) {
00353 if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
00354 goto done;
00355 } else
00356 trigger_level +=
00357 ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
00358
00359
00360
00361
00362 if (ah->ah_version == AR5K_AR5210)
00363 ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL);
00364 else
00365 AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
00366 AR5K_TXCFG_TXFULL, trigger_level);
00367
00368 ret = 0;
00369
00370 done:
00371
00372
00373
00374 ath5k_hw_set_imr(ah, imr);
00375
00376 return ret;
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 int ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
00392 {
00393 return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0;
00394 }
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
00413 {
00414 u32 data;
00415
00416
00417
00418
00419
00420 if (ah->ah_version == AR5K_AR5210) {
00421 data = ath5k_hw_reg_read(ah, AR5K_ISR);
00422 if (data == AR5K_INT_NOCARD) {
00423 *interrupt_mask = data;
00424 return -ENODEV;
00425 }
00426 } else {
00427
00428
00429
00430
00431
00432
00433 data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
00434 if (data == AR5K_INT_NOCARD) {
00435 *interrupt_mask = data;
00436 return -ENODEV;
00437 }
00438 }
00439
00440
00441
00442
00443 *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
00444
00445 if (ah->ah_version != AR5K_AR5210) {
00446 u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2);
00447
00448
00449 if (data & (AR5K_ISR_HIUERR))
00450 *interrupt_mask |= AR5K_INT_FATAL;
00451
00452
00453 if (data & (AR5K_ISR_BNR))
00454 *interrupt_mask |= AR5K_INT_BNR;
00455
00456 if (sisr2 & (AR5K_SISR2_SSERR | AR5K_SISR2_DPERR |
00457 AR5K_SISR2_MCABT))
00458 *interrupt_mask |= AR5K_INT_FATAL;
00459
00460 if (data & AR5K_ISR_TIM)
00461 *interrupt_mask |= AR5K_INT_TIM;
00462
00463 if (data & AR5K_ISR_BCNMISC) {
00464 if (sisr2 & AR5K_SISR2_TIM)
00465 *interrupt_mask |= AR5K_INT_TIM;
00466 if (sisr2 & AR5K_SISR2_DTIM)
00467 *interrupt_mask |= AR5K_INT_DTIM;
00468 if (sisr2 & AR5K_SISR2_DTIM_SYNC)
00469 *interrupt_mask |= AR5K_INT_DTIM_SYNC;
00470 if (sisr2 & AR5K_SISR2_BCN_TIMEOUT)
00471 *interrupt_mask |= AR5K_INT_BCN_TIMEOUT;
00472 if (sisr2 & AR5K_SISR2_CAB_TIMEOUT)
00473 *interrupt_mask |= AR5K_INT_CAB_TIMEOUT;
00474 }
00475
00476 if (data & AR5K_ISR_RXDOPPLER)
00477 *interrupt_mask |= AR5K_INT_RX_DOPPLER;
00478 if (data & AR5K_ISR_QCBRORN) {
00479 *interrupt_mask |= AR5K_INT_QCBRORN;
00480 ah->ah_txq_isr |= AR5K_REG_MS(
00481 ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
00482 AR5K_SISR3_QCBRORN);
00483 }
00484 if (data & AR5K_ISR_QCBRURN) {
00485 *interrupt_mask |= AR5K_INT_QCBRURN;
00486 ah->ah_txq_isr |= AR5K_REG_MS(
00487 ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
00488 AR5K_SISR3_QCBRURN);
00489 }
00490 if (data & AR5K_ISR_QTRIG) {
00491 *interrupt_mask |= AR5K_INT_QTRIG;
00492 ah->ah_txq_isr |= AR5K_REG_MS(
00493 ath5k_hw_reg_read(ah, AR5K_RAC_SISR4),
00494 AR5K_SISR4_QTRIG);
00495 }
00496
00497 if (data & AR5K_ISR_TXOK)
00498 ah->ah_txq_isr |= AR5K_REG_MS(
00499 ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
00500 AR5K_SISR0_QCU_TXOK);
00501
00502 if (data & AR5K_ISR_TXDESC)
00503 ah->ah_txq_isr |= AR5K_REG_MS(
00504 ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
00505 AR5K_SISR0_QCU_TXDESC);
00506
00507 if (data & AR5K_ISR_TXERR)
00508 ah->ah_txq_isr |= AR5K_REG_MS(
00509 ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
00510 AR5K_SISR1_QCU_TXERR);
00511
00512 if (data & AR5K_ISR_TXEOL)
00513 ah->ah_txq_isr |= AR5K_REG_MS(
00514 ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
00515 AR5K_SISR1_QCU_TXEOL);
00516
00517 if (data & AR5K_ISR_TXURN)
00518 ah->ah_txq_isr |= AR5K_REG_MS(
00519 ath5k_hw_reg_read(ah, AR5K_RAC_SISR2),
00520 AR5K_SISR2_QCU_TXURN);
00521 } else {
00522 if (data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT |
00523 AR5K_ISR_HIUERR | AR5K_ISR_DPERR))
00524 *interrupt_mask |= AR5K_INT_FATAL;
00525
00526
00527
00528
00529
00530
00531
00532
00533 }
00534
00535 return 0;
00536 }
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
00549 {
00550 enum ath5k_int old_mask, int_mask;
00551
00552 old_mask = ah->ah_imr;
00553
00554
00555
00556
00557
00558
00559 if (old_mask & AR5K_INT_GLOBAL) {
00560 ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
00561 ath5k_hw_reg_read(ah, AR5K_IER);
00562 }
00563
00564
00565
00566
00567
00568 int_mask = new_mask & AR5K_INT_COMMON;
00569
00570 if (ah->ah_version != AR5K_AR5210) {
00571
00572 u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2)
00573 & AR5K_SIMR2_QCU_TXURN;
00574
00575 if (new_mask & AR5K_INT_FATAL) {
00576 int_mask |= AR5K_IMR_HIUERR;
00577 simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR
00578 | AR5K_SIMR2_DPERR);
00579 }
00580
00581
00582 if (new_mask & AR5K_INT_BNR)
00583 int_mask |= AR5K_INT_BNR;
00584
00585 if (new_mask & AR5K_INT_TIM)
00586 int_mask |= AR5K_IMR_TIM;
00587
00588 if (new_mask & AR5K_INT_TIM)
00589 simr2 |= AR5K_SISR2_TIM;
00590 if (new_mask & AR5K_INT_DTIM)
00591 simr2 |= AR5K_SISR2_DTIM;
00592 if (new_mask & AR5K_INT_DTIM_SYNC)
00593 simr2 |= AR5K_SISR2_DTIM_SYNC;
00594 if (new_mask & AR5K_INT_BCN_TIMEOUT)
00595 simr2 |= AR5K_SISR2_BCN_TIMEOUT;
00596 if (new_mask & AR5K_INT_CAB_TIMEOUT)
00597 simr2 |= AR5K_SISR2_CAB_TIMEOUT;
00598
00599 if (new_mask & AR5K_INT_RX_DOPPLER)
00600 int_mask |= AR5K_IMR_RXDOPPLER;
00601
00602
00603
00604 ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
00605 ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
00606
00607 } else {
00608 if (new_mask & AR5K_INT_FATAL)
00609 int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT
00610 | AR5K_IMR_HIUERR | AR5K_IMR_DPERR);
00611
00612 ath5k_hw_reg_write(ah, int_mask, AR5K_IMR);
00613 }
00614
00615
00616
00617 if (!(new_mask & AR5K_INT_RXNOFRM))
00618 ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM);
00619
00620
00621 ah->ah_imr = new_mask;
00622
00623
00624 if (new_mask & AR5K_INT_GLOBAL) {
00625 ath5k_hw_reg_write(ah, ah->ah_ier, AR5K_IER);
00626 ath5k_hw_reg_read(ah, AR5K_IER);
00627 }
00628
00629 return old_mask;
00630 }
00631