From 05415a68029e6bef8ca8014bb1055604a47c2c3d Mon Sep 17 00:00:00 2001 From: coypu Date: Fri, 16 Sep 2016 12:34:43 +0300 Subject: [PATCH 02/27] double quote vendor import --- sys/external/isc/atheros_hal/dist/ah.c | 1469 ++++++++++ sys/external/isc/atheros_hal/dist/ah.h | 1804 ++++++++++++ sys/external/isc/atheros_hal/dist/ah_debug.h | 61 + sys/external/isc/atheros_hal/dist/ah_decode.h | 69 + sys/external/isc/atheros_hal/dist/ah_desc.h | 287 ++ sys/external/isc/atheros_hal/dist/ah_devid.h | 101 + sys/external/isc/atheros_hal/dist/ah_diagcodes.h | 72 + sys/external/isc/atheros_hal/dist/ah_eeprom.h | 168 ++ sys/external/isc/atheros_hal/dist/ah_eeprom_9287.c | 408 +++ sys/external/isc/atheros_hal/dist/ah_eeprom_9287.h | 168 ++ sys/external/isc/atheros_hal/dist/ah_eeprom_v1.c | 253 ++ sys/external/isc/atheros_hal/dist/ah_eeprom_v1.h | 99 + sys/external/isc/atheros_hal/dist/ah_eeprom_v14.c | 447 +++ sys/external/isc/atheros_hal/dist/ah_eeprom_v14.h | 292 ++ sys/external/isc/atheros_hal/dist/ah_eeprom_v3.c | 1876 +++++++++++++ sys/external/isc/atheros_hal/dist/ah_eeprom_v3.h | 462 ++++ sys/external/isc/atheros_hal/dist/ah_eeprom_v4k.c | 397 +++ sys/external/isc/atheros_hal/dist/ah_eeprom_v4k.h | 182 ++ sys/external/isc/atheros_hal/dist/ah_internal.h | 1047 +++++++ sys/external/isc/atheros_hal/dist/ah_regdomain.c | 875 ++++++ sys/external/isc/atheros_hal/dist/ah_regdomain.h | 163 ++ .../isc/atheros_hal/dist/ah_regdomain/ah_rd_ctry.h | 170 ++ .../atheros_hal/dist/ah_regdomain/ah_rd_domains.h | 774 ++++++ .../dist/ah_regdomain/ah_rd_freqbands.h | 419 +++ .../atheros_hal/dist/ah_regdomain/ah_rd_regenum.h | 250 ++ .../atheros_hal/dist/ah_regdomain/ah_rd_regmap.h | 135 + sys/external/isc/atheros_hal/dist/ah_soc.h | 91 + sys/external/isc/atheros_hal/dist/ar5210/ar5210.h | 301 ++ .../isc/atheros_hal/dist/ar5210/ar5210_attach.c | 415 +++ .../isc/atheros_hal/dist/ar5210/ar5210_beacon.c | 202 ++ .../atheros_hal/dist/ar5210/ar5210_interrupts.c | 134 + .../isc/atheros_hal/dist/ar5210/ar5210_keycache.c | 156 ++ .../isc/atheros_hal/dist/ar5210/ar5210_misc.c | 703 +++++ .../isc/atheros_hal/dist/ar5210/ar5210_phy.c | 85 + .../isc/atheros_hal/dist/ar5210/ar5210_power.c | 138 + .../isc/atheros_hal/dist/ar5210/ar5210_recv.c | 270 ++ .../isc/atheros_hal/dist/ar5210/ar5210_reset.c | 1006 +++++++ .../isc/atheros_hal/dist/ar5210/ar5210_xmit.c | 670 +++++ .../isc/atheros_hal/dist/ar5210/ar5210desc.h | 130 + .../isc/atheros_hal/dist/ar5210/ar5210phy.h | 59 + .../isc/atheros_hal/dist/ar5210/ar5210reg.h | 413 +++ .../isc/atheros_hal/dist/ar5210/ar5k_0007.ini | 194 ++ sys/external/isc/atheros_hal/dist/ar5211/ar5211.h | 327 +++ .../isc/atheros_hal/dist/ar5211/ar5211_attach.c | 552 ++++ .../isc/atheros_hal/dist/ar5211/ar5211_beacon.c | 184 ++ .../atheros_hal/dist/ar5211/ar5211_interrupts.c | 160 ++ .../isc/atheros_hal/dist/ar5211/ar5211_keycache.c | 178 ++ .../isc/atheros_hal/dist/ar5211/ar5211_misc.c | 727 +++++ .../isc/atheros_hal/dist/ar5211/ar5211_phy.c | 104 + .../isc/atheros_hal/dist/ar5211/ar5211_power.c | 140 + .../isc/atheros_hal/dist/ar5211/ar5211_recv.c | 249 ++ .../isc/atheros_hal/dist/ar5211/ar5211_reset.c | 2120 ++++++++++++++ .../isc/atheros_hal/dist/ar5211/ar5211_xmit.c | 701 +++++ .../isc/atheros_hal/dist/ar5211/ar5211desc.h | 132 + .../isc/atheros_hal/dist/ar5211/ar5211phy.h | 94 + .../isc/atheros_hal/dist/ar5211/ar5211reg.h | 864 ++++++ sys/external/isc/atheros_hal/dist/ar5211/boss.ini | 358 +++ sys/external/isc/atheros_hal/dist/ar5212/ar2316.c | 763 ++++++ sys/external/isc/atheros_hal/dist/ar5212/ar2317.c | 741 +++++ sys/external/isc/atheros_hal/dist/ar5212/ar2413.c | 756 +++++ sys/external/isc/atheros_hal/dist/ar5212/ar2425.c | 719 +++++ sys/external/isc/atheros_hal/dist/ar5212/ar5111.c | 719 +++++ sys/external/isc/atheros_hal/dist/ar5212/ar5112.c | 889 ++++++ sys/external/isc/atheros_hal/dist/ar5212/ar5212.h | 659 +++++ .../isc/atheros_hal/dist/ar5212/ar5212.ini | 2171 +++++++++++++++ .../isc/atheros_hal/dist/ar5212/ar5212_ani.c | 1041 +++++++ .../isc/atheros_hal/dist/ar5212/ar5212_attach.c | 947 +++++++ .../isc/atheros_hal/dist/ar5212/ar5212_beacon.c | 275 ++ .../isc/atheros_hal/dist/ar5212/ar5212_eeprom.c | 50 + .../isc/atheros_hal/dist/ar5212/ar5212_gpio.c | 124 + .../atheros_hal/dist/ar5212/ar5212_interrupts.c | 201 ++ .../isc/atheros_hal/dist/ar5212/ar5212_keycache.c | 302 ++ .../isc/atheros_hal/dist/ar5212/ar5212_misc.c | 1459 ++++++++++ .../isc/atheros_hal/dist/ar5212/ar5212_phy.c | 201 ++ .../isc/atheros_hal/dist/ar5212/ar5212_power.c | 179 ++ .../isc/atheros_hal/dist/ar5212/ar5212_recv.c | 317 +++ .../isc/atheros_hal/dist/ar5212/ar5212_reset.c | 2799 +++++++++++++++++++ .../isc/atheros_hal/dist/ar5212/ar5212_rfgain.c | 333 +++ .../isc/atheros_hal/dist/ar5212/ar5212_xmit.c | 1002 +++++++ .../isc/atheros_hal/dist/ar5212/ar5212desc.h | 176 ++ .../isc/atheros_hal/dist/ar5212/ar5212phy.h | 360 +++ .../isc/atheros_hal/dist/ar5212/ar5212reg.h | 1006 +++++++ .../isc/atheros_hal/dist/ar5212/ar5311reg.h | 50 + sys/external/isc/atheros_hal/dist/ar5212/ar5413.c | 802 ++++++ sys/external/isc/atheros_hal/dist/ar5312/ar5312.h | 83 + .../isc/atheros_hal/dist/ar5312/ar5312_attach.c | 335 +++ .../isc/atheros_hal/dist/ar5312/ar5312_eeprom.c | 47 + .../isc/atheros_hal/dist/ar5312/ar5312_gpio.c | 131 + .../atheros_hal/dist/ar5312/ar5312_interrupts.c | 47 + .../isc/atheros_hal/dist/ar5312/ar5312_misc.c | 168 ++ .../isc/atheros_hal/dist/ar5312/ar5312_power.c | 124 + .../isc/atheros_hal/dist/ar5312/ar5312_reset.c | 888 ++++++ .../isc/atheros_hal/dist/ar5312/ar5312phy.h | 31 + .../isc/atheros_hal/dist/ar5312/ar5312reg.h | 139 + .../isc/atheros_hal/dist/ar5312/ar5315_gpio.c | 130 + sys/external/isc/atheros_hal/dist/ar5416/ar2133.c | 587 ++++ sys/external/isc/atheros_hal/dist/ar5416/ar5416.h | 426 +++ .../isc/atheros_hal/dist/ar5416/ar5416.ini | 705 +++++ .../isc/atheros_hal/dist/ar5416/ar5416_ani.c | 991 +++++++ .../isc/atheros_hal/dist/ar5416/ar5416_attach.c | 1075 ++++++++ .../isc/atheros_hal/dist/ar5416/ar5416_beacon.c | 288 ++ .../isc/atheros_hal/dist/ar5416/ar5416_btcoex.c | 394 +++ .../isc/atheros_hal/dist/ar5416/ar5416_btcoex.h | 31 + .../isc/atheros_hal/dist/ar5416/ar5416_cal.c | 832 ++++++ .../isc/atheros_hal/dist/ar5416/ar5416_cal.h | 121 + .../isc/atheros_hal/dist/ar5416/ar5416_cal_adcdc.c | 111 + .../atheros_hal/dist/ar5416/ar5416_cal_adcgain.c | 116 + .../isc/atheros_hal/dist/ar5416/ar5416_cal_iq.c | 132 + .../isc/atheros_hal/dist/ar5416/ar5416_eeprom.c | 44 + .../isc/atheros_hal/dist/ar5416/ar5416_gpio.c | 278 ++ .../atheros_hal/dist/ar5416/ar5416_interrupts.c | 378 +++ .../isc/atheros_hal/dist/ar5416/ar5416_keycache.c | 66 + .../isc/atheros_hal/dist/ar5416/ar5416_misc.c | 754 +++++ .../isc/atheros_hal/dist/ar5416/ar5416_phy.c | 126 + .../isc/atheros_hal/dist/ar5416/ar5416_power.c | 189 ++ .../isc/atheros_hal/dist/ar5416/ar5416_radar.c | 432 +++ .../isc/atheros_hal/dist/ar5416/ar5416_recv.c | 279 ++ .../isc/atheros_hal/dist/ar5416/ar5416_reset.c | 2891 ++++++++++++++++++++ .../isc/atheros_hal/dist/ar5416/ar5416_spectral.c | 244 ++ .../isc/atheros_hal/dist/ar5416/ar5416_xmit.c | 1494 ++++++++++ .../isc/atheros_hal/dist/ar5416/ar5416desc.h | 422 +++ .../isc/atheros_hal/dist/ar5416/ar5416phy.h | 394 +++ .../isc/atheros_hal/dist/ar5416/ar5416reg.h | 813 ++++++ .../isc/atheros_hal/dist/ar9001/ar9130.ini | 669 +++++ .../isc/atheros_hal/dist/ar9001/ar9130_attach.c | 323 +++ .../isc/atheros_hal/dist/ar9001/ar9130_eeprom.c | 18 + .../isc/atheros_hal/dist/ar9001/ar9130_eeprom.h | 22 + .../isc/atheros_hal/dist/ar9001/ar9130_phy.c | 47 + .../isc/atheros_hal/dist/ar9001/ar9130_phy.h | 25 + .../isc/atheros_hal/dist/ar9001/ar9130reg.h | 27 + .../isc/atheros_hal/dist/ar9001/ar9160.ini | 717 +++++ .../isc/atheros_hal/dist/ar9001/ar9160_attach.c | 341 +++ .../isc/atheros_hal/dist/ar9002/ar9002phy.h | 57 + sys/external/isc/atheros_hal/dist/ar9002/ar9280.c | 458 ++++ sys/external/isc/atheros_hal/dist/ar9002/ar9280.h | 64 + .../isc/atheros_hal/dist/ar9002/ar9280_attach.c | 976 +++++++ .../isc/atheros_hal/dist/ar9002/ar9280_olc.c | 408 +++ .../isc/atheros_hal/dist/ar9002/ar9280_olc.h | 53 + .../isc/atheros_hal/dist/ar9002/ar9280v1.ini | 582 ++++ .../isc/atheros_hal/dist/ar9002/ar9280v2.ini | 929 +++++++ sys/external/isc/atheros_hal/dist/ar9002/ar9285.c | 87 + sys/external/isc/atheros_hal/dist/ar9002/ar9285.h | 56 + .../isc/atheros_hal/dist/ar9002/ar9285.ini | 699 +++++ .../isc/atheros_hal/dist/ar9002/ar9285_attach.c | 581 ++++ .../isc/atheros_hal/dist/ar9002/ar9285_btcoex.c | 152 + .../isc/atheros_hal/dist/ar9002/ar9285_cal.c | 269 ++ .../isc/atheros_hal/dist/ar9002/ar9285_cal.h | 34 + .../isc/atheros_hal/dist/ar9002/ar9285_diversity.c | 156 ++ .../isc/atheros_hal/dist/ar9002/ar9285_diversity.h | 33 + .../isc/atheros_hal/dist/ar9002/ar9285_phy.c | 105 + .../isc/atheros_hal/dist/ar9002/ar9285_phy.h | 41 + .../isc/atheros_hal/dist/ar9002/ar9285_reset.c | 801 ++++++ .../isc/atheros_hal/dist/ar9002/ar9285an.h | 124 + .../isc/atheros_hal/dist/ar9002/ar9285phy.h | 130 + .../isc/atheros_hal/dist/ar9002/ar9285v2.ini | 835 ++++++ sys/external/isc/atheros_hal/dist/ar9002/ar9287.c | 400 +++ sys/external/isc/atheros_hal/dist/ar9002/ar9287.h | 60 + .../isc/atheros_hal/dist/ar9002/ar9287.ini | 783 ++++++ .../isc/atheros_hal/dist/ar9002/ar9287_attach.c | 494 ++++ .../isc/atheros_hal/dist/ar9002/ar9287_cal.c | 73 + .../isc/atheros_hal/dist/ar9002/ar9287_cal.h | 33 + .../isc/atheros_hal/dist/ar9002/ar9287_olc.c | 171 ++ .../isc/atheros_hal/dist/ar9002/ar9287_olc.h | 31 + .../isc/atheros_hal/dist/ar9002/ar9287_reset.c | 586 ++++ .../isc/atheros_hal/dist/ar9002/ar9287_reset.h | 27 + .../isc/atheros_hal/dist/ar9002/ar9287an.h | 49 + .../isc/atheros_hal/dist/ar9002/ar9287phy.h | 26 + .../isc/atheros_hal/dist/ar9003/ar9300_btcoex.h | 59 + .../isc/atheros_hal/dist/ar9003/ar9300_devid.h | 79 + 169 files changed, 72772 insertions(+) create mode 100644 sys/external/isc/atheros_hal/dist/ah.c create mode 100644 sys/external/isc/atheros_hal/dist/ah.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_debug.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_decode.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_desc.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_devid.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_diagcodes.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_eeprom.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_eeprom_9287.c create mode 100644 sys/external/isc/atheros_hal/dist/ah_eeprom_9287.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_eeprom_v1.c create mode 100644 sys/external/isc/atheros_hal/dist/ah_eeprom_v1.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_eeprom_v14.c create mode 100644 sys/external/isc/atheros_hal/dist/ah_eeprom_v14.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_eeprom_v3.c create mode 100644 sys/external/isc/atheros_hal/dist/ah_eeprom_v3.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_eeprom_v4k.c create mode 100644 sys/external/isc/atheros_hal/dist/ah_eeprom_v4k.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_internal.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_regdomain.c create mode 100644 sys/external/isc/atheros_hal/dist/ah_regdomain.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_ctry.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_domains.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_freqbands.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_regenum.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_regmap.h create mode 100644 sys/external/isc/atheros_hal/dist/ah_soc.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210_attach.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210_beacon.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210_interrupts.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210_keycache.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210_misc.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210_phy.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210_power.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210_recv.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210_reset.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210_xmit.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210desc.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210phy.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5210reg.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5210/ar5k_0007.ini create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211_attach.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211_beacon.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211_interrupts.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211_keycache.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211_misc.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211_phy.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211_power.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211_recv.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211_reset.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211_xmit.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211desc.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211phy.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/ar5211reg.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5211/boss.ini create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar2316.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar2317.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar2413.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar2425.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5111.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5112.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212.ini create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_ani.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_attach.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_beacon.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_eeprom.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_gpio.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_interrupts.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_keycache.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_misc.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_phy.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_power.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_recv.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_reset.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_rfgain.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212_xmit.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212desc.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212phy.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5212reg.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5311reg.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5212/ar5413.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5312/ar5312.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5312/ar5312_attach.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5312/ar5312_eeprom.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5312/ar5312_gpio.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5312/ar5312_interrupts.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5312/ar5312_misc.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5312/ar5312_power.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5312/ar5312_reset.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5312/ar5312phy.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5312/ar5312reg.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5312/ar5315_gpio.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar2133.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416.ini create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_ani.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_attach.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_beacon.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_btcoex.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_btcoex.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_adcdc.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_adcgain.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_iq.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_eeprom.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_gpio.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_interrupts.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_keycache.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_misc.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_phy.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_power.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_radar.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_recv.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_reset.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_spectral.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416_xmit.c create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416desc.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416phy.h create mode 100644 sys/external/isc/atheros_hal/dist/ar5416/ar5416reg.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9001/ar9130.ini create mode 100644 sys/external/isc/atheros_hal/dist/ar9001/ar9130_attach.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9001/ar9130_eeprom.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9001/ar9130_eeprom.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9001/ar9130_phy.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9001/ar9130_phy.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9001/ar9130reg.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9001/ar9160.ini create mode 100644 sys/external/isc/atheros_hal/dist/ar9001/ar9160_attach.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9002phy.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9280.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9280.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9280_attach.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9280_olc.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9280_olc.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9280v1.ini create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9280v2.ini create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285.ini create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285_attach.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285_btcoex.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285_cal.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285_cal.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285_diversity.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285_diversity.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285_phy.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285_phy.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285_reset.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285an.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285phy.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9285v2.ini create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9287.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9287.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9287.ini create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9287_attach.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9287_cal.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9287_cal.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9287_olc.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9287_olc.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9287_reset.c create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9287_reset.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9287an.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9002/ar9287phy.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9003/ar9300_btcoex.h create mode 100644 sys/external/isc/atheros_hal/dist/ar9003/ar9300_devid.h diff --git a/sys/external/isc/atheros_hal/dist/ah.c b/sys/external/isc/atheros_hal/dist/ah.c new file mode 100644 index 0000000..8333f10 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah.c @@ -0,0 +1,1469 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#include "ah_eeprom.h" /* for 5ghz fast clock flag */ + +#include "ar5416/ar5416reg.h" /* NB: includes ar5212reg.h */ +#include "ar9003/ar9300_devid.h" + +/* linker set of registered chips */ +OS_SET_DECLARE(ah_chips, struct ath_hal_chip); + +/* + * Check the set of registered chips to see if any recognize + * the device as one they can support. + */ +const char* +ath_hal_probe(uint16_t vendorid, uint16_t devid) +{ + struct ath_hal_chip * const *pchip; + + OS_SET_FOREACH(pchip, ah_chips) { + const char *name = (*pchip)->probe(vendorid, devid); + if (name != AH_NULL) + return name; + } + return AH_NULL; +} + +/* + * Attach detects device chip revisions, initializes the hwLayer + * function list, reads EEPROM information, + * selects reset vectors, and performs a short self test. + * Any failures will return an error that should cause a hardware + * disable. + */ +struct ath_hal* +ath_hal_attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_OPS_CONFIG *ah_config, + HAL_STATUS *error) +{ + struct ath_hal_chip * const *pchip; + + OS_SET_FOREACH(pchip, ah_chips) { + struct ath_hal_chip *chip = *pchip; + struct ath_hal *ah; + + /* XXX don't have vendorid, assume atheros one works */ + if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL) + continue; + ah = chip->attach(devid, sc, st, sh, eepromdata, ah_config, + error); + if (ah != AH_NULL) { + /* copy back private state to public area */ + ah->ah_devid = AH_PRIVATE(ah)->ah_devid; + ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid; + ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion; + ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev; + ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev; + ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev; + ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev; + return ah; + } + } + return AH_NULL; +} + +const char * +ath_hal_mac_name(struct ath_hal *ah) +{ + switch (ah->ah_macVersion) { + case AR_SREV_VERSION_CRETE: + case AR_SREV_VERSION_MAUI_1: + return "AR5210"; + case AR_SREV_VERSION_MAUI_2: + case AR_SREV_VERSION_OAHU: + return "AR5211"; + case AR_SREV_VERSION_VENICE: + return "AR5212"; + case AR_SREV_VERSION_GRIFFIN: + return "AR2413"; + case AR_SREV_VERSION_CONDOR: + return "AR5424"; + case AR_SREV_VERSION_EAGLE: + return "AR5413"; + case AR_SREV_VERSION_COBRA: + return "AR2415"; + case AR_SREV_2425: /* Swan */ + return "AR2425"; + case AR_SREV_2417: /* Nala */ + return "AR2417"; + case AR_XSREV_VERSION_OWL_PCI: + return "AR5416"; + case AR_XSREV_VERSION_OWL_PCIE: + return "AR5418"; + case AR_XSREV_VERSION_HOWL: + return "AR9130"; + case AR_XSREV_VERSION_SOWL: + return "AR9160"; + case AR_XSREV_VERSION_MERLIN: + if (AH_PRIVATE(ah)->ah_ispcie) + return "AR9280"; + return "AR9220"; + case AR_XSREV_VERSION_KITE: + return "AR9285"; + case AR_XSREV_VERSION_KIWI: + if (AH_PRIVATE(ah)->ah_ispcie) + return "AR9287"; + return "AR9227"; + case AR_SREV_VERSION_AR9380: + if (ah->ah_macRev >= AR_SREV_REVISION_AR9580_10) + return "AR9580"; + return "AR9380"; + case AR_SREV_VERSION_AR9460: + return "AR9460"; + case AR_SREV_VERSION_AR9330: + return "AR9330"; + case AR_SREV_VERSION_AR9340: + return "AR9340"; + case AR_SREV_VERSION_QCA9550: + return "QCA9550"; + case AR_SREV_VERSION_AR9485: + return "AR9485"; + case AR_SREV_VERSION_QCA9565: + return "QCA9565"; + case AR_SREV_VERSION_QCA9530: + return "QCA9530"; + } + return "????"; +} + +/* + * Return the mask of available modes based on the hardware capabilities. + */ +u_int +ath_hal_getwirelessmodes(struct ath_hal*ah) +{ + return ath_hal_getWirelessModes(ah); +} + +/* linker set of registered RF backends */ +OS_SET_DECLARE(ah_rfs, struct ath_hal_rf); + +/* + * Check the set of registered RF backends to see if + * any recognize the device as one they can support. + */ +struct ath_hal_rf * +ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode) +{ + struct ath_hal_rf * const *prf; + + OS_SET_FOREACH(prf, ah_rfs) { + struct ath_hal_rf *rf = *prf; + if (rf->probe(ah)) + return rf; + } + *ecode = HAL_ENOTSUPP; + return AH_NULL; +} + +const char * +ath_hal_rf_name(struct ath_hal *ah) +{ + switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { + case 0: /* 5210 */ + return "5110"; /* NB: made up */ + case AR_RAD5111_SREV_MAJOR: + case AR_RAD5111_SREV_PROD: + return "5111"; + case AR_RAD2111_SREV_MAJOR: + return "2111"; + case AR_RAD5112_SREV_MAJOR: + case AR_RAD5112_SREV_2_0: + case AR_RAD5112_SREV_2_1: + return "5112"; + case AR_RAD2112_SREV_MAJOR: + case AR_RAD2112_SREV_2_0: + case AR_RAD2112_SREV_2_1: + return "2112"; + case AR_RAD2413_SREV_MAJOR: + return "2413"; + case AR_RAD5413_SREV_MAJOR: + return "5413"; + case AR_RAD2316_SREV_MAJOR: + return "2316"; + case AR_RAD2317_SREV_MAJOR: + return "2317"; + case AR_RAD5424_SREV_MAJOR: + return "5424"; + + case AR_RAD5133_SREV_MAJOR: + return "5133"; + case AR_RAD2133_SREV_MAJOR: + return "2133"; + case AR_RAD5122_SREV_MAJOR: + return "5122"; + case AR_RAD2122_SREV_MAJOR: + return "2122"; + } + return "????"; +} + +/* + * Poll the register looking for a specific value. + */ +HAL_BOOL +ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val) +{ +#define AH_TIMEOUT 1000 + return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT); +#undef AH_TIMEOUT +} + +HAL_BOOL +ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout) +{ + int i; + + for (i = 0; i < timeout; i++) { + if ((OS_REG_READ(ah, reg) & mask) == val) + return AH_TRUE; + OS_DELAY(10); + } + HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO, + "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", + __func__, reg, OS_REG_READ(ah, reg), mask, val); + return AH_FALSE; +} + +/* + * Reverse the bits starting at the low bit for a value of + * bit_count in size + */ +uint32_t +ath_hal_reverseBits(uint32_t val, uint32_t n) +{ + uint32_t retval; + int i; + + for (i = 0, retval = 0; i < n; i++) { + retval = (retval << 1) | (val & 1); + val >>= 1; + } + return retval; +} + +/* 802.11n related timing definitions */ + +#define OFDM_PLCP_BITS 22 +#define HT_L_STF 8 +#define HT_L_LTF 8 +#define HT_L_SIG 4 +#define HT_SIG 8 +#define HT_STF 4 +#define HT_LTF(n) ((n) * 4) + +#define HT_RC_2_MCS(_rc) ((_rc) & 0xf) +#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) +#define IS_HT_RATE(_rc) ( (_rc) & IEEE80211_RATE_MCS) + +/* + * Calculate the duration of a packet whether it is 11n or legacy. + */ +uint32_t +ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen, + uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble) +{ + uint8_t rc; + int numStreams; + + rc = rates->info[rateix].rateCode; + + /* Legacy rate? Return the old way */ + if (! IS_HT_RATE(rc)) + return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble); + + /* 11n frame - extract out the number of spatial streams */ + numStreams = HT_RC_2_STREAMS(rc); + KASSERT(numStreams > 0 && numStreams <= 4, + ("number of spatial streams needs to be 1..3: MCS rate 0x%x!", + rateix)); + + return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble); +} + +static const uint16_t ht20_bps[32] = { + 26, 52, 78, 104, 156, 208, 234, 260, + 52, 104, 156, 208, 312, 416, 468, 520, + 78, 156, 234, 312, 468, 624, 702, 780, + 104, 208, 312, 416, 624, 832, 936, 1040 +}; +static const uint16_t ht40_bps[32] = { + 54, 108, 162, 216, 324, 432, 486, 540, + 108, 216, 324, 432, 648, 864, 972, 1080, + 162, 324, 486, 648, 972, 1296, 1458, 1620, + 216, 432, 648, 864, 1296, 1728, 1944, 2160 +}; + +/* + * Calculate the transmit duration of an 11n frame. + */ +uint32_t +ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams, + HAL_BOOL isht40, HAL_BOOL isShortGI) +{ + uint32_t bitsPerSymbol, numBits, numSymbols, txTime; + + KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate)); + KASSERT((rate &~ IEEE80211_RATE_MCS) < 31, ("bad mcs 0x%x", rate)); + + if (isht40) + bitsPerSymbol = ht40_bps[rate & 0x1f]; + else + bitsPerSymbol = ht20_bps[rate & 0x1f]; + numBits = OFDM_PLCP_BITS + (frameLen << 3); + numSymbols = howmany(numBits, bitsPerSymbol); + if (isShortGI) + txTime = ((numSymbols * 18) + 4) / 5; /* 3.6us */ + else + txTime = numSymbols * 4; /* 4us */ + return txTime + HT_L_STF + HT_L_LTF + + HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams); +} + +/* + * Compute the time to transmit a frame of length frameLen bytes + * using the specified rate, phy, and short preamble setting. + */ +uint16_t +ath_hal_computetxtime(struct ath_hal *ah, + const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix, + HAL_BOOL shortPreamble) +{ + uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime; + uint32_t kbps; + + /* Warn if this function is called for 11n rates; it should not be! */ + if (IS_HT_RATE(rates->info[rateix].rateCode)) + ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n", + __func__, rateix, rates->info[rateix].rateCode); + + kbps = rates->info[rateix].rateKbps; + /* + * index can be invalid duting dynamic Turbo transitions. + * XXX + */ + if (kbps == 0) + return 0; + switch (rates->info[rateix].phy) { + case IEEE80211_T_CCK: + phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; + if (shortPreamble && rates->info[rateix].shortPreamble) + phyTime >>= 1; + numBits = frameLen << 3; + txTime = CCK_SIFS_TIME + phyTime + + ((numBits * 1000)/kbps); + break; + case IEEE80211_T_OFDM: + bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000; + HALASSERT(bitsPerSymbol != 0); + + numBits = OFDM_PLCP_BITS + (frameLen << 3); + numSymbols = howmany(numBits, bitsPerSymbol); + txTime = OFDM_SIFS_TIME + + OFDM_PREAMBLE_TIME + + (numSymbols * OFDM_SYMBOL_TIME); + break; + case IEEE80211_T_OFDM_HALF: + bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000; + HALASSERT(bitsPerSymbol != 0); + + numBits = OFDM_HALF_PLCP_BITS + (frameLen << 3); + numSymbols = howmany(numBits, bitsPerSymbol); + txTime = OFDM_HALF_SIFS_TIME + + OFDM_HALF_PREAMBLE_TIME + + (numSymbols * OFDM_HALF_SYMBOL_TIME); + break; + case IEEE80211_T_OFDM_QUARTER: + bitsPerSymbol = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000; + HALASSERT(bitsPerSymbol != 0); + + numBits = OFDM_QUARTER_PLCP_BITS + (frameLen << 3); + numSymbols = howmany(numBits, bitsPerSymbol); + txTime = OFDM_QUARTER_SIFS_TIME + + OFDM_QUARTER_PREAMBLE_TIME + + (numSymbols * OFDM_QUARTER_SYMBOL_TIME); + break; + case IEEE80211_T_TURBO: + bitsPerSymbol = (kbps * TURBO_SYMBOL_TIME) / 1000; + HALASSERT(bitsPerSymbol != 0); + + numBits = TURBO_PLCP_BITS + (frameLen << 3); + numSymbols = howmany(numBits, bitsPerSymbol); + txTime = TURBO_SIFS_TIME + + TURBO_PREAMBLE_TIME + + (numSymbols * TURBO_SYMBOL_TIME); + break; + default: + HALDEBUG(ah, HAL_DEBUG_PHYIO, + "%s: unknown phy %u (rate ix %u)\n", + __func__, rates->info[rateix].phy, rateix); + txTime = 0; + break; + } + return txTime; +} + +int +ath_hal_get_curmode(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + /* + * Pick a default mode at bootup. A channel change is inevitable. + */ + if (!chan) + return HAL_MODE_11NG_HT20; + + if (IEEE80211_IS_CHAN_TURBO(chan)) + return HAL_MODE_TURBO; + + /* check for NA_HT before plain A, since IS_CHAN_A includes NA_HT */ + if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan)) + return HAL_MODE_11NA_HT20; + if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan)) + return HAL_MODE_11NA_HT40PLUS; + if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan)) + return HAL_MODE_11NA_HT40MINUS; + if (IEEE80211_IS_CHAN_A(chan)) + return HAL_MODE_11A; + + /* check for NG_HT before plain G, since IS_CHAN_G includes NG_HT */ + if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan)) + return HAL_MODE_11NG_HT20; + if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan)) + return HAL_MODE_11NG_HT40PLUS; + if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan)) + return HAL_MODE_11NG_HT40MINUS; + + /* + * XXX For FreeBSD, will this work correctly given the DYN + * chan mode (OFDM+CCK dynamic) ? We have pure-G versions DYN-BG.. + */ + if (IEEE80211_IS_CHAN_G(chan)) + return HAL_MODE_11G; + if (IEEE80211_IS_CHAN_B(chan)) + return HAL_MODE_11B; + + HALASSERT(0); + return HAL_MODE_11NG_HT20; +} + + +typedef enum { + WIRELESS_MODE_11a = 0, + WIRELESS_MODE_TURBO = 1, + WIRELESS_MODE_11b = 2, + WIRELESS_MODE_11g = 3, + WIRELESS_MODE_108g = 4, + + WIRELESS_MODE_MAX +} WIRELESS_MODE; + +static WIRELESS_MODE +ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + if (IEEE80211_IS_CHAN_B(chan)) + return WIRELESS_MODE_11b; + if (IEEE80211_IS_CHAN_G(chan)) + return WIRELESS_MODE_11g; + if (IEEE80211_IS_CHAN_108G(chan)) + return WIRELESS_MODE_108g; + if (IEEE80211_IS_CHAN_TURBO(chan)) + return WIRELESS_MODE_TURBO; + return WIRELESS_MODE_11a; +} + +/* + * Convert between microseconds and core system clocks. + */ + /* 11a Turbo 11b 11g 108g */ +static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 }; + +#define CLOCK_FAST_RATE_5GHZ_OFDM 44 + +u_int +ath_hal_mac_clks(struct ath_hal *ah, u_int usecs) +{ + const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan; + u_int clks; + + /* NB: ah_curchan may be null when called attach time */ + /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */ + if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) { + clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM; + if (IEEE80211_IS_CHAN_HT40(c)) + clks <<= 1; + } else if (c != AH_NULL) { + clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)]; + if (IEEE80211_IS_CHAN_HT40(c)) + clks <<= 1; + } else + clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b]; + + /* Compensate for half/quarter rate */ + if (c != AH_NULL && IEEE80211_IS_CHAN_HALF(c)) + clks = clks / 2; + else if (c != AH_NULL && IEEE80211_IS_CHAN_QUARTER(c)) + clks = clks / 4; + + return clks; +} + +u_int +ath_hal_mac_usec(struct ath_hal *ah, u_int clks) +{ + const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan; + u_int usec; + + /* NB: ah_curchan may be null when called attach time */ + /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */ + if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) { + usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM; + if (IEEE80211_IS_CHAN_HT40(c)) + usec >>= 1; + } else if (c != AH_NULL) { + usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)]; + if (IEEE80211_IS_CHAN_HT40(c)) + usec >>= 1; + } else + usec = clks / CLOCK_RATE[WIRELESS_MODE_11b]; + return usec; +} + +/* + * Setup a h/w rate table's reverse lookup table and + * fill in ack durations. This routine is called for + * each rate table returned through the ah_getRateTable + * method. The reverse lookup tables are assumed to be + * initialized to zero (or at least the first entry). + * We use this as a key that indicates whether or not + * we've previously setup the reverse lookup table. + * + * XXX not reentrant, but shouldn't matter + */ +void +ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + int i; + + if (rt->rateCodeToIndex[0] != 0) /* already setup */ + return; + for (i = 0; i < N(rt->rateCodeToIndex); i++) + rt->rateCodeToIndex[i] = (uint8_t) -1; + for (i = 0; i < rt->rateCount; i++) { + uint8_t code = rt->info[i].rateCode; + uint8_t cix = rt->info[i].controlRate; + + HALASSERT(code < N(rt->rateCodeToIndex)); + rt->rateCodeToIndex[code] = i; + HALASSERT((code | rt->info[i].shortPreamble) < + N(rt->rateCodeToIndex)); + rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i; + /* + * XXX for 11g the control rate to use for 5.5 and 11 Mb/s + * depends on whether they are marked as basic rates; + * the static tables are setup with an 11b-compatible + * 2Mb/s rate which will work but is suboptimal + */ + rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt, + WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE); + rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt, + WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE); + } +#undef N +} + +HAL_STATUS +ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t *result) +{ + const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + switch (type) { + case HAL_CAP_REG_DMN: /* regulatory domain */ + *result = AH_PRIVATE(ah)->ah_currentRD; + return HAL_OK; + case HAL_CAP_DFS_DMN: /* DFS Domain */ + *result = AH_PRIVATE(ah)->ah_dfsDomain; + return HAL_OK; + case HAL_CAP_CIPHER: /* cipher handled in hardware */ + case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ + return HAL_ENOTSUPP; + case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ + return HAL_ENOTSUPP; + case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */ + return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO; + case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */ + return HAL_ENOTSUPP; + case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */ + return HAL_ENOTSUPP; + case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */ + *result = pCap->halKeyCacheSize; + return HAL_OK; + case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */ + *result = pCap->halTotalQueues; + return HAL_OK; + case HAL_CAP_VEOL: /* hardware supports virtual EOL */ + return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */ + return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK; + case HAL_CAP_COMPRESSION: + return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_BURST: + return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_FASTFRAME: + return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_DIAG: /* hardware diagnostic support */ + *result = AH_PRIVATE(ah)->ah_diagreg; + return HAL_OK; + case HAL_CAP_TXPOW: /* global tx power limit */ + switch (capability) { + case 0: /* facility is supported */ + return HAL_OK; + case 1: /* current limit */ + *result = AH_PRIVATE(ah)->ah_powerLimit; + return HAL_OK; + case 2: /* current max tx power */ + *result = AH_PRIVATE(ah)->ah_maxPowerLevel; + return HAL_OK; + case 3: /* scale factor */ + *result = AH_PRIVATE(ah)->ah_tpScale; + return HAL_OK; + } + return HAL_ENOTSUPP; + case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */ + return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ + return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ + return HAL_ENOTSUPP; + case HAL_CAP_RFSILENT: /* rfsilent support */ + switch (capability) { + case 0: /* facility is supported */ + return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP; + case 1: /* current setting */ + return AH_PRIVATE(ah)->ah_rfkillEnabled ? + HAL_OK : HAL_ENOTSUPP; + case 2: /* rfsilent config */ + *result = AH_PRIVATE(ah)->ah_rfsilent; + return HAL_OK; + } + return HAL_ENOTSUPP; + case HAL_CAP_11D: + return HAL_OK; + + case HAL_CAP_HT: + return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_GTXTO: + return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_FAST_CC: + return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */ + *result = pCap->halTxChainMask; + return HAL_OK; + case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */ + *result = pCap->halRxChainMask; + return HAL_OK; + case HAL_CAP_NUM_GPIO_PINS: + *result = pCap->halNumGpioPins; + return HAL_OK; + case HAL_CAP_CST: + return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_RTS_AGGR_LIMIT: + *result = pCap->halRtsAggrLimit; + return HAL_OK; + case HAL_CAP_4ADDR_AGGR: + return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_EXT_CHAN_DFS: + return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_RX_STBC: + return pCap->halRxStbcSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_TX_STBC: + return pCap->halTxStbcSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_COMBINED_RADAR_RSSI: + return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_AUTO_SLEEP: + return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_MBSSID_AGGR_SUPPORT: + return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_SPLIT_4KB_TRANS: /* hardware handles descriptors straddling 4k page boundary */ + return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_REG_FLAG: + *result = AH_PRIVATE(ah)->ah_currentRDext; + return HAL_OK; + case HAL_CAP_ENHANCED_DMA_SUPPORT: + return pCap->halEnhancedDmaSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_NUM_TXMAPS: + *result = pCap->halNumTxMaps; + return HAL_OK; + case HAL_CAP_TXDESCLEN: + *result = pCap->halTxDescLen; + return HAL_OK; + case HAL_CAP_TXSTATUSLEN: + *result = pCap->halTxStatusLen; + return HAL_OK; + case HAL_CAP_RXSTATUSLEN: + *result = pCap->halRxStatusLen; + return HAL_OK; + case HAL_CAP_RXFIFODEPTH: + switch (capability) { + case HAL_RX_QUEUE_HP: + *result = pCap->halRxHpFifoDepth; + return HAL_OK; + case HAL_RX_QUEUE_LP: + *result = pCap->halRxLpFifoDepth; + return HAL_OK; + default: + return HAL_ENOTSUPP; + } + case HAL_CAP_RXBUFSIZE: + case HAL_CAP_NUM_MR_RETRIES: + *result = pCap->halNumMRRetries; + return HAL_OK; + case HAL_CAP_BT_COEX: + return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_SPECTRAL_SCAN: + return pCap->halSpectralScanSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_HT20_SGI: + return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */ + *result = pCap->halTstampPrecision; + return HAL_OK; + case HAL_CAP_ANT_DIV_COMB: /* AR9285/AR9485 LNA diversity */ + return pCap->halAntDivCombSupport ? HAL_OK : HAL_ENOTSUPP; + + case HAL_CAP_ENHANCED_DFS_SUPPORT: + return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP; + + /* FreeBSD-specific entries for now */ + case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ + return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_INTRMASK: /* mask of supported interrupts */ + *result = pCap->halIntrMask; + return HAL_OK; + case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */ + return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_STREAMS: /* number of 11n spatial streams */ + switch (capability) { + case 0: /* TX */ + *result = pCap->halTxStreams; + return HAL_OK; + case 1: /* RX */ + *result = pCap->halRxStreams; + return HAL_OK; + default: + return HAL_ENOTSUPP; + } + case HAL_CAP_RXDESC_SELFLINK: /* hardware supports self-linked final RX descriptors correctly */ + return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_LONG_RXDESC_TSF: /* 32 bit TSF in RX descriptor? */ + return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_BB_READ_WAR: /* Baseband read WAR */ + return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_SERIALISE_WAR: /* PCI register serialisation */ + return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_MFP: /* Management frame protection setting */ + *result = pCap->halMfpSupport; + return HAL_OK; + case HAL_CAP_RX_LNA_MIXING: /* Hardware uses an RX LNA mixer to map 2 antennas to a 1 stream receiver */ + return pCap->halRxUsingLnaMixing ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_DO_MYBEACON: /* Hardware supports filtering my-beacons */ + return pCap->halRxDoMyBeacon ? HAL_OK : HAL_ENOTSUPP; + default: + return HAL_EINVAL; + } +} + +HAL_BOOL +ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t setting, HAL_STATUS *status) +{ + + switch (type) { + case HAL_CAP_TXPOW: + switch (capability) { + case 3: + if (setting <= HAL_TP_SCALE_MIN) { + AH_PRIVATE(ah)->ah_tpScale = setting; + return AH_TRUE; + } + break; + } + break; + case HAL_CAP_RFSILENT: /* rfsilent support */ + /* + * NB: allow even if halRfSilentSupport is false + * in case the EEPROM is misprogrammed. + */ + switch (capability) { + case 1: /* current setting */ + AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0); + return AH_TRUE; + case 2: /* rfsilent config */ + /* XXX better done per-chip for validation? */ + AH_PRIVATE(ah)->ah_rfsilent = setting; + return AH_TRUE; + } + break; + case HAL_CAP_REG_DMN: /* regulatory domain */ + AH_PRIVATE(ah)->ah_currentRD = setting; + return AH_TRUE; + case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ + AH_PRIVATE(ah)->ah_rxornIsFatal = setting; + return AH_TRUE; + default: + break; + } + if (status) + *status = HAL_EINVAL; + return AH_FALSE; +} + +/* + * Common support for getDiagState method. + */ + +static u_int +ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs, + void *dstbuf, int space) +{ + uint32_t *dp = dstbuf; + int i; + + for (i = 0; space >= 2*sizeof(uint32_t); i++) { + uint32_t r = regs[i].start; + uint32_t e = regs[i].end; + *dp++ = r; + *dp++ = e; + space -= 2*sizeof(uint32_t); + do { + *dp++ = OS_REG_READ(ah, r); + r += sizeof(uint32_t); + space -= sizeof(uint32_t); + } while (r <= e && space >= sizeof(uint32_t)); + } + return (char *) dp - (char *) dstbuf; +} + +static void +ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space) +{ + while (space >= sizeof(HAL_REGWRITE)) { + OS_REG_WRITE(ah, regs->addr, regs->value); + regs++, space -= sizeof(HAL_REGWRITE); + } +} + +HAL_BOOL +ath_hal_getdiagstate(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize) +{ + + switch (request) { + case HAL_DIAG_REVS: + *result = &AH_PRIVATE(ah)->ah_devid; + *resultsize = sizeof(HAL_REVS); + return AH_TRUE; + case HAL_DIAG_REGS: + *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize); + return AH_TRUE; + case HAL_DIAG_SETREGS: + ath_hal_setregs(ah, args, argsize); + *resultsize = 0; + return AH_TRUE; + case HAL_DIAG_FATALERR: + *result = &AH_PRIVATE(ah)->ah_fatalState[0]; + *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState); + return AH_TRUE; + case HAL_DIAG_EEREAD: + if (argsize != sizeof(uint16_t)) + return AH_FALSE; + if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result)) + return AH_FALSE; + *resultsize = sizeof(uint16_t); + return AH_TRUE; +#ifdef AH_PRIVATE_DIAG + case HAL_DIAG_SETKEY: { + const HAL_DIAG_KEYVAL *dk; + + if (argsize != sizeof(HAL_DIAG_KEYVAL)) + return AH_FALSE; + dk = (const HAL_DIAG_KEYVAL *)args; + return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix, + &dk->dk_keyval, dk->dk_mac, dk->dk_xor); + } + case HAL_DIAG_RESETKEY: + if (argsize != sizeof(uint16_t)) + return AH_FALSE; + return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args); +#ifdef AH_SUPPORT_WRITE_EEPROM + case HAL_DIAG_EEWRITE: { + const HAL_DIAG_EEVAL *ee; + if (argsize != sizeof(HAL_DIAG_EEVAL)) + return AH_FALSE; + ee = (const HAL_DIAG_EEVAL *)args; + return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data); + } +#endif /* AH_SUPPORT_WRITE_EEPROM */ +#endif /* AH_PRIVATE_DIAG */ + case HAL_DIAG_11NCOMPAT: + if (argsize == 0) { + *resultsize = sizeof(uint32_t); + *((uint32_t *)(*result)) = + AH_PRIVATE(ah)->ah_11nCompat; + } else if (argsize == sizeof(uint32_t)) { + AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args; + } else + return AH_FALSE; + return AH_TRUE; + case HAL_DIAG_CHANSURVEY: + *result = &AH_PRIVATE(ah)->ah_chansurvey; + *resultsize = sizeof(HAL_CHANNEL_SURVEY); + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Set the properties of the tx queue with the parameters + * from qInfo. + */ +HAL_BOOL +ath_hal_setTxQProps(struct ath_hal *ah, + HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo) +{ + uint32_t cw; + + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: inactive queue\n", __func__); + return AH_FALSE; + } + /* XXX validate parameters */ + qi->tqi_ver = qInfo->tqi_ver; + qi->tqi_subtype = qInfo->tqi_subtype; + qi->tqi_qflags = qInfo->tqi_qflags; + qi->tqi_priority = qInfo->tqi_priority; + if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT) + qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255); + else + qi->tqi_aifs = INIT_AIFS; + if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) { + cw = AH_MIN(qInfo->tqi_cwmin, 1024); + /* make sure that the CWmin is of the form (2^n - 1) */ + qi->tqi_cwmin = 1; + while (qi->tqi_cwmin < cw) + qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1; + } else + qi->tqi_cwmin = qInfo->tqi_cwmin; + if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) { + cw = AH_MIN(qInfo->tqi_cwmax, 1024); + /* make sure that the CWmax is of the form (2^n - 1) */ + qi->tqi_cwmax = 1; + while (qi->tqi_cwmax < cw) + qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1; + } else + qi->tqi_cwmax = INIT_CWMAX; + /* Set retry limit values */ + if (qInfo->tqi_shretry != 0) + qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15); + else + qi->tqi_shretry = INIT_SH_RETRY; + if (qInfo->tqi_lgretry != 0) + qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15); + else + qi->tqi_lgretry = INIT_LG_RETRY; + qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod; + qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit; + qi->tqi_burstTime = qInfo->tqi_burstTime; + qi->tqi_readyTime = qInfo->tqi_readyTime; + + switch (qInfo->tqi_subtype) { + case HAL_WME_UPSD: + if (qi->tqi_type == HAL_TX_QUEUE_DATA) + qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS; + break; + default: + break; /* NB: silence compiler */ + } + return AH_TRUE; +} + +HAL_BOOL +ath_hal_getTxQProps(struct ath_hal *ah, + HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi) +{ + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: inactive queue\n", __func__); + return AH_FALSE; + } + + qInfo->tqi_qflags = qi->tqi_qflags; + qInfo->tqi_ver = qi->tqi_ver; + qInfo->tqi_subtype = qi->tqi_subtype; + qInfo->tqi_qflags = qi->tqi_qflags; + qInfo->tqi_priority = qi->tqi_priority; + qInfo->tqi_aifs = qi->tqi_aifs; + qInfo->tqi_cwmin = qi->tqi_cwmin; + qInfo->tqi_cwmax = qi->tqi_cwmax; + qInfo->tqi_shretry = qi->tqi_shretry; + qInfo->tqi_lgretry = qi->tqi_lgretry; + qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod; + qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit; + qInfo->tqi_burstTime = qi->tqi_burstTime; + qInfo->tqi_readyTime = qi->tqi_readyTime; + return AH_TRUE; +} + + /* 11a Turbo 11b 11g 108g */ +static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 }; + +/* + * Read the current channel noise floor and return. + * If nf cal hasn't finished, channel noise floor should be 0 + * and we return a nominal value based on band and frequency. + * + * NB: This is a private routine used by per-chip code to + * implement the ah_getChanNoise method. + */ +int16_t +ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + HAL_CHANNEL_INTERNAL *ichan; + + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->ic_freq, chan->ic_flags); + return 0; + } + if (ichan->rawNoiseFloor == 0) { + WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan); + + HALASSERT(mode < WIRELESS_MODE_MAX); + return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan); + } else + return ichan->rawNoiseFloor + ichan->noiseFloorAdjust; +} + +/* + * Fetch the current setup of ctl/ext noise floor values. + * + * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply + * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust(). + * + * The caller must supply ctl/ext NF arrays which are at least + * AH_MAX_CHAINS entries long. + */ +int +ath_hal_get_mimo_chan_noise(struct ath_hal *ah, + const struct ieee80211_channel *chan, int16_t *nf_ctl, + int16_t *nf_ext) +{ +#ifdef AH_SUPPORT_AR5416 + HAL_CHANNEL_INTERNAL *ichan; + int i; + + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->ic_freq, chan->ic_flags); + for (i = 0; i < AH_MAX_CHAINS; i++) { + nf_ctl[i] = nf_ext[i] = 0; + } + return 0; + } + + /* Return 0 if there's no valid MIMO values (yet) */ + if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) { + for (i = 0; i < AH_MAX_CHAINS; i++) { + nf_ctl[i] = nf_ext[i] = 0; + } + return 0; + } + if (ichan->rawNoiseFloor == 0) { + WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan); + HALASSERT(mode < WIRELESS_MODE_MAX); + /* + * See the comment below - this could cause issues for + * stations which have a very low RSSI, below the + * 'normalised' NF values in NOISE_FLOOR[]. + */ + for (i = 0; i < AH_MAX_CHAINS; i++) { + nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] + + ath_hal_getNfAdjust(ah, ichan); + } + return 1; + } else { + /* + * The value returned here from a MIMO radio is presumed to be + * "good enough" as a NF calculation. As RSSI values are calculated + * against this, an adjusted NF may be higher than the RSSI value + * returned from a vary weak station, resulting in an obscenely + * high signal strength calculation being returned. + * + * This should be re-evaluated at a later date, along with any + * signal strength calculations which are made. Quite likely the + * RSSI values will need to be adjusted to ensure the calculations + * don't "wrap" when RSSI is less than the "adjusted" NF value. + * ("Adjust" here is via ichan->noiseFloorAdjust.) + */ + for (i = 0; i < AH_MAX_CHAINS; i++) { + nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan); + nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan); + } + return 1; + } +#else + return 0; +#endif /* AH_SUPPORT_AR5416 */ +} + +/* + * Process all valid raw noise floors into the dBm noise floor values. + * Though our device has no reference for a dBm noise floor, we perform + * a relative minimization of NF's based on the lowest NF found across a + * channel scan. + */ +void +ath_hal_process_noisefloor(struct ath_hal *ah) +{ + HAL_CHANNEL_INTERNAL *c; + int16_t correct2, correct5; + int16_t lowest2, lowest5; + int i; + + /* + * Find the lowest 2GHz and 5GHz noise floor values after adjusting + * for statistically recorded NF/channel deviation. + */ + correct2 = lowest2 = 0; + correct5 = lowest5 = 0; + for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) { + WIRELESS_MODE mode; + int16_t nf; + + c = &AH_PRIVATE(ah)->ah_channels[i]; + if (c->rawNoiseFloor >= 0) + continue; + /* XXX can't identify proper mode */ + mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g; + nf = c->rawNoiseFloor + NOISE_FLOOR[mode] + + ath_hal_getNfAdjust(ah, c); + if (IS_CHAN_5GHZ(c)) { + if (nf < lowest5) { + lowest5 = nf; + correct5 = NOISE_FLOOR[mode] - + (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c)); + } + } else { + if (nf < lowest2) { + lowest2 = nf; + correct2 = NOISE_FLOOR[mode] - + (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c)); + } + } + } + + /* Correct the channels to reach the expected NF value */ + for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) { + c = &AH_PRIVATE(ah)->ah_channels[i]; + if (c->rawNoiseFloor >= 0) + continue; + /* Apply correction factor */ + c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) + + (IS_CHAN_5GHZ(c) ? correct5 : correct2); + HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n", + c->channel, c->rawNoiseFloor, c->noiseFloorAdjust); + } +} + +/* + * INI support routines. + */ + +int +ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, + int col, int regWr) +{ + int r; + + HALASSERT(col < ia->cols); + for (r = 0; r < ia->rows; r++) { + OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), + HAL_INI_VAL(ia, r, col)); + + /* Analog shift register delay seems needed for Merlin - PR kern/154220 */ + if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900) + OS_DELAY(100); + + DMA_YIELD(regWr); + } + return regWr; +} + +void +ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col) +{ + int r; + + HALASSERT(col < ia->cols); + for (r = 0; r < ia->rows; r++) + data[r] = HAL_INI_VAL(ia, r, col); +} + +int +ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, + const uint32_t data[], int regWr) +{ + int r; + + for (r = 0; r < ia->rows; r++) { + OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]); + DMA_YIELD(regWr); + } + return regWr; +} + +/* + * These are EEPROM board related routines which should likely live in + * a helper library of some sort. + */ + +/************************************************************** + * ath_ee_getLowerUppderIndex + * + * Return indices surrounding the value in sorted integer lists. + * Requirement: the input list must be monotonically increasing + * and populated up to the list size + * Returns: match is set if an index in the array matches exactly + * or a the target is before or after the range of the array. + */ +HAL_BOOL +ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize, + uint16_t *indexL, uint16_t *indexR) +{ + uint16_t i; + + /* + * Check first and last elements for beyond ordered array cases. + */ + if (target <= pList[0]) { + *indexL = *indexR = 0; + return AH_TRUE; + } + if (target >= pList[listSize-1]) { + *indexL = *indexR = (uint16_t)(listSize - 1); + return AH_TRUE; + } + + /* look for value being near or between 2 values in list */ + for (i = 0; i < listSize - 1; i++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (pList[i] == target) { + *indexL = *indexR = i; + return AH_TRUE; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < pList[i + 1]) { + *indexL = i; + *indexR = (uint16_t)(i + 1); + return AH_FALSE; + } + } + HALASSERT(0); + *indexL = *indexR = 0; + return AH_FALSE; +} + +/************************************************************** + * ath_ee_FillVpdTable + * + * Fill the Vpdlist for indices Pmax-Pmin + * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4 + */ +HAL_BOOL +ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList, + uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList) +{ + uint16_t i, k; + uint8_t currPwr = pwrMin; + uint16_t idxL, idxR; + + HALASSERT(pwrMax > pwrMin); + for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) { + ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts, + &(idxL), &(idxR)); + if (idxR < 1) + idxR = 1; /* extrapolate below */ + if (idxL == numIntercepts - 1) + idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */ + if (pPwrList[idxL] == pPwrList[idxR]) + k = pVpdList[idxL]; + else + k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) / + (pPwrList[idxR] - pPwrList[idxL]) ); + HALASSERT(k < 256); + pRetVpdList[i] = (uint8_t)k; + currPwr += 2; /* half dB steps */ + } + + return AH_TRUE; +} + +/************************************************************************** + * ath_ee_interpolate + * + * Returns signed interpolated or the scaled up interpolated value + */ +int16_t +ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight == srcLeft) { + rv = targetLeft; + } else { + rv = (int16_t)( ((target - srcLeft) * targetRight + + (srcRight - target) * targetLeft) / (srcRight - srcLeft) ); + } + return rv; +} + +/* + * Adjust the TSF. + */ +void +ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta) +{ + /* XXX handle wrap/overflow */ + OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta); +} + +/* + * Enable or disable CCA. + */ +void +ath_hal_setcca(struct ath_hal *ah, int ena) +{ + /* + * NB: fill me in; this is not provided by default because disabling + * CCA in most locales violates regulatory. + */ +} + +/* + * Get CCA setting. + */ +int +ath_hal_getcca(struct ath_hal *ah) +{ + u_int32_t diag; + if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK) + return 1; + return ((diag & 0x500000) == 0); +} + +/* + * This routine is only needed when supporting EEPROM-in-RAM setups + * (eg embedded SoCs and on-board PCI/PCIe devices.) + */ +/* NB: This is in 16 bit words; not bytes */ +/* XXX This doesn't belong here! */ +#define ATH_DATA_EEPROM_SIZE 2048 + +HAL_BOOL +ath_hal_EepromDataRead(struct ath_hal *ah, u_int off, uint16_t *data) +{ + if (ah->ah_eepromdata == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no eeprom data!\n", __func__); + return AH_FALSE; + } + if (off > ATH_DATA_EEPROM_SIZE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: offset %x > %x\n", + __func__, off, ATH_DATA_EEPROM_SIZE); + return AH_FALSE; + } + (*data) = ah->ah_eepromdata[off]; + return AH_TRUE; +} + +/* + * Do a 2GHz specific MHz->IEEE based on the hardware + * frequency. + * + * This is the unmapped frequency which is programmed into the hardware. + */ +int +ath_hal_mhz2ieee_2ghz(struct ath_hal *ah, int freq) +{ + + if (freq == 2484) + return 14; + if (freq < 2484) + return ((int) freq - 2407) / 5; + else + return 15 + ((freq - 2512) / 20); +} + +/* + * Clear the current survey data. + * + * This should be done during a channel change. + */ +void +ath_hal_survey_clear(struct ath_hal *ah) +{ + + OS_MEMZERO(&AH_PRIVATE(ah)->ah_chansurvey, + sizeof(AH_PRIVATE(ah)->ah_chansurvey)); +} + +/* + * Add a sample to the channel survey. + */ +void +ath_hal_survey_add_sample(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hs) +{ + HAL_CHANNEL_SURVEY *cs; + + cs = &AH_PRIVATE(ah)->ah_chansurvey; + + OS_MEMCPY(&cs->samples[cs->cur_sample], hs, sizeof(*hs)); + cs->samples[cs->cur_sample].seq_num = cs->cur_seq; + cs->cur_sample = (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT; + cs->cur_seq++; +} diff --git a/sys/external/isc/atheros_hal/dist/ah.h b/sys/external/isc/atheros_hal/dist/ah.h new file mode 100644 index 0000000..76f37d6 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah.h @@ -0,0 +1,1804 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef _ATH_AH_H_ +#define _ATH_AH_H_ +/* + * Atheros Hardware Access Layer + * + * Clients of the HAL call ath_hal_attach to obtain a reference to an ath_hal + * structure for use with the device. Hardware-related operations that + * follow must call back into the HAL through interface, supplying the + * reference as the first parameter. + */ + +#include "ah_osdep.h" + +/* + * The maximum number of TX/RX chains supported. + * This is intended to be used by various statistics gathering operations + * (NF, RSSI, EVM). + */ +#define AH_MAX_CHAINS 3 +#define AH_MIMO_MAX_EVM_PILOTS 6 + +/* + * __ahdecl is analogous to _cdecl; it defines the calling + * convention used within the HAL. For most systems this + * can just default to be empty and the compiler will (should) + * use _cdecl. For systems where _cdecl is not compatible this + * must be defined. See linux/ah_osdep.h for an example. + */ +#ifndef __ahdecl +#define __ahdecl +#endif + +/* + * Status codes that may be returned by the HAL. Note that + * interfaces that return a status code set it only when an + * error occurs--i.e. you cannot check it for success. + */ +typedef enum { + HAL_OK = 0, /* No error */ + HAL_ENXIO = 1, /* No hardware present */ + HAL_ENOMEM = 2, /* Memory allocation failed */ + HAL_EIO = 3, /* Hardware didn't respond as expected */ + HAL_EEMAGIC = 4, /* EEPROM magic number invalid */ + HAL_EEVERSION = 5, /* EEPROM version invalid */ + HAL_EELOCKED = 6, /* EEPROM unreadable */ + HAL_EEBADSUM = 7, /* EEPROM checksum invalid */ + HAL_EEREAD = 8, /* EEPROM read problem */ + HAL_EEBADMAC = 9, /* EEPROM mac address invalid */ + HAL_EESIZE = 10, /* EEPROM size not supported */ + HAL_EEWRITE = 11, /* Attempt to change write-locked EEPROM */ + HAL_EINVAL = 12, /* Invalid parameter to function */ + HAL_ENOTSUPP = 13, /* Hardware revision not supported */ + HAL_ESELFTEST = 14, /* Hardware self-test failed */ + HAL_EINPROGRESS = 15, /* Operation incomplete */ + HAL_EEBADREG = 16, /* EEPROM invalid regulatory contents */ + HAL_EEBADCC = 17, /* EEPROM invalid country code */ + HAL_INV_PMODE = 18, /* Couldn't bring out of sleep state */ +} HAL_STATUS; + +typedef enum { + AH_FALSE = 0, /* NB: lots of code assumes false is zero */ + AH_TRUE = 1, +} HAL_BOOL; + +typedef enum { + HAL_CAP_REG_DMN = 0, /* current regulatory domain */ + HAL_CAP_CIPHER = 1, /* hardware supports cipher */ + HAL_CAP_TKIP_MIC = 2, /* handle TKIP MIC in hardware */ + HAL_CAP_TKIP_SPLIT = 3, /* hardware TKIP uses split keys */ + HAL_CAP_PHYCOUNTERS = 4, /* hardware PHY error counters */ + HAL_CAP_DIVERSITY = 5, /* hardware supports fast diversity */ + HAL_CAP_KEYCACHE_SIZE = 6, /* number of entries in key cache */ + HAL_CAP_NUM_TXQUEUES = 7, /* number of hardware xmit queues */ + HAL_CAP_VEOL = 9, /* hardware supports virtual EOL */ + HAL_CAP_PSPOLL = 10, /* hardware has working PS-Poll support */ + HAL_CAP_DIAG = 11, /* hardware diagnostic support */ + HAL_CAP_COMPRESSION = 12, /* hardware supports compression */ + HAL_CAP_BURST = 13, /* hardware supports packet bursting */ + HAL_CAP_FASTFRAME = 14, /* hardware supoprts fast frames */ + HAL_CAP_TXPOW = 15, /* global tx power limit */ + HAL_CAP_TPC = 16, /* per-packet tx power control */ + HAL_CAP_PHYDIAG = 17, /* hardware phy error diagnostic */ + HAL_CAP_BSSIDMASK = 18, /* hardware supports bssid mask */ + HAL_CAP_MCAST_KEYSRCH = 19, /* hardware has multicast key search */ + HAL_CAP_TSF_ADJUST = 20, /* hardware has beacon tsf adjust */ + /* 21 was HAL_CAP_XR */ + HAL_CAP_WME_TKIPMIC = 22, /* hardware can support TKIP MIC when WMM is turned on */ + /* 23 was HAL_CAP_CHAN_HALFRATE */ + /* 24 was HAL_CAP_CHAN_QUARTERRATE */ + HAL_CAP_RFSILENT = 25, /* hardware has rfsilent support */ + HAL_CAP_TPC_ACK = 26, /* ack txpower with per-packet tpc */ + HAL_CAP_TPC_CTS = 27, /* cts txpower with per-packet tpc */ + HAL_CAP_11D = 28, /* 11d beacon support for changing cc */ + HAL_CAP_PCIE_PS = 29, + HAL_CAP_HT = 30, /* hardware can support HT */ + HAL_CAP_GTXTO = 31, /* hardware supports global tx timeout */ + HAL_CAP_FAST_CC = 32, /* hardware supports fast channel change */ + HAL_CAP_TX_CHAINMASK = 33, /* mask of TX chains supported */ + HAL_CAP_RX_CHAINMASK = 34, /* mask of RX chains supported */ + HAL_CAP_NUM_GPIO_PINS = 36, /* number of GPIO pins */ + + HAL_CAP_CST = 38, /* hardware supports carrier sense timeout */ + HAL_CAP_RIFS_RX = 39, + HAL_CAP_RIFS_TX = 40, + HAL_CAP_FORCE_PPM = 41, + HAL_CAP_RTS_AGGR_LIMIT = 42, /* aggregation limit with RTS */ + HAL_CAP_4ADDR_AGGR = 43, /* hardware is capable of 4addr aggregation */ + HAL_CAP_DFS_DMN = 44, /* current DFS domain */ + HAL_CAP_EXT_CHAN_DFS = 45, /* DFS support for extension channel */ + HAL_CAP_COMBINED_RADAR_RSSI = 46, /* Is combined RSSI for radar accurate */ + + HAL_CAP_AUTO_SLEEP = 48, /* hardware can go to network sleep + automatically after waking up to receive TIM */ + HAL_CAP_MBSSID_AGGR_SUPPORT = 49, /* Support for mBSSID Aggregation */ + HAL_CAP_SPLIT_4KB_TRANS = 50, /* hardware supports descriptors straddling a 4k page boundary */ + HAL_CAP_REG_FLAG = 51, /* Regulatory domain flags */ + HAL_CAP_BB_RIFS_HANG = 52, + HAL_CAP_RIFS_RX_ENABLED = 53, + HAL_CAP_BB_DFS_HANG = 54, + + HAL_CAP_RX_STBC = 58, + HAL_CAP_TX_STBC = 59, + + HAL_CAP_BT_COEX = 60, /* hardware is capable of bluetooth coexistence */ + HAL_CAP_DYNAMIC_SMPS = 61, /* Dynamic MIMO Power Save hardware support */ + + HAL_CAP_DS = 67, /* 2 stream */ + HAL_CAP_BB_RX_CLEAR_STUCK_HANG = 68, + HAL_CAP_MAC_HANG = 69, /* can MAC hang */ + HAL_CAP_MFP = 70, /* Management Frame Protection in hardware */ + + HAL_CAP_TS = 72, /* 3 stream */ + + HAL_CAP_ENHANCED_DMA_SUPPORT = 75, /* DMA FIFO support */ + HAL_CAP_NUM_TXMAPS = 76, /* Number of buffers in a transmit descriptor */ + HAL_CAP_TXDESCLEN = 77, /* Length of transmit descriptor */ + HAL_CAP_TXSTATUSLEN = 78, /* Length of transmit status descriptor */ + HAL_CAP_RXSTATUSLEN = 79, /* Length of transmit status descriptor */ + HAL_CAP_RXFIFODEPTH = 80, /* Receive hardware FIFO depth */ + HAL_CAP_RXBUFSIZE = 81, /* Receive Buffer Length */ + HAL_CAP_NUM_MR_RETRIES = 82, /* limit on multirate retries */ + HAL_CAP_OL_PWRCTRL = 84, /* Open loop TX power control */ + HAL_CAP_SPECTRAL_SCAN = 90, /* Hardware supports spectral scan */ + + HAL_CAP_BB_PANIC_WATCHDOG = 92, + + HAL_CAP_HT20_SGI = 96, /* hardware supports HT20 short GI */ + + HAL_CAP_LDPC = 99, + + HAL_CAP_RXTSTAMP_PREC = 100, /* rx desc tstamp precision (bits) */ + + HAL_CAP_ANT_DIV_COMB = 105, /* Enable antenna diversity/combining */ + HAL_CAP_PHYRESTART_CLR_WAR = 106, /* in some cases, clear phy restart to fix bb hang */ + HAL_CAP_ENTERPRISE_MODE = 107, /* Enterprise mode features */ + HAL_CAP_LDPCWAR = 108, + HAL_CAP_CHANNEL_SWITCH_TIME_USEC = 109, /* Channel change time, usec */ + HAL_CAP_ENABLE_APM = 110, /* APM enabled */ + HAL_CAP_PCIE_LCR_EXTSYNC_EN = 111, + HAL_CAP_PCIE_LCR_OFFSET = 112, + + HAL_CAP_ENHANCED_DFS_SUPPORT = 117, /* hardware supports enhanced DFS */ + HAL_CAP_MCI = 118, + HAL_CAP_SMARTANTENNA = 119, + HAL_CAP_TRAFFIC_FAST_RECOVER = 120, + HAL_CAP_TX_DIVERSITY = 121, + HAL_CAP_CRDC = 122, + + /* The following are private to the FreeBSD HAL (224 onward) */ + + HAL_CAP_INTMIT = 229, /* interference mitigation */ + HAL_CAP_RXORN_FATAL = 230, /* HAL_INT_RXORN treated as fatal */ + HAL_CAP_BB_HANG = 235, /* can baseband hang */ + HAL_CAP_INTRMASK = 237, /* bitmask of supported interrupts */ + HAL_CAP_BSSIDMATCH = 238, /* hardware has disable bssid match */ + HAL_CAP_STREAMS = 239, /* how many 802.11n spatial streams are available */ + HAL_CAP_RXDESC_SELFLINK = 242, /* support a self-linked tail RX descriptor */ + HAL_CAP_LONG_RXDESC_TSF = 243, /* hardware supports 32bit TSF in RX descriptor */ + HAL_CAP_BB_READ_WAR = 244, /* baseband read WAR */ + HAL_CAP_SERIALISE_WAR = 245, /* serialise register access on PCI */ + HAL_CAP_ENFORCE_TXOP = 246, /* Enforce TXOP if supported */ + HAL_CAP_RX_LNA_MIXING = 247, /* RX hardware uses LNA mixing */ + HAL_CAP_DO_MYBEACON = 248, /* Supports HAL_RX_FILTER_MYBEACON */ +} HAL_CAPABILITY_TYPE; + +/* + * "States" for setting the LED. These correspond to + * the possible 802.11 operational states and there may + * be a many-to-one mapping between these states and the + * actual hardware state for the LED's (i.e. the hardware + * may have fewer states). + */ +typedef enum { + HAL_LED_INIT = 0, + HAL_LED_SCAN = 1, + HAL_LED_AUTH = 2, + HAL_LED_ASSOC = 3, + HAL_LED_RUN = 4 +} HAL_LED_STATE; + +/* + * Transmit queue types/numbers. These are used to tag + * each transmit queue in the hardware and to identify a set + * of transmit queues for operations such as start/stop dma. + */ +typedef enum { + HAL_TX_QUEUE_INACTIVE = 0, /* queue is inactive/unused */ + HAL_TX_QUEUE_DATA = 1, /* data xmit q's */ + HAL_TX_QUEUE_BEACON = 2, /* beacon xmit q */ + HAL_TX_QUEUE_CAB = 3, /* "crap after beacon" xmit q */ + HAL_TX_QUEUE_UAPSD = 4, /* u-apsd power save xmit q */ + HAL_TX_QUEUE_PSPOLL = 5, /* power save poll xmit q */ + HAL_TX_QUEUE_CFEND = 6, + HAL_TX_QUEUE_PAPRD = 7, +} HAL_TX_QUEUE; + +#define HAL_NUM_TX_QUEUES 10 /* max possible # of queues */ + +/* + * Receive queue types. These are used to tag + * each transmit queue in the hardware and to identify a set + * of transmit queues for operations such as start/stop dma. + */ +typedef enum { + HAL_RX_QUEUE_HP = 0, /* high priority recv queue */ + HAL_RX_QUEUE_LP = 1, /* low priority recv queue */ +} HAL_RX_QUEUE; + +#define HAL_NUM_RX_QUEUES 2 /* max possible # of queues */ + +#define HAL_TXFIFO_DEPTH 8 /* transmit fifo depth */ + +/* + * Transmit queue subtype. These map directly to + * WME Access Categories (except for UPSD). Refer + * to Table 5 of the WME spec. + */ +typedef enum { + HAL_WME_AC_BK = 0, /* background access category */ + HAL_WME_AC_BE = 1, /* best effort access category*/ + HAL_WME_AC_VI = 2, /* video access category */ + HAL_WME_AC_VO = 3, /* voice access category */ + HAL_WME_UPSD = 4, /* uplink power save */ +} HAL_TX_QUEUE_SUBTYPE; + +/* + * Transmit queue flags that control various + * operational parameters. + */ +typedef enum { + /* + * Per queue interrupt enables. When set the associated + * interrupt may be delivered for packets sent through + * the queue. Without these enabled no interrupts will + * be delivered for transmits through the queue. + */ + HAL_TXQ_TXOKINT_ENABLE = 0x0001, /* enable TXOK interrupt */ + HAL_TXQ_TXERRINT_ENABLE = 0x0001, /* enable TXERR interrupt */ + HAL_TXQ_TXDESCINT_ENABLE = 0x0002, /* enable TXDESC interrupt */ + HAL_TXQ_TXEOLINT_ENABLE = 0x0004, /* enable TXEOL interrupt */ + HAL_TXQ_TXURNINT_ENABLE = 0x0008, /* enable TXURN interrupt */ + /* + * Enable hardware compression for packets sent through + * the queue. The compression buffer must be setup and + * packets must have a key entry marked in the tx descriptor. + */ + HAL_TXQ_COMPRESSION_ENABLE = 0x0010, /* enable h/w compression */ + /* + * Disable queue when veol is hit or ready time expires. + * By default the queue is disabled only on reaching the + * physical end of queue (i.e. a null link ptr in the + * descriptor chain). + */ + HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE = 0x0020, + /* + * Schedule frames on delivery of a DBA (DMA Beacon Alert) + * event. Frames will be transmitted only when this timer + * fires, e.g to transmit a beacon in ap or adhoc modes. + */ + HAL_TXQ_DBA_GATED = 0x0040, /* schedule based on DBA */ + /* + * Each transmit queue has a counter that is incremented + * each time the queue is enabled and decremented when + * the list of frames to transmit is traversed (or when + * the ready time for the queue expires). This counter + * must be non-zero for frames to be scheduled for + * transmission. The following controls disable bumping + * this counter under certain conditions. Typically this + * is used to gate frames based on the contents of another + * queue (e.g. CAB traffic may only follow a beacon frame). + * These are meaningful only when frames are scheduled + * with a non-ASAP policy (e.g. DBA-gated). + */ + HAL_TXQ_CBR_DIS_QEMPTY = 0x0080, /* disable on this q empty */ + HAL_TXQ_CBR_DIS_BEMPTY = 0x0100, /* disable on beacon q empty */ + + /* + * Fragment burst backoff policy. Normally the no backoff + * is done after a successful transmission, the next fragment + * is sent at SIFS. If this flag is set backoff is done + * after each fragment, regardless whether it was ack'd or + * not, after the backoff count reaches zero a normal channel + * access procedure is done before the next transmit (i.e. + * wait AIFS instead of SIFS). + */ + HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE = 0x00800000, + /* + * Disable post-tx backoff following each frame. + */ + HAL_TXQ_BACKOFF_DISABLE = 0x00010000, /* disable post backoff */ + /* + * DCU arbiter lockout control. This controls how + * lower priority tx queues are handled with respect to + * to a specific queue when multiple queues have frames + * to send. No lockout means lower priority queues arbitrate + * concurrently with this queue. Intra-frame lockout + * means lower priority queues are locked out until the + * current frame transmits (e.g. including backoffs and bursting). + * Global lockout means nothing lower can arbitrary so + * long as there is traffic activity on this queue (frames, + * backoff, etc). + */ + HAL_TXQ_ARB_LOCKOUT_INTRA = 0x00020000, /* intra-frame lockout */ + HAL_TXQ_ARB_LOCKOUT_GLOBAL = 0x00040000, /* full lockout s */ + + HAL_TXQ_IGNORE_VIRTCOL = 0x00080000, /* ignore virt collisions */ + HAL_TXQ_SEQNUM_INC_DIS = 0x00100000, /* disable seqnum increment */ +} HAL_TX_QUEUE_FLAGS; + +typedef struct { + uint32_t tqi_ver; /* hal TXQ version */ + HAL_TX_QUEUE_SUBTYPE tqi_subtype; /* subtype if applicable */ + HAL_TX_QUEUE_FLAGS tqi_qflags; /* flags (see above) */ + uint32_t tqi_priority; /* (not used) */ + uint32_t tqi_aifs; /* aifs */ + uint32_t tqi_cwmin; /* cwMin */ + uint32_t tqi_cwmax; /* cwMax */ + uint16_t tqi_shretry; /* rts retry limit */ + uint16_t tqi_lgretry; /* long retry limit (not used)*/ + uint32_t tqi_cbrPeriod; /* CBR period (us) */ + uint32_t tqi_cbrOverflowLimit; /* threshold for CBROVF int */ + uint32_t tqi_burstTime; /* max burst duration (us) */ + uint32_t tqi_readyTime; /* frame schedule time (us) */ + uint32_t tqi_compBuf; /* comp buffer phys addr */ +} HAL_TXQ_INFO; + +#define HAL_TQI_NONVAL 0xffff + +/* token to use for aifs, cwmin, cwmax */ +#define HAL_TXQ_USEDEFAULT ((uint32_t) -1) + +/* compression definitions */ +#define HAL_COMP_BUF_MAX_SIZE 9216 /* 9K */ +#define HAL_COMP_BUF_ALIGN_SIZE 512 + +/* + * Transmit packet types. This belongs in ah_desc.h, but + * is here so we can give a proper type to various parameters + * (and not require everyone include the file). + * + * NB: These values are intentionally assigned for + * direct use when setting up h/w descriptors. + */ +typedef enum { + HAL_PKT_TYPE_NORMAL = 0, + HAL_PKT_TYPE_ATIM = 1, + HAL_PKT_TYPE_PSPOLL = 2, + HAL_PKT_TYPE_BEACON = 3, + HAL_PKT_TYPE_PROBE_RESP = 4, + HAL_PKT_TYPE_CHIRP = 5, + HAL_PKT_TYPE_GRP_POLL = 6, + HAL_PKT_TYPE_AMPDU = 7, +} HAL_PKT_TYPE; + +/* Rx Filter Frame Types */ +typedef enum { + /* + * These bits correspond to AR_RX_FILTER for all chips. + * Not all bits are supported by all chips. + */ + HAL_RX_FILTER_UCAST = 0x00000001, /* Allow unicast frames */ + HAL_RX_FILTER_MCAST = 0x00000002, /* Allow multicast frames */ + HAL_RX_FILTER_BCAST = 0x00000004, /* Allow broadcast frames */ + HAL_RX_FILTER_CONTROL = 0x00000008, /* Allow control frames */ + HAL_RX_FILTER_BEACON = 0x00000010, /* Allow beacon frames */ + HAL_RX_FILTER_PROM = 0x00000020, /* Promiscuous mode */ + HAL_RX_FILTER_PROBEREQ = 0x00000080, /* Allow probe request frames */ + HAL_RX_FILTER_PHYERR = 0x00000100, /* Allow phy errors */ + HAL_RX_FILTER_MYBEACON = 0x00000200, /* Filter beacons other than mine */ + HAL_RX_FILTER_COMPBAR = 0x00000400, /* Allow compressed BAR */ + HAL_RX_FILTER_COMP_BA = 0x00000800, /* Allow compressed blockack */ + HAL_RX_FILTER_PHYRADAR = 0x00002000, /* Allow phy radar errors */ + HAL_RX_FILTER_PSPOLL = 0x00004000, /* Allow PS-POLL frames */ + HAL_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, + /* Allow all mcast/bcast frames */ + + /* + * Magic RX filter flags that aren't targetting hardware bits + * but instead the HAL sets individual bits - eg PHYERR will result + * in OFDM/CCK timing error frames being received. + */ + HAL_RX_FILTER_BSSID = 0x40000000, /* Disable BSSID match */ +} HAL_RX_FILTER; + +typedef enum { + HAL_PM_AWAKE = 0, + HAL_PM_FULL_SLEEP = 1, + HAL_PM_NETWORK_SLEEP = 2, + HAL_PM_UNDEFINED = 3 +} HAL_POWER_MODE; + +/* + * Enterprise mode flags + */ +#define AH_ENT_DUAL_BAND_DISABLE 0x00000001 +#define AH_ENT_CHAIN2_DISABLE 0x00000002 +#define AH_ENT_5MHZ_DISABLE 0x00000004 +#define AH_ENT_10MHZ_DISABLE 0x00000008 +#define AH_ENT_49GHZ_DISABLE 0x00000010 +#define AH_ENT_LOOPBACK_DISABLE 0x00000020 +#define AH_ENT_TPC_PERF_DISABLE 0x00000040 +#define AH_ENT_MIN_PKT_SIZE_DISABLE 0x00000080 +#define AH_ENT_SPECTRAL_PRECISION 0x00000300 +#define AH_ENT_SPECTRAL_PRECISION_S 8 +#define AH_ENT_RTSCTS_DELIM_WAR 0x00010000 + +#define AH_FIRST_DESC_NDELIMS 60 + +/* + * NOTE WELL: + * These are mapped to take advantage of the common locations for many of + * the bits on all of the currently supported MAC chips. This is to make + * the ISR as efficient as possible, while still abstracting HW differences. + * When new hardware breaks this commonality this enumerated type, as well + * as the HAL functions using it, must be modified. All values are directly + * mapped unless commented otherwise. + */ +typedef enum { + HAL_INT_RX = 0x00000001, /* Non-common mapping */ + HAL_INT_RXDESC = 0x00000002, /* Legacy mapping */ + HAL_INT_RXERR = 0x00000004, + HAL_INT_RXHP = 0x00000001, /* EDMA */ + HAL_INT_RXLP = 0x00000002, /* EDMA */ + HAL_INT_RXNOFRM = 0x00000008, + HAL_INT_RXEOL = 0x00000010, + HAL_INT_RXORN = 0x00000020, + HAL_INT_TX = 0x00000040, /* Non-common mapping */ + HAL_INT_TXDESC = 0x00000080, + HAL_INT_TIM_TIMER= 0x00000100, + HAL_INT_MCI = 0x00000200, + HAL_INT_BBPANIC = 0x00000400, + HAL_INT_TXURN = 0x00000800, + HAL_INT_MIB = 0x00001000, + HAL_INT_RXPHY = 0x00004000, + HAL_INT_RXKCM = 0x00008000, + HAL_INT_SWBA = 0x00010000, + HAL_INT_BRSSI = 0x00020000, + HAL_INT_BMISS = 0x00040000, + HAL_INT_BNR = 0x00100000, + HAL_INT_TIM = 0x00200000, /* Non-common mapping */ + HAL_INT_DTIM = 0x00400000, /* Non-common mapping */ + HAL_INT_DTIMSYNC= 0x00800000, /* Non-common mapping */ + HAL_INT_GPIO = 0x01000000, + HAL_INT_CABEND = 0x02000000, /* Non-common mapping */ + HAL_INT_TSFOOR = 0x04000000, /* Non-common mapping */ + HAL_INT_TBTT = 0x08000000, /* Non-common mapping */ + /* Atheros ref driver has a generic timer interrupt now..*/ + HAL_INT_GENTIMER = 0x08000000, /* Non-common mapping */ + HAL_INT_CST = 0x10000000, /* Non-common mapping */ + HAL_INT_GTT = 0x20000000, /* Non-common mapping */ + HAL_INT_FATAL = 0x40000000, /* Non-common mapping */ +#define HAL_INT_GLOBAL 0x80000000 /* Set/clear IER */ + HAL_INT_BMISC = HAL_INT_TIM + | HAL_INT_DTIM + | HAL_INT_DTIMSYNC + | HAL_INT_CABEND + | HAL_INT_TBTT, + + /* Interrupt bits that map directly to ISR/IMR bits */ + HAL_INT_COMMON = HAL_INT_RXNOFRM + | HAL_INT_RXDESC + | HAL_INT_RXEOL + | HAL_INT_RXORN + | HAL_INT_TXDESC + | HAL_INT_TXURN + | HAL_INT_MIB + | HAL_INT_RXPHY + | HAL_INT_RXKCM + | HAL_INT_SWBA + | HAL_INT_BMISS + | HAL_INT_BRSSI + | HAL_INT_BNR + | HAL_INT_GPIO, +} HAL_INT; + +/* + * MSI vector assignments + */ +typedef enum { + HAL_MSIVEC_MISC = 0, + HAL_MSIVEC_TX = 1, + HAL_MSIVEC_RXLP = 2, + HAL_MSIVEC_RXHP = 3, +} HAL_MSIVEC; + +typedef enum { + HAL_INT_LINE = 0, + HAL_INT_MSI = 1, +} HAL_INT_TYPE; + +/* For interrupt mitigation registers */ +typedef enum { + HAL_INT_RX_FIRSTPKT=0, + HAL_INT_RX_LASTPKT, + HAL_INT_TX_FIRSTPKT, + HAL_INT_TX_LASTPKT, + HAL_INT_THRESHOLD +} HAL_INT_MITIGATION; + +/* XXX this is duplicate information! */ +typedef struct { + u_int32_t cyclecnt_diff; /* delta cycle count */ + u_int32_t rxclr_cnt; /* rx clear count */ + u_int32_t extrxclr_cnt; /* ext chan rx clear count */ + u_int32_t txframecnt_diff; /* delta tx frame count */ + u_int32_t rxframecnt_diff; /* delta rx frame count */ + u_int32_t listen_time; /* listen time in msec - time for which ch is free */ + u_int32_t ofdmphyerr_cnt; /* OFDM err count since last reset */ + u_int32_t cckphyerr_cnt; /* CCK err count since last reset */ + u_int32_t ofdmphyerrcnt_diff; /* delta OFDM Phy Error Count */ + HAL_BOOL valid; /* if the stats are valid*/ +} HAL_ANISTATS; + +typedef struct { + u_int8_t txctl_offset; + u_int8_t txctl_numwords; + u_int8_t txstatus_offset; + u_int8_t txstatus_numwords; + + u_int8_t rxctl_offset; + u_int8_t rxctl_numwords; + u_int8_t rxstatus_offset; + u_int8_t rxstatus_numwords; + + u_int8_t macRevision; +} HAL_DESC_INFO; + +typedef enum { + HAL_GPIO_OUTPUT_MUX_AS_OUTPUT = 0, + HAL_GPIO_OUTPUT_MUX_PCIE_ATTENTION_LED = 1, + HAL_GPIO_OUTPUT_MUX_PCIE_POWER_LED = 2, + HAL_GPIO_OUTPUT_MUX_MAC_NETWORK_LED = 3, + HAL_GPIO_OUTPUT_MUX_MAC_POWER_LED = 4, + HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE = 5, + HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME = 6, + + HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA, + HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK, + HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA, + HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK, + HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX, + HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX, + HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX, + HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX, + HAL_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE, + HAL_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA, + HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0, + HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1, + HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2, + HAL_GPIO_OUTPUT_MUX_NUM_ENTRIES +} HAL_GPIO_MUX_TYPE; + +typedef enum { + HAL_GPIO_INTR_LOW = 0, + HAL_GPIO_INTR_HIGH = 1, + HAL_GPIO_INTR_DISABLE = 2 +} HAL_GPIO_INTR_TYPE; + +typedef struct halCounters { + u_int32_t tx_frame_count; + u_int32_t rx_frame_count; + u_int32_t rx_clear_count; + u_int32_t cycle_count; + u_int8_t is_rx_active; // true (1) or false (0) + u_int8_t is_tx_active; // true (1) or false (0) +} HAL_COUNTERS; + +typedef enum { + HAL_RFGAIN_INACTIVE = 0, + HAL_RFGAIN_READ_REQUESTED = 1, + HAL_RFGAIN_NEED_CHANGE = 2 +} HAL_RFGAIN; + +typedef uint16_t HAL_CTRY_CODE; /* country code */ +typedef uint16_t HAL_REG_DOMAIN; /* regulatory domain code */ + +#define HAL_ANTENNA_MIN_MODE 0 +#define HAL_ANTENNA_FIXED_A 1 +#define HAL_ANTENNA_FIXED_B 2 +#define HAL_ANTENNA_MAX_MODE 3 + +typedef struct { + uint32_t ackrcv_bad; + uint32_t rts_bad; + uint32_t rts_good; + uint32_t fcs_bad; + uint32_t beacons; +} HAL_MIB_STATS; + +/* + * These bits represent what's in ah_currentRDext. + */ +typedef enum { + REG_EXT_FCC_MIDBAND = 0, + REG_EXT_JAPAN_MIDBAND = 1, + REG_EXT_FCC_DFS_HT40 = 2, + REG_EXT_JAPAN_NONDFS_HT40 = 3, + REG_EXT_JAPAN_DFS_HT40 = 4 +} REG_EXT_BITMAP; + +enum { + HAL_MODE_11A = 0x001, /* 11a channels */ + HAL_MODE_TURBO = 0x002, /* 11a turbo-only channels */ + HAL_MODE_11B = 0x004, /* 11b channels */ + HAL_MODE_PUREG = 0x008, /* 11g channels (OFDM only) */ +#ifdef notdef + HAL_MODE_11G = 0x010, /* 11g channels (OFDM/CCK) */ +#else + HAL_MODE_11G = 0x008, /* XXX historical */ +#endif + HAL_MODE_108G = 0x020, /* 11g+Turbo channels */ + HAL_MODE_108A = 0x040, /* 11a+Turbo channels */ + HAL_MODE_11A_HALF_RATE = 0x200, /* 11a half width channels */ + HAL_MODE_11A_QUARTER_RATE = 0x400, /* 11a quarter width channels */ + HAL_MODE_11G_HALF_RATE = 0x800, /* 11g half width channels */ + HAL_MODE_11G_QUARTER_RATE = 0x1000, /* 11g quarter width channels */ + HAL_MODE_11NG_HT20 = 0x008000, + HAL_MODE_11NA_HT20 = 0x010000, + HAL_MODE_11NG_HT40PLUS = 0x020000, + HAL_MODE_11NG_HT40MINUS = 0x040000, + HAL_MODE_11NA_HT40PLUS = 0x080000, + HAL_MODE_11NA_HT40MINUS = 0x100000, + HAL_MODE_ALL = 0xffffff +}; + +typedef struct { + int rateCount; /* NB: for proper padding */ + uint8_t rateCodeToIndex[256]; /* back mapping */ + struct { + uint8_t valid; /* valid for rate control use */ + uint8_t phy; /* CCK/OFDM/XR */ + uint32_t rateKbps; /* transfer rate in kbs */ + uint8_t rateCode; /* rate for h/w descriptors */ + uint8_t shortPreamble; /* mask for enabling short + * preamble in CCK rate code */ + uint8_t dot11Rate; /* value for supported rates + * info element of MLME */ + uint8_t controlRate; /* index of next lower basic + * rate; used for dur. calcs */ + uint16_t lpAckDuration; /* long preamble ACK duration */ + uint16_t spAckDuration; /* short preamble ACK duration*/ + } info[64]; +} HAL_RATE_TABLE; + +typedef struct { + u_int rs_count; /* number of valid entries */ + uint8_t rs_rates[64]; /* rates */ +} HAL_RATE_SET; + +/* + * 802.11n specific structures and enums + */ +typedef enum { + HAL_CHAINTYPE_TX = 1, /* Tx chain type */ + HAL_CHAINTYPE_RX = 2, /* RX chain type */ +} HAL_CHAIN_TYPE; + +typedef struct { + u_int Tries; + u_int Rate; /* hardware rate code */ + u_int RateIndex; /* rate series table index */ + u_int PktDuration; + u_int ChSel; + u_int RateFlags; +#define HAL_RATESERIES_RTS_CTS 0x0001 /* use rts/cts w/this series */ +#define HAL_RATESERIES_2040 0x0002 /* use ext channel for series */ +#define HAL_RATESERIES_HALFGI 0x0004 /* use half-gi for series */ +#define HAL_RATESERIES_STBC 0x0008 /* use STBC for series */ + u_int tx_power_cap; /* in 1/2 dBm units XXX TODO */ +} HAL_11N_RATE_SERIES; + +typedef enum { + HAL_HT_MACMODE_20 = 0, /* 20 MHz operation */ + HAL_HT_MACMODE_2040 = 1, /* 20/40 MHz operation */ +} HAL_HT_MACMODE; + +typedef enum { + HAL_HT_PHYMODE_20 = 0, /* 20 MHz operation */ + HAL_HT_PHYMODE_2040 = 1, /* 20/40 MHz operation */ +} HAL_HT_PHYMODE; + +typedef enum { + HAL_HT_EXTPROTSPACING_20 = 0, /* 20 MHz spacing */ + HAL_HT_EXTPROTSPACING_25 = 1, /* 25 MHz spacing */ +} HAL_HT_EXTPROTSPACING; + + +typedef enum { + HAL_RX_CLEAR_CTL_LOW = 0x1, /* force control channel to appear busy */ + HAL_RX_CLEAR_EXT_LOW = 0x2, /* force extension channel to appear busy */ +} HAL_HT_RXCLEAR; + +typedef enum { + HAL_FREQ_BAND_5GHZ = 0, + HAL_FREQ_BAND_2GHZ = 1, +} HAL_FREQ_BAND; + +/* + * Antenna switch control. By default antenna selection + * enables multiple (2) antenna use. To force use of the + * A or B antenna only specify a fixed setting. Fixing + * the antenna will also disable any diversity support. + */ +typedef enum { + HAL_ANT_VARIABLE = 0, /* variable by programming */ + HAL_ANT_FIXED_A = 1, /* fixed antenna A */ + HAL_ANT_FIXED_B = 2, /* fixed antenna B */ +} HAL_ANT_SETTING; + +typedef enum { + HAL_M_STA = 1, /* infrastructure station */ + HAL_M_IBSS = 0, /* IBSS (adhoc) station */ + HAL_M_HOSTAP = 6, /* Software Access Point */ + HAL_M_MONITOR = 8 /* Monitor mode */ +} HAL_OPMODE; + +typedef enum { + HAL_RESET_NORMAL = 0, /* Do normal reset */ + HAL_RESET_BBPANIC = 1, /* Reset because of BB panic */ + HAL_RESET_FORCE_COLD = 2, /* Force full reset */ +} HAL_RESET_TYPE; + +typedef struct { + uint8_t kv_type; /* one of HAL_CIPHER */ + uint8_t kv_apsd; /* Mask for APSD enabled ACs */ + uint16_t kv_len; /* length in bits */ + uint8_t kv_val[16]; /* enough for 128-bit keys */ + uint8_t kv_mic[8]; /* TKIP MIC key */ + uint8_t kv_txmic[8]; /* TKIP TX MIC key (optional) */ +} HAL_KEYVAL; + +/* + * This is the TX descriptor field which marks the key padding requirement. + * The naming is unfortunately unclear. + */ +#define AH_KEYTYPE_MASK 0x0F +typedef enum { + HAL_KEY_TYPE_CLEAR, + HAL_KEY_TYPE_WEP, + HAL_KEY_TYPE_AES, + HAL_KEY_TYPE_TKIP, +} HAL_KEY_TYPE; + +typedef enum { + HAL_CIPHER_WEP = 0, + HAL_CIPHER_AES_OCB = 1, + HAL_CIPHER_AES_CCM = 2, + HAL_CIPHER_CKIP = 3, + HAL_CIPHER_TKIP = 4, + HAL_CIPHER_CLR = 5, /* no encryption */ + + HAL_CIPHER_MIC = 127 /* TKIP-MIC, not a cipher */ +} HAL_CIPHER; + +enum { + HAL_SLOT_TIME_6 = 6, /* NB: for turbo mode */ + HAL_SLOT_TIME_9 = 9, + HAL_SLOT_TIME_20 = 20, +}; + +/* + * Per-station beacon timer state. Note that the specified + * beacon interval (given in TU's) can also include flags + * to force a TSF reset and to enable the beacon xmit logic. + * If bs_cfpmaxduration is non-zero the hardware is setup to + * coexist with a PCF-capable AP. + */ +typedef struct { + uint32_t bs_nexttbtt; /* next beacon in TU */ + uint32_t bs_nextdtim; /* next DTIM in TU */ + uint32_t bs_intval; /* beacon interval+flags */ +/* + * HAL_BEACON_PERIOD, HAL_BEACON_ENA and HAL_BEACON_RESET_TSF + * are all 1:1 correspondances with the pre-11n chip AR_BEACON + * register. + */ +#define HAL_BEACON_PERIOD 0x0000ffff /* beacon interval period */ +#define HAL_BEACON_PERIOD_TU8 0x0007ffff /* beacon interval, tu/8 */ +#define HAL_BEACON_ENA 0x00800000 /* beacon xmit enable */ +#define HAL_BEACON_RESET_TSF 0x01000000 /* clear TSF */ +#define HAL_TSFOOR_THRESHOLD 0x00004240 /* TSF OOR thresh (16k uS) */ + uint32_t bs_dtimperiod; + uint16_t bs_cfpperiod; /* CFP period in TU */ + uint16_t bs_cfpmaxduration; /* max CFP duration in TU */ + uint32_t bs_cfpnext; /* next CFP in TU */ + uint16_t bs_timoffset; /* byte offset to TIM bitmap */ + uint16_t bs_bmissthreshold; /* beacon miss threshold */ + uint32_t bs_sleepduration; /* max sleep duration */ + uint32_t bs_tsfoor_threshold; /* TSF out of range threshold */ +} HAL_BEACON_STATE; + +/* + * Like HAL_BEACON_STATE but for non-station mode setup. + * NB: see above flag definitions for bt_intval. + */ +typedef struct { + uint32_t bt_intval; /* beacon interval+flags */ + uint32_t bt_nexttbtt; /* next beacon in TU */ + uint32_t bt_nextatim; /* next ATIM in TU */ + uint32_t bt_nextdba; /* next DBA in 1/8th TU */ + uint32_t bt_nextswba; /* next SWBA in 1/8th TU */ + uint32_t bt_flags; /* timer enables */ +#define HAL_BEACON_TBTT_EN 0x00000001 +#define HAL_BEACON_DBA_EN 0x00000002 +#define HAL_BEACON_SWBA_EN 0x00000004 +} HAL_BEACON_TIMERS; + +/* + * Per-node statistics maintained by the driver for use in + * optimizing signal quality and other operational aspects. + */ +typedef struct { + uint32_t ns_avgbrssi; /* average beacon rssi */ + uint32_t ns_avgrssi; /* average data rssi */ + uint32_t ns_avgtxrssi; /* average tx rssi */ +} HAL_NODE_STATS; + +#define HAL_RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */ + +/* + * This is the ANI state and MIB stats. + * + * It's used by the HAL modules to keep state /and/ by the debug ioctl + * to fetch ANI information. + */ +typedef struct { + uint32_t ast_ani_niup; /* ANI increased noise immunity */ + uint32_t ast_ani_nidown; /* ANI decreased noise immunity */ + uint32_t ast_ani_spurup; /* ANI increased spur immunity */ + uint32_t ast_ani_spurdown;/* ANI descreased spur immunity */ + uint32_t ast_ani_ofdmon; /* ANI OFDM weak signal detect on */ + uint32_t ast_ani_ofdmoff;/* ANI OFDM weak signal detect off */ + uint32_t ast_ani_cckhigh;/* ANI CCK weak signal threshold high */ + uint32_t ast_ani_ccklow; /* ANI CCK weak signal threshold low */ + uint32_t ast_ani_stepup; /* ANI increased first step level */ + uint32_t ast_ani_stepdown;/* ANI decreased first step level */ + uint32_t ast_ani_ofdmerrs;/* ANI cumulative ofdm phy err count */ + uint32_t ast_ani_cckerrs;/* ANI cumulative cck phy err count */ + uint32_t ast_ani_reset; /* ANI parameters zero'd for non-STA */ + uint32_t ast_ani_lzero; /* ANI listen time forced to zero */ + uint32_t ast_ani_lneg; /* ANI listen time calculated < 0 */ + HAL_MIB_STATS ast_mibstats; /* MIB counter stats */ + HAL_NODE_STATS ast_nodestats; /* Latest rssi stats from driver */ +} HAL_ANI_STATS; + +typedef struct { + uint8_t noiseImmunityLevel; + uint8_t spurImmunityLevel; + uint8_t firstepLevel; + uint8_t ofdmWeakSigDetectOff; + uint8_t cckWeakSigThreshold; + uint32_t listenTime; + + /* NB: intentionally ordered so data exported to user space is first */ + uint32_t txFrameCount; /* Last txFrameCount */ + uint32_t rxFrameCount; /* Last rx Frame count */ + uint32_t cycleCount; /* Last cycleCount + (to detect wrap-around) */ + uint32_t ofdmPhyErrCount;/* OFDM err count since last reset */ + uint32_t cckPhyErrCount; /* CCK err count since last reset */ +} HAL_ANI_STATE; + +struct ath_desc; +struct ath_tx_status; +struct ath_rx_status; +struct ieee80211_channel; + +/* + * This is a channel survey sample entry. + * + * The AR5212 ANI routines fill these samples. The ANI code then uses it + * when calculating listen time; it is also exported via a diagnostic + * API. + */ +typedef struct { + uint32_t seq_num; + uint32_t tx_busy; + uint32_t rx_busy; + uint32_t chan_busy; + uint32_t ext_chan_busy; + uint32_t cycle_count; + /* XXX TODO */ + uint32_t ofdm_phyerr_count; + uint32_t cck_phyerr_count; +} HAL_SURVEY_SAMPLE; + +/* + * This provides 3.2 seconds of sample space given an + * ANI time of 1/10th of a second. This may not be enough! + */ +#define CHANNEL_SURVEY_SAMPLE_COUNT 32 + +typedef struct { + HAL_SURVEY_SAMPLE samples[CHANNEL_SURVEY_SAMPLE_COUNT]; + uint32_t cur_sample; /* current sample in sequence */ + uint32_t cur_seq; /* current sequence number */ +} HAL_CHANNEL_SURVEY; + +/* + * ANI commands. + * + * These are used both internally and externally via the diagnostic + * API. + * + * Note that this is NOT the ANI commands being used via the INTMIT + * capability - that has a different mapping for some reason. + */ +typedef enum { + HAL_ANI_PRESENT = 0, /* is ANI support present */ + HAL_ANI_NOISE_IMMUNITY_LEVEL = 1, /* set level */ + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION = 2, /* enable/disable */ + HAL_ANI_CCK_WEAK_SIGNAL_THR = 3, /* enable/disable */ + HAL_ANI_FIRSTEP_LEVEL = 4, /* set level */ + HAL_ANI_SPUR_IMMUNITY_LEVEL = 5, /* set level */ + HAL_ANI_MODE = 6, /* 0 => manual, 1 => auto (XXX do not change) */ + HAL_ANI_PHYERR_RESET = 7, /* reset phy error stats */ + HAL_ANI_MRC_CCK = 8, +} HAL_ANI_CMD; + +#define HAL_ANI_ALL 0xffffffff + +/* + * This is the layout of the ANI INTMIT capability. + * + * Notice that the command values differ to HAL_ANI_CMD. + */ +typedef enum { + HAL_CAP_INTMIT_PRESENT = 0, + HAL_CAP_INTMIT_ENABLE = 1, + HAL_CAP_INTMIT_NOISE_IMMUNITY_LEVEL = 2, + HAL_CAP_INTMIT_OFDM_WEAK_SIGNAL_LEVEL = 3, + HAL_CAP_INTMIT_CCK_WEAK_SIGNAL_THR = 4, + HAL_CAP_INTMIT_FIRSTEP_LEVEL = 5, + HAL_CAP_INTMIT_SPUR_IMMUNITY_LEVEL = 6 +} HAL_CAP_INTMIT_CMD; + +typedef struct { + int32_t pe_firpwr; /* FIR pwr out threshold */ + int32_t pe_rrssi; /* Radar rssi thresh */ + int32_t pe_height; /* Pulse height thresh */ + int32_t pe_prssi; /* Pulse rssi thresh */ + int32_t pe_inband; /* Inband thresh */ + + /* The following params are only for AR5413 and later */ + u_int32_t pe_relpwr; /* Relative power threshold in 0.5dB steps */ + u_int32_t pe_relstep; /* Pulse Relative step threshold in 0.5dB steps */ + u_int32_t pe_maxlen; /* Max length of radar sign in 0.8us units */ + int32_t pe_usefir128; /* Use the average in-band power measured over 128 cycles */ + int32_t pe_blockradar; /* + * Enable to block radar check if pkt detect is done via OFDM + * weak signal detect or pkt is detected immediately after tx + * to rx transition + */ + int32_t pe_enmaxrssi; /* + * Enable to use the max rssi instead of the last rssi during + * fine gain changes for radar detection + */ + int32_t pe_extchannel; /* Enable DFS on ext channel */ + int32_t pe_enabled; /* Whether radar detection is enabled */ + int32_t pe_enrelpwr; + int32_t pe_en_relstep_check; +} HAL_PHYERR_PARAM; + +#define HAL_PHYERR_PARAM_NOVAL 65535 + +typedef struct { + u_int16_t ss_fft_period; /* Skip interval for FFT reports */ + u_int16_t ss_period; /* Spectral scan period */ + u_int16_t ss_count; /* # of reports to return from ss_active */ + u_int16_t ss_short_report;/* Set to report ony 1 set of FFT results */ + u_int8_t radar_bin_thresh_sel; /* strong signal radar FFT threshold configuration */ + u_int16_t ss_spectral_pri; /* are we doing a noise power cal ? */ + int8_t ss_nf_cal[AH_MAX_CHAINS*2]; /* nf calibrated values for ctl+ext from eeprom */ + int8_t ss_nf_pwr[AH_MAX_CHAINS*2]; /* nf pwr values for ctl+ext from eeprom */ + int32_t ss_nf_temp_data; /* temperature data taken during nf scan */ + int ss_enabled; + int ss_active; +} HAL_SPECTRAL_PARAM; +#define HAL_SPECTRAL_PARAM_NOVAL 0xFFFF +#define HAL_SPECTRAL_PARAM_ENABLE 0x8000 /* Enable/Disable if applicable */ + +/* + * DFS operating mode flags. + */ +typedef enum { + HAL_DFS_UNINIT_DOMAIN = 0, /* Uninitialized dfs domain */ + HAL_DFS_FCC_DOMAIN = 1, /* FCC3 dfs domain */ + HAL_DFS_ETSI_DOMAIN = 2, /* ETSI dfs domain */ + HAL_DFS_MKK4_DOMAIN = 3, /* Japan dfs domain */ +} HAL_DFS_DOMAIN; + + +/* + * MFP decryption options for initializing the MAC. + */ +typedef enum { + HAL_MFP_QOSDATA = 0, /* Decrypt MFP frames like QoS data frames. All chips before Merlin. */ + HAL_MFP_PASSTHRU, /* Don't decrypt MFP frames at all. Passthrough */ + HAL_MFP_HW_CRYPTO /* hardware decryption enabled. Merlin can do it. */ +} HAL_MFP_OPT_T; + +/* LNA config supported */ +typedef enum { + HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2 = 0, + HAL_ANT_DIV_COMB_LNA2 = 1, + HAL_ANT_DIV_COMB_LNA1 = 2, + HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2 = 3, +} HAL_ANT_DIV_COMB_LNA_CONF; + +typedef struct { + u_int8_t main_lna_conf; + u_int8_t alt_lna_conf; + u_int8_t fast_div_bias; + u_int8_t main_gaintb; + u_int8_t alt_gaintb; + u_int8_t antdiv_configgroup; + int8_t lna1_lna2_delta; +} HAL_ANT_COMB_CONFIG; + +#define DEFAULT_ANTDIV_CONFIG_GROUP 0x00 +#define HAL_ANTDIV_CONFIG_GROUP_1 0x01 +#define HAL_ANTDIV_CONFIG_GROUP_2 0x02 +#define HAL_ANTDIV_CONFIG_GROUP_3 0x03 + +/* + * Flag for setting QUIET period + */ +typedef enum { + HAL_QUIET_DISABLE = 0x0, + HAL_QUIET_ENABLE = 0x1, + HAL_QUIET_ADD_CURRENT_TSF = 0x2, /* add current TSF to next_start offset */ + HAL_QUIET_ADD_SWBA_RESP_TIME = 0x4, /* add beacon response time to next_start offset */ +} HAL_QUIET_FLAG; + +#define HAL_DFS_EVENT_PRICH 0x0000001 +#define HAL_DFS_EVENT_EXTCH 0x0000002 +#define HAL_DFS_EVENT_EXTEARLY 0x0000004 +#define HAL_DFS_EVENT_ISDC 0x0000008 + +struct hal_dfs_event { + uint64_t re_full_ts; /* 64-bit full timestamp from interrupt time */ + uint32_t re_ts; /* Original 15 bit recv timestamp */ + uint8_t re_rssi; /* rssi of radar event */ + uint8_t re_dur; /* duration of radar pulse */ + uint32_t re_flags; /* Flags (see above) */ +}; +typedef struct hal_dfs_event HAL_DFS_EVENT; + +/* + * Generic Timer domain + */ +typedef enum { + HAL_GEN_TIMER_TSF = 0, + HAL_GEN_TIMER_TSF2, + HAL_GEN_TIMER_TSF_ANY +} HAL_GEN_TIMER_DOMAIN; + +/* + * BT Co-existence definitions + */ +typedef enum { + HAL_BT_MODULE_CSR_BC4 = 0, /* CSR BlueCore v4 */ + HAL_BT_MODULE_JANUS = 1, /* Kite + Valkyrie combo */ + HAL_BT_MODULE_HELIUS = 2, /* Kiwi + Valkyrie combo */ + HAL_MAX_BT_MODULES +} HAL_BT_MODULE; + +typedef struct { + HAL_BT_MODULE bt_module; + u_int8_t bt_coex_config; + u_int8_t bt_gpio_bt_active; + u_int8_t bt_gpio_bt_priority; + u_int8_t bt_gpio_wlan_active; + u_int8_t bt_active_polarity; + HAL_BOOL bt_single_ant; + u_int8_t bt_dutyCycle; + u_int8_t bt_isolation; + u_int8_t bt_period; +} HAL_BT_COEX_INFO; + +typedef enum { + HAL_BT_COEX_MODE_LEGACY = 0, /* legacy rx_clear mode */ + HAL_BT_COEX_MODE_UNSLOTTED = 1, /* untimed/unslotted mode */ + HAL_BT_COEX_MODE_SLOTTED = 2, /* slotted mode */ + HAL_BT_COEX_MODE_DISALBED = 3, /* coexistence disabled */ +} HAL_BT_COEX_MODE; + +typedef enum { + HAL_BT_COEX_CFG_NONE, /* No bt coex enabled */ + HAL_BT_COEX_CFG_2WIRE_2CH, /* 2-wire with 2 chains */ + HAL_BT_COEX_CFG_2WIRE_CH1, /* 2-wire with ch1 */ + HAL_BT_COEX_CFG_2WIRE_CH0, /* 2-wire with ch0 */ + HAL_BT_COEX_CFG_3WIRE, /* 3-wire */ + HAL_BT_COEX_CFG_MCI /* MCI */ +} HAL_BT_COEX_CFG; + +typedef enum { + HAL_BT_COEX_SET_ACK_PWR = 0, /* Change ACK power setting */ + HAL_BT_COEX_LOWER_TX_PWR, /* Change transmit power */ + HAL_BT_COEX_ANTENNA_DIVERSITY, /* Enable RX diversity for Kite */ + HAL_BT_COEX_MCI_MAX_TX_PWR, /* Set max tx power for concurrent tx */ + HAL_BT_COEX_MCI_FTP_STOMP_RX, /* Use a different weight for stomp low */ +} HAL_BT_COEX_SET_PARAMETER; + +#define HAL_BT_COEX_FLAG_LOW_ACK_PWR 0x00000001 +#define HAL_BT_COEX_FLAG_LOWER_TX_PWR 0x00000002 +/* Check Rx Diversity is allowed */ +#define HAL_BT_COEX_FLAG_ANT_DIV_ALLOW 0x00000004 +/* Check Diversity is on or off */ +#define HAL_BT_COEX_FLAG_ANT_DIV_ENABLE 0x00000008 + +#define HAL_BT_COEX_ANTDIV_CONTROL1_ENABLE 0x0b +/* main: LNA1, alt: LNA2 */ +#define HAL_BT_COEX_ANTDIV_CONTROL2_ENABLE 0x09 +#define HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_A 0x04 +#define HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_A 0x09 +#define HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_B 0x02 +#define HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_B 0x06 + +#define HAL_BT_COEX_ISOLATION_FOR_NO_COEX 30 + +#define HAL_BT_COEX_ANT_DIV_SWITCH_COM 0x66666666 + +#define HAL_BT_COEX_HELIUS_CHAINMASK 0x02 + +#define HAL_BT_COEX_LOW_ACK_POWER 0x0 +#define HAL_BT_COEX_HIGH_ACK_POWER 0x3f3f3f + +typedef enum { + HAL_BT_COEX_NO_STOMP = 0, + HAL_BT_COEX_STOMP_ALL, + HAL_BT_COEX_STOMP_LOW, + HAL_BT_COEX_STOMP_NONE, + HAL_BT_COEX_STOMP_ALL_FORCE, + HAL_BT_COEX_STOMP_LOW_FORCE, +} HAL_BT_COEX_STOMP_TYPE; + +typedef struct { + /* extend rx_clear after tx/rx to protect the burst (in usec). */ + u_int8_t bt_time_extend; + + /* + * extend rx_clear as long as txsm is + * transmitting or waiting for ack. + */ + HAL_BOOL bt_txstate_extend; + + /* + * extend rx_clear so that when tx_frame + * is asserted, rx_clear will drop. + */ + HAL_BOOL bt_txframe_extend; + + /* + * coexistence mode + */ + HAL_BT_COEX_MODE bt_mode; + + /* + * treat BT high priority traffic as + * a quiet collision + */ + HAL_BOOL bt_quiet_collision; + + /* + * invert rx_clear as WLAN_ACTIVE + */ + HAL_BOOL bt_rxclear_polarity; + + /* + * slotted mode only. indicate the time in usec + * from the rising edge of BT_ACTIVE to the time + * BT_PRIORITY can be sampled to indicate priority. + */ + u_int8_t bt_priority_time; + + /* + * slotted mode only. indicate the time in usec + * from the rising edge of BT_ACTIVE to the time + * BT_PRIORITY can be sampled to indicate tx/rx and + * BT_FREQ is sampled. + */ + u_int8_t bt_first_slot_time; + + /* + * slotted mode only. rx_clear and bt_ant decision + * will be held the entire time that BT_ACTIVE is asserted, + * otherwise the decision is made before every slot boundry. + */ + HAL_BOOL bt_hold_rxclear; +} HAL_BT_COEX_CONFIG; + +struct hal_bb_panic_info { + u_int32_t status; + u_int32_t tsf; + u_int32_t phy_panic_wd_ctl1; + u_int32_t phy_panic_wd_ctl2; + u_int32_t phy_gen_ctrl; + u_int32_t rxc_pcnt; + u_int32_t rxf_pcnt; + u_int32_t txf_pcnt; + u_int32_t cycles; + u_int32_t wd; + u_int32_t det; + u_int32_t rdar; + u_int32_t r_odfm; + u_int32_t r_cck; + u_int32_t t_odfm; + u_int32_t t_cck; + u_int32_t agc; + u_int32_t src; +}; + +/* Serialize Register Access Mode */ +typedef enum { + SER_REG_MODE_OFF = 0, + SER_REG_MODE_ON = 1, + SER_REG_MODE_AUTO = 2, +} SER_REG_MODE; + +typedef struct +{ + int ah_debug; /* only used if AH_DEBUG is defined */ + int ah_ar5416_biasadj; /* enable AR2133 radio specific bias fiddling */ + + /* NB: these are deprecated; they exist for now for compatibility */ + int ah_dma_beacon_response_time;/* in TU's */ + int ah_sw_beacon_response_time; /* in TU's */ + int ah_additional_swba_backoff; /* in TU's */ + int ah_force_full_reset; /* force full chip reset rather then warm reset */ + int ah_serialise_reg_war; /* force serialisation of register IO */ + + /* XXX these don't belong here, they're just for the ar9300 HAL port effort */ + int ath_hal_desc_tpc; /* Per-packet TPC */ + int ath_hal_sta_update_tx_pwr_enable; /* GreenTX */ + int ath_hal_sta_update_tx_pwr_enable_S1; /* GreenTX */ + int ath_hal_sta_update_tx_pwr_enable_S2; /* GreenTX */ + int ath_hal_sta_update_tx_pwr_enable_S3; /* GreenTX */ + + /* I'm not sure what the default values for these should be */ + int ath_hal_pll_pwr_save; + int ath_hal_pcie_power_save_enable; + int ath_hal_intr_mitigation_rx; + int ath_hal_intr_mitigation_tx; + + int ath_hal_pcie_clock_req; +#define AR_PCIE_PLL_PWRSAVE_CONTROL (1<<0) +#define AR_PCIE_PLL_PWRSAVE_ON_D3 (1<<1) +#define AR_PCIE_PLL_PWRSAVE_ON_D0 (1<<2) + + int ath_hal_pcie_waen; + int ath_hal_pcie_ser_des_write; + + /* these are important for correct AR9300 behaviour */ + int ath_hal_ht_enable; /* needs to be enabled for AR9300 HT */ + int ath_hal_diversity_control; + int ath_hal_antenna_switch_swap; + int ath_hal_ext_lna_ctl_gpio; + int ath_hal_spur_mode; + int ath_hal_6mb_ack; /* should set this to 1 for 11a/11na? */ + int ath_hal_enable_msi; /* enable MSI interrupts (needed?) */ + int ath_hal_beacon_filter_interval; /* ok to be 0 for now? */ + + /* For now, set this to 0 - net80211 needs to know about hardware MFP support */ + int ath_hal_mfp_support; + + int ath_hal_enable_ani; /* should set this.. */ + int ath_hal_cwm_ignore_ext_cca; + int ath_hal_show_bb_panic; + int ath_hal_ant_ctrl_comm2g_switch_enable; + int ath_hal_ext_atten_margin_cfg; + int ath_hal_min_gainidx; + int ath_hal_war70c; + uint32_t ath_hal_mci_config; +} HAL_OPS_CONFIG; + +/* + * Hardware Access Layer (HAL) API. + * + * Clients of the HAL call ath_hal_attach to obtain a reference to an + * ath_hal structure for use with the device. Hardware-related operations + * that follow must call back into the HAL through interface, supplying + * the reference as the first parameter. Note that before using the + * reference returned by ath_hal_attach the caller should verify the + * ABI version number. + */ +struct ath_hal { + uint32_t ah_magic; /* consistency check magic number */ + uint16_t ah_devid; /* PCI device ID */ + uint16_t ah_subvendorid; /* PCI subvendor ID */ + HAL_SOFTC ah_sc; /* back pointer to driver/os state */ + HAL_BUS_TAG ah_st; /* params for register r+w */ + HAL_BUS_HANDLE ah_sh; + HAL_CTRY_CODE ah_countryCode; + + uint32_t ah_macVersion; /* MAC version id */ + uint16_t ah_macRev; /* MAC revision */ + uint16_t ah_phyRev; /* PHY revision */ + /* NB: when only one radio is present the rev is in 5Ghz */ + uint16_t ah_analog5GhzRev;/* 5GHz radio revision */ + uint16_t ah_analog2GhzRev;/* 2GHz radio revision */ + + uint16_t *ah_eepromdata; /* eeprom buffer, if needed */ + + uint32_t ah_intrstate[8]; /* last int state */ + uint32_t ah_syncstate; /* last sync intr state */ + + /* Current powerstate from HAL calls */ + HAL_POWER_MODE ah_powerMode; + + HAL_OPS_CONFIG ah_config; + const HAL_RATE_TABLE *__ahdecl(*ah_getRateTable)(struct ath_hal *, + u_int mode); + void __ahdecl(*ah_detach)(struct ath_hal*); + + /* Reset functions */ + HAL_BOOL __ahdecl(*ah_reset)(struct ath_hal *, HAL_OPMODE, + struct ieee80211_channel *, + HAL_BOOL bChannelChange, + HAL_RESET_TYPE resetType, + HAL_STATUS *status); + HAL_BOOL __ahdecl(*ah_phyDisable)(struct ath_hal *); + HAL_BOOL __ahdecl(*ah_disable)(struct ath_hal *); + void __ahdecl(*ah_configPCIE)(struct ath_hal *, HAL_BOOL restore, + HAL_BOOL power_off); + void __ahdecl(*ah_disablePCIE)(struct ath_hal *); + void __ahdecl(*ah_setPCUConfig)(struct ath_hal *); + HAL_BOOL __ahdecl(*ah_perCalibration)(struct ath_hal*, + struct ieee80211_channel *, HAL_BOOL *); + HAL_BOOL __ahdecl(*ah_perCalibrationN)(struct ath_hal *, + struct ieee80211_channel *, u_int chainMask, + HAL_BOOL longCal, HAL_BOOL *isCalDone); + HAL_BOOL __ahdecl(*ah_resetCalValid)(struct ath_hal *, + const struct ieee80211_channel *); + HAL_BOOL __ahdecl(*ah_setTxPower)(struct ath_hal *, + const struct ieee80211_channel *, uint16_t *); + HAL_BOOL __ahdecl(*ah_setTxPowerLimit)(struct ath_hal *, uint32_t); + HAL_BOOL __ahdecl(*ah_setBoardValues)(struct ath_hal *, + const struct ieee80211_channel *); + + /* Transmit functions */ + HAL_BOOL __ahdecl(*ah_updateTxTrigLevel)(struct ath_hal*, + HAL_BOOL incTrigLevel); + int __ahdecl(*ah_setupTxQueue)(struct ath_hal *, HAL_TX_QUEUE, + const HAL_TXQ_INFO *qInfo); + HAL_BOOL __ahdecl(*ah_setTxQueueProps)(struct ath_hal *, int q, + const HAL_TXQ_INFO *qInfo); + HAL_BOOL __ahdecl(*ah_getTxQueueProps)(struct ath_hal *, int q, + HAL_TXQ_INFO *qInfo); + HAL_BOOL __ahdecl(*ah_releaseTxQueue)(struct ath_hal *ah, u_int q); + HAL_BOOL __ahdecl(*ah_resetTxQueue)(struct ath_hal *ah, u_int q); + uint32_t __ahdecl(*ah_getTxDP)(struct ath_hal*, u_int); + HAL_BOOL __ahdecl(*ah_setTxDP)(struct ath_hal*, u_int, uint32_t txdp); + uint32_t __ahdecl(*ah_numTxPending)(struct ath_hal *, u_int q); + HAL_BOOL __ahdecl(*ah_startTxDma)(struct ath_hal*, u_int); + HAL_BOOL __ahdecl(*ah_stopTxDma)(struct ath_hal*, u_int); + HAL_BOOL __ahdecl(*ah_setupTxDesc)(struct ath_hal *, struct ath_desc *, + u_int pktLen, u_int hdrLen, + HAL_PKT_TYPE type, u_int txPower, + u_int txRate0, u_int txTries0, + u_int keyIx, u_int antMode, u_int flags, + u_int rtsctsRate, u_int rtsctsDuration, + u_int compicvLen, u_int compivLen, + u_int comp); + HAL_BOOL __ahdecl(*ah_setupXTxDesc)(struct ath_hal *, struct ath_desc*, + u_int txRate1, u_int txTries1, + u_int txRate2, u_int txTries2, + u_int txRate3, u_int txTries3); + HAL_BOOL __ahdecl(*ah_fillTxDesc)(struct ath_hal *, struct ath_desc *, + HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, + u_int descId, u_int qcuId, HAL_BOOL firstSeg, + HAL_BOOL lastSeg, const struct ath_desc *); + HAL_STATUS __ahdecl(*ah_procTxDesc)(struct ath_hal *, + struct ath_desc *, struct ath_tx_status *); + void __ahdecl(*ah_getTxIntrQueue)(struct ath_hal *, uint32_t *); + void __ahdecl(*ah_reqTxIntrDesc)(struct ath_hal *, struct ath_desc*); + HAL_BOOL __ahdecl(*ah_getTxCompletionRates)(struct ath_hal *, + const struct ath_desc *ds, int *rates, int *tries); + void __ahdecl(*ah_setTxDescLink)(struct ath_hal *ah, void *ds, + uint32_t link); + void __ahdecl(*ah_getTxDescLink)(struct ath_hal *ah, void *ds, + uint32_t *link); + void __ahdecl(*ah_getTxDescLinkPtr)(struct ath_hal *ah, void *ds, + uint32_t **linkptr); + void __ahdecl(*ah_setupTxStatusRing)(struct ath_hal *, + void *ts_start, uint32_t ts_paddr_start, + uint16_t size); + void __ahdecl(*ah_getTxRawTxDesc)(struct ath_hal *, u_int32_t *); + + /* Receive Functions */ + uint32_t __ahdecl(*ah_getRxDP)(struct ath_hal*, HAL_RX_QUEUE); + void __ahdecl(*ah_setRxDP)(struct ath_hal*, uint32_t rxdp, HAL_RX_QUEUE); + void __ahdecl(*ah_enableReceive)(struct ath_hal*); + HAL_BOOL __ahdecl(*ah_stopDmaReceive)(struct ath_hal*); + void __ahdecl(*ah_startPcuReceive)(struct ath_hal*); + void __ahdecl(*ah_stopPcuReceive)(struct ath_hal*); + void __ahdecl(*ah_setMulticastFilter)(struct ath_hal*, + uint32_t filter0, uint32_t filter1); + HAL_BOOL __ahdecl(*ah_setMulticastFilterIndex)(struct ath_hal*, + uint32_t index); + HAL_BOOL __ahdecl(*ah_clrMulticastFilterIndex)(struct ath_hal*, + uint32_t index); + uint32_t __ahdecl(*ah_getRxFilter)(struct ath_hal*); + void __ahdecl(*ah_setRxFilter)(struct ath_hal*, uint32_t); + HAL_BOOL __ahdecl(*ah_setupRxDesc)(struct ath_hal *, struct ath_desc *, + uint32_t size, u_int flags); + HAL_STATUS __ahdecl(*ah_procRxDesc)(struct ath_hal *, + struct ath_desc *, uint32_t phyAddr, + struct ath_desc *next, uint64_t tsf, + struct ath_rx_status *); + void __ahdecl(*ah_rxMonitor)(struct ath_hal *, + const HAL_NODE_STATS *, + const struct ieee80211_channel *); + void __ahdecl(*ah_aniPoll)(struct ath_hal *, + const struct ieee80211_channel *); + void __ahdecl(*ah_procMibEvent)(struct ath_hal *, + const HAL_NODE_STATS *); + + /* Misc Functions */ + HAL_STATUS __ahdecl(*ah_getCapability)(struct ath_hal *, + HAL_CAPABILITY_TYPE, uint32_t capability, + uint32_t *result); + HAL_BOOL __ahdecl(*ah_setCapability)(struct ath_hal *, + HAL_CAPABILITY_TYPE, uint32_t capability, + uint32_t setting, HAL_STATUS *); + HAL_BOOL __ahdecl(*ah_getDiagState)(struct ath_hal *, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); + void __ahdecl(*ah_getMacAddress)(struct ath_hal *, uint8_t *); + HAL_BOOL __ahdecl(*ah_setMacAddress)(struct ath_hal *, const uint8_t*); + void __ahdecl(*ah_getBssIdMask)(struct ath_hal *, uint8_t *); + HAL_BOOL __ahdecl(*ah_setBssIdMask)(struct ath_hal *, const uint8_t*); + HAL_BOOL __ahdecl(*ah_setRegulatoryDomain)(struct ath_hal*, + uint16_t, HAL_STATUS *); + void __ahdecl(*ah_setLedState)(struct ath_hal*, HAL_LED_STATE); + void __ahdecl(*ah_writeAssocid)(struct ath_hal*, + const uint8_t *bssid, uint16_t assocId); + HAL_BOOL __ahdecl(*ah_gpioCfgOutput)(struct ath_hal *, + uint32_t gpio, HAL_GPIO_MUX_TYPE); + HAL_BOOL __ahdecl(*ah_gpioCfgInput)(struct ath_hal *, uint32_t gpio); + uint32_t __ahdecl(*ah_gpioGet)(struct ath_hal *, uint32_t gpio); + HAL_BOOL __ahdecl(*ah_gpioSet)(struct ath_hal *, + uint32_t gpio, uint32_t val); + void __ahdecl(*ah_gpioSetIntr)(struct ath_hal*, u_int, uint32_t); + uint32_t __ahdecl(*ah_getTsf32)(struct ath_hal*); + uint64_t __ahdecl(*ah_getTsf64)(struct ath_hal*); + void __ahdecl(*ah_setTsf64)(struct ath_hal *, uint64_t); + void __ahdecl(*ah_resetTsf)(struct ath_hal*); + HAL_BOOL __ahdecl(*ah_detectCardPresent)(struct ath_hal*); + void __ahdecl(*ah_updateMibCounters)(struct ath_hal*, + HAL_MIB_STATS*); + HAL_RFGAIN __ahdecl(*ah_getRfGain)(struct ath_hal*); + u_int __ahdecl(*ah_getDefAntenna)(struct ath_hal*); + void __ahdecl(*ah_setDefAntenna)(struct ath_hal*, u_int); + HAL_ANT_SETTING __ahdecl(*ah_getAntennaSwitch)(struct ath_hal*); + HAL_BOOL __ahdecl(*ah_setAntennaSwitch)(struct ath_hal*, + HAL_ANT_SETTING); + HAL_BOOL __ahdecl(*ah_setSifsTime)(struct ath_hal*, u_int); + u_int __ahdecl(*ah_getSifsTime)(struct ath_hal*); + HAL_BOOL __ahdecl(*ah_setSlotTime)(struct ath_hal*, u_int); + u_int __ahdecl(*ah_getSlotTime)(struct ath_hal*); + HAL_BOOL __ahdecl(*ah_setAckTimeout)(struct ath_hal*, u_int); + u_int __ahdecl(*ah_getAckTimeout)(struct ath_hal*); + HAL_BOOL __ahdecl(*ah_setAckCTSRate)(struct ath_hal*, u_int); + u_int __ahdecl(*ah_getAckCTSRate)(struct ath_hal*); + HAL_BOOL __ahdecl(*ah_setCTSTimeout)(struct ath_hal*, u_int); + u_int __ahdecl(*ah_getCTSTimeout)(struct ath_hal*); + HAL_BOOL __ahdecl(*ah_setDecompMask)(struct ath_hal*, uint16_t, int); + void __ahdecl(*ah_setCoverageClass)(struct ath_hal*, uint8_t, int); + HAL_STATUS __ahdecl(*ah_setQuiet)(struct ath_hal *ah, uint32_t period, + uint32_t duration, uint32_t nextStart, + HAL_QUIET_FLAG flag); + void __ahdecl(*ah_setChainMasks)(struct ath_hal *, + uint32_t, uint32_t); + + /* DFS functions */ + void __ahdecl(*ah_enableDfs)(struct ath_hal *ah, + HAL_PHYERR_PARAM *pe); + void __ahdecl(*ah_getDfsThresh)(struct ath_hal *ah, + HAL_PHYERR_PARAM *pe); + HAL_BOOL __ahdecl(*ah_getDfsDefaultThresh)(struct ath_hal *ah, + HAL_PHYERR_PARAM *pe); + HAL_BOOL __ahdecl(*ah_procRadarEvent)(struct ath_hal *ah, + struct ath_rx_status *rxs, uint64_t fulltsf, + const char *buf, HAL_DFS_EVENT *event); + HAL_BOOL __ahdecl(*ah_isFastClockEnabled)(struct ath_hal *ah); + + /* Spectral Scan functions */ + void __ahdecl(*ah_spectralConfigure)(struct ath_hal *ah, + HAL_SPECTRAL_PARAM *sp); + void __ahdecl(*ah_spectralGetConfig)(struct ath_hal *ah, + HAL_SPECTRAL_PARAM *sp); + void __ahdecl(*ah_spectralStart)(struct ath_hal *); + void __ahdecl(*ah_spectralStop)(struct ath_hal *); + HAL_BOOL __ahdecl(*ah_spectralIsEnabled)(struct ath_hal *); + HAL_BOOL __ahdecl(*ah_spectralIsActive)(struct ath_hal *); + /* XXX getNfPri() and getNfExt() */ + + /* Key Cache Functions */ + uint32_t __ahdecl(*ah_getKeyCacheSize)(struct ath_hal*); + HAL_BOOL __ahdecl(*ah_resetKeyCacheEntry)(struct ath_hal*, uint16_t); + HAL_BOOL __ahdecl(*ah_isKeyCacheEntryValid)(struct ath_hal *, + uint16_t); + HAL_BOOL __ahdecl(*ah_setKeyCacheEntry)(struct ath_hal*, + uint16_t, const HAL_KEYVAL *, + const uint8_t *, int); + HAL_BOOL __ahdecl(*ah_setKeyCacheEntryMac)(struct ath_hal*, + uint16_t, const uint8_t *); + + /* Power Management Functions */ + HAL_BOOL __ahdecl(*ah_setPowerMode)(struct ath_hal*, + HAL_POWER_MODE mode, int setChip); + HAL_POWER_MODE __ahdecl(*ah_getPowerMode)(struct ath_hal*); + int16_t __ahdecl(*ah_getChanNoise)(struct ath_hal *, + const struct ieee80211_channel *); + + /* Beacon Management Functions */ + void __ahdecl(*ah_setBeaconTimers)(struct ath_hal*, + const HAL_BEACON_TIMERS *); + /* NB: deprecated, use ah_setBeaconTimers instead */ + void __ahdecl(*ah_beaconInit)(struct ath_hal *, + uint32_t nexttbtt, uint32_t intval); + void __ahdecl(*ah_setStationBeaconTimers)(struct ath_hal*, + const HAL_BEACON_STATE *); + void __ahdecl(*ah_resetStationBeaconTimers)(struct ath_hal*); + uint64_t __ahdecl(*ah_getNextTBTT)(struct ath_hal *); + + /* 802.11n Functions */ + HAL_BOOL __ahdecl(*ah_chainTxDesc)(struct ath_hal *, + struct ath_desc *, + HAL_DMA_ADDR *bufAddrList, + uint32_t *segLenList, + u_int, u_int, HAL_PKT_TYPE, + u_int, HAL_CIPHER, uint8_t, HAL_BOOL, + HAL_BOOL, HAL_BOOL); + HAL_BOOL __ahdecl(*ah_setupFirstTxDesc)(struct ath_hal *, + struct ath_desc *, u_int, u_int, u_int, + u_int, u_int, u_int, u_int, u_int); + HAL_BOOL __ahdecl(*ah_setupLastTxDesc)(struct ath_hal *, + struct ath_desc *, const struct ath_desc *); + void __ahdecl(*ah_set11nRateScenario)(struct ath_hal *, + struct ath_desc *, u_int, u_int, + HAL_11N_RATE_SERIES [], u_int, u_int); + + /* + * The next 4 (set11ntxdesc -> set11naggrlast) are specific + * to the EDMA HAL. Descriptors are chained together by + * using filltxdesc (not ChainTxDesc) and then setting the + * aggregate flags appropriately using first/middle/last. + */ + void __ahdecl(*ah_set11nTxDesc)(struct ath_hal *, + void *, u_int, HAL_PKT_TYPE, u_int, u_int, + u_int); + void __ahdecl(*ah_set11nAggrFirst)(struct ath_hal *, + struct ath_desc *, u_int, u_int); + void __ahdecl(*ah_set11nAggrMiddle)(struct ath_hal *, + struct ath_desc *, u_int); + void __ahdecl(*ah_set11nAggrLast)(struct ath_hal *, + struct ath_desc *); + void __ahdecl(*ah_clr11nAggr)(struct ath_hal *, + struct ath_desc *); + void __ahdecl(*ah_set11nBurstDuration)(struct ath_hal *, + struct ath_desc *, u_int); + void __ahdecl(*ah_set11nVirtMoreFrag)(struct ath_hal *, + struct ath_desc *, u_int); + + HAL_BOOL __ahdecl(*ah_getMibCycleCounts) (struct ath_hal *, + HAL_SURVEY_SAMPLE *); + + uint32_t __ahdecl(*ah_get11nExtBusy)(struct ath_hal *); + void __ahdecl(*ah_set11nMac2040)(struct ath_hal *, + HAL_HT_MACMODE); + HAL_HT_RXCLEAR __ahdecl(*ah_get11nRxClear)(struct ath_hal *ah); + void __ahdecl(*ah_set11nRxClear)(struct ath_hal *, + HAL_HT_RXCLEAR); + + /* Interrupt functions */ + HAL_BOOL __ahdecl(*ah_isInterruptPending)(struct ath_hal*); + HAL_BOOL __ahdecl(*ah_getPendingInterrupts)(struct ath_hal*, HAL_INT*); + HAL_INT __ahdecl(*ah_getInterrupts)(struct ath_hal*); + HAL_INT __ahdecl(*ah_setInterrupts)(struct ath_hal*, HAL_INT); + + /* Bluetooth Coexistence functions */ + void __ahdecl(*ah_btCoexSetInfo)(struct ath_hal *, + HAL_BT_COEX_INFO *); + void __ahdecl(*ah_btCoexSetConfig)(struct ath_hal *, + HAL_BT_COEX_CONFIG *); + void __ahdecl(*ah_btCoexSetQcuThresh)(struct ath_hal *, + int); + void __ahdecl(*ah_btCoexSetWeights)(struct ath_hal *, + uint32_t); + void __ahdecl(*ah_btCoexSetBmissThresh)(struct ath_hal *, + uint32_t); + void __ahdecl(*ah_btCoexSetParameter)(struct ath_hal *, + uint32_t, uint32_t); + void __ahdecl(*ah_btCoexDisable)(struct ath_hal *); + int __ahdecl(*ah_btCoexEnable)(struct ath_hal *); + + /* Bluetooth MCI methods */ + void __ahdecl(*ah_btMciSetup)(struct ath_hal *, + uint32_t, void *, uint16_t, uint32_t); + HAL_BOOL __ahdecl(*ah_btMciSendMessage)(struct ath_hal *, + uint8_t, uint32_t, uint32_t *, uint8_t, + HAL_BOOL, HAL_BOOL); + uint32_t __ahdecl(*ah_btMciGetInterrupt)(struct ath_hal *, + uint32_t *, uint32_t *); + uint32_t __ahdecl(*ah_btMciGetState)(struct ath_hal *, + uint32_t, uint32_t *); + void __ahdecl(*ah_btMciDetach)(struct ath_hal *); + + /* LNA diversity configuration */ + void __ahdecl(*ah_divLnaConfGet)(struct ath_hal *, + HAL_ANT_COMB_CONFIG *); + void __ahdecl(*ah_divLnaConfSet)(struct ath_hal *, + HAL_ANT_COMB_CONFIG *); +}; + +/* + * Check the PCI vendor ID and device ID against Atheros' values + * and return a printable description for any Atheros hardware. + * AH_NULL is returned if the ID's do not describe Atheros hardware. + */ +extern const char *__ahdecl ath_hal_probe(uint16_t vendorid, uint16_t devid); + +/* + * Attach the HAL for use with the specified device. The device is + * defined by the PCI device ID. The caller provides an opaque pointer + * to an upper-layer data structure (HAL_SOFTC) that is stored in the + * HAL state block for later use. Hardware register accesses are done + * using the specified bus tag and handle. On successful return a + * reference to a state block is returned that must be supplied in all + * subsequent HAL calls. Storage associated with this reference is + * dynamically allocated and must be freed by calling the ah_detach + * method when the client is done. If the attach operation fails a + * null (AH_NULL) reference will be returned and a status code will + * be returned if the status parameter is non-zero. + */ +extern struct ath_hal * __ahdecl ath_hal_attach(uint16_t devid, HAL_SOFTC, + HAL_BUS_TAG, HAL_BUS_HANDLE, uint16_t *eepromdata, + HAL_OPS_CONFIG *ah_config, HAL_STATUS* status); + +extern const char *ath_hal_mac_name(struct ath_hal *); +extern const char *ath_hal_rf_name(struct ath_hal *); + +/* + * Regulatory interfaces. Drivers should use ath_hal_init_channels to + * request a set of channels for a particular country code and/or + * regulatory domain. If CTRY_DEFAULT and SKU_NONE are specified then + * this list is constructed according to the contents of the EEPROM. + * ath_hal_getchannels acts similarly but does not alter the operating + * state; this can be used to collect information for a particular + * regulatory configuration. Finally ath_hal_set_channels installs a + * channel list constructed outside the driver. The HAL will adopt the + * channel list and setup internal state according to the specified + * regulatory configuration (e.g. conformance test limits). + * + * For all interfaces the channel list is returned in the supplied array. + * maxchans defines the maximum size of this array. nchans contains the + * actual number of channels returned. If a problem occurred then a + * status code != HAL_OK is returned. + */ +struct ieee80211_channel; + +/* + * Return a list of channels according to the specified regulatory. + */ +extern HAL_STATUS __ahdecl ath_hal_getchannels(struct ath_hal *, + struct ieee80211_channel *chans, u_int maxchans, int *nchans, + u_int modeSelect, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn, + HAL_BOOL enableExtendedChannels); + +/* + * Return a list of channels and install it as the current operating + * regulatory list. + */ +extern HAL_STATUS __ahdecl ath_hal_init_channels(struct ath_hal *, + struct ieee80211_channel *chans, u_int maxchans, int *nchans, + u_int modeSelect, HAL_CTRY_CODE cc, HAL_REG_DOMAIN rd, + HAL_BOOL enableExtendedChannels); + +/* + * Install the list of channels as the current operating regulatory + * and setup related state according to the country code and sku. + */ +extern HAL_STATUS __ahdecl ath_hal_set_channels(struct ath_hal *, + struct ieee80211_channel *chans, int nchans, + HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn); + +/* + * Fetch the ctl/ext noise floor values reported by a MIMO + * radio. Returns 1 for valid results, 0 for invalid channel. + */ +extern int __ahdecl ath_hal_get_mimo_chan_noise(struct ath_hal *ah, + const struct ieee80211_channel *chan, int16_t *nf_ctl, + int16_t *nf_ext); + +/* + * Calibrate noise floor data following a channel scan or similar. + * This must be called prior retrieving noise floor data. + */ +extern void __ahdecl ath_hal_process_noisefloor(struct ath_hal *ah); + +/* + * Return bit mask of wireless modes supported by the hardware. + */ +extern u_int __ahdecl ath_hal_getwirelessmodes(struct ath_hal*); + +/* + * Get the HAL wireless mode for the given channel. + */ +extern int ath_hal_get_curmode(struct ath_hal *ah, + const struct ieee80211_channel *chan); + +/* + * Calculate the packet TX time for a legacy or 11n frame + */ +extern uint32_t __ahdecl ath_hal_pkt_txtime(struct ath_hal *ah, + const HAL_RATE_TABLE *rates, uint32_t frameLen, + uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble); + +/* + * Calculate the duration of an 11n frame. + */ +extern uint32_t __ahdecl ath_computedur_ht(uint32_t frameLen, uint16_t rate, + int streams, HAL_BOOL isht40, HAL_BOOL isShortGI); + +/* + * Calculate the transmit duration of a legacy frame. + */ +extern uint16_t __ahdecl ath_hal_computetxtime(struct ath_hal *, + const HAL_RATE_TABLE *rates, uint32_t frameLen, + uint16_t rateix, HAL_BOOL shortPreamble); + +/* + * Adjust the TSF. + */ +extern void __ahdecl ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta); + +/* + * Enable or disable CCA. + */ +void __ahdecl ath_hal_setcca(struct ath_hal *ah, int ena); + +/* + * Get CCA setting. + */ +int __ahdecl ath_hal_getcca(struct ath_hal *ah); + +/* + * Read EEPROM data from ah_eepromdata + */ +HAL_BOOL __ahdecl ath_hal_EepromDataRead(struct ath_hal *ah, + u_int off, uint16_t *data); + +/* + * For now, simply pass through MFP frames. + */ +static inline u_int32_t +ath_hal_get_mfp_qos(struct ath_hal *ah) +{ + //return AH_PRIVATE(ah)->ah_mfp_qos; + return HAL_MFP_QOSDATA; +} + +#endif /* _ATH_AH_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ah_debug.h b/sys/external/isc/atheros_hal/dist/ah_debug.h new file mode 100644 index 0000000..933811f --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_debug.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AH_DEBUG_H_ +#define _ATH_AH_DEBUG_H_ +/* + * Atheros Device Hardware Access Layer (HAL). + * + * Debug mask definitions. + */ +enum { + HAL_DEBUG_REGDOMAIN = 0x00000001, /* regulatory handling */ + HAL_DEBUG_ATTACH = 0x00000002, /* work done in attach */ + HAL_DEBUG_RESET = 0x00000004, /* reset work */ + HAL_DEBUG_NFCAL = 0x00000008, /* noise floor calibration */ + HAL_DEBUG_PERCAL = 0x00000010, /* periodic calibration */ + HAL_DEBUG_ANI = 0x00000020, /* ANI operation */ + HAL_DEBUG_PHYIO = 0x00000040, /* phy i/o operations */ + HAL_DEBUG_REGIO = 0x00000080, /* register i/o operations */ + HAL_DEBUG_RFPARAM = 0x00000100, + HAL_DEBUG_TXQUEUE = 0x00000200, /* tx queue handling */ + HAL_DEBUG_TX = 0x00000400, + HAL_DEBUG_TXDESC = 0x00000800, + HAL_DEBUG_RX = 0x00001000, + HAL_DEBUG_RXDESC = 0x00002000, + HAL_DEBUG_KEYCACHE = 0x00004000, /* keycache handling */ + HAL_DEBUG_EEPROM = 0x00008000, + HAL_DEBUG_BEACON = 0x00010000, /* beacon setup work */ + HAL_DEBUG_POWER = 0x00020000, /* power management */ + HAL_DEBUG_GPIO = 0x00040000, /* GPIO debugging */ + HAL_DEBUG_INTERRUPT = 0x00080000, /* interrupt handling */ + HAL_DEBUG_DIVERSITY = 0x00100000, /* diversity debugging */ + HAL_DEBUG_DFS = 0x00200000, /* DFS debugging */ + HAL_DEBUG_HANG = 0x00400000, /* BB/MAC hang debugging */ + HAL_DEBUG_CALIBRATE = 0x00800000, /* setup calibration */ + HAL_DEBUG_POWER_MGMT = 0x01000000, /* power calibration */ + HAL_DEBUG_CHANNEL = 0x02000000, + HAL_DEBUG_QUEUE = 0x04000000, + HAL_DEBUG_PRINT_REG = 0x08000000, + HAL_DEBUG_FCS_RTT = 0x10000000, + HAL_DEBUG_BT_COEX = 0x20000000, + + HAL_DEBUG_UNMASKABLE = 0x80000000, /* always printed */ + HAL_DEBUG_ANY = 0xffffffff +}; +#endif /* _ATH_AH_DEBUG_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ah_decode.h b/sys/external/isc/atheros_hal/dist/ah_decode.h new file mode 100644 index 0000000..3aca975 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_decode.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AH_DECODE_H_ +#define _ATH_AH_DECODE_H_ +/* + * Register tracing support. + * + * Setting hw.ath.hal.alq=1 enables tracing of all register reads and + * writes to the file /tmp/ath_hal.log. The file format is a simple + * fixed-size array of records. When done logging set hw.ath.hal.alq=0 + * and then decode the file with the arcode program (that is part of the + * HAL). If you start+stop tracing the data will be appended to an + * existing file. + */ +struct athregrec { + uint32_t threadid; + uint32_t op : 8, + reg : 24; + uint32_t val; +}; + +enum { + OP_READ = 0, /* register read */ + OP_WRITE = 1, /* register write */ + OP_DEVICE = 2, /* device identification */ + OP_MARK = 3, /* application marker */ +}; + +enum { + AH_MARK_RESET, /* ar*Reset entry, bChannelChange */ + AH_MARK_RESET_LINE, /* ar*_reset.c, line %d */ + AH_MARK_RESET_DONE, /* ar*Reset exit, error code */ + AH_MARK_CHIPRESET, /* ar*ChipReset, channel num */ + AH_MARK_PERCAL, /* ar*PerCalibration, channel num */ + AH_MARK_SETCHANNEL, /* ar*SetChannel, channel num */ + AH_MARK_ANI_RESET, /* ar*AniReset, opmode */ + AH_MARK_ANI_POLL, /* ar*AniReset, listen time */ + AH_MARK_ANI_CONTROL, /* ar*AniReset, cmd */ + AH_MARK_RX_CTL, /* RX DMA control */ + AH_MARK_CHIP_POWER, /* chip power control, mode */ + AH_MARK_CHIP_POWER_DONE, /* chip power control done, status */ +}; + +enum { + AH_MARK_RX_CTL_PCU_START, + AH_MARK_RX_CTL_PCU_STOP, + AH_MARK_RX_CTL_DMA_START, + AH_MARK_RX_CTL_DMA_STOP, + AH_MARK_RX_CTL_DMA_STOP_ERR, + AH_MARK_RX_CTL_DMA_STOP_OK, +}; + +#endif /* _ATH_AH_DECODE_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ah_desc.h b/sys/external/isc/atheros_hal/dist/ah_desc.h new file mode 100644 index 0000000..9f58dce --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_desc.h @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef _DEV_ATH_DESC_H +#define _DEV_ATH_DESC_H + +#include "opt_ah.h" /* NB: required for AH_SUPPORT_AR5416 */ + +/* + * For now, define this for the structure definitions. + * Because of how the HAL / driver module currently builds, + * it's not very feasible to build the module without + * this defined. The rest of the code (eg in the driver + * body) can work fine with these fields being uninitialised; + * they'll be initialised to 0 anyway. + */ + +#ifndef AH_SUPPORT_AR5416 +#define AH_SUPPORT_AR5416 1 +#endif + +/* + * Transmit descriptor status. This structure is filled + * in only after the tx descriptor process method finds a + * ``done'' descriptor; at which point it returns something + * other than HAL_EINPROGRESS. + * + * Note that ts_antenna may not be valid for all h/w. It + * should be used only if non-zero. + */ +struct ath_tx_status { + uint16_t ts_seqnum; /* h/w assigned sequence number */ + uint16_t ts_tstamp; /* h/w assigned timestamp */ + uint8_t ts_status; /* frame status, 0 => xmit ok */ + uint8_t ts_rate; /* h/w transmit rate index */ + int8_t ts_rssi; /* tx ack RSSI */ + uint8_t ts_shortretry; /* # short retries */ + uint8_t ts_longretry; /* # long retries */ + uint8_t ts_virtcol; /* virtual collision count */ + uint8_t ts_antenna; /* antenna information */ + uint8_t ts_finaltsi; /* final transmit series index */ +#ifdef AH_SUPPORT_AR5416 + /* 802.11n status */ + uint8_t ts_flags; /* misc flags */ + uint8_t ts_queue_id; /* AR9300: TX queue id */ + uint8_t ts_desc_id; /* AR9300: TX descriptor id */ + uint8_t ts_tid; /* TID */ +/* #define ts_rssi ts_rssi_combined */ + uint32_t ts_ba_low; /* blockack bitmap low */ + uint32_t ts_ba_high; /* blockack bitmap high */ + uint32_t ts_evm0; /* evm bytes */ + uint32_t ts_evm1; + uint32_t ts_evm2; + int8_t ts_rssi_ctl[3]; /* tx ack RSSI [ctl, chain 0-2] */ + int8_t ts_rssi_ext[3]; /* tx ack RSSI [ext, chain 0-2] */ + uint8_t ts_pad[2]; +#endif /* AH_SUPPORT_AR5416 */ +}; + +/* bits found in ts_status */ +#define HAL_TXERR_XRETRY 0x01 /* excessive retries */ +#define HAL_TXERR_FILT 0x02 /* blocked by tx filtering */ +#define HAL_TXERR_FIFO 0x04 /* fifo underrun */ +#define HAL_TXERR_XTXOP 0x08 /* txop exceeded */ +#define HAL_TXERR_TIMER_EXPIRED 0x10 /* Tx timer expired */ + +/* bits found in ts_flags */ +#define HAL_TX_BA 0x01 /* Block Ack seen */ +#define HAL_TX_AGGR 0x02 /* Aggregate */ +#define HAL_TX_DESC_CFG_ERR 0x10 /* Error in 20/40 desc config */ +#define HAL_TX_DATA_UNDERRUN 0x20 /* Tx buffer underrun */ +#define HAL_TX_DELIM_UNDERRUN 0x40 /* Tx delimiter underrun */ + +/* + * Receive descriptor status. This structure is filled + * in only after the rx descriptor process method finds a + * ``done'' descriptor; at which point it returns something + * other than HAL_EINPROGRESS. + * + * If rx_status is zero, then the frame was received ok; + * otherwise the error information is indicated and rs_phyerr + * contains a phy error code if HAL_RXERR_PHY is set. In general + * the frame contents is undefined when an error occurred thought + * for some errors (e.g. a decryption error), it may be meaningful. + * + * Note that the receive timestamp is expanded using the TSF to + * at least 15 bits (regardless of what the h/w provides directly). + * Newer hardware supports a full 32-bits; use HAL_CAP_32TSTAMP to + * find out if the hardware is capable. + * + * rx_rssi is in units of dbm above the noise floor. This value + * is measured during the preamble and PLCP; i.e. with the initial + * 4us of detection. The noise floor is typically a consistent + * -96dBm absolute power in a 20MHz channel. + */ +struct ath_rx_status { + uint16_t rs_datalen; /* rx frame length */ + uint8_t rs_status; /* rx status, 0 => recv ok */ + uint8_t rs_phyerr; /* phy error code */ + int8_t rs_rssi; /* rx frame RSSI (combined for 11n) */ + uint8_t rs_keyix; /* key cache index */ + uint8_t rs_rate; /* h/w receive rate index */ + uint8_t rs_more; /* more descriptors follow */ + uint32_t rs_tstamp; /* h/w assigned timestamp */ + uint32_t rs_antenna; /* antenna information */ +#ifdef AH_SUPPORT_AR5416 + /* 802.11n status */ + int8_t rs_rssi_ctl[3]; /* rx frame RSSI [ctl, chain 0-2] */ + int8_t rs_rssi_ext[3]; /* rx frame RSSI [ext, chain 0-2] */ + uint8_t rs_isaggr; /* is part of the aggregate */ + uint8_t rs_moreaggr; /* more frames in aggr to follow */ + uint16_t rs_flags; /* misc flags */ + uint8_t rs_num_delims; /* number of delims in aggr */ + uint8_t rs_spare0; /* padding */ + uint32_t rs_evm0; /* evm bytes */ + uint32_t rs_evm1; + uint32_t rs_evm2; + uint32_t rs_evm3; /* needed for ar9300 and later */ + uint32_t rs_evm4; /* needed for ar9300 and later */ +#endif /* AH_SUPPORT_AR5416 */ +}; + +/* bits found in rs_status */ +#define HAL_RXERR_CRC 0x01 /* CRC error on frame */ +#define HAL_RXERR_PHY 0x02 /* PHY error, rs_phyerr is valid */ +#define HAL_RXERR_FIFO 0x04 /* fifo overrun */ +#define HAL_RXERR_DECRYPT 0x08 /* non-Michael decrypt error */ +#define HAL_RXERR_MIC 0x10 /* Michael MIC decrypt error */ +#define HAL_RXERR_INCOMP 0x20 /* Rx Desc processing is incomplete */ +#define HAL_RXERR_KEYMISS 0x40 /* Key not found in keycache */ + +/* bits found in rs_flags */ +#define HAL_RX_MORE 0x0001 /* more descriptors follow */ +#define HAL_RX_MORE_AGGR 0x0002 /* more frames in aggr */ +#define HAL_RX_GI 0x0004 /* full gi */ +#define HAL_RX_2040 0x0008 /* 40 Mhz */ +#define HAL_RX_DELIM_CRC_PRE 0x0010 /* crc error in delimiter pre */ +#define HAL_RX_DELIM_CRC_POST 0x0020 /* crc error in delim after */ +#define HAL_RX_DECRYPT_BUSY 0x0040 /* decrypt was too slow */ +#define HAL_RX_HI_RX_CHAIN 0x0080 /* SM power save: hi Rx chain control */ +#define HAL_RX_IS_APSD 0x0100 /* Is ASPD trigger frame */ +#define HAL_RX_STBC 0x0200 /* Is an STBC frame */ + +/* + * This is the format of RSSI[2] on the AR9285/AR9485. + * It encodes the LNA configuration information. + * + * For boards with an external diversity antenna switch, + * HAL_RX_LNA_EXTCFG encodes which configuration was + * used (antenna 1 or antenna 2.) This feeds into the + * switch table and ensures that the given antenna was + * connected to an LNA. + */ +#define HAL_RX_LNA_LNACFG 0x80 /* 1 = main LNA config used, 0 = ALT */ +#define HAL_RX_LNA_EXTCFG 0x40 /* 0 = external diversity ant1, 1 = ant2 */ +#define HAL_RX_LNA_CFG_USED 0x30 /* 2 bits; LNA config used on RX */ +#define HAL_RX_LNA_CFG_USED_S 4 +#define HAL_RX_LNA_CFG_MAIN 0x0c /* 2 bits; "Main" LNA config */ +#define HAL_RX_LNA_CFG_ALT 0x02 /* 2 bits; "Alt" LNA config */ + +/* + * This is the format of RSSI_EXT[2] on the AR9285/AR9485. + * It encodes the switch table configuration and fast diversity + * value. + */ +#define HAL_RX_LNA_FASTDIV 0x40 /* 1 = fast diversity measurement done */ +#define HAL_RX_LNA_SWITCH_0 0x30 /* 2 bits; sw_0[1:0] */ +#define HAL_RX_LNA_SWITCH_COM 0x0f /* 4 bits, sw_com[3:0] */ + +enum { + HAL_PHYERR_UNDERRUN = 0, /* Transmit underrun */ + HAL_PHYERR_TIMING = 1, /* Timing error */ + HAL_PHYERR_PARITY = 2, /* Illegal parity */ + HAL_PHYERR_RATE = 3, /* Illegal rate */ + HAL_PHYERR_LENGTH = 4, /* Illegal length */ + HAL_PHYERR_RADAR = 5, /* Radar detect */ + HAL_PHYERR_SERVICE = 6, /* Illegal service */ + HAL_PHYERR_TOR = 7, /* Transmit override receive */ + /* NB: these are specific to the 5212 and later */ + HAL_PHYERR_OFDM_TIMING = 17, /* */ + HAL_PHYERR_OFDM_SIGNAL_PARITY = 18, /* */ + HAL_PHYERR_OFDM_RATE_ILLEGAL = 19, /* */ + HAL_PHYERR_OFDM_LENGTH_ILLEGAL = 20, /* */ + HAL_PHYERR_OFDM_POWER_DROP = 21, /* */ + HAL_PHYERR_OFDM_SERVICE = 22, /* */ + HAL_PHYERR_OFDM_RESTART = 23, /* */ + HAL_PHYERR_FALSE_RADAR_EXT = 24, /* */ + HAL_PHYERR_CCK_TIMING = 25, /* */ + HAL_PHYERR_CCK_HEADER_CRC = 26, /* */ + HAL_PHYERR_CCK_RATE_ILLEGAL = 27, /* */ + HAL_PHYERR_CCK_SERVICE = 30, /* */ + HAL_PHYERR_CCK_RESTART = 31, /* */ + HAL_PHYERR_CCK_LENGTH_ILLEGAL = 32, /* */ + HAL_PHYERR_CCK_POWER_DROP = 33, /* */ + /* AR5416 and later */ + HAL_PHYERR_HT_CRC_ERROR = 34, /* */ + HAL_PHYERR_HT_LENGTH_ILLEGAL = 35, /* */ + HAL_PHYERR_HT_RATE_ILLEGAL = 36, /* */ + + HAL_PHYERR_SPECTRAL = 38, +}; + +/* value found in rs_keyix to mark invalid entries */ +#define HAL_RXKEYIX_INVALID ((uint8_t) -1) +/* value used to specify no encryption key for xmit */ +#define HAL_TXKEYIX_INVALID ((u_int) -1) + +/* XXX rs_antenna definitions */ + +/* + * Definitions for the software frame/packet descriptors used by + * the Atheros HAL. This definition obscures hardware-specific + * details from the driver. Drivers are expected to fillin the + * portions of a descriptor that are not opaque then use HAL calls + * to complete the work. Status for completed frames is returned + * in a device-independent format. + */ +#ifdef AH_SUPPORT_AR5416 +#define HAL_DESC_HW_SIZE 20 +#else +#define HAL_DESC_HW_SIZE 4 +#endif /* AH_SUPPORT_AR5416 */ + +struct ath_desc { + /* + * The following definitions are passed directly + * the hardware and managed by the HAL. Drivers + * should not touch those elements marked opaque. + */ + uint32_t ds_link; /* phys address of next descriptor */ + uint32_t ds_data; /* phys address of data buffer */ + uint32_t ds_ctl0; /* opaque DMA control 0 */ + uint32_t ds_ctl1; /* opaque DMA control 1 */ + uint32_t ds_hw[HAL_DESC_HW_SIZE]; /* opaque h/w region */ +}; + +struct ath_desc_txedma { + uint32_t ds_info; + uint32_t ds_link; + uint32_t ds_hw[21]; /* includes buf/len */ +}; + +struct ath_desc_status { + union { + struct ath_tx_status tx;/* xmit status */ + struct ath_rx_status rx;/* recv status */ + } ds_us; +}; + +#define ds_txstat ds_us.tx +#define ds_rxstat ds_us.rx + +/* flags passed to tx descriptor setup methods */ +/* This is a uint16_t field in ath_buf, just be warned! */ +#define HAL_TXDESC_CLRDMASK 0x0001 /* clear destination filter mask */ +#define HAL_TXDESC_NOACK 0x0002 /* don't wait for ACK */ +#define HAL_TXDESC_RTSENA 0x0004 /* enable RTS */ +#define HAL_TXDESC_CTSENA 0x0008 /* enable CTS */ +#define HAL_TXDESC_INTREQ 0x0010 /* enable per-descriptor interrupt */ +#define HAL_TXDESC_VEOL 0x0020 /* mark virtual EOL */ +/* NB: this only affects frame, not any RTS/CTS */ +#define HAL_TXDESC_DURENA 0x0040 /* enable h/w write of duration field */ +#define HAL_TXDESC_EXT_ONLY 0x0080 /* send on ext channel only (11n) */ +#define HAL_TXDESC_EXT_AND_CTL 0x0100 /* send on ext + ctl channels (11n) */ +#define HAL_TXDESC_VMF 0x0200 /* virtual more frag */ +#define HAL_TXDESC_LOWRXCHAIN 0x0400 /* switch to low RX chain */ +#define HAL_TXDESC_LDPC 0x1000 + +/* flags passed to rx descriptor setup methods */ +#define HAL_RXDESC_INTREQ 0x0020 /* enable per-descriptor interrupt */ +#endif /* _DEV_ATH_DESC_H */ diff --git a/sys/external/isc/atheros_hal/dist/ah_devid.h b/sys/external/isc/atheros_hal/dist/ah_devid.h new file mode 100644 index 0000000..a5006a0 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_devid.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef _DEV_ATH_DEVID_H_ +#define _DEV_ATH_DEVID_H_ + +#define ATHEROS_VENDOR_ID 0x168c /* Atheros PCI vendor ID */ +/* + * NB: all Atheros-based devices should have a PCI vendor ID + * of 0x168c, but some vendors, in their infinite wisdom + * do not follow this so we must handle them specially. + */ +#define ATHEROS_3COM_VENDOR_ID 0xa727 /* 3Com 3CRPAG175 vendor ID */ +#define ATHEROS_3COM2_VENDOR_ID 0x10b7 /* 3Com 3CRDAG675 vendor ID */ + +/* AR5210 (for reference) */ +#define AR5210_DEFAULT 0x1107 /* No eeprom HW default */ +#define AR5210_PROD 0x0007 /* Final device ID */ +#define AR5210_AP 0x0207 /* Early AP11s */ + +/* AR5211 */ +#define AR5211_DEFAULT 0x1112 /* No eeprom HW default */ +#define AR5311_DEVID 0x0011 /* Final ar5311 devid */ +#define AR5211_DEVID 0x0012 /* Final ar5211 devid */ +#define AR5211_LEGACY 0xff12 /* Original emulation board */ +#define AR5211_FPGA11B 0xf11b /* 11b emulation board */ + +/* AR5212 */ +#define AR5212_DEFAULT 0x1113 /* No eeprom HW default */ +#define AR5212_DEVID 0x0013 /* Final ar5212 devid */ +#define AR5212_FPGA 0xf013 /* Emulation board */ +#define AR5212_DEVID_IBM 0x1014 /* IBM minipci ID */ +#define AR5212_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */ +#define AR5212_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */ +#define AR5212_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */ +#define AR5212_AR2315_REV6 0x0086 /* AR2315 WMAC (AP51-Light) */ +#define AR5212_AR2315_REV7 0x0087 /* AR2315 WMAC (AP51-Full) */ +#define AR5212_AR2317_REV1 0x0090 /* AR2317 WMAC (AP61-Light) */ +#define AR5212_AR2317_REV2 0x0091 /* AR2317 WMAC (AP61-Full) */ + +/* AR5212 compatible devid's also attach to 5212 */ +#define AR5212_DEVID_0014 0x0014 +#define AR5212_DEVID_0015 0x0015 +#define AR5212_DEVID_0016 0x0016 +#define AR5212_DEVID_0017 0x0017 +#define AR5212_DEVID_0018 0x0018 +#define AR5212_DEVID_0019 0x0019 +#define AR5212_AR2413 0x001a /* AR2413 aka Griffin-lite */ +#define AR5212_AR5413 0x001b /* Eagle */ +#define AR5212_AR5424 0x001c /* Condor (PCI express) */ +#define AR5212_AR2417 0x001d /* Nala, PCI */ +#define AR5212_DEVID_FF19 0xff19 /* XXX PCI express */ + +/* AR5213 */ +#define AR5213_SREV_1_0 0x0055 +#define AR5213_SREV_REG 0x4020 + +/* AR5416 compatible devid's */ +#define AR5416_DEVID_PCI 0x0023 /* AR5416 PCI (MB/CB) Owl */ +#define AR5416_DEVID_PCIE 0x0024 /* AR5418 PCI-E (XB) Owl */ +#define AR5416_AR9130_DEVID 0x000b /* AR9130 SoC WiMAC */ +#define AR9160_DEVID_PCI 0x0027 /* AR9160 PCI Sowl */ +#define AR9280_DEVID_PCI 0x0029 /* AR9280 PCI Merlin */ +#define AR9280_DEVID_PCIE 0x002a /* AR9220 PCI-E Merlin */ +#define AR9285_DEVID_PCIE 0x002b /* AR9285 PCI-E Kite */ +#define AR2427_DEVID_PCIE 0x002c /* AR2427 PCI-E w/ 802.11n bonded out */ +#define AR9287_DEVID_PCI 0x002d /* AR9227 PCI Kiwi */ +#define AR9287_DEVID_PCIE 0x002e /* AR9287 PCI-E Kiwi */ + +/* AR9300 */ +#define AR9300_DEVID_AR9380_PCIE 0x0030 +#define AR9300_DEVID_EMU_PCIE 0xabcd +#define AR9300_DEVID_AR9340 0x0031 +#define AR9300_DEVID_AR9485_PCIE 0x0032 +#define AR9300_DEVID_AR9580_PCIE 0x0033 +#define AR9300_DEVID_AR946X_PCIE 0x0034 +#define AR9300_DEVID_AR9330 0x0035 +#define AR9300_DEVID_QCA9565 0x0036 +#define AR9300_DEVID_AR1111_PCIE 0x0037 +#define AR9300_DEVID_QCA955X 0x0039 +#define AR9300_DEVID_QCA953X 0x003d /* Honey Bee */ + +#define AR_SUBVENDOR_ID_NOG 0x0e11 /* No 11G subvendor ID */ +#define AR_SUBVENDOR_ID_NEW_A 0x7065 /* Update device to new RD */ +#endif /* _DEV_ATH_DEVID_H */ diff --git a/sys/external/isc/atheros_hal/dist/ah_diagcodes.h b/sys/external/isc/atheros_hal/dist/ah_diagcodes.h new file mode 100644 index 0000000..df23242 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_diagcodes.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AH_DIAGCODES_H_ +#define _ATH_AH_DIAGCODES_H_ +/* + * Atheros Device Hardware Access Layer (HAL). + * + * Internal diagnostic API definitions. + */ + +/* + * Diagnostic interface. This is an open-ended interface that + * is opaque to applications. Diagnostic programs use this to + * retrieve internal data structures, etc. There is no guarantee + * that calling conventions for calls other than HAL_DIAG_REVS + * are stable between HAL releases; a diagnostic application must + * use the HAL revision information to deal with ABI/API differences. + * + * NB: do not renumber these, certain codes are publicly used. + */ +enum { + HAL_DIAG_REVS = 0, /* MAC/PHY/Radio revs */ + HAL_DIAG_EEPROM = 1, /* EEPROM contents */ + HAL_DIAG_EEPROM_EXP_11A = 2, /* EEPROM 5112 power exp for 11a */ + HAL_DIAG_EEPROM_EXP_11B = 3, /* EEPROM 5112 power exp for 11b */ + HAL_DIAG_EEPROM_EXP_11G = 4, /* EEPROM 5112 power exp for 11g */ + HAL_DIAG_ANI_CURRENT = 5, /* ANI current channel state */ + HAL_DIAG_ANI_OFDM = 6, /* ANI OFDM timing error stats */ + HAL_DIAG_ANI_CCK = 7, /* ANI CCK timing error stats */ + HAL_DIAG_ANI_STATS = 8, /* ANI statistics */ + HAL_DIAG_RFGAIN = 9, /* RfGain GAIN_VALUES */ + HAL_DIAG_RFGAIN_CURSTEP = 10, /* RfGain GAIN_OPTIMIZATION_STEP */ + HAL_DIAG_PCDAC = 11, /* PCDAC table */ + HAL_DIAG_TXRATES = 12, /* Transmit rate table */ + HAL_DIAG_REGS = 13, /* Registers */ + HAL_DIAG_ANI_CMD = 14, /* ANI issue command (XXX do not change!) */ + HAL_DIAG_SETKEY = 15, /* Set keycache backdoor */ + HAL_DIAG_RESETKEY = 16, /* Reset keycache backdoor */ + HAL_DIAG_EEREAD = 17, /* Read EEPROM word */ + HAL_DIAG_EEWRITE = 18, /* Write EEPROM word */ + /* 19-26 removed, do not reuse */ + HAL_DIAG_RDWRITE = 27, /* Write regulatory domain */ + HAL_DIAG_RDREAD = 28, /* Get regulatory domain */ + HAL_DIAG_FATALERR = 29, /* Read cached interrupt state */ + HAL_DIAG_11NCOMPAT = 30, /* 11n compatibility tweaks */ + HAL_DIAG_ANI_PARAMS = 31, /* ANI noise immunity parameters */ + HAL_DIAG_CHECK_HANGS = 32, /* check h/w hangs */ + HAL_DIAG_SETREGS = 33, /* write registers */ + HAL_DIAG_CHANSURVEY = 34, /* channel survey */ + HAL_DIAG_PRINT_REG = 35, + HAL_DIAG_PRINT_REG_ALL = 36, + HAL_DIAG_CHANNELS = 37, + HAL_DIAG_PRINT_REG_COUNTER = 38, +}; + +#endif /* _ATH_AH_DIAGCODES_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ah_eeprom.h b/sys/external/isc/atheros_hal/dist/ah_eeprom.h new file mode 100644 index 0000000..3e9330b --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_eeprom.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AH_EEPROM_H_ +#define _ATH_AH_EEPROM_H_ + +#define AR_EEPROM_VER1 0x1000 /* Version 1.0; 5210 only */ +/* + * Version 3 EEPROMs are all 16K. + * 3.1 adds turbo limit, antenna gain, 16 CTL's, 11g info, + * and 2.4Ghz ob/db for B & G + * 3.2 has more accurate pcdac intercepts and analog chip + * calibration. + * 3.3 adds ctl in-band limit, 32 ctl's, and frequency + * expansion + * 3.4 adds xr power, gainI, and 2.4 turbo params + */ +#define AR_EEPROM_VER3 0x3000 /* Version 3.0; start of 16k EEPROM */ +#define AR_EEPROM_VER3_1 0x3001 /* Version 3.1 */ +#define AR_EEPROM_VER3_2 0x3002 /* Version 3.2 */ +#define AR_EEPROM_VER3_3 0x3003 /* Version 3.3 */ +#define AR_EEPROM_VER3_4 0x3004 /* Version 3.4 */ +#define AR_EEPROM_VER4 0x4000 /* Version 4.x */ +#define AR_EEPROM_VER4_0 0x4000 /* Version 4.0 */ +#define AR_EEPROM_VER4_1 0x4001 /* Version 4.0 */ +#define AR_EEPROM_VER4_2 0x4002 /* Version 4.0 */ +#define AR_EEPROM_VER4_3 0x4003 /* Version 4.0 */ +#define AR_EEPROM_VER4_6 0x4006 /* Version 4.0 */ +#define AR_EEPROM_VER4_7 0x3007 /* Version 4.7 */ +#define AR_EEPROM_VER4_9 0x4009 /* EEPROM EAR futureproofing */ +#define AR_EEPROM_VER5 0x5000 /* Version 5.x */ +#define AR_EEPROM_VER5_0 0x5000 /* Adds new 2413 cal powers and added params */ +#define AR_EEPROM_VER5_1 0x5001 /* Adds capability values */ +#define AR_EEPROM_VER5_3 0x5003 /* Adds spur mitigation table */ +#define AR_EEPROM_VER5_4 0x5004 +/* + * Version 14 EEPROMs came in with AR5416. + * 14.2 adds txFrameToPaOn, txFrameToDataStart, ht40PowerInc + * 14.3 adds bswAtten, bswMargin, swSettle, and base OpFlags for HT20/40 + */ +#define AR_EEPROM_VER14 0xE000 /* Version 14.x */ +#define AR_EEPROM_VER14_1 0xE001 /* Adds 11n support */ +#define AR_EEPROM_VER14_2 0xE002 +#define AR_EEPROM_VER14_3 0xE003 +#define AR_EEPROM_VER14_7 0xE007 +#define AR_EEPROM_VER14_9 0xE009 +#define AR_EEPROM_VER14_16 0xE010 +#define AR_EEPROM_VER14_17 0xE011 +#define AR_EEPROM_VER14_19 0xE013 + +enum { + AR_EEP_RFKILL, /* use ath_hal_eepromGetFlag */ + AR_EEP_AMODE, /* use ath_hal_eepromGetFlag */ + AR_EEP_BMODE, /* use ath_hal_eepromGetFlag */ + AR_EEP_GMODE, /* use ath_hal_eepromGetFlag */ + AR_EEP_TURBO5DISABLE, /* use ath_hal_eepromGetFlag */ + AR_EEP_TURBO2DISABLE, /* use ath_hal_eepromGetFlag */ + AR_EEP_ISTALON, /* use ath_hal_eepromGetFlag */ + AR_EEP_32KHZCRYSTAL, /* use ath_hal_eepromGetFlag */ + AR_EEP_MACADDR, /* uint8_t* */ + AR_EEP_COMPRESS, /* use ath_hal_eepromGetFlag */ + AR_EEP_FASTFRAME, /* use ath_hal_eepromGetFlag */ + AR_EEP_AES, /* use ath_hal_eepromGetFlag */ + AR_EEP_BURST, /* use ath_hal_eepromGetFlag */ + AR_EEP_MAXQCU, /* uint16_t* */ + AR_EEP_KCENTRIES, /* uint16_t* */ + AR_EEP_NFTHRESH_5, /* int16_t* */ + AR_EEP_NFTHRESH_2, /* int16_t* */ + AR_EEP_REGDMN_0, /* uint16_t* */ + AR_EEP_REGDMN_1, /* uint16_t* */ + AR_EEP_OPCAP, /* uint16_t* */ + AR_EEP_OPMODE, /* uint16_t* */ + AR_EEP_RFSILENT, /* uint16_t* */ + AR_EEP_OB_5, /* uint8_t* */ + AR_EEP_DB_5, /* uint8_t* */ + AR_EEP_OB_2, /* uint8_t* */ + AR_EEP_DB_2, /* uint8_t* */ + AR_EEP_TXMASK, /* uint8_t* */ + AR_EEP_RXMASK, /* uint8_t* */ + AR_EEP_RXGAIN_TYPE, /* uint8_t* */ + AR_EEP_TXGAIN_TYPE, /* uint8_t* */ + AR_EEP_DAC_HPWR_5G, /* uint8_t* */ + AR_EEP_OL_PWRCTRL, /* use ath_hal_eepromGetFlag */ + AR_EEP_FSTCLK_5G, /* use ath_hal_eepromGetFlag */ + AR_EEP_ANTGAINMAX_5, /* int8_t* */ + AR_EEP_ANTGAINMAX_2, /* int8_t* */ + AR_EEP_WRITEPROTECT, /* use ath_hal_eepromGetFlag */ + AR_EEP_PWR_TABLE_OFFSET,/* int8_t* */ + AR_EEP_PWDCLKIND, /* uint8_t* */ + AR_EEP_TEMPSENSE_SLOPE, /* int8_t* */ + AR_EEP_TEMPSENSE_SLOPE_PAL_ON, /* int8_t* */ + AR_EEP_FRAC_N_5G, /* uint8_t* */ + + /* New fields for AR9300 and later */ + AR_EEP_DRIVE_STRENGTH, + AR_EEP_PAPRD_ENABLED, +}; + +typedef struct { + uint16_t rdEdge; + uint16_t twice_rdEdgePower; + HAL_BOOL flag; +} RD_EDGES_POWER; + +/* XXX should probably be version-dependent */ +#define SD_NO_CTL 0xf0 +#define NO_CTL 0xff +#define CTL_MODE_M 0x0f +#define CTL_11A 0 +#define CTL_11B 1 +#define CTL_11G 2 +#define CTL_TURBO 3 +#define CTL_108G 4 +#define CTL_2GHT20 5 +#define CTL_5GHT20 6 +#define CTL_2GHT40 7 +#define CTL_5GHT40 8 + +/* XXX must match what FCC/MKK/ETSI are defined as in ah_regdomain.h */ +#define HAL_REG_DMN_MASK 0xf0 +#define HAL_REGDMN_FCC 0x10 +#define HAL_REGDMN_MKK 0x40 +#define HAL_REGDMN_ETSI 0x30 + +#define is_reg_dmn_fcc(reg_dmn) \ + (((reg_dmn & HAL_REG_DMN_MASK) == HAL_REGDMN_FCC) ? 1 : 0) +#define is_reg_dmn_etsi(reg_dmn) \ + (((reg_dmn & HAL_REG_DMN_MASK) == HAL_REGDMN_ETSI) ? 1 : 0) +#define is_reg_dmn_mkk(reg_dmn) \ + (((reg_dmn & HAL_REG_DMN_MASK) == HAL_REGDMN_MKK) ? 1 : 0) + +#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040 +#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080 +#define AR_EEPROM_EEREGCAP_EN_KK_U2 0x0100 +#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200 +#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400 +#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800 + +/* regulatory capabilities prior to eeprom version 4.0 */ +#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0 0x4000 +#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000 + +#define AR_NO_SPUR 0x8000 + +/* XXX exposed to chip code */ +#define MAX_RATE_POWER 63 + +HAL_STATUS ath_hal_v1EepromAttach(struct ath_hal *ah); +HAL_STATUS ath_hal_legacyEepromAttach(struct ath_hal *ah); +HAL_STATUS ath_hal_v14EepromAttach(struct ath_hal *ah); +HAL_STATUS ath_hal_v4kEepromAttach(struct ath_hal *ah); +HAL_STATUS ath_hal_9287EepromAttach(struct ath_hal *ah); +#endif /* _ATH_AH_EEPROM_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ah_eeprom_9287.c b/sys/external/isc/atheros_hal/dist/ah_eeprom_9287.c new file mode 100644 index 0000000..abdbce0 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_eeprom_9287.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_eeprom_v14.h" +#include "ah_eeprom_9287.h" + +static HAL_STATUS +v9287EepromGet(struct ath_hal *ah, int param, void *val) +{ +#define CHAN_A_IDX 0 +#define CHAN_B_IDX 1 +#define IS_VERS(op, v) ((pBase->version & AR5416_EEP_VER_MINOR_MASK) op (v)) + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + const MODAL_EEP_9287_HEADER *pModal = &ee->ee_base.modalHeader; + const BASE_EEP_9287_HEADER *pBase = &ee->ee_base.baseEepHeader; + uint32_t sum; + uint8_t *macaddr; + int i; + + switch (param) { + case AR_EEP_NFTHRESH_2: + *(int16_t *)val = pModal->noiseFloorThreshCh[0]; + return HAL_OK; + case AR_EEP_MACADDR: /* Get MAC Address */ + sum = 0; + macaddr = val; + for (i = 0; i < 6; i++) { + macaddr[i] = pBase->macAddr[i]; + sum += pBase->macAddr[i]; + } + if (sum == 0 || sum == 0xffff*3) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad mac address %s\n", + __func__, ath_hal_ether_sprintf(macaddr)); + return HAL_EEBADMAC; + } + return HAL_OK; + case AR_EEP_REGDMN_0: + return pBase->regDmn[0]; + case AR_EEP_REGDMN_1: + return pBase->regDmn[1]; + case AR_EEP_OPCAP: + return pBase->deviceCap; + case AR_EEP_OPMODE: + return pBase->opCapFlags; + case AR_EEP_RFSILENT: + return pBase->rfSilent; + case AR_EEP_TXMASK: + return pBase->txMask; + case AR_EEP_RXMASK: + return pBase->rxMask; + case AR_EEP_OL_PWRCTRL: + HALASSERT(val == AH_NULL); + return pBase->openLoopPwrCntl ? HAL_OK : HAL_EIO; + case AR_EEP_AMODE: + return HAL_EIO; /* no 5GHz for Kiwi */ + case AR_EEP_BMODE: + case AR_EEP_GMODE: + HALASSERT(val == AH_NULL); + return pBase->opCapFlags & AR5416_OPFLAGS_11G ? + HAL_OK : HAL_EIO; + case AR_EEP_32KHZCRYSTAL: + case AR_EEP_COMPRESS: + case AR_EEP_FASTFRAME: /* XXX policy decision, h/w can do it */ + case AR_EEP_WRITEPROTECT: /* NB: no write protect bit */ + HALASSERT(val == AH_NULL); + /* fall thru... */ + case AR_EEP_MAXQCU: /* NB: not in opCapFlags */ + case AR_EEP_KCENTRIES: /* NB: not in opCapFlags */ + return HAL_EIO; + case AR_EEP_AES: + case AR_EEP_BURST: + case AR_EEP_RFKILL: + case AR_EEP_TURBO5DISABLE: + case AR_EEP_TURBO2DISABLE: + HALASSERT(val == AH_NULL); + return HAL_OK; + case AR_EEP_ANTGAINMAX_2: + *(int8_t *) val = ee->ee_antennaGainMax[1]; + return HAL_OK; + case AR_EEP_PWR_TABLE_OFFSET: + *(int8_t *) val = pBase->pwrTableOffset; + return HAL_OK; + case AR_EEP_TEMPSENSE_SLOPE: + if (IS_VERS(>=, AR9287_EEP_MINOR_VER_2)) + *(int8_t *)val = pBase->tempSensSlope; + else + *(int8_t *)val = 0; + return HAL_OK; + case AR_EEP_TEMPSENSE_SLOPE_PAL_ON: + if (IS_VERS(>=, AR9287_EEP_MINOR_VER_3)) + *(int8_t *)val = pBase->tempSensSlopePalOn; + else + *(int8_t *)val = 0; + return HAL_OK; + default: + HALASSERT(0); + return HAL_EINVAL; + } +#undef IS_VERS +#undef CHAN_A_IDX +#undef CHAN_B_IDX +} + +static HAL_STATUS +v9287EepromSet(struct ath_hal *ah, int param, int v) +{ + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (param) { + case AR_EEP_ANTGAINMAX_2: + ee->ee_antennaGainMax[1] = (int8_t) v; + return HAL_OK; + default: + return HAL_EINVAL; + } +} + +static HAL_BOOL +v9287EepromDiag(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, void **result, uint32_t *resultsize) +{ + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (request) { + case HAL_DIAG_EEPROM: + *result = ee; + *resultsize = sizeof(HAL_EEPROM_9287); + return AH_TRUE; + } + return AH_FALSE; +} + +/* Do structure specific swaps if Eeprom format is non native to host */ +static void +eepromSwap(HAL_EEPROM_9287 *ee) +{ + uint32_t integer, i; + uint16_t word; + MODAL_EEP_9287_HEADER *pModal; + + /* convert Base Eep header */ + word = __bswap16(ee->ee_base.baseEepHeader.length); + ee->ee_base.baseEepHeader.length = word; + + word = __bswap16(ee->ee_base.baseEepHeader.checksum); + ee->ee_base.baseEepHeader.checksum = word; + + word = __bswap16(ee->ee_base.baseEepHeader.version); + ee->ee_base.baseEepHeader.version = word; + + word = __bswap16(ee->ee_base.baseEepHeader.regDmn[0]); + ee->ee_base.baseEepHeader.regDmn[0] = word; + + word = __bswap16(ee->ee_base.baseEepHeader.regDmn[1]); + ee->ee_base.baseEepHeader.regDmn[1] = word; + + word = __bswap16(ee->ee_base.baseEepHeader.rfSilent); + ee->ee_base.baseEepHeader.rfSilent = word; + + word = __bswap16(ee->ee_base.baseEepHeader.blueToothOptions); + ee->ee_base.baseEepHeader.blueToothOptions = word; + + word = __bswap16(ee->ee_base.baseEepHeader.deviceCap); + ee->ee_base.baseEepHeader.deviceCap = word; + + /* convert Modal Eep header */ + + /* only 2.4ghz here; so only one modal header entry */ + pModal = &ee->ee_base.modalHeader; + + /* XXX linux/ah_osdep.h only defines __bswap32 for BE */ + integer = __bswap32(pModal->antCtrlCommon); + pModal->antCtrlCommon = integer; + + for (i = 0; i < AR9287_MAX_CHAINS; i++) { + integer = __bswap32(pModal->antCtrlChain[i]); + pModal->antCtrlChain[i] = integer; + } + for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { + word = __bswap16(pModal->spurChans[i].spurChan); + pModal->spurChans[i].spurChan = word; + } +} + +static uint16_t +v9287EepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) +{ + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + + HALASSERT(is2GHz == AH_TRUE); + if (is2GHz != AH_TRUE) + return 0; /* XXX ? */ + + HALASSERT(0 <= ix && ix < AR5416_EEPROM_MODAL_SPURS); + return ee->ee_base.modalHeader.spurChans[ix].spurChan; +} + +/************************************************************************** + * fbin2freq + * + * Get channel value from binary representation held in eeprom + * RETURNS: the frequency in MHz + */ +static uint16_t +fbin2freq(uint8_t fbin, HAL_BOOL is2GHz) +{ + /* + * Reserved value 0xFF provides an empty definition both as + * an fbin and as a frequency - do not convert + */ + if (fbin == AR5416_BCHAN_UNUSED) + return fbin; + return (uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); +} + + +/* + * Copy EEPROM Conformance Testing Limits contents + * into the allocated space + */ +/* USE CTLS from chain zero */ +#define CTL_CHAIN 0 + +static void +v9287EepromReadCTLInfo(struct ath_hal *ah, HAL_EEPROM_9287 *ee) +{ + RD_EDGES_POWER *rep = ee->ee_rdEdgesPower; + int i, j; + + HALASSERT(AR9287_NUM_CTLS <= sizeof(ee->ee_rdEdgesPower)/NUM_EDGES); + + for (i = 0; ee->ee_base.ctlIndex[i] != 0 && i < AR9287_NUM_CTLS; i++) { + for (j = 0; j < NUM_EDGES; j ++) { + /* XXX Confirm this is the right thing to do when an invalid channel is stored */ + if (ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].bChannel == AR5416_BCHAN_UNUSED) { + rep[j].rdEdge = 0; + rep[j].twice_rdEdgePower = 0; + rep[j].flag = 0; + } else { + rep[j].rdEdge = fbin2freq( + ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].bChannel, + (ee->ee_base.ctlIndex[i] & CTL_MODE_M) != CTL_11A); + rep[j].twice_rdEdgePower = MS(ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].tPowerFlag, CAL_CTL_EDGES_POWER); + rep[j].flag = MS(ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].tPowerFlag, CAL_CTL_EDGES_FLAG) != 0; + } + } + rep += NUM_EDGES; + } + ee->ee_numCtls = i; + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "%s Numctls = %u\n",__func__,i); +} + +/* + * Reclaim any EEPROM-related storage. + */ +static void +v9287EepromDetach(struct ath_hal *ah) +{ + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + + ath_hal_free(ee); + AH_PRIVATE(ah)->ah_eeprom = AH_NULL; +} + +#define owl_get_eep_ver(_ee) \ + (((_ee)->ee_base.baseEepHeader.version >> 12) & 0xF) +#define owl_get_eep_rev(_ee) \ + (((_ee)->ee_base.baseEepHeader.version) & 0xFFF) + +HAL_STATUS +ath_hal_9287EepromAttach(struct ath_hal *ah) +{ +#define NW(a) (sizeof(a) / sizeof(uint16_t)) + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t *eep_data, magic; + HAL_BOOL need_swap; + u_int w, off, len; + uint32_t sum; + + HALASSERT(ee == AH_NULL); + + /* + * Don't check magic if we're supplied with an EEPROM block, + * typically this is from Howl but it may also be from later + * boards w/ an embedded WMAC. + */ + if (ah->ah_eepromdata == NULL) { + if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s Error reading Eeprom MAGIC\n", __func__); + return HAL_EEREAD; + } + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s Eeprom Magic = 0x%x\n", + __func__, magic); + if (magic != AR5416_EEPROM_MAGIC) { + HALDEBUG(ah, HAL_DEBUG_ANY, "Bad magic number\n"); + return HAL_EEMAGIC; + } + } + + ee = ath_hal_malloc(sizeof(HAL_EEPROM_9287)); + if (ee == AH_NULL) { + /* XXX message */ + return HAL_ENOMEM; + } + + eep_data = (uint16_t *) ee; + for (w = 0; w < NW(struct ar9287_eeprom); w++) { + off = AR9287_EEP_START_LOC + w; + if (!ath_hal_eepromRead(ah, off, &eep_data[w])) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s eeprom read error at offset 0x%x\n", + __func__, off); + return HAL_EEREAD; + } + } + /* Convert to eeprom native eeprom endian format */ + /* + * XXX this is likely incorrect but will do for now + * XXX to get embedded boards working. + */ + if (ah->ah_eepromdata == NULL && isBigEndian()) { + for (w = 0; w < NW(HAL_EEPROM_9287); w++) + eep_data[w] = __bswap16(eep_data[w]); + } + + /* + * At this point, we're in the native eeprom endian format + * Now, determine the eeprom endian by looking at byte 26?? + */ + need_swap = ((ee->ee_base.baseEepHeader.eepMisc & AR5416_EEPMISC_BIG_ENDIAN) != 0) ^ isBigEndian(); + if (need_swap) { + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "Byte swap EEPROM contents.\n"); + len = __bswap16(ee->ee_base.baseEepHeader.length); + } else { + len = ee->ee_base.baseEepHeader.length; + } + len = AH_MIN(len, sizeof(HAL_EEPROM_9287)) / sizeof(uint16_t); + + /* Apply the checksum, done in native eeprom format */ + /* XXX - Need to check to make sure checksum calculation is done + * in the correct endian format. Right now, it seems it would + * cast the raw data to host format and do the calculation, which may + * not be correct as the calculation may need to be done in the native + * eeprom format + */ + sum = 0; + for (w = 0; w < len; w++) + sum ^= eep_data[w]; + /* Check CRC - Attach should fail on a bad checksum */ + if (sum != 0xffff) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "Bad EEPROM checksum 0x%x (Len=%u)\n", sum, len); + return HAL_EEBADSUM; + } + + if (need_swap) + eepromSwap(ee); /* byte swap multi-byte data */ + + /* swap words 0+2 so version is at the front */ + magic = eep_data[0]; + eep_data[0] = eep_data[2]; + eep_data[2] = magic; + + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "%s Eeprom Version %u.%u\n", __func__, + owl_get_eep_ver(ee), owl_get_eep_rev(ee)); + + /* NB: must be after all byte swapping */ + if (owl_get_eep_ver(ee) != AR5416_EEP_VER) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "Bad EEPROM version 0x%x\n", owl_get_eep_ver(ee)); + return HAL_EEBADSUM; + } + + v9287EepromReadCTLInfo(ah, ee); /* Get CTLs */ + + AH_PRIVATE(ah)->ah_eeprom = ee; + AH_PRIVATE(ah)->ah_eeversion = ee->ee_base.baseEepHeader.version; + AH_PRIVATE(ah)->ah_eepromDetach = v9287EepromDetach; + AH_PRIVATE(ah)->ah_eepromGet = v9287EepromGet; + AH_PRIVATE(ah)->ah_eepromSet = v9287EepromSet; + AH_PRIVATE(ah)->ah_getSpurChan = v9287EepromGetSpurChan; + AH_PRIVATE(ah)->ah_eepromDiag = v9287EepromDiag; + return HAL_OK; +#undef NW +} diff --git a/sys/external/isc/atheros_hal/dist/ah_eeprom_9287.h b/sys/external/isc/atheros_hal/dist/ah_eeprom_9287.h new file mode 100644 index 0000000..ff8080a --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_eeprom_9287.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2008-2009 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AH_EEPROM_9287_H__ +#define __AH_EEPROM_9287_H__ + +#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \ + ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) + +#define AR9287_EEP_VER 0xE +#define AR9287_EEP_VER_MINOR_MASK 0xFFF +#define AR9287_EEP_MINOR_VER_1 0x1 +#define AR9287_EEP_MINOR_VER_2 0x2 +#define AR9287_EEP_MINOR_VER_3 0x3 +#define AR9287_EEP_MINOR_VER AR9287_EEP_MINOR_VER_3 +#define AR9287_EEP_MINOR_VER_b AR9287_EEP_MINOR_VER +#define AR9287_EEP_NO_BACK_VER AR9287_EEP_MINOR_VER_1 + +#define AR9287_RDEXT_DEFAULT 0x1F + +#define AR9287_EEP_START_LOC 128 +#define AR9287_HTC_EEP_START_LOC 256 +#define AR9287_NUM_2G_CAL_PIERS 3 +#define AR9287_NUM_2G_CCK_TARGET_POWERS 3 +#define AR9287_NUM_2G_20_TARGET_POWERS 3 +#define AR9287_NUM_2G_40_TARGET_POWERS 3 +#define AR9287_NUM_CTLS 12 +#define AR9287_NUM_BAND_EDGES 4 +#define AR9287_PD_GAIN_ICEPTS 1 +#define AR9287_EEPMISC_BIG_ENDIAN 0x01 +#define AR9287_EEPMISC_WOW 0x02 +#define AR9287_MAX_CHAINS 2 +#define AR9287_ANT_16S 32 + +#define AR9287_DATA_SZ 32 + +#define AR9287_PWR_TABLE_OFFSET_DB -5 + +#define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1) + +struct base_eep_ar9287_header { + uint16_t version; /* Swapped w/ length; check ah_eeprom_v14.h */ + uint16_t checksum; + uint16_t length; + uint8_t opCapFlags; + uint8_t eepMisc; + uint16_t regDmn[2]; + uint8_t macAddr[6]; + uint8_t rxMask; + uint8_t txMask; + uint16_t rfSilent; + uint16_t blueToothOptions; + uint16_t deviceCap; + uint32_t binBuildNumber; + uint8_t deviceType; + uint8_t openLoopPwrCntl; + int8_t pwrTableOffset; + int8_t tempSensSlope; + int8_t tempSensSlopePalOn; + uint8_t futureBase[29]; +} __packed; + +struct modal_eep_ar9287_header { + uint32_t antCtrlChain[AR9287_MAX_CHAINS]; + uint32_t antCtrlCommon; + int8_t antennaGainCh[AR9287_MAX_CHAINS]; + uint8_t switchSettling; + uint8_t txRxAttenCh[AR9287_MAX_CHAINS]; + uint8_t rxTxMarginCh[AR9287_MAX_CHAINS]; + int8_t adcDesiredSize; + uint8_t txEndToXpaOff; + uint8_t txEndToRxOn; + uint8_t txFrameToXpaOn; + uint8_t thresh62; + int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS]; + uint8_t xpdGain; + uint8_t xpd; + int8_t iqCalICh[AR9287_MAX_CHAINS]; + int8_t iqCalQCh[AR9287_MAX_CHAINS]; + uint8_t pdGainOverlap; + uint8_t xpaBiasLvl; + uint8_t txFrameToDataStart; + uint8_t txFrameToPaOn; + uint8_t ht40PowerIncForPdadc; + uint8_t bswAtten[AR9287_MAX_CHAINS]; + uint8_t bswMargin[AR9287_MAX_CHAINS]; + uint8_t swSettleHt40; + uint8_t version; + uint8_t db1; + uint8_t db2; + uint8_t ob_cck; + uint8_t ob_psk; + uint8_t ob_qam; + uint8_t ob_pal_off; + uint8_t futureModal[30]; + SPUR_CHAN spurChans[AR5416_EEPROM_MODAL_SPURS]; +} __packed; + +struct cal_data_op_loop_ar9287 { + uint8_t pwrPdg[2][5]; + uint8_t vpdPdg[2][5]; + uint8_t pcdac[2][5]; + uint8_t empty[2][5]; +} __packed; + +struct cal_data_per_freq_ar9287 { + uint8_t pwrPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; + uint8_t vpdPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; +} __packed; + +union cal_data_per_freq_ar9287_u { + struct cal_data_op_loop_ar9287 calDataOpen; + struct cal_data_per_freq_ar9287 calDataClose; +} __packed; + +struct cal_ctl_data_ar9287 { + CAL_CTL_EDGES ctlEdges[AR9287_MAX_CHAINS][AR9287_NUM_BAND_EDGES]; +} __packed; + +struct ar9287_eeprom { + struct base_eep_ar9287_header baseEepHeader; + uint8_t custData[AR9287_DATA_SZ]; + struct modal_eep_ar9287_header modalHeader; + uint8_t calFreqPier2G[AR9287_NUM_2G_CAL_PIERS]; + union cal_data_per_freq_ar9287_u + calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS]; + CAL_TARGET_POWER_LEG + calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS]; + CAL_TARGET_POWER_LEG + calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT + calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT + calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS]; + uint8_t ctlIndex[AR9287_NUM_CTLS]; + struct cal_ctl_data_ar9287 ctlData[AR9287_NUM_CTLS]; + uint8_t padding; +} __packed; + +typedef struct { + struct ar9287_eeprom ee_base; +#define NUM_EDGES 8 + uint16_t ee_numCtls; + RD_EDGES_POWER ee_rdEdgesPower[NUM_EDGES*AR9287_NUM_CTLS]; + /* XXX these are dynamically calculated for use by shared code */ + int8_t ee_antennaGainMax[2]; +} HAL_EEPROM_9287; + +typedef struct modal_eep_ar9287_header MODAL_EEP_9287_HEADER; +typedef struct base_eep_ar9287_header BASE_EEP_9287_HEADER; + + +#endif /* __AH_EEPROM_9287_H__ */ diff --git a/sys/external/isc/atheros_hal/dist/ah_eeprom_v1.c b/sys/external/isc/atheros_hal/dist/ah_eeprom_v1.c new file mode 100644 index 0000000..8b4664f --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_eeprom_v1.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_eeprom_v1.h" + +static HAL_STATUS +v1EepromGet(struct ath_hal *ah, int param, void *val) +{ + HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + uint32_t sum; + uint16_t eeval; + uint8_t *macaddr; + int i; + + switch (param) { + case AR_EEP_MACADDR: /* Get MAC Address */ + sum = 0; + macaddr = val; + for (i = 0; i < 3; i++) { + if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(i), &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM location %u\n", + __func__, i); + return HAL_EEREAD; + } + sum += eeval; + macaddr[2*i + 0] = eeval >> 8; + macaddr[2*i + 1] = eeval & 0xff; + } + if (sum == 0 || sum == 0xffff*3) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad mac address %s\n", + __func__, ath_hal_ether_sprintf(macaddr)); + return HAL_EEBADMAC; + } + return HAL_OK; + case AR_EEP_REGDMN_0: + *(uint16_t *) val = ee->ee_regDomain[0]; + return HAL_OK; + case AR_EEP_RFKILL: + HALASSERT(val == AH_NULL); + return ee->ee_rfKill ? HAL_OK : HAL_EIO; + case AR_EEP_WRITEPROTECT: + HALASSERT(val == AH_NULL); + return (ee->ee_protect & AR_EEPROM_PROTOTECT_WP_128_191) ? + HAL_OK : HAL_EIO; + default: + HALASSERT(0); + return HAL_EINVAL; + } +} + +static HAL_STATUS +v1EepromSet(struct ath_hal *ah, int param, int v) +{ + return HAL_EINVAL; +} + +static HAL_BOOL +v1EepromDiag(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, void **result, uint32_t *resultsize) +{ + HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (request) { + case HAL_DIAG_EEPROM: + *result = ee; + *resultsize = sizeof(*ee); + return AH_TRUE; + } + return AH_FALSE; +} + +static uint16_t +v1EepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) +{ + return AR_NO_SPUR; +} + +/* + * Reclaim any EEPROM-related storage. + */ +static void +v1EepromDetach(struct ath_hal *ah) +{ + HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + + ath_hal_free(ee); + AH_PRIVATE(ah)->ah_eeprom = AH_NULL; +} + +HAL_STATUS +ath_hal_v1EepromAttach(struct ath_hal *ah) +{ + HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t athvals[AR_EEPROM_ATHEROS_MAX]; /* XXX off stack */ + uint16_t protect, eeprom_version, eeval; + uint32_t sum; + int i, loc; + + HALASSERT(ee == AH_NULL); + + if (!ath_hal_eepromRead(ah, AR_EEPROM_MAGIC, &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM magic number\n", __func__); + return HAL_EEREAD; + } + if (eeval != 0x5aa5) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid EEPROM magic number 0x%x\n", __func__, eeval); + return HAL_EEMAGIC; + } + + if (!ath_hal_eepromRead(ah, AR_EEPROM_PROTECT, &protect)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM protection bits; read locked?\n", + __func__); + return HAL_EEREAD; + } + HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", protect); + /* XXX check proper access before continuing */ + + if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &eeprom_version)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to read EEPROM version\n", __func__); + return HAL_EEREAD; + } + if (((eeprom_version>>12) & 0xf) != 1) { + /* + * This code only groks the version 1 EEPROM layout. + */ + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unsupported EEPROM version 0x%x found\n", + __func__, eeprom_version); + return HAL_EEVERSION; + } + + /* + * Read the Atheros EEPROM entries and calculate the checksum. + */ + sum = 0; + for (i = 0; i < AR_EEPROM_ATHEROS_MAX; i++) { + if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &athvals[i])) + return HAL_EEREAD; + sum ^= athvals[i]; + } + if (sum != 0xffff) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n", + __func__, sum); + return HAL_EEBADSUM; + } + + /* + * Valid checksum, fetch the regulatory domain and save values. + */ + if (!ath_hal_eepromRead(ah, AR_EEPROM_REG_DOMAIN, &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read regdomain from EEPROM\n", __func__); + return HAL_EEREAD; + } + + ee = ath_hal_malloc(sizeof(HAL_EEPROM_v1)); + if (ee == AH_NULL) { + /* XXX message */ + return HAL_ENOMEM; + } + + ee->ee_version = eeprom_version; + ee->ee_protect = protect; + ee->ee_antenna = athvals[2]; + ee->ee_biasCurrents = athvals[3]; + ee->ee_thresh62 = athvals[4] & 0xff; + ee->ee_xlnaOn = (athvals[4] >> 8) & 0xff; + ee->ee_xpaOn = athvals[5] & 0xff; + ee->ee_xpaOff = (athvals[5] >> 8) & 0xff; + ee->ee_regDomain[0] = (athvals[6] >> 8) & 0xff; + ee->ee_regDomain[1] = athvals[6] & 0xff; + ee->ee_regDomain[2] = (athvals[7] >> 8) & 0xff; + ee->ee_regDomain[3] = athvals[7] & 0xff; + ee->ee_rfKill = athvals[8] & 0x1; + ee->ee_devType = (athvals[8] >> 1) & 0x7; + + for (i = 0, loc = AR_EEPROM_ATHEROS_TP_SETTINGS; i < AR_CHANNELS_MAX; i++, loc += AR_TP_SETTINGS_SIZE) { + struct tpcMap *chan = &ee->ee_tpc[i]; + + /* Copy pcdac and gain_f values from EEPROM */ + chan->pcdac[0] = (athvals[loc] >> 10) & 0x3F; + chan->gainF[0] = (athvals[loc] >> 4) & 0x3F; + chan->pcdac[1] = ((athvals[loc] << 2) & 0x3C) + | ((athvals[loc+1] >> 14) & 0x03); + chan->gainF[1] = (athvals[loc+1] >> 8) & 0x3F; + chan->pcdac[2] = (athvals[loc+1] >> 2) & 0x3F; + chan->gainF[2] = ((athvals[loc+1] << 4) & 0x30) + | ((athvals[loc+2] >> 12) & 0x0F); + chan->pcdac[3] = (athvals[loc+2] >> 6) & 0x3F; + chan->gainF[3] = athvals[loc+2] & 0x3F; + chan->pcdac[4] = (athvals[loc+3] >> 10) & 0x3F; + chan->gainF[4] = (athvals[loc+3] >> 4) & 0x3F; + chan->pcdac[5] = ((athvals[loc+3] << 2) & 0x3C) + | ((athvals[loc+4] >> 14) & 0x03); + chan->gainF[5] = (athvals[loc+4] >> 8) & 0x3F; + chan->pcdac[6] = (athvals[loc+4] >> 2) & 0x3F; + chan->gainF[6] = ((athvals[loc+4] << 4) & 0x30) + | ((athvals[loc+5] >> 12) & 0x0F); + chan->pcdac[7] = (athvals[loc+5] >> 6) & 0x3F; + chan->gainF[7] = athvals[loc+5] & 0x3F; + chan->pcdac[8] = (athvals[loc+6] >> 10) & 0x3F; + chan->gainF[8] = (athvals[loc+6] >> 4) & 0x3F; + chan->pcdac[9] = ((athvals[loc+6] << 2) & 0x3C) + | ((athvals[loc+7] >> 14) & 0x03); + chan->gainF[9] = (athvals[loc+7] >> 8) & 0x3F; + chan->pcdac[10] = (athvals[loc+7] >> 2) & 0x3F; + chan->gainF[10] = ((athvals[loc+7] << 4) & 0x30) + | ((athvals[loc+8] >> 12) & 0x0F); + + /* Copy Regulatory Domain and Rate Information from EEPROM */ + chan->rate36 = (athvals[loc+8] >> 6) & 0x3F; + chan->rate48 = athvals[loc+8] & 0x3F; + chan->rate54 = (athvals[loc+9] >> 10) & 0x3F; + chan->regdmn[0] = (athvals[loc+9] >> 4) & 0x3F; + chan->regdmn[1] = ((athvals[loc+9] << 2) & 0x3C) + | ((athvals[loc+10] >> 14) & 0x03); + chan->regdmn[2] = (athvals[loc+10] >> 8) & 0x3F; + chan->regdmn[3] = (athvals[loc+10] >> 2) & 0x3F; + } + + AH_PRIVATE(ah)->ah_eeprom = ee; + AH_PRIVATE(ah)->ah_eeversion = eeprom_version; + AH_PRIVATE(ah)->ah_eepromDetach = v1EepromDetach; + AH_PRIVATE(ah)->ah_eepromGet = v1EepromGet; + AH_PRIVATE(ah)->ah_eepromSet = v1EepromSet; + AH_PRIVATE(ah)->ah_getSpurChan = v1EepromGetSpurChan; + AH_PRIVATE(ah)->ah_eepromDiag = v1EepromDiag; + return HAL_OK; +} diff --git a/sys/external/isc/atheros_hal/dist/ah_eeprom_v1.h b/sys/external/isc/atheros_hal/dist/ah_eeprom_v1.h new file mode 100644 index 0000000..22fce8a --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_eeprom_v1.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AH_EEPROM_V1_H_ +#define _ATH_AH_EEPROM_V1_H_ + +#include "ah_eeprom.h" + +/* + * EEPROM defines for Version 1 Crete EEPROM. + * + * The EEPROM is segmented into three sections: + * + * PCI/Cardbus default configuration settings + * Cardbus CIS tuples and vendor-specific data + * Atheros-specific data + * + * EEPROM entries are read 32-bits at a time through the PCI bus + * interface but are all 16-bit values. + * + * Access to the Atheros-specific data is controlled by protection + * bits and the data is checksum'd. The driver reads the Atheros + * data from the EEPROM at attach and caches it in its private state. + * This data includes the local regulatory domain, channel calibration + * settings, and phy-related configuration settings. + */ +#define AR_EEPROM_MAC(i) (0x1f-(i))/* MAC address word */ +#define AR_EEPROM_MAGIC 0x3d /* magic number */ +#define AR_EEPROM_PROTECT 0x3f /* Atheros segment protect register */ +#define AR_EEPROM_PROTOTECT_WP_128_191 0x80 +#define AR_EEPROM_REG_DOMAIN 0xbf /* Current regulatory domain register */ +#define AR_EEPROM_ATHEROS_BASE 0xc0 /* Base of Atheros-specific data */ +#define AR_EEPROM_ATHEROS_MAX 64 /* 64x2=128 bytes of EEPROM settings */ +#define AR_EEPROM_ATHEROS(n) (AR_EEPROM_ATHEROS_BASE+(n)) +#define AR_EEPROM_VERSION AR_EEPROM_ATHEROS(1) +#define AR_EEPROM_ATHEROS_TP_SETTINGS 0x09 /* Transmit power settings */ +#define AR_REG_DOMAINS_MAX 4 /* # of Regulatory Domains */ +#define AR_CHANNELS_MAX 5 /* # of Channel calibration groups */ +#define AR_TP_SETTINGS_SIZE 11 /* # locations/Channel group */ +#define AR_TP_SCALING_ENTRIES 11 /* # entries in transmit power dBm->pcdac */ + +/* + * NB: we store the rfsilent select+polarity data packed + * with the encoding used in later parts so values + * returned to applications are consistent. + */ +#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c +#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 +#define AR_EEPROM_RFSILENT_POLARITY 0x0002 +#define AR_EEPROM_RFSILENT_POLARITY_S 1 + +#define AR_I2DBM(x) ((uint8_t)((x * 2) + 3)) + +/* + * Transmit power and channel calibration settings. + */ +struct tpcMap { + uint8_t pcdac[AR_TP_SCALING_ENTRIES]; + uint8_t gainF[AR_TP_SCALING_ENTRIES]; + uint8_t rate36; + uint8_t rate48; + uint8_t rate54; + uint8_t regdmn[AR_REG_DOMAINS_MAX]; +}; + +/* + * Information retrieved from EEPROM. + */ +typedef struct { + uint16_t ee_version; /* Version field */ + uint16_t ee_protect; /* EEPROM protect field */ + uint16_t ee_antenna; /* Antenna Settings */ + uint16_t ee_biasCurrents; /* OB, DB */ + uint8_t ee_thresh62; /* thresh62 */ + uint8_t ee_xlnaOn; /* External LNA timing */ + uint8_t ee_xpaOff; /* Extern output stage timing */ + uint8_t ee_xpaOn; /* Extern output stage timing */ + uint8_t ee_rfKill; /* Single low bit signalling if RF Kill is implemented */ + uint8_t ee_devType; /* Type: PCI, miniPCI, CB */ + uint8_t ee_regDomain[AR_REG_DOMAINS_MAX]; + /* calibrated reg domains */ + struct tpcMap ee_tpc[AR_CHANNELS_MAX]; +} HAL_EEPROM_v1; +#endif /* _ATH_AH_EEPROM_V1_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ah_eeprom_v14.c b/sys/external/isc/atheros_hal/dist/ah_eeprom_v14.c new file mode 100644 index 0000000..37e973c --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_eeprom_v14.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_eeprom_v14.h" + +static HAL_STATUS +v14EepromGet(struct ath_hal *ah, int param, void *val) +{ +#define CHAN_A_IDX 0 +#define CHAN_B_IDX 1 +#define IS_VERS(op, v) ((pBase->version & AR5416_EEP_VER_MINOR_MASK) op (v)) + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + const MODAL_EEP_HEADER *pModal = ee->ee_base.modalHeader; + const BASE_EEP_HEADER *pBase = &ee->ee_base.baseEepHeader; + uint32_t sum; + uint8_t *macaddr; + int i; + + switch (param) { + case AR_EEP_NFTHRESH_5: + *(int16_t *)val = pModal[0].noiseFloorThreshCh[0]; + return HAL_OK; + case AR_EEP_NFTHRESH_2: + *(int16_t *)val = pModal[1].noiseFloorThreshCh[0]; + return HAL_OK; + case AR_EEP_MACADDR: /* Get MAC Address */ + sum = 0; + macaddr = val; + for (i = 0; i < 6; i++) { + macaddr[i] = pBase->macAddr[i]; + sum += pBase->macAddr[i]; + } + if (sum == 0 || sum == 0xffff*3) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad mac address %s\n", + __func__, ath_hal_ether_sprintf(macaddr)); + return HAL_EEBADMAC; + } + return HAL_OK; + case AR_EEP_REGDMN_0: + return pBase->regDmn[0]; + case AR_EEP_REGDMN_1: + return pBase->regDmn[1]; + case AR_EEP_OPCAP: + return pBase->deviceCap; + case AR_EEP_OPMODE: + return pBase->opCapFlags; + case AR_EEP_RFSILENT: + return pBase->rfSilent; + case AR_EEP_OB_5: + return pModal[CHAN_A_IDX].ob; + case AR_EEP_DB_5: + return pModal[CHAN_A_IDX].db; + case AR_EEP_OB_2: + return pModal[CHAN_B_IDX].ob; + case AR_EEP_DB_2: + return pModal[CHAN_B_IDX].db; + case AR_EEP_TXMASK: + return pBase->txMask; + case AR_EEP_RXMASK: + return pBase->rxMask; + case AR_EEP_RXGAIN_TYPE: + return IS_VERS(>=, AR5416_EEP_MINOR_VER_17) ? + pBase->rxGainType : AR5416_EEP_RXGAIN_ORIG; + case AR_EEP_TXGAIN_TYPE: + return IS_VERS(>=, AR5416_EEP_MINOR_VER_19) ? + pBase->txGainType : AR5416_EEP_TXGAIN_ORIG; + case AR_EEP_FSTCLK_5G: + /* 5ghz fastclock is always enabled for Merlin minor <= 16 */ + if (IS_VERS(<=, AR5416_EEP_MINOR_VER_16)) + return HAL_OK; + return pBase->fastClk5g ? HAL_OK : HAL_EIO; + case AR_EEP_OL_PWRCTRL: + HALASSERT(val == AH_NULL); + return pBase->openLoopPwrCntl ? HAL_OK : HAL_EIO; + case AR_EEP_DAC_HPWR_5G: + if (IS_VERS(>=, AR5416_EEP_MINOR_VER_20)) { + *(uint8_t *) val = pBase->dacHiPwrMode_5G; + return HAL_OK; + } else + return HAL_EIO; + case AR_EEP_FRAC_N_5G: + if (IS_VERS(>=, AR5416_EEP_MINOR_VER_22)) { + *(uint8_t *) val = pBase->frac_n_5g; + } else + *(uint8_t *) val = 0; + return HAL_OK; + case AR_EEP_AMODE: + HALASSERT(val == AH_NULL); + return pBase->opCapFlags & AR5416_OPFLAGS_11A ? + HAL_OK : HAL_EIO; + case AR_EEP_BMODE: + case AR_EEP_GMODE: + HALASSERT(val == AH_NULL); + return pBase->opCapFlags & AR5416_OPFLAGS_11G ? + HAL_OK : HAL_EIO; + case AR_EEP_32KHZCRYSTAL: + case AR_EEP_COMPRESS: + case AR_EEP_FASTFRAME: /* XXX policy decision, h/w can do it */ + case AR_EEP_WRITEPROTECT: /* NB: no write protect bit */ + HALASSERT(val == AH_NULL); + /* fall thru... */ + case AR_EEP_MAXQCU: /* NB: not in opCapFlags */ + case AR_EEP_KCENTRIES: /* NB: not in opCapFlags */ + return HAL_EIO; + case AR_EEP_AES: + case AR_EEP_BURST: + case AR_EEP_RFKILL: + case AR_EEP_TURBO5DISABLE: + case AR_EEP_TURBO2DISABLE: + HALASSERT(val == AH_NULL); + return HAL_OK; + case AR_EEP_ANTGAINMAX_2: + *(int8_t *) val = ee->ee_antennaGainMax[1]; + return HAL_OK; + case AR_EEP_ANTGAINMAX_5: + *(int8_t *) val = ee->ee_antennaGainMax[0]; + return HAL_OK; + case AR_EEP_PWR_TABLE_OFFSET: + if (IS_VERS(>=, AR5416_EEP_MINOR_VER_21)) + *(int8_t *) val = pBase->pwr_table_offset; + else + *(int8_t *) val = AR5416_PWR_TABLE_OFFSET_DB; + return HAL_OK; + case AR_EEP_PWDCLKIND: + if (IS_VERS(>=, AR5416_EEP_MINOR_VER_10)) { + *(uint8_t *) val = pBase->pwdclkind; + return HAL_OK; + } + return HAL_EIO; + + default: + HALASSERT(0); + return HAL_EINVAL; + } +#undef IS_VERS +#undef CHAN_A_IDX +#undef CHAN_B_IDX +} + +static HAL_STATUS +v14EepromSet(struct ath_hal *ah, int param, int v) +{ + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (param) { + case AR_EEP_ANTGAINMAX_2: + ee->ee_antennaGainMax[1] = (int8_t) v; + return HAL_OK; + case AR_EEP_ANTGAINMAX_5: + ee->ee_antennaGainMax[0] = (int8_t) v; + return HAL_OK; + } + return HAL_EINVAL; +} + +static HAL_BOOL +v14EepromDiag(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, void **result, uint32_t *resultsize) +{ + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (request) { + case HAL_DIAG_EEPROM: + *result = ee; + *resultsize = sizeof(HAL_EEPROM_v14); + return AH_TRUE; + } + return AH_FALSE; +} + +/* Do structure specific swaps if Eeprom format is non native to host */ +static void +eepromSwap(struct ar5416eeprom *ee) +{ + uint32_t integer, i, j; + uint16_t word; + MODAL_EEP_HEADER *pModal; + + /* convert Base Eep header */ + word = __bswap16(ee->baseEepHeader.length); + ee->baseEepHeader.length = word; + + word = __bswap16(ee->baseEepHeader.checksum); + ee->baseEepHeader.checksum = word; + + word = __bswap16(ee->baseEepHeader.version); + ee->baseEepHeader.version = word; + + word = __bswap16(ee->baseEepHeader.regDmn[0]); + ee->baseEepHeader.regDmn[0] = word; + + word = __bswap16(ee->baseEepHeader.regDmn[1]); + ee->baseEepHeader.regDmn[1] = word; + + word = __bswap16(ee->baseEepHeader.rfSilent); + ee->baseEepHeader.rfSilent = word; + + word = __bswap16(ee->baseEepHeader.blueToothOptions); + ee->baseEepHeader.blueToothOptions = word; + + word = __bswap16(ee->baseEepHeader.deviceCap); + ee->baseEepHeader.deviceCap = word; + + /* convert Modal Eep header */ + for (j = 0; j < 2; j++) { + pModal = &ee->modalHeader[j]; + + /* XXX linux/ah_osdep.h only defines __bswap32 for BE */ + integer = __bswap32(pModal->antCtrlCommon); + pModal->antCtrlCommon = integer; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + integer = __bswap32(pModal->antCtrlChain[i]); + pModal->antCtrlChain[i] = integer; + } + for (i = 0; i < 3; i++) { + word = __bswap16(pModal->xpaBiasLvlFreq[i]); + pModal->xpaBiasLvlFreq[i] = word; + } + for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { + word = __bswap16(pModal->spurChans[i].spurChan); + pModal->spurChans[i].spurChan = word; + } + } +} + +static uint16_t +v14EepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) +{ + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + + HALASSERT(0 <= ix && ix < AR5416_EEPROM_MODAL_SPURS); + return ee->ee_base.modalHeader[is2GHz].spurChans[ix].spurChan; +} + +/************************************************************************** + * fbin2freq + * + * Get channel value from binary representation held in eeprom + * RETURNS: the frequency in MHz + */ +static uint16_t +fbin2freq(uint8_t fbin, HAL_BOOL is2GHz) +{ + /* + * Reserved value 0xFF provides an empty definition both as + * an fbin and as a frequency - do not convert + */ + if (fbin == AR5416_BCHAN_UNUSED) + return fbin; + return (uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); +} + +/* + * Copy EEPROM Conformance Testing Limits contents + * into the allocated space + */ +/* USE CTLS from chain zero */ +#define CTL_CHAIN 0 + +static void +v14EepromReadCTLInfo(struct ath_hal *ah, HAL_EEPROM_v14 *ee) +{ + RD_EDGES_POWER *rep = ee->ee_rdEdgesPower; + int i, j; + + HALASSERT(AR5416_NUM_CTLS <= sizeof(ee->ee_rdEdgesPower)/NUM_EDGES); + + for (i = 0; ee->ee_base.ctlIndex[i] != 0 && i < AR5416_NUM_CTLS; i++) { + for (j = 0; j < NUM_EDGES; j ++) { + /* XXX Confirm this is the right thing to do when an invalid channel is stored */ + if (ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].bChannel == AR5416_BCHAN_UNUSED) { + rep[j].rdEdge = 0; + rep[j].twice_rdEdgePower = 0; + rep[j].flag = 0; + } else { + rep[j].rdEdge = fbin2freq( + ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].bChannel, + (ee->ee_base.ctlIndex[i] & CTL_MODE_M) != CTL_11A); + rep[j].twice_rdEdgePower = MS(ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].tPowerFlag, CAL_CTL_EDGES_POWER); + rep[j].flag = MS(ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].tPowerFlag, CAL_CTL_EDGES_FLAG) != 0; + } + } + rep += NUM_EDGES; + } + ee->ee_numCtls = i; + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "%s Numctls = %u\n",__func__,i); +} + +/* + * Reclaim any EEPROM-related storage. + */ +static void +v14EepromDetach(struct ath_hal *ah) +{ + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + + ath_hal_free(ee); + AH_PRIVATE(ah)->ah_eeprom = AH_NULL; +} + +#define owl_get_eep_ver(_ee) \ + (((_ee)->ee_base.baseEepHeader.version >> 12) & 0xF) +#define owl_get_eep_rev(_ee) \ + (((_ee)->ee_base.baseEepHeader.version) & 0xFFF) + +/* + * Howl is (hopefully) a special case where the endian-ness of the EEPROM + * matches the native endian-ness; and that supplied EEPROMs don't have + * a magic value to check. + */ +HAL_STATUS +ath_hal_v14EepromAttach(struct ath_hal *ah) +{ +#define NW(a) (sizeof(a) / sizeof(uint16_t)) + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t *eep_data, magic; + HAL_BOOL need_swap; + u_int w, off, len; + uint32_t sum; + + HALASSERT(ee == AH_NULL); + + /* + * Don't check magic if we're supplied with an EEPROM block, + * typically this is from Howl but it may also be from later + * boards w/ an embedded Merlin. + */ + if (ah->ah_eepromdata == NULL) { + if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s Error reading Eeprom MAGIC\n", __func__); + return HAL_EEREAD; + } + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s Eeprom Magic = 0x%x\n", + __func__, magic); + if (magic != AR5416_EEPROM_MAGIC) { + HALDEBUG(ah, HAL_DEBUG_ANY, "Bad magic number\n"); + return HAL_EEMAGIC; + } + } + + ee = ath_hal_malloc(sizeof(HAL_EEPROM_v14)); + if (ee == AH_NULL) { + /* XXX message */ + return HAL_ENOMEM; + } + + eep_data = (uint16_t *)&ee->ee_base; + for (w = 0; w < NW(struct ar5416eeprom); w++) { + off = owl_eep_start_loc + w; /* NB: AP71 starts at 0 */ + if (!ath_hal_eepromRead(ah, off, &eep_data[w])) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s eeprom read error at offset 0x%x\n", + __func__, off); + return HAL_EEREAD; + } + } + /* Convert to eeprom native eeprom endian format */ + /* XXX this is likely incorrect but will do for now to get howl/ap83 working. */ + if (ah->ah_eepromdata == NULL && isBigEndian()) { + for (w = 0; w < NW(struct ar5416eeprom); w++) + eep_data[w] = __bswap16(eep_data[w]); + } + + /* + * At this point, we're in the native eeprom endian format + * Now, determine the eeprom endian by looking at byte 26?? + */ + need_swap = ((ee->ee_base.baseEepHeader.eepMisc & AR5416_EEPMISC_BIG_ENDIAN) != 0) ^ isBigEndian(); + if (need_swap) { + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "Byte swap EEPROM contents.\n"); + len = __bswap16(ee->ee_base.baseEepHeader.length); + } else { + len = ee->ee_base.baseEepHeader.length; + } + len = AH_MIN(len, sizeof(struct ar5416eeprom)) / sizeof(uint16_t); + + /* Apply the checksum, done in native eeprom format */ + /* XXX - Need to check to make sure checksum calculation is done + * in the correct endian format. Right now, it seems it would + * cast the raw data to host format and do the calculation, which may + * not be correct as the calculation may need to be done in the native + * eeprom format + */ + sum = 0; + for (w = 0; w < len; w++) + sum ^= eep_data[w]; + /* Check CRC - Attach should fail on a bad checksum */ + if (sum != 0xffff) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "Bad EEPROM checksum 0x%x (Len=%u)\n", sum, len); + return HAL_EEBADSUM; + } + + if (need_swap) + eepromSwap(&ee->ee_base); /* byte swap multi-byte data */ + + /* swap words 0+2 so version is at the front */ + magic = eep_data[0]; + eep_data[0] = eep_data[2]; + eep_data[2] = magic; + + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "%s Eeprom Version %u.%u\n", __func__, + owl_get_eep_ver(ee), owl_get_eep_rev(ee)); + + /* NB: must be after all byte swapping */ + if (owl_get_eep_ver(ee) != AR5416_EEP_VER) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "Bad EEPROM version 0x%x\n", owl_get_eep_ver(ee)); + return HAL_EEBADSUM; + } + + v14EepromReadCTLInfo(ah, ee); /* Get CTLs */ + + AH_PRIVATE(ah)->ah_eeprom = ee; + AH_PRIVATE(ah)->ah_eeversion = ee->ee_base.baseEepHeader.version; + AH_PRIVATE(ah)->ah_eepromDetach = v14EepromDetach; + AH_PRIVATE(ah)->ah_eepromGet = v14EepromGet; + AH_PRIVATE(ah)->ah_eepromSet = v14EepromSet; + AH_PRIVATE(ah)->ah_getSpurChan = v14EepromGetSpurChan; + AH_PRIVATE(ah)->ah_eepromDiag = v14EepromDiag; + return HAL_OK; +#undef NW +} diff --git a/sys/external/isc/atheros_hal/dist/ah_eeprom_v14.h b/sys/external/isc/atheros_hal/dist/ah_eeprom_v14.h new file mode 100644 index 0000000..7b2c898 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_eeprom_v14.h @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _AH_EEPROM_V14_H_ +#define _AH_EEPROM_V14_H_ + +#include "ah_eeprom.h" + +/* reg_off = 4 * (eep_off) */ +#define AR5416_EEPROM_S 2 +#define AR5416_EEPROM_OFFSET 0x2000 +#define AR5416_EEPROM_START_ADDR 0x503f1200 +#define AR5416_EEPROM_MAX 0xae0 /* Ignore for the moment used only on the flash implementations */ +#define AR5416_EEPROM_MAGIC 0xa55a +#define AR5416_EEPROM_MAGIC_OFFSET 0x0 + +#define owl_get_ntxchains(_txchainmask) \ + (((_txchainmask >> 2) & 1) + ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) + +#ifdef __LINUX_ARM_ARCH__ /* AP71 */ +#define owl_eep_start_loc 0 +#else +#define owl_eep_start_loc 256 +#endif + +/* End temp defines */ + +#define AR5416_EEP_NO_BACK_VER 0x1 +#define AR5416_EEP_VER 0xE +#define AR5416_EEP_VER_MINOR_MASK 0xFFF +// Adds modal params txFrameToPaOn, txFrametoDataStart, ht40PowerInc +#define AR5416_EEP_MINOR_VER_2 0x2 +// Adds modal params bswAtten, bswMargin, swSettle and base OpFlags for HT20/40 Disable +#define AR5416_EEP_MINOR_VER_3 0x3 +#define AR5416_EEP_MINOR_VER_7 0x7 +#define AR5416_EEP_MINOR_VER_9 0x9 +#define AR5416_EEP_MINOR_VER_10 0xa +#define AR5416_EEP_MINOR_VER_16 0x10 +#define AR5416_EEP_MINOR_VER_17 0x11 +#define AR5416_EEP_MINOR_VER_19 0x13 +#define AR5416_EEP_MINOR_VER_20 0x14 +#define AR5416_EEP_MINOR_VER_21 0x15 +#define AR5416_EEP_MINOR_VER_22 0x16 + +// 16-bit offset location start of calibration struct +#define AR5416_EEP_START_LOC 256 +#define AR5416_NUM_5G_CAL_PIERS 8 +#define AR5416_NUM_2G_CAL_PIERS 4 +#define AR5416_NUM_5G_20_TARGET_POWERS 8 +#define AR5416_NUM_5G_40_TARGET_POWERS 8 +#define AR5416_NUM_2G_CCK_TARGET_POWERS 3 +#define AR5416_NUM_2G_20_TARGET_POWERS 4 +#define AR5416_NUM_2G_40_TARGET_POWERS 4 +#define AR5416_NUM_CTLS 24 +#define AR5416_NUM_BAND_EDGES 8 +#define AR5416_NUM_PD_GAINS 4 +#define AR5416_PD_GAINS_IN_MASK 4 +#define AR5416_PD_GAIN_ICEPTS 5 +#define AR5416_EEPROM_MODAL_SPURS 5 +#define AR5416_MAX_RATE_POWER 63 +#define AR5416_NUM_PDADC_VALUES 128 +#define AR5416_NUM_RATES 16 +#define AR5416_BCHAN_UNUSED 0xFF +#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 +#define AR5416_EEPMISC_BIG_ENDIAN 0x01 +#define FREQ2FBIN(x,y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) +#define AR5416_MAX_CHAINS 3 +#define AR5416_PWR_TABLE_OFFSET_DB -5 +#define AR5416_ANT_16S 25 + +#define AR5416_NUM_ANT_CHAIN_FIELDS 7 +#define AR5416_NUM_ANT_COMMON_FIELDS 4 +#define AR5416_SIZE_ANT_CHAIN_FIELD 3 +#define AR5416_SIZE_ANT_COMMON_FIELD 4 +#define AR5416_ANT_CHAIN_MASK 0x7 +#define AR5416_ANT_COMMON_MASK 0xf +#define AR5416_CHAIN_0_IDX 0 +#define AR5416_CHAIN_1_IDX 1 +#define AR5416_CHAIN_2_IDX 2 + +#define AR5416_OPFLAGS_11A 0x01 +#define AR5416_OPFLAGS_11G 0x02 +#define AR5416_OPFLAGS_N_5G_HT40 0x04 /* If set, disable 5G HT40 */ +#define AR5416_OPFLAGS_N_2G_HT40 0x08 +#define AR5416_OPFLAGS_N_5G_HT20 0x10 +#define AR5416_OPFLAGS_N_2G_HT20 0x20 + +/* RF silent fields in EEPROM */ +#define EEP_RFSILENT_ENABLED 0x0001 /* enabled/disabled */ +#define EEP_RFSILENT_ENABLED_S 0 +#define EEP_RFSILENT_POLARITY 0x0002 /* polarity */ +#define EEP_RFSILENT_POLARITY_S 1 +#define EEP_RFSILENT_GPIO_SEL 0x001c /* gpio PIN */ +#define EEP_RFSILENT_GPIO_SEL_S 2 + +/* Rx gain type values */ +#define AR5416_EEP_RXGAIN_23dB_BACKOFF 0 +#define AR5416_EEP_RXGAIN_13dB_BACKOFF 1 +#define AR5416_EEP_RXGAIN_ORIG 2 + +/* Tx gain type values */ +#define AR5416_EEP_TXGAIN_ORIG 0 +#define AR5416_EEP_TXGAIN_HIGH_POWER 1 + +typedef struct spurChanStruct { + uint16_t spurChan; + uint8_t spurRangeLow; + uint8_t spurRangeHigh; +} __packed SPUR_CHAN; + +typedef struct CalTargetPowerLegacy { + uint8_t bChannel; + uint8_t tPow2x[4]; +} __packed CAL_TARGET_POWER_LEG; + +typedef struct CalTargetPowerHt { + uint8_t bChannel; + uint8_t tPow2x[8]; +} __packed CAL_TARGET_POWER_HT; + +typedef struct CalCtlEdges { + uint8_t bChannel; + uint8_t tPowerFlag; /* [0..5] tPower [6..7] flag */ +#define CAL_CTL_EDGES_POWER 0x3f +#define CAL_CTL_EDGES_POWER_S 0 +#define CAL_CTL_EDGES_FLAG 0xc0 +#define CAL_CTL_EDGES_FLAG_S 6 +} __packed CAL_CTL_EDGES; + +/* + * These are the secondary regulatory domain flags + * for regDmn[1]. + */ +#define AR5416_REGDMN_EN_FCC_MID 0x01 /* 5.47 - 5.7GHz operation */ +#define AR5416_REGDMN_EN_JAP_MID 0x02 /* 5.47 - 5.7GHz operation */ +#define AR5416_REGDMN_EN_FCC_DFS_HT40 0x04 /* FCC HT40 + DFS operation */ +#define AR5416_REGDMN_EN_JAP_HT40 0x08 /* JP HT40 operation */ +#define AR5416_REGDMN_EN_JAP_DFS_HT40 0x10 /* JP HT40 + DFS operation */ + +/* + * NB: The format in EEPROM has words 0 and 2 swapped (i.e. version + * and length are swapped). We reverse their position after reading + * the data into host memory so the version field is at the same + * offset as in previous EEPROM layouts. This makes utilities that + * inspect the EEPROM contents work without looking at the PCI device + * id which may or may not be reliable. + */ +typedef struct BaseEepHeader { + uint16_t version; /* NB: length in EEPROM */ + uint16_t checksum; + uint16_t length; /* NB: version in EEPROM */ + uint8_t opCapFlags; + uint8_t eepMisc; + uint16_t regDmn[2]; + uint8_t macAddr[6]; + uint8_t rxMask; + uint8_t txMask; + uint16_t rfSilent; + uint16_t blueToothOptions; + uint16_t deviceCap; + uint32_t binBuildNumber; + uint8_t deviceType; + uint8_t pwdclkind; + uint8_t fastClk5g; + uint8_t divChain; + uint8_t rxGainType; + uint8_t dacHiPwrMode_5G;/* use the DAC high power mode (MB91) */ + uint8_t openLoopPwrCntl;/* 1: use open loop power control, + 0: use closed loop power control */ + uint8_t dacLpMode; + uint8_t txGainType; /* high power tx gain table support */ + uint8_t rcChainMask; /* "1" if the card is an HB93 1x2 */ + uint8_t desiredScaleCCK; + uint8_t pwr_table_offset; + uint8_t frac_n_5g; /* + * bit 0: indicates that fracN synth + * mode applies to all 5G channels + */ + uint8_t futureBase[21]; +} __packed BASE_EEP_HEADER; // 64 B + +typedef struct ModalEepHeader { + uint32_t antCtrlChain[AR5416_MAX_CHAINS]; // 12 + uint32_t antCtrlCommon; // 4 + int8_t antennaGainCh[AR5416_MAX_CHAINS]; // 3 + uint8_t switchSettling; // 1 + uint8_t txRxAttenCh[AR5416_MAX_CHAINS]; // 3 + uint8_t rxTxMarginCh[AR5416_MAX_CHAINS]; // 3 + uint8_t adcDesiredSize; // 1 + int8_t pgaDesiredSize; // 1 + uint8_t xlnaGainCh[AR5416_MAX_CHAINS]; // 3 + uint8_t txEndToXpaOff; // 1 + uint8_t txEndToRxOn; // 1 + uint8_t txFrameToXpaOn; // 1 + uint8_t thresh62; // 1 + uint8_t noiseFloorThreshCh[AR5416_MAX_CHAINS]; // 3 + uint8_t xpdGain; // 1 + uint8_t xpd; // 1 + int8_t iqCalICh[AR5416_MAX_CHAINS]; // 1 + int8_t iqCalQCh[AR5416_MAX_CHAINS]; // 1 + uint8_t pdGainOverlap; // 1 + uint8_t ob; // 1 + uint8_t db; // 1 + uint8_t xpaBiasLvl; // 1 + uint8_t pwrDecreaseFor2Chain; // 1 + uint8_t pwrDecreaseFor3Chain; // 1 -> 48 B + uint8_t txFrameToDataStart; // 1 + uint8_t txFrameToPaOn; // 1 + uint8_t ht40PowerIncForPdadc; // 1 + uint8_t bswAtten[AR5416_MAX_CHAINS]; // 3 + uint8_t bswMargin[AR5416_MAX_CHAINS]; // 3 + uint8_t swSettleHt40; // 1 + uint8_t xatten2Db[AR5416_MAX_CHAINS]; // 3 -> New for AR9280 (0xa20c/b20c 11:6) + uint8_t xatten2Margin[AR5416_MAX_CHAINS]; // 3 -> New for AR9280 (0xa20c/b20c 21:17) + uint8_t ob_ch1; // 1 -> ob and db become chain specific from AR9280 + uint8_t db_ch1; // 1 + uint8_t flagBits; // 1 +#define AR5416_EEP_FLAG_USEANT1 0x80 /* +1 configured antenna */ +#define AR5416_EEP_FLAG_FORCEXPAON 0x40 /* force XPA bit for 5G */ +#define AR5416_EEP_FLAG_LOCALBIAS 0x20 /* enable local bias */ +#define AR5416_EEP_FLAG_FEMBANDSELECT 0x10 /* FEM band select used */ +#define AR5416_EEP_FLAG_XLNABUFIN 0x08 +#define AR5416_EEP_FLAG_XLNAISEL1 0x04 +#define AR5416_EEP_FLAG_XLNAISEL2 0x02 +#define AR5416_EEP_FLAG_XLNABUFMODE 0x01 + uint8_t miscBits; // [0..1]: bb_tx_dac_scale_cck + uint16_t xpaBiasLvlFreq[3]; // 3 + uint8_t futureModal[6]; // 6 + + SPUR_CHAN spurChans[AR5416_EEPROM_MODAL_SPURS]; // 20 B +} __packed MODAL_EEP_HEADER; // == 100 B + +typedef struct calDataPerFreqOpLoop { + uint8_t pwrPdg[2][5]; /* power measurement */ + uint8_t vpdPdg[2][5]; /* pdadc voltage at power measurement */ + uint8_t pcdac[2][5]; /* pcdac used for power measurement */ + uint8_t empty[2][5]; /* future use */ +} __packed CAL_DATA_PER_FREQ_OP_LOOP; + +typedef struct CalCtlData { + CAL_CTL_EDGES ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; +} __packed CAL_CTL_DATA; + +typedef struct calDataPerFreq { + uint8_t pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; + uint8_t vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; +} __packed CAL_DATA_PER_FREQ; + +struct ar5416eeprom { + BASE_EEP_HEADER baseEepHeader; // 64 B + uint8_t custData[64]; // 64 B + MODAL_EEP_HEADER modalHeader[2]; // 200 B + uint8_t calFreqPier5G[AR5416_NUM_5G_CAL_PIERS]; + uint8_t calFreqPier2G[AR5416_NUM_2G_CAL_PIERS]; + CAL_DATA_PER_FREQ calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS]; + CAL_DATA_PER_FREQ calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; + CAL_TARGET_POWER_LEG calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS]; + CAL_TARGET_POWER_LEG calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS]; + CAL_TARGET_POWER_LEG calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS]; + uint8_t ctlIndex[AR5416_NUM_CTLS]; + CAL_CTL_DATA ctlData[AR5416_NUM_CTLS]; + uint8_t padding; +} __packed; + +typedef struct { + struct ar5416eeprom ee_base; +#define NUM_EDGES 8 + uint16_t ee_numCtls; + RD_EDGES_POWER ee_rdEdgesPower[NUM_EDGES*AR5416_NUM_CTLS]; + /* XXX these are dynamically calculated for use by shared code */ + int8_t ee_antennaGainMax[2]; +} HAL_EEPROM_v14; +#endif /* _AH_EEPROM_V14_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ah_eeprom_v3.c b/sys/external/isc/atheros_hal/dist/ah_eeprom_v3.c new file mode 100644 index 0000000..3a7b0cc --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_eeprom_v3.c @@ -0,0 +1,1876 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_eeprom_v3.h" + +static void +getPcdacInterceptsFromPcdacMinMax(HAL_EEPROM *ee, + uint16_t pcdacMin, uint16_t pcdacMax, uint16_t *vp) +{ + static const uint16_t intercepts3[] = + { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; + static const uint16_t intercepts3_2[] = + { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; + const uint16_t *ip = ee->ee_version < AR_EEPROM_VER3_2 ? + intercepts3 : intercepts3_2; + int i; + + /* loop for the percentages in steps or 5 */ + for (i = 0; i < NUM_INTERCEPTS; i++ ) + *vp++ = (ip[i] * pcdacMax + (100 - ip[i]) * pcdacMin) / 100; +} + +/* + * Get channel value from binary representation held in eeprom + */ +static uint16_t +fbin2freq(HAL_EEPROM *ee, uint16_t fbin) +{ + if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */ + return fbin; + return ee->ee_version <= AR_EEPROM_VER3_2 ? + (fbin > 62 ? 5100 + 10*62 + 5*(fbin-62) : 5100 + 10*fbin) : + 4800 + 5*fbin; +} + +static uint16_t +fbin2freq_2p4(HAL_EEPROM *ee, uint16_t fbin) +{ + if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */ + return fbin; + return ee->ee_version <= AR_EEPROM_VER3_2 ? + 2400 + fbin : + 2300 + fbin; +} + +/* + * Now copy EEPROM frequency pier contents into the allocated space + */ +static HAL_BOOL +readEepromFreqPierInfo(struct ath_hal *ah, HAL_EEPROM *ee) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + uint16_t eeval, off; + int i; + + if (ee->ee_version >= AR_EEPROM_VER4_0 && + ee->ee_eepMap && !ee->ee_Amode) { + /* + * V4.0 EEPROMs with map type 1 have frequency pier + * data only when 11a mode is supported. + */ + return AH_TRUE; + } + if (ee->ee_version >= AR_EEPROM_VER3_3) { + off = GROUPS_OFFSET3_3 + GROUP1_OFFSET; + for (i = 0; i < ee->ee_numChannels11a; i += 2) { + EEREAD(off++); + ee->ee_channels11a[i] = (eeval >> 8) & FREQ_MASK_3_3; + ee->ee_channels11a[i+1] = eeval & FREQ_MASK_3_3; + } + } else { + off = GROUPS_OFFSET3_2 + GROUP1_OFFSET; + + EEREAD(off++); + ee->ee_channels11a[0] = (eeval >> 9) & FREQ_MASK; + ee->ee_channels11a[1] = (eeval >> 2) & FREQ_MASK; + ee->ee_channels11a[2] = (eeval << 5) & FREQ_MASK; + + EEREAD(off++); + ee->ee_channels11a[2] |= (eeval >> 11) & 0x1f; + ee->ee_channels11a[3] = (eeval >> 4) & FREQ_MASK; + ee->ee_channels11a[4] = (eeval << 3) & FREQ_MASK; + + EEREAD(off++); + ee->ee_channels11a[4] |= (eeval >> 13) & 0x7; + ee->ee_channels11a[5] = (eeval >> 6) & FREQ_MASK; + ee->ee_channels11a[6] = (eeval << 1) & FREQ_MASK; + + EEREAD(off++); + ee->ee_channels11a[6] |= (eeval >> 15) & 0x1; + ee->ee_channels11a[7] = (eeval >> 8) & FREQ_MASK; + ee->ee_channels11a[8] = (eeval >> 1) & FREQ_MASK; + ee->ee_channels11a[9] = (eeval << 6) & FREQ_MASK; + + EEREAD(off++); + ee->ee_channels11a[9] |= (eeval >> 10) & 0x3f; + } + + for (i = 0; i < ee->ee_numChannels11a; i++) + ee->ee_channels11a[i] = fbin2freq(ee, ee->ee_channels11a[i]); + + return AH_TRUE; +#undef EEREAD +} + +/* + * Rev 4 Eeprom 5112 Power Extract Functions + */ + +/* + * Allocate the power information based on the number of channels + * recorded by the calibration. These values are then initialized. + */ +static HAL_BOOL +eepromAllocExpnPower5112(struct ath_hal *ah, + const EEPROM_POWER_5112 *pCalDataset, + EEPROM_POWER_EXPN_5112 *pPowerExpn) +{ + uint16_t numChannels = pCalDataset->numChannels; + const uint16_t *pChanList = pCalDataset->pChannels; + void *data; + int i, j; + + /* Allocate the channel and Power Data arrays together */ + data = ath_hal_malloc( + roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)) + + sizeof(EXPN_DATA_PER_CHANNEL_5112) * numChannels); + if (data == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s unable to allocate raw data struct (gen3)\n", __func__); + return AH_FALSE; + } + pPowerExpn->pChannels = data; + pPowerExpn->pDataPerChannel = (void *)(((char *)data) + + roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t))); + + pPowerExpn->numChannels = numChannels; + for (i = 0; i < numChannels; i++) { + pPowerExpn->pChannels[i] = + pPowerExpn->pDataPerChannel[i].channelValue = + pChanList[i]; + for (j = 0; j < NUM_XPD_PER_CHANNEL; j++) { + pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].xpd_gain = j; + pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].numPcdacs = 0; + } + pPowerExpn->pDataPerChannel[i].pDataPerXPD[0].numPcdacs = 4; + pPowerExpn->pDataPerChannel[i].pDataPerXPD[3].numPcdacs = 3; + } + return AH_TRUE; +} + +/* + * Expand the dataSet from the calibration information into the + * final power structure for 5112 + */ +static HAL_BOOL +eepromExpandPower5112(struct ath_hal *ah, + const EEPROM_POWER_5112 *pCalDataset, + EEPROM_POWER_EXPN_5112 *pPowerExpn) +{ + int ii, jj, kk; + int16_t maxPower_t4; + EXPN_DATA_PER_XPD_5112 *pExpnXPD; + /* ptr to array of info held per channel */ + const EEPROM_DATA_PER_CHANNEL_5112 *pCalCh; + uint16_t xgainList[2], xpdMask; + + pPowerExpn->xpdMask = pCalDataset->xpdMask; + + xgainList[0] = 0xDEAD; + xgainList[1] = 0xDEAD; + + kk = 0; + xpdMask = pPowerExpn->xpdMask; + for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) { + if (((xpdMask >> jj) & 1) > 0) { + if (kk > 1) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: too many xpdGains in dataset: %u\n", + __func__, kk); + return AH_FALSE; + } + xgainList[kk++] = jj; + } + } + + pPowerExpn->numChannels = pCalDataset->numChannels; + if (pPowerExpn->numChannels == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no channels\n", __func__); + return AH_FALSE; + } + + for (ii = 0; ii < pPowerExpn->numChannels; ii++) { + pCalCh = &pCalDataset->pDataPerChannel[ii]; + pPowerExpn->pDataPerChannel[ii].channelValue = + pCalCh->channelValue; + pPowerExpn->pDataPerChannel[ii].maxPower_t4 = + pCalCh->maxPower_t4; + maxPower_t4 = pPowerExpn->pDataPerChannel[ii].maxPower_t4; + + for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) + pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj].numPcdacs = 0; + if (xgainList[1] == 0xDEAD) { + jj = xgainList[0]; + pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; + pExpnXPD->numPcdacs = 4; + pExpnXPD->pcdac[0] = pCalCh->pcd1_xg0; + pExpnXPD->pcdac[1] = (uint16_t) + (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0); + pExpnXPD->pcdac[2] = (uint16_t) + (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0); + pExpnXPD->pcdac[3] = (uint16_t) + (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0); + + pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0; + pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0; + pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0; + pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0; + + } else { + pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[0]].pcdac[0] = pCalCh->pcd1_xg0; + pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[0] = 20; + pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[1] = 35; + pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[2] = 63; + + jj = xgainList[0]; + pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; + pExpnXPD->numPcdacs = 4; + pExpnXPD->pcdac[1] = (uint16_t) + (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0); + pExpnXPD->pcdac[2] = (uint16_t) + (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0); + pExpnXPD->pcdac[3] = (uint16_t) + (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0); + pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0; + pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0; + pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0; + pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0; + + jj = xgainList[1]; + pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; + pExpnXPD->numPcdacs = 3; + + pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg3; + pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg3; + pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg3; + } + } + return AH_TRUE; +} + +static HAL_BOOL +readEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + const uint16_t dbmmask = 0xff; + const uint16_t pcdac_delta_mask = 0x1f; + const uint16_t pcdac_mask = 0x3f; + const uint16_t freqmask = 0xff; + + int i, mode, numPiers; + uint32_t off; + uint16_t eeval; + uint16_t freq[NUM_11A_EEPROM_CHANNELS]; + EEPROM_POWER_5112 eePower; + + HALASSERT(ee->ee_version >= AR_EEPROM_VER4_0); + off = GROUPS_OFFSET3_3; + for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { + numPiers = 0; + switch (mode) { + case headerInfo11A: + if (!ee->ee_Amode) /* no 11a calibration data */ + continue; + while (numPiers < NUM_11A_EEPROM_CHANNELS) { + EEREAD(off++); + if ((eeval & freqmask) == 0) + break; + freq[numPiers++] = fbin2freq(ee, + eeval & freqmask); + + if (((eeval >> 8) & freqmask) == 0) + break; + freq[numPiers++] = fbin2freq(ee, + (eeval>>8) & freqmask); + } + break; + case headerInfo11B: + if (!ee->ee_Bmode) /* no 11b calibration data */ + continue; + for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) + if (ee->ee_calPier11b[i] != CHANNEL_UNUSED) + freq[numPiers++] = ee->ee_calPier11b[i]; + break; + case headerInfo11G: + if (!ee->ee_Gmode) /* no 11g calibration data */ + continue; + for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) + if (ee->ee_calPier11g[i] != CHANNEL_UNUSED) + freq[numPiers++] = ee->ee_calPier11g[i]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", + __func__, mode); + return AH_FALSE; + } + + OS_MEMZERO(&eePower, sizeof(eePower)); + eePower.numChannels = numPiers; + + for (i = 0; i < numPiers; i++) { + eePower.pChannels[i] = freq[i]; + eePower.pDataPerChannel[i].channelValue = freq[i]; + + EEREAD(off++); + eePower.pDataPerChannel[i].pwr1_xg0 = (int16_t) + ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); + eePower.pDataPerChannel[i].pwr2_xg0 = (int16_t) + (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); + + EEREAD(off++); + eePower.pDataPerChannel[i].pwr3_xg0 = (int16_t) + ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); + eePower.pDataPerChannel[i].pwr4_xg0 = (int16_t) + (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); + + EEREAD(off++); + eePower.pDataPerChannel[i].pcd2_delta_xg0 = (uint16_t) + (eeval & pcdac_delta_mask); + eePower.pDataPerChannel[i].pcd3_delta_xg0 = (uint16_t) + ((eeval >> 5) & pcdac_delta_mask); + eePower.pDataPerChannel[i].pcd4_delta_xg0 = (uint16_t) + ((eeval >> 10) & pcdac_delta_mask); + + EEREAD(off++); + eePower.pDataPerChannel[i].pwr1_xg3 = (int16_t) + ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); + eePower.pDataPerChannel[i].pwr2_xg3 = (int16_t) + (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); + + EEREAD(off++); + eePower.pDataPerChannel[i].pwr3_xg3 = (int16_t) + ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); + if (ee->ee_version >= AR_EEPROM_VER4_3) { + eePower.pDataPerChannel[i].maxPower_t4 = + eePower.pDataPerChannel[i].pwr4_xg0; + eePower.pDataPerChannel[i].pcd1_xg0 = (uint16_t) + ((eeval >> 8) & pcdac_mask); + } else { + eePower.pDataPerChannel[i].maxPower_t4 = (int16_t) + (((eeval >> 8) & dbmmask) - + ((eeval >> 15) & 0x1)*256); + eePower.pDataPerChannel[i].pcd1_xg0 = 1; + } + } + eePower.xpdMask = ee->ee_xgain[mode]; + + if (!eepromAllocExpnPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: did not allocate power struct\n", __func__); + return AH_FALSE; + } + if (!eepromExpandPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: did not expand power struct\n", __func__); + return AH_FALSE; + } + } + return AH_TRUE; +#undef EEREAD +} + +static void +freeEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee) +{ + int mode; + void *data; + + for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { + EEPROM_POWER_EXPN_5112 *pPowerExpn = + &ee->ee_modePowerArray5112[mode]; + data = pPowerExpn->pChannels; + if (data != AH_NULL) { + pPowerExpn->pChannels = AH_NULL; + ath_hal_free(data); + } + } +} + +static void +ar2413SetupEEPROMDataset(EEPROM_DATA_STRUCT_2413 *pEEPROMDataset2413, + uint16_t myNumRawChannels, uint16_t *pMyRawChanList) +{ + uint16_t i, channelValue; + uint32_t xpd_mask; + uint16_t numPdGainsUsed; + + pEEPROMDataset2413->numChannels = myNumRawChannels; + + xpd_mask = pEEPROMDataset2413->xpd_mask; + numPdGainsUsed = 0; + if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++; + if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++; + if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++; + if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++; + + for (i = 0; i < myNumRawChannels; i++) { + channelValue = pMyRawChanList[i]; + pEEPROMDataset2413->pChannels[i] = channelValue; + pEEPROMDataset2413->pDataPerChannel[i].channelValue = channelValue; + pEEPROMDataset2413->pDataPerChannel[i].numPdGains = numPdGainsUsed; + } +} + +static HAL_BOOL +ar2413ReadCalDataset(struct ath_hal *ah, HAL_EEPROM *ee, + EEPROM_DATA_STRUCT_2413 *pCalDataset, + uint32_t start_offset, uint32_t maxPiers, uint8_t mode) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + const uint16_t dbm_I_mask = 0x1F; /* 5-bits. 1dB step. */ + const uint16_t dbm_delta_mask = 0xF; /* 4-bits. 0.5dB step. */ + const uint16_t Vpd_I_mask = 0x7F; /* 7-bits. 0-128 */ + const uint16_t Vpd_delta_mask = 0x3F; /* 6-bits. 0-63 */ + const uint16_t freqmask = 0xff; + + uint16_t ii, eeval; + uint16_t idx, numPiers; + uint16_t freq[NUM_11A_EEPROM_CHANNELS]; + + idx = start_offset; + for (numPiers = 0; numPiers < maxPiers;) { + EEREAD(idx++); + if ((eeval & freqmask) == 0) + break; + if (mode == headerInfo11A) + freq[numPiers++] = fbin2freq(ee, (eeval & freqmask)); + else + freq[numPiers++] = fbin2freq_2p4(ee, (eeval & freqmask)); + + if (((eeval >> 8) & freqmask) == 0) + break; + if (mode == headerInfo11A) + freq[numPiers++] = fbin2freq(ee, (eeval >> 8) & freqmask); + else + freq[numPiers++] = fbin2freq_2p4(ee, (eeval >> 8) & freqmask); + } + ar2413SetupEEPROMDataset(pCalDataset, numPiers, &freq[0]); + + idx = start_offset + (maxPiers / 2); + for (ii = 0; ii < pCalDataset->numChannels; ii++) { + EEPROM_DATA_PER_CHANNEL_2413 *currCh = + &(pCalDataset->pDataPerChannel[ii]); + + if (currCh->numPdGains > 0) { + /* + * Read the first NUM_POINTS_OTHER_PDGAINS pwr + * and Vpd values for pdgain_0 + */ + EEREAD(idx++); + currCh->pwr_I[0] = eeval & dbm_I_mask; + currCh->Vpd_I[0] = (eeval >> 5) & Vpd_I_mask; + currCh->pwr_delta_t2[0][0] = + (eeval >> 12) & dbm_delta_mask; + + EEREAD(idx++); + currCh->Vpd_delta[0][0] = eeval & Vpd_delta_mask; + currCh->pwr_delta_t2[1][0] = + (eeval >> 6) & dbm_delta_mask; + currCh->Vpd_delta[1][0] = + (eeval >> 10) & Vpd_delta_mask; + + EEREAD(idx++); + currCh->pwr_delta_t2[2][0] = eeval & dbm_delta_mask; + currCh->Vpd_delta[2][0] = (eeval >> 4) & Vpd_delta_mask; + } + + if (currCh->numPdGains > 1) { + /* + * Read the first NUM_POINTS_OTHER_PDGAINS pwr + * and Vpd values for pdgain_1 + */ + currCh->pwr_I[1] = (eeval >> 10) & dbm_I_mask; + currCh->Vpd_I[1] = (eeval >> 15) & 0x1; + + EEREAD(idx++); + /* upper 6 bits */ + currCh->Vpd_I[1] |= (eeval & 0x3F) << 1; + currCh->pwr_delta_t2[0][1] = + (eeval >> 6) & dbm_delta_mask; + currCh->Vpd_delta[0][1] = + (eeval >> 10) & Vpd_delta_mask; + + EEREAD(idx++); + currCh->pwr_delta_t2[1][1] = eeval & dbm_delta_mask; + currCh->Vpd_delta[1][1] = (eeval >> 4) & Vpd_delta_mask; + currCh->pwr_delta_t2[2][1] = + (eeval >> 10) & dbm_delta_mask; + currCh->Vpd_delta[2][1] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 4 bits */ + currCh->Vpd_delta[2][1] |= (eeval & 0xF) << 2; + } else if (currCh->numPdGains == 1) { + /* + * Read the last pwr and Vpd values for pdgain_0 + */ + currCh->pwr_delta_t2[3][0] = + (eeval >> 10) & dbm_delta_mask; + currCh->Vpd_delta[3][0] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 4 bits */ + currCh->Vpd_delta[3][0] |= (eeval & 0xF) << 2; + + /* 4 words if numPdGains == 1 */ + } + + if (currCh->numPdGains > 2) { + /* + * Read the first NUM_POINTS_OTHER_PDGAINS pwr + * and Vpd values for pdgain_2 + */ + currCh->pwr_I[2] = (eeval >> 4) & dbm_I_mask; + currCh->Vpd_I[2] = (eeval >> 9) & Vpd_I_mask; + + EEREAD(idx++); + currCh->pwr_delta_t2[0][2] = + (eeval >> 0) & dbm_delta_mask; + currCh->Vpd_delta[0][2] = (eeval >> 4) & Vpd_delta_mask; + currCh->pwr_delta_t2[1][2] = + (eeval >> 10) & dbm_delta_mask; + currCh->Vpd_delta[1][2] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 4 bits */ + currCh->Vpd_delta[1][2] |= (eeval & 0xF) << 2; + currCh->pwr_delta_t2[2][2] = + (eeval >> 4) & dbm_delta_mask; + currCh->Vpd_delta[2][2] = (eeval >> 8) & Vpd_delta_mask; + } else if (currCh->numPdGains == 2) { + /* + * Read the last pwr and Vpd values for pdgain_1 + */ + currCh->pwr_delta_t2[3][1] = + (eeval >> 4) & dbm_delta_mask; + currCh->Vpd_delta[3][1] = (eeval >> 8) & Vpd_delta_mask; + + /* 6 words if numPdGains == 2 */ + } + + if (currCh->numPdGains > 3) { + /* + * Read the first NUM_POINTS_OTHER_PDGAINS pwr + * and Vpd values for pdgain_3 + */ + currCh->pwr_I[3] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 3 bits */ + currCh->pwr_I[3] |= ((eeval >> 0) & 0x7) << 2; + currCh->Vpd_I[3] = (eeval >> 3) & Vpd_I_mask; + currCh->pwr_delta_t2[0][3] = + (eeval >> 10) & dbm_delta_mask; + currCh->Vpd_delta[0][3] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 4 bits */ + currCh->Vpd_delta[0][3] |= (eeval & 0xF) << 2; + currCh->pwr_delta_t2[1][3] = + (eeval >> 4) & dbm_delta_mask; + currCh->Vpd_delta[1][3] = (eeval >> 8) & Vpd_delta_mask; + currCh->pwr_delta_t2[2][3] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 2 bits */ + currCh->pwr_delta_t2[2][3] |= ((eeval >> 0) & 0x3) << 2; + currCh->Vpd_delta[2][3] = (eeval >> 2) & Vpd_delta_mask; + currCh->pwr_delta_t2[3][3] = + (eeval >> 8) & dbm_delta_mask; + currCh->Vpd_delta[3][3] = (eeval >> 12) & 0xF; + + EEREAD(idx++); + /* upper 2 bits */ + currCh->Vpd_delta[3][3] |= ((eeval >> 0) & 0x3) << 4; + + /* 12 words if numPdGains == 4 */ + } else if (currCh->numPdGains == 3) { + /* read the last pwr and Vpd values for pdgain_2 */ + currCh->pwr_delta_t2[3][2] = (eeval >> 14) & 0x3; + + EEREAD(idx++); + /* upper 2 bits */ + currCh->pwr_delta_t2[3][2] |= ((eeval >> 0) & 0x3) << 2; + currCh->Vpd_delta[3][2] = (eeval >> 2) & Vpd_delta_mask; + + /* 9 words if numPdGains == 3 */ + } + } + return AH_TRUE; +#undef EEREAD +} + +static void +ar2413SetupRawDataset(RAW_DATA_STRUCT_2413 *pRaw, EEPROM_DATA_STRUCT_2413 *pCal) +{ + uint16_t i, j, kk, channelValue; + uint16_t xpd_mask; + uint16_t numPdGainsUsed; + + pRaw->numChannels = pCal->numChannels; + + xpd_mask = pRaw->xpd_mask; + numPdGainsUsed = 0; + if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++; + if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++; + if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++; + if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++; + + for (i = 0; i < pCal->numChannels; i++) { + channelValue = pCal->pChannels[i]; + + pRaw->pChannels[i] = channelValue; + + pRaw->pDataPerChannel[i].channelValue = channelValue; + pRaw->pDataPerChannel[i].numPdGains = numPdGainsUsed; + + kk = 0; + for (j = 0; j < MAX_NUM_PDGAINS_PER_CHANNEL; j++) { + pRaw->pDataPerChannel[i].pDataPerPDGain[j].pd_gain = j; + if ((xpd_mask >> j) & 0x1) { + pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_OTHER_PDGAINS; + kk++; + if (kk == 1) { + /* + * lowest pd_gain corresponds + * to highest power and thus, + * has one more point + */ + pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_LAST_PDGAIN; + } + } else { + pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = 0; + } + } + } +} + +static HAL_BOOL +ar2413EepromToRawDataset(struct ath_hal *ah, + EEPROM_DATA_STRUCT_2413 *pCal, RAW_DATA_STRUCT_2413 *pRaw) +{ + uint16_t ii, jj, kk, ss; + RAW_DATA_PER_PDGAIN_2413 *pRawXPD; + /* ptr to array of info held per channel */ + EEPROM_DATA_PER_CHANNEL_2413 *pCalCh; + uint16_t xgain_list[MAX_NUM_PDGAINS_PER_CHANNEL]; + uint16_t xpd_mask; + uint32_t numPdGainsUsed; + + HALASSERT(pRaw->xpd_mask == pCal->xpd_mask); + + xgain_list[0] = 0xDEAD; + xgain_list[1] = 0xDEAD; + xgain_list[2] = 0xDEAD; + xgain_list[3] = 0xDEAD; + + numPdGainsUsed = 0; + xpd_mask = pRaw->xpd_mask; + for (jj = 0; jj < MAX_NUM_PDGAINS_PER_CHANNEL; jj++) { + if ((xpd_mask >> (MAX_NUM_PDGAINS_PER_CHANNEL-jj-1)) & 1) + xgain_list[numPdGainsUsed++] = MAX_NUM_PDGAINS_PER_CHANNEL-jj-1; + } + + pRaw->numChannels = pCal->numChannels; + for (ii = 0; ii < pRaw->numChannels; ii++) { + pCalCh = &(pCal->pDataPerChannel[ii]); + pRaw->pDataPerChannel[ii].channelValue = pCalCh->channelValue; + + /* numVpd has already been setup appropriately for the relevant pdGains */ + for (jj = 0; jj < numPdGainsUsed; jj++) { + /* use jj for calDataset and ss for rawDataset */ + ss = xgain_list[jj]; + pRawXPD = &(pRaw->pDataPerChannel[ii].pDataPerPDGain[ss]); + HALASSERT(pRawXPD->numVpd >= 1); + + pRawXPD->pwr_t4[0] = (uint16_t)(4*pCalCh->pwr_I[jj]); + pRawXPD->Vpd[0] = pCalCh->Vpd_I[jj]; + + for (kk = 1; kk < pRawXPD->numVpd; kk++) { + pRawXPD->pwr_t4[kk] = (int16_t)(pRawXPD->pwr_t4[kk-1] + 2*pCalCh->pwr_delta_t2[kk-1][jj]); + pRawXPD->Vpd[kk] = (uint16_t)(pRawXPD->Vpd[kk-1] + pCalCh->Vpd_delta[kk-1][jj]); + } + /* loop over Vpds */ + } + /* loop over pd_gains */ + } + /* loop over channels */ + return AH_TRUE; +} + +static HAL_BOOL +readEepromRawPowerCalInfo2413(struct ath_hal *ah, HAL_EEPROM *ee) +{ + /* NB: index is 1 less than numPdgains */ + static const uint16_t wordsForPdgains[] = { 4, 6, 9, 12 }; + EEPROM_DATA_STRUCT_2413 *pCal = AH_NULL; + RAW_DATA_STRUCT_2413 *pRaw; + int numEEPROMWordsPerChannel; + uint32_t off; + HAL_BOOL ret = AH_FALSE; + + HALASSERT(ee->ee_version >= AR_EEPROM_VER5_0); + HALASSERT(ee->ee_eepMap == 2); + + pCal = ath_hal_malloc(sizeof(EEPROM_DATA_STRUCT_2413)); + if (pCal == AH_NULL) + goto exit; + + off = ee->ee_eepMap2PowerCalStart; + if (ee->ee_Amode) { + OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413)); + pCal->xpd_mask = ee->ee_xgain[headerInfo11A]; + if (!ar2413ReadCalDataset(ah, ee, pCal, off, + NUM_11A_EEPROM_CHANNELS_2413, headerInfo11A)) { + goto exit; + } + pRaw = &ee->ee_rawDataset2413[headerInfo11A]; + pRaw->xpd_mask = ee->ee_xgain[headerInfo11A]; + ar2413SetupRawDataset(pRaw, pCal); + if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) { + goto exit; + } + /* setup offsets for mode_11a next */ + numEEPROMWordsPerChannel = wordsForPdgains[ + pCal->pDataPerChannel[0].numPdGains - 1]; + off += pCal->numChannels * numEEPROMWordsPerChannel + 5; + } + if (ee->ee_Bmode) { + OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413)); + pCal->xpd_mask = ee->ee_xgain[headerInfo11B]; + if (!ar2413ReadCalDataset(ah, ee, pCal, off, + NUM_2_4_EEPROM_CHANNELS_2413 , headerInfo11B)) { + goto exit; + } + pRaw = &ee->ee_rawDataset2413[headerInfo11B]; + pRaw->xpd_mask = ee->ee_xgain[headerInfo11B]; + ar2413SetupRawDataset(pRaw, pCal); + if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) { + goto exit; + } + /* setup offsets for mode_11g next */ + numEEPROMWordsPerChannel = wordsForPdgains[ + pCal->pDataPerChannel[0].numPdGains - 1]; + off += pCal->numChannels * numEEPROMWordsPerChannel + 2; + } + if (ee->ee_Gmode) { + OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413)); + pCal->xpd_mask = ee->ee_xgain[headerInfo11G]; + if (!ar2413ReadCalDataset(ah, ee, pCal, off, + NUM_2_4_EEPROM_CHANNELS_2413, headerInfo11G)) { + goto exit; + } + pRaw = &ee->ee_rawDataset2413[headerInfo11G]; + pRaw->xpd_mask = ee->ee_xgain[headerInfo11G]; + ar2413SetupRawDataset(pRaw, pCal); + if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) { + goto exit; + } + } + ret = AH_TRUE; + exit: + if (pCal != AH_NULL) + ath_hal_free(pCal); + return ret; +} + +/* + * Now copy EEPROM Raw Power Calibration per frequency contents + * into the allocated space + */ +static HAL_BOOL +readEepromRawPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + uint16_t eeval, nchan; + uint32_t off; + int i, j, mode; + + if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1) + return readEepromRawPowerCalInfo5112(ah, ee); + if (ee->ee_version >= AR_EEPROM_VER5_0 && ee->ee_eepMap == 2) + return readEepromRawPowerCalInfo2413(ah, ee); + + /* + * Group 2: read raw power data for all frequency piers + * + * NOTE: Group 2 contains the raw power calibration + * information for each of the channels that + * we recorded above. + */ + for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { + uint16_t *pChannels = AH_NULL; + DATA_PER_CHANNEL *pChannelData = AH_NULL; + + off = ee->ee_version >= AR_EEPROM_VER3_3 ? + GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2; + switch (mode) { + case headerInfo11A: + off += GROUP2_OFFSET; + nchan = ee->ee_numChannels11a; + pChannelData = ee->ee_dataPerChannel11a; + pChannels = ee->ee_channels11a; + break; + case headerInfo11B: + if (!ee->ee_Bmode) + continue; + off += GROUP3_OFFSET; + nchan = ee->ee_numChannels2_4; + pChannelData = ee->ee_dataPerChannel11b; + pChannels = ee->ee_channels11b; + break; + case headerInfo11G: + if (!ee->ee_Gmode) + continue; + off += GROUP4_OFFSET; + nchan = ee->ee_numChannels2_4; + pChannelData = ee->ee_dataPerChannel11g; + pChannels = ee->ee_channels11g; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", + __func__, mode); + return AH_FALSE; + } + for (i = 0; i < nchan; i++) { + pChannelData->channelValue = pChannels[i]; + + EEREAD(off++); + pChannelData->pcdacMax = (uint16_t)((eeval >> 10) & PCDAC_MASK); + pChannelData->pcdacMin = (uint16_t)((eeval >> 4) & PCDAC_MASK); + pChannelData->PwrValues[0] = (uint16_t)((eeval << 2) & POWER_MASK); + + EEREAD(off++); + pChannelData->PwrValues[0] |= (uint16_t)((eeval >> 14) & 0x3); + pChannelData->PwrValues[1] = (uint16_t)((eeval >> 8) & POWER_MASK); + pChannelData->PwrValues[2] = (uint16_t)((eeval >> 2) & POWER_MASK); + pChannelData->PwrValues[3] = (uint16_t)((eeval << 4) & POWER_MASK); + + EEREAD(off++); + pChannelData->PwrValues[3] |= (uint16_t)((eeval >> 12) & 0xf); + pChannelData->PwrValues[4] = (uint16_t)((eeval >> 6) & POWER_MASK); + pChannelData->PwrValues[5] = (uint16_t)(eeval & POWER_MASK); + + EEREAD(off++); + pChannelData->PwrValues[6] = (uint16_t)((eeval >> 10) & POWER_MASK); + pChannelData->PwrValues[7] = (uint16_t)((eeval >> 4) & POWER_MASK); + pChannelData->PwrValues[8] = (uint16_t)((eeval << 2) & POWER_MASK); + + EEREAD(off++); + pChannelData->PwrValues[8] |= (uint16_t)((eeval >> 14) & 0x3); + pChannelData->PwrValues[9] = (uint16_t)((eeval >> 8) & POWER_MASK); + pChannelData->PwrValues[10] = (uint16_t)((eeval >> 2) & POWER_MASK); + + getPcdacInterceptsFromPcdacMinMax(ee, + pChannelData->pcdacMin, pChannelData->pcdacMax, + pChannelData->PcdacValues) ; + + for (j = 0; j < pChannelData->numPcdacValues; j++) { + pChannelData->PwrValues[j] = (uint16_t)( + PWR_STEP * pChannelData->PwrValues[j]); + /* Note these values are scaled up. */ + } + pChannelData++; + } + } + return AH_TRUE; +#undef EEREAD +} + +/* + * Copy EEPROM Target Power Calbration per rate contents + * into the allocated space + */ +static HAL_BOOL +readEepromTargetPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + uint16_t eeval, enable24; + uint32_t off; + int i, mode, nchan; + + enable24 = ee->ee_Bmode || ee->ee_Gmode; + for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { + TRGT_POWER_INFO *pPowerInfo; + uint16_t *pNumTrgtChannels; + + off = ee->ee_version >= AR_EEPROM_VER4_0 ? + ee->ee_targetPowersStart - GROUP5_OFFSET : + ee->ee_version >= AR_EEPROM_VER3_3 ? + GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2; + switch (mode) { + case headerInfo11A: + off += GROUP5_OFFSET; + nchan = NUM_TEST_FREQUENCIES; + pPowerInfo = ee->ee_trgtPwr_11a; + pNumTrgtChannels = &ee->ee_numTargetPwr_11a; + break; + case headerInfo11B: + if (!enable24) + continue; + off += GROUP6_OFFSET; + nchan = 2; + pPowerInfo = ee->ee_trgtPwr_11b; + pNumTrgtChannels = &ee->ee_numTargetPwr_11b; + break; + case headerInfo11G: + if (!enable24) + continue; + off += GROUP7_OFFSET; + nchan = 3; + pPowerInfo = ee->ee_trgtPwr_11g; + pNumTrgtChannels = &ee->ee_numTargetPwr_11g; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", + __func__, mode); + return AH_FALSE; + } + *pNumTrgtChannels = 0; + for (i = 0; i < nchan; i++) { + EEREAD(off++); + if (ee->ee_version >= AR_EEPROM_VER3_3) { + pPowerInfo->testChannel = (eeval >> 8) & 0xff; + } else { + pPowerInfo->testChannel = (eeval >> 9) & 0x7f; + } + + if (pPowerInfo->testChannel != 0) { + /* get the channel value and read rest of info */ + if (mode == headerInfo11A) { + pPowerInfo->testChannel = fbin2freq(ee, pPowerInfo->testChannel); + } else { + pPowerInfo->testChannel = fbin2freq_2p4(ee, pPowerInfo->testChannel); + } + + if (ee->ee_version >= AR_EEPROM_VER3_3) { + pPowerInfo->twicePwr6_24 = (eeval >> 2) & POWER_MASK; + pPowerInfo->twicePwr36 = (eeval << 4) & POWER_MASK; + } else { + pPowerInfo->twicePwr6_24 = (eeval >> 3) & POWER_MASK; + pPowerInfo->twicePwr36 = (eeval << 3) & POWER_MASK; + } + + EEREAD(off++); + if (ee->ee_version >= AR_EEPROM_VER3_3) { + pPowerInfo->twicePwr36 |= (eeval >> 12) & 0xf; + pPowerInfo->twicePwr48 = (eeval >> 6) & POWER_MASK; + pPowerInfo->twicePwr54 = eeval & POWER_MASK; + } else { + pPowerInfo->twicePwr36 |= (eeval >> 13) & 0x7; + pPowerInfo->twicePwr48 = (eeval >> 7) & POWER_MASK; + pPowerInfo->twicePwr54 = (eeval >> 1) & POWER_MASK; + } + (*pNumTrgtChannels)++; + } + pPowerInfo++; + } + } + return AH_TRUE; +#undef EEREAD +} + +/* + * Now copy EEPROM Coformance Testing Limits contents + * into the allocated space + */ +static HAL_BOOL +readEepromCTLInfo(struct ath_hal *ah, HAL_EEPROM *ee) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + RD_EDGES_POWER *rep; + uint16_t eeval; + uint32_t off; + int i, j; + + rep = ee->ee_rdEdgesPower; + + off = GROUP8_OFFSET + + (ee->ee_version >= AR_EEPROM_VER4_0 ? + ee->ee_targetPowersStart - GROUP5_OFFSET : + ee->ee_version >= AR_EEPROM_VER3_3 ? + GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2); + for (i = 0; i < ee->ee_numCtls; i++) { + if (ee->ee_ctl[i] == 0) { + /* Move offset and edges */ + off += (ee->ee_version >= AR_EEPROM_VER3_3 ? 8 : 7); + rep += NUM_EDGES; + continue; + } + if (ee->ee_version >= AR_EEPROM_VER3_3) { + for (j = 0; j < NUM_EDGES; j += 2) { + EEREAD(off++); + rep[j].rdEdge = (eeval >> 8) & FREQ_MASK_3_3; + rep[j+1].rdEdge = eeval & FREQ_MASK_3_3; + } + for (j = 0; j < NUM_EDGES; j += 2) { + EEREAD(off++); + rep[j].twice_rdEdgePower = + (eeval >> 8) & POWER_MASK; + rep[j].flag = (eeval >> 14) & 1; + rep[j+1].twice_rdEdgePower = eeval & POWER_MASK; + rep[j+1].flag = (eeval >> 6) & 1; + } + } else { + EEREAD(off++); + rep[0].rdEdge = (eeval >> 9) & FREQ_MASK; + rep[1].rdEdge = (eeval >> 2) & FREQ_MASK; + rep[2].rdEdge = (eeval << 5) & FREQ_MASK; + + EEREAD(off++); + rep[2].rdEdge |= (eeval >> 11) & 0x1f; + rep[3].rdEdge = (eeval >> 4) & FREQ_MASK; + rep[4].rdEdge = (eeval << 3) & FREQ_MASK; + + EEREAD(off++); + rep[4].rdEdge |= (eeval >> 13) & 0x7; + rep[5].rdEdge = (eeval >> 6) & FREQ_MASK; + rep[6].rdEdge = (eeval << 1) & FREQ_MASK; + + EEREAD(off++); + rep[6].rdEdge |= (eeval >> 15) & 0x1; + rep[7].rdEdge = (eeval >> 8) & FREQ_MASK; + + rep[0].twice_rdEdgePower = (eeval >> 2) & POWER_MASK; + rep[1].twice_rdEdgePower = (eeval << 4) & POWER_MASK; + + EEREAD(off++); + rep[1].twice_rdEdgePower |= (eeval >> 12) & 0xf; + rep[2].twice_rdEdgePower = (eeval >> 6) & POWER_MASK; + rep[3].twice_rdEdgePower = eeval & POWER_MASK; + + EEREAD(off++); + rep[4].twice_rdEdgePower = (eeval >> 10) & POWER_MASK; + rep[5].twice_rdEdgePower = (eeval >> 4) & POWER_MASK; + rep[6].twice_rdEdgePower = (eeval << 2) & POWER_MASK; + + EEREAD(off++); + rep[6].twice_rdEdgePower |= (eeval >> 14) & 0x3; + rep[7].twice_rdEdgePower = (eeval >> 8) & POWER_MASK; + } + + for (j = 0; j < NUM_EDGES; j++ ) { + if (rep[j].rdEdge != 0 || rep[j].twice_rdEdgePower != 0) { + if ((ee->ee_ctl[i] & CTL_MODE_M) == CTL_11A || + (ee->ee_ctl[i] & CTL_MODE_M) == CTL_TURBO) { + rep[j].rdEdge = fbin2freq(ee, rep[j].rdEdge); + } else { + rep[j].rdEdge = fbin2freq_2p4(ee, rep[j].rdEdge); + } + } + } + rep += NUM_EDGES; + } + return AH_TRUE; +#undef EEREAD +} + +/* + * Read the individual header fields for a Rev 3 EEPROM + */ +static HAL_BOOL +readHeaderInfo(struct ath_hal *ah, HAL_EEPROM *ee) +{ +#define EEREAD(_off) do { \ + if (!ath_hal_eepromRead(ah, _off, &eeval)) \ + return AH_FALSE; \ +} while (0) + static const uint32_t headerOffset3_0[] = { + 0x00C2, /* 0 - Mode bits, device type, max turbo power */ + 0x00C4, /* 1 - 2.4 and 5 antenna gain */ + 0x00C5, /* 2 - Begin 11A modal section */ + 0x00D0, /* 3 - Begin 11B modal section */ + 0x00DA, /* 4 - Begin 11G modal section */ + 0x00E4 /* 5 - Begin CTL section */ + }; + static const uint32_t headerOffset3_3[] = { + 0x00C2, /* 0 - Mode bits, device type, max turbo power */ + 0x00C3, /* 1 - 2.4 and 5 antenna gain */ + 0x00D4, /* 2 - Begin 11A modal section */ + 0x00F2, /* 3 - Begin 11B modal section */ + 0x010D, /* 4 - Begin 11G modal section */ + 0x0128 /* 5 - Begin CTL section */ + }; + + static const uint32_t regCapOffsetPre4_0 = 0x00CF; + static const uint32_t regCapOffsetPost4_0 = 0x00CA; + + const uint32_t *header; + uint32_t off; + uint16_t eeval; + int i; + + /* initialize cckOfdmGainDelta for < 4.2 eeprom */ + ee->ee_cckOfdmGainDelta = CCK_OFDM_GAIN_DELTA; + ee->ee_scaledCh14FilterCckDelta = TENX_CH14_FILTER_CCK_DELTA_INIT; + + if (ee->ee_version >= AR_EEPROM_VER3_3) { + header = headerOffset3_3; + ee->ee_numCtls = NUM_CTLS_3_3; + } else { + header = headerOffset3_0; + ee->ee_numCtls = NUM_CTLS; + } + HALASSERT(ee->ee_numCtls <= NUM_CTLS_MAX); + + EEREAD(header[0]); + ee->ee_turbo5Disable = (eeval >> 15) & 0x01; + ee->ee_rfKill = (eeval >> 14) & 0x01; + ee->ee_deviceType = (eeval >> 11) & 0x07; + ee->ee_turbo2WMaxPower5 = (eeval >> 4) & 0x7F; + if (ee->ee_version >= AR_EEPROM_VER4_0) + ee->ee_turbo2Disable = (eeval >> 3) & 0x01; + else + ee->ee_turbo2Disable = 1; + ee->ee_Gmode = (eeval >> 2) & 0x01; + ee->ee_Bmode = (eeval >> 1) & 0x01; + ee->ee_Amode = (eeval & 0x01); + + off = header[1]; + EEREAD(off++); + ee->ee_antennaGainMax[0] = (int8_t)((eeval >> 8) & 0xFF); + ee->ee_antennaGainMax[1] = (int8_t)(eeval & 0xFF); + if (ee->ee_version >= AR_EEPROM_VER4_0) { + EEREAD(off++); + ee->ee_eepMap = (eeval>>14) & 0x3; + ee->ee_disableXr5 = (eeval>>13) & 0x1; + ee->ee_disableXr2 = (eeval>>12) & 0x1; + ee->ee_earStart = eeval & 0xfff; + + EEREAD(off++); + ee->ee_targetPowersStart = eeval & 0xfff; + ee->ee_exist32kHzCrystal = (eeval>>14) & 0x1; + + if (ee->ee_version >= AR_EEPROM_VER5_0) { + off += 2; + EEREAD(off); + ee->ee_eepMap2PowerCalStart = (eeval >> 4) & 0xfff; + /* Properly cal'ed 5.0 devices should be non-zero */ + } + } + + /* Read the moded sections of the EEPROM header in the order A, B, G */ + for (i = headerInfo11A; i <= headerInfo11G; i++) { + /* Set the offset via the index */ + off = header[2 + i]; + + EEREAD(off++); + ee->ee_switchSettling[i] = (eeval >> 8) & 0x7f; + ee->ee_txrxAtten[i] = (eeval >> 2) & 0x3f; + ee->ee_antennaControl[0][i] = (eeval << 4) & 0x3f; + + EEREAD(off++); + ee->ee_antennaControl[0][i] |= (eeval >> 12) & 0x0f; + ee->ee_antennaControl[1][i] = (eeval >> 6) & 0x3f; + ee->ee_antennaControl[2][i] = eeval & 0x3f; + + EEREAD(off++); + ee->ee_antennaControl[3][i] = (eeval >> 10) & 0x3f; + ee->ee_antennaControl[4][i] = (eeval >> 4) & 0x3f; + ee->ee_antennaControl[5][i] = (eeval << 2) & 0x3f; + + EEREAD(off++); + ee->ee_antennaControl[5][i] |= (eeval >> 14) & 0x03; + ee->ee_antennaControl[6][i] = (eeval >> 8) & 0x3f; + ee->ee_antennaControl[7][i] = (eeval >> 2) & 0x3f; + ee->ee_antennaControl[8][i] = (eeval << 4) & 0x3f; + + EEREAD(off++); + ee->ee_antennaControl[8][i] |= (eeval >> 12) & 0x0f; + ee->ee_antennaControl[9][i] = (eeval >> 6) & 0x3f; + ee->ee_antennaControl[10][i] = eeval & 0x3f; + + EEREAD(off++); + ee->ee_adcDesiredSize[i] = (int8_t)((eeval >> 8) & 0xff); + switch (i) { + case headerInfo11A: + ee->ee_ob4 = (eeval >> 5) & 0x07; + ee->ee_db4 = (eeval >> 2) & 0x07; + ee->ee_ob3 = (eeval << 1) & 0x07; + break; + case headerInfo11B: + ee->ee_obFor24 = (eeval >> 4) & 0x07; + ee->ee_dbFor24 = eeval & 0x07; + break; + case headerInfo11G: + ee->ee_obFor24g = (eeval >> 4) & 0x07; + ee->ee_dbFor24g = eeval & 0x07; + break; + } + + if (i == headerInfo11A) { + EEREAD(off++); + ee->ee_ob3 |= (eeval >> 15) & 0x01; + ee->ee_db3 = (eeval >> 12) & 0x07; + ee->ee_ob2 = (eeval >> 9) & 0x07; + ee->ee_db2 = (eeval >> 6) & 0x07; + ee->ee_ob1 = (eeval >> 3) & 0x07; + ee->ee_db1 = eeval & 0x07; + } + + EEREAD(off++); + ee->ee_txEndToXLNAOn[i] = (eeval >> 8) & 0xff; + ee->ee_thresh62[i] = eeval & 0xff; + + EEREAD(off++); + ee->ee_txEndToXPAOff[i] = (eeval >> 8) & 0xff; + ee->ee_txFrameToXPAOn[i] = eeval & 0xff; + + EEREAD(off++); + ee->ee_pgaDesiredSize[i] = (int8_t)((eeval >> 8) & 0xff); + ee->ee_noiseFloorThresh[i] = eeval & 0xff; + if (ee->ee_noiseFloorThresh[i] & 0x80) { + ee->ee_noiseFloorThresh[i] = 0 - + ((ee->ee_noiseFloorThresh[i] ^ 0xff) + 1); + } + + EEREAD(off++); + ee->ee_xlnaGain[i] = (eeval >> 5) & 0xff; + ee->ee_xgain[i] = (eeval >> 1) & 0x0f; + ee->ee_xpd[i] = eeval & 0x01; + if (ee->ee_version >= AR_EEPROM_VER4_0) { + switch (i) { + case headerInfo11A: + ee->ee_fixedBias5 = (eeval >> 13) & 0x1; + break; + case headerInfo11G: + ee->ee_fixedBias2 = (eeval >> 13) & 0x1; + break; + } + } + + if (ee->ee_version >= AR_EEPROM_VER3_3) { + EEREAD(off++); + ee->ee_falseDetectBackoff[i] = (eeval >> 6) & 0x7F; + switch (i) { + case headerInfo11B: + ee->ee_ob2GHz[0] = eeval & 0x7; + ee->ee_db2GHz[0] = (eeval >> 3) & 0x7; + break; + case headerInfo11G: + ee->ee_ob2GHz[1] = eeval & 0x7; + ee->ee_db2GHz[1] = (eeval >> 3) & 0x7; + break; + case headerInfo11A: + ee->ee_xrTargetPower5 = eeval & 0x3f; + break; + } + } + if (ee->ee_version >= AR_EEPROM_VER3_4) { + ee->ee_gainI[i] = (eeval >> 13) & 0x07; + + EEREAD(off++); + ee->ee_gainI[i] |= (eeval << 3) & 0x38; + if (i == headerInfo11G) { + ee->ee_cckOfdmPwrDelta = (eeval >> 3) & 0xFF; + if (ee->ee_version >= AR_EEPROM_VER4_6) + ee->ee_scaledCh14FilterCckDelta = + (eeval >> 11) & 0x1f; + } + if (i == headerInfo11A && + ee->ee_version >= AR_EEPROM_VER4_0) { + ee->ee_iqCalI[0] = (eeval >> 8 ) & 0x3f; + ee->ee_iqCalQ[0] = (eeval >> 3 ) & 0x1f; + } + } else { + ee->ee_gainI[i] = 10; + ee->ee_cckOfdmPwrDelta = TENX_OFDM_CCK_DELTA_INIT; + } + if (ee->ee_version >= AR_EEPROM_VER4_0) { + switch (i) { + case headerInfo11B: + EEREAD(off++); + ee->ee_calPier11b[0] = + fbin2freq_2p4(ee, eeval&0xff); + ee->ee_calPier11b[1] = + fbin2freq_2p4(ee, (eeval >> 8)&0xff); + EEREAD(off++); + ee->ee_calPier11b[2] = + fbin2freq_2p4(ee, eeval&0xff); + if (ee->ee_version >= AR_EEPROM_VER4_1) + ee->ee_rxtxMargin[headerInfo11B] = + (eeval >> 8) & 0x3f; + break; + case headerInfo11G: + EEREAD(off++); + ee->ee_calPier11g[0] = + fbin2freq_2p4(ee, eeval & 0xff); + ee->ee_calPier11g[1] = + fbin2freq_2p4(ee, (eeval >> 8) & 0xff); + + EEREAD(off++); + ee->ee_turbo2WMaxPower2 = eeval & 0x7F; + ee->ee_xrTargetPower2 = (eeval >> 7) & 0x3f; + + EEREAD(off++); + ee->ee_calPier11g[2] = + fbin2freq_2p4(ee, eeval & 0xff); + if (ee->ee_version >= AR_EEPROM_VER4_1) + ee->ee_rxtxMargin[headerInfo11G] = + (eeval >> 8) & 0x3f; + + EEREAD(off++); + ee->ee_iqCalI[1] = (eeval >> 5) & 0x3F; + ee->ee_iqCalQ[1] = eeval & 0x1F; + + if (ee->ee_version >= AR_EEPROM_VER4_2) { + EEREAD(off++); + ee->ee_cckOfdmGainDelta = + (uint8_t)(eeval & 0xFF); + if (ee->ee_version >= AR_EEPROM_VER5_0) { + ee->ee_switchSettlingTurbo[1] = + (eeval >> 8) & 0x7f; + ee->ee_txrxAttenTurbo[1] = + (eeval >> 15) & 0x1; + EEREAD(off++); + ee->ee_txrxAttenTurbo[1] |= + (eeval & 0x1F) << 1; + ee->ee_rxtxMarginTurbo[1] = + (eeval >> 5) & 0x3F; + ee->ee_adcDesiredSizeTurbo[1] = + (eeval >> 11) & 0x1F; + EEREAD(off++); + ee->ee_adcDesiredSizeTurbo[1] |= + (eeval & 0x7) << 5; + ee->ee_pgaDesiredSizeTurbo[1] = + (eeval >> 3) & 0xFF; + } + } + break; + case headerInfo11A: + if (ee->ee_version >= AR_EEPROM_VER4_1) { + EEREAD(off++); + ee->ee_rxtxMargin[headerInfo11A] = + eeval & 0x3f; + if (ee->ee_version >= AR_EEPROM_VER5_0) { + ee->ee_switchSettlingTurbo[0] = + (eeval >> 6) & 0x7f; + ee->ee_txrxAttenTurbo[0] = + (eeval >> 13) & 0x7; + EEREAD(off++); + ee->ee_txrxAttenTurbo[0] |= + (eeval & 0x7) << 3; + ee->ee_rxtxMarginTurbo[0] = + (eeval >> 3) & 0x3F; + ee->ee_adcDesiredSizeTurbo[0] = + (eeval >> 9) & 0x7F; + EEREAD(off++); + ee->ee_adcDesiredSizeTurbo[0] |= + (eeval & 0x1) << 7; + ee->ee_pgaDesiredSizeTurbo[0] = + (eeval >> 1) & 0xFF; + } + } + break; + } + } + } + if (ee->ee_version < AR_EEPROM_VER3_3) { + /* Version 3.1+ specific parameters */ + EEREAD(0xec); + ee->ee_ob2GHz[0] = eeval & 0x7; + ee->ee_db2GHz[0] = (eeval >> 3) & 0x7; + + EEREAD(0xed); + ee->ee_ob2GHz[1] = eeval & 0x7; + ee->ee_db2GHz[1] = (eeval >> 3) & 0x7; + } + + /* Initialize corner cal (thermal tx gain adjust parameters) */ + ee->ee_cornerCal.clip = 4; + ee->ee_cornerCal.pd90 = 1; + ee->ee_cornerCal.pd84 = 1; + ee->ee_cornerCal.gSel = 0; + + /* + * Read the conformance test limit identifiers + * These are used to match regulatory domain testing needs with + * the RD-specific tests that have been calibrated in the EEPROM. + */ + off = header[5]; + for (i = 0; i < ee->ee_numCtls; i += 2) { + EEREAD(off++); + ee->ee_ctl[i] = (eeval >> 8) & 0xff; + ee->ee_ctl[i+1] = eeval & 0xff; + } + + if (ee->ee_version < AR_EEPROM_VER5_3) { + /* XXX only for 5413? */ + ee->ee_spurChans[0][1] = AR_SPUR_5413_1; + ee->ee_spurChans[1][1] = AR_SPUR_5413_2; + ee->ee_spurChans[2][1] = AR_NO_SPUR; + ee->ee_spurChans[0][0] = AR_NO_SPUR; + } else { + /* Read spur mitigation data */ + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { + EEREAD(off); + ee->ee_spurChans[i][0] = eeval; + EEREAD(off+AR_EEPROM_MODAL_SPURS); + ee->ee_spurChans[i][1] = eeval; + off++; + } + } + + /* for recent changes to NF scale */ + if (ee->ee_version <= AR_EEPROM_VER3_2) { + ee->ee_noiseFloorThresh[headerInfo11A] = -54; + ee->ee_noiseFloorThresh[headerInfo11B] = -1; + ee->ee_noiseFloorThresh[headerInfo11G] = -1; + } + /* to override thresh62 for better 2.4 and 5 operation */ + if (ee->ee_version <= AR_EEPROM_VER3_2) { + ee->ee_thresh62[headerInfo11A] = 15; /* 11A */ + ee->ee_thresh62[headerInfo11B] = 28; /* 11B */ + ee->ee_thresh62[headerInfo11G] = 28; /* 11G */ + } + + /* Check for regulatory capabilities */ + if (ee->ee_version >= AR_EEPROM_VER4_0) { + EEREAD(regCapOffsetPost4_0); + } else { + EEREAD(regCapOffsetPre4_0); + } + + ee->ee_regCap = eeval; + + if (ee->ee_Amode == 0) { + /* Check for valid Amode in upgraded h/w */ + if (ee->ee_version >= AR_EEPROM_VER4_0) { + ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A)?1:0; + } else { + ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0)?1:0; + } + } + + if (ee->ee_version >= AR_EEPROM_VER5_1) + EEREAD(AR_EEPROM_CAPABILITIES_OFFSET); + else + eeval = 0; + ee->ee_opCap = eeval; + + EEREAD(AR_EEPROM_REG_DOMAIN); + ee->ee_regdomain = eeval; + + return AH_TRUE; +#undef EEREAD +} + +/* + * Now verify and copy EEPROM contents into the allocated space + */ +static HAL_BOOL +legacyEepromReadContents(struct ath_hal *ah, HAL_EEPROM *ee) +{ + /* Read the header information here */ + if (!readHeaderInfo(ah, ee)) + return AH_FALSE; +#if 0 + /* Require 5112 devices to have EEPROM 4.0 EEP_MAP set */ + if (IS_5112(ah) && !ee->ee_eepMap) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5112 devices must have EEPROM 4.0 with the " + "EEP_MAP set\n", __func__); + return AH_FALSE; + } +#endif + /* + * Group 1: frequency pier locations readback + * check that the structure has been populated + * with enough space to hold the channels + * + * NOTE: Group 1 contains the 5 GHz channel numbers + * that have dBm->pcdac calibrated information. + */ + if (!readEepromFreqPierInfo(ah, ee)) + return AH_FALSE; + + /* + * Group 2: readback data for all frequency piers + * + * NOTE: Group 2 contains the raw power calibration + * information for each of the channels that we + * recorded above. + */ + if (!readEepromRawPowerCalInfo(ah, ee)) + return AH_FALSE; + + /* + * Group 5: target power values per rate + * + * NOTE: Group 5 contains the recorded maximum power + * in dB that can be attained for the given rate. + */ + /* Read the power per rate info for test channels */ + if (!readEepromTargetPowerCalInfo(ah, ee)) + return AH_FALSE; + + /* + * Group 8: Conformance Test Limits information + * + * NOTE: Group 8 contains the values to limit the + * maximum transmit power value based on any + * band edge violations. + */ + /* Read the RD edge power limits */ + return readEepromCTLInfo(ah, ee); +} + +static HAL_STATUS +legacyEepromGet(struct ath_hal *ah, int param, void *val) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint8_t *macaddr; + uint16_t eeval; + uint32_t sum; + int i; + + switch (param) { + case AR_EEP_OPCAP: + *(uint16_t *) val = ee->ee_opCap; + return HAL_OK; + case AR_EEP_REGDMN_0: + *(uint16_t *) val = ee->ee_regdomain; + return HAL_OK; + case AR_EEP_RFSILENT: + if (!ath_hal_eepromRead(ah, AR_EEPROM_RFSILENT, &eeval)) + return HAL_EEREAD; + *(uint16_t *) val = eeval; + return HAL_OK; + case AR_EEP_MACADDR: + sum = 0; + macaddr = val; + for (i = 0; i < 3; i++) { + if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(2-i), &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM location %u\n", + __func__, i); + return HAL_EEREAD; + } + sum += eeval; + macaddr[2*i] = eeval >> 8; + macaddr[2*i + 1] = eeval & 0xff; + } + if (sum == 0 || sum == 0xffff*3) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: mac address read failed: %s\n", __func__, + ath_hal_ether_sprintf(macaddr)); + return HAL_EEBADMAC; + } + return HAL_OK; + case AR_EEP_RFKILL: + HALASSERT(val == AH_NULL); + return ee->ee_rfKill ? HAL_OK : HAL_EIO; + case AR_EEP_AMODE: + HALASSERT(val == AH_NULL); + return ee->ee_Amode ? HAL_OK : HAL_EIO; + case AR_EEP_BMODE: + HALASSERT(val == AH_NULL); + return ee->ee_Bmode ? HAL_OK : HAL_EIO; + case AR_EEP_GMODE: + HALASSERT(val == AH_NULL); + return ee->ee_Gmode ? HAL_OK : HAL_EIO; + case AR_EEP_TURBO5DISABLE: + HALASSERT(val == AH_NULL); + return ee->ee_turbo5Disable ? HAL_OK : HAL_EIO; + case AR_EEP_TURBO2DISABLE: + HALASSERT(val == AH_NULL); + return ee->ee_turbo2Disable ? HAL_OK : HAL_EIO; + case AR_EEP_ISTALON: /* Talon detect */ + HALASSERT(val == AH_NULL); + return (ee->ee_version >= AR_EEPROM_VER5_4 && + ath_hal_eepromRead(ah, 0x0b, &eeval) && eeval == 1) ? + HAL_OK : HAL_EIO; + case AR_EEP_32KHZCRYSTAL: + HALASSERT(val == AH_NULL); + return ee->ee_exist32kHzCrystal ? HAL_OK : HAL_EIO; + case AR_EEP_COMPRESS: + HALASSERT(val == AH_NULL); + return (ee->ee_opCap & AR_EEPROM_EEPCAP_COMPRESS_DIS) == 0 ? + HAL_OK : HAL_EIO; + case AR_EEP_FASTFRAME: + HALASSERT(val == AH_NULL); + return (ee->ee_opCap & AR_EEPROM_EEPCAP_FASTFRAME_DIS) == 0 ? + HAL_OK : HAL_EIO; + case AR_EEP_AES: + HALASSERT(val == AH_NULL); + return (ee->ee_opCap & AR_EEPROM_EEPCAP_AES_DIS) == 0 ? + HAL_OK : HAL_EIO; + case AR_EEP_BURST: + HALASSERT(val == AH_NULL); + return (ee->ee_opCap & AR_EEPROM_EEPCAP_BURST_DIS) == 0 ? + HAL_OK : HAL_EIO; + case AR_EEP_MAXQCU: + if (ee->ee_opCap & AR_EEPROM_EEPCAP_MAXQCU) { + *(uint16_t *) val = + MS(ee->ee_opCap, AR_EEPROM_EEPCAP_MAXQCU); + return HAL_OK; + } else + return HAL_EIO; + case AR_EEP_KCENTRIES: + if (ee->ee_opCap & AR_EEPROM_EEPCAP_KC_ENTRIES) { + *(uint16_t *) val = + 1 << MS(ee->ee_opCap, AR_EEPROM_EEPCAP_KC_ENTRIES); + return HAL_OK; + } else + return HAL_EIO; + case AR_EEP_ANTGAINMAX_5: + *(int8_t *) val = ee->ee_antennaGainMax[0]; + return HAL_OK; + case AR_EEP_ANTGAINMAX_2: + *(int8_t *) val = ee->ee_antennaGainMax[1]; + return HAL_OK; + case AR_EEP_WRITEPROTECT: + HALASSERT(val == AH_NULL); + return (ee->ee_protect & AR_EEPROM_PROTECT_WP_128_191) ? + HAL_OK : HAL_EIO; + } + return HAL_EINVAL; +} + +static HAL_STATUS +legacyEepromSet(struct ath_hal *ah, int param, int v) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (param) { + case AR_EEP_AMODE: + ee->ee_Amode = v; + return HAL_OK; + case AR_EEP_BMODE: + ee->ee_Bmode = v; + return HAL_OK; + case AR_EEP_GMODE: + ee->ee_Gmode = v; + return HAL_OK; + case AR_EEP_TURBO5DISABLE: + ee->ee_turbo5Disable = v; + return HAL_OK; + case AR_EEP_TURBO2DISABLE: + ee->ee_turbo2Disable = v; + return HAL_OK; + case AR_EEP_COMPRESS: + if (v) + ee->ee_opCap &= ~AR_EEPROM_EEPCAP_COMPRESS_DIS; + else + ee->ee_opCap |= AR_EEPROM_EEPCAP_COMPRESS_DIS; + return HAL_OK; + case AR_EEP_FASTFRAME: + if (v) + ee->ee_opCap &= ~AR_EEPROM_EEPCAP_FASTFRAME_DIS; + else + ee->ee_opCap |= AR_EEPROM_EEPCAP_FASTFRAME_DIS; + return HAL_OK; + case AR_EEP_AES: + if (v) + ee->ee_opCap &= ~AR_EEPROM_EEPCAP_AES_DIS; + else + ee->ee_opCap |= AR_EEPROM_EEPCAP_AES_DIS; + return HAL_OK; + case AR_EEP_BURST: + if (v) + ee->ee_opCap &= ~AR_EEPROM_EEPCAP_BURST_DIS; + else + ee->ee_opCap |= AR_EEPROM_EEPCAP_BURST_DIS; + return HAL_OK; + } + return HAL_EINVAL; +} + +static HAL_BOOL +legacyEepromDiag(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, void **result, uint32_t *resultsize) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const EEPROM_POWER_EXPN_5112 *pe; + + switch (request) { + case HAL_DIAG_EEPROM: + *result = ee; + *resultsize = sizeof(*ee); + return AH_TRUE; + case HAL_DIAG_EEPROM_EXP_11A: + case HAL_DIAG_EEPROM_EXP_11B: + case HAL_DIAG_EEPROM_EXP_11G: + pe = &ee->ee_modePowerArray5112[ + request - HAL_DIAG_EEPROM_EXP_11A]; + *result = pe->pChannels; + *resultsize = (*result == AH_NULL) ? 0 : + roundup(sizeof(uint16_t) * pe->numChannels, + sizeof(uint32_t)) + + sizeof(EXPN_DATA_PER_CHANNEL_5112) * pe->numChannels; + return AH_TRUE; + } + return AH_FALSE; +} + +static uint16_t +legacyEepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + HALASSERT(0 <= ix && ix < AR_EEPROM_MODAL_SPURS); + return ee->ee_spurChans[ix][is2GHz]; +} + +/* + * Reclaim any EEPROM-related storage. + */ +static void +legacyEepromDetach(struct ath_hal *ah) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1) + freeEepromRawPowerCalInfo5112(ah, ee); + ath_hal_free(ee); + AH_PRIVATE(ah)->ah_eeprom = AH_NULL; +} + +/* + * These are not valid 2.4 channels, either we change 'em + * or we need to change the coding to accept them. + */ +static const uint16_t channels11b[] = { 2412, 2447, 2484 }; +static const uint16_t channels11g[] = { 2312, 2412, 2484 }; + +HAL_STATUS +ath_hal_legacyEepromAttach(struct ath_hal *ah) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint32_t sum, eepMax; + uint16_t eeversion, eeprotect, eeval; + u_int i; + + HALASSERT(ee == AH_NULL); + + if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &eeversion)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to read EEPROM version\n", __func__); + return HAL_EEREAD; + } + if (eeversion < AR_EEPROM_VER3) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM version " + "%u (0x%x) found\n", __func__, eeversion, eeversion); + return HAL_EEVERSION; + } + + if (!ath_hal_eepromRead(ah, AR_EEPROM_PROTECT, &eeprotect)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cannot read EEPROM protection " + "bits; read locked?\n", __func__); + return HAL_EEREAD; + } + HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", eeprotect); + /* XXX check proper access before continuing */ + + /* + * Read the Atheros EEPROM entries and calculate the checksum. + */ + if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_UPPER, &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM upper size\n" , __func__); + return HAL_EEREAD; + } + if (eeval != 0) { + eepMax = (eeval & AR_EEPROM_SIZE_UPPER_MASK) << + AR_EEPROM_SIZE_ENDLOC_SHIFT; + if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_LOWER, &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM lower size\n" , __func__); + return HAL_EEREAD; + } + eepMax = (eepMax | eeval) - AR_EEPROM_ATHEROS_BASE; + } else + eepMax = AR_EEPROM_ATHEROS_MAX; + sum = 0; + for (i = 0; i < eepMax; i++) { + if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &eeval)) { + return HAL_EEREAD; + } + sum ^= eeval; + } + if (sum != 0xffff) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n", + __func__, sum); + return HAL_EEBADSUM; + } + + ee = ath_hal_malloc(sizeof(HAL_EEPROM)); + if (ee == AH_NULL) { + /* XXX message */ + return HAL_ENOMEM; + } + + ee->ee_protect = eeprotect; + ee->ee_version = eeversion; + + ee->ee_numChannels11a = NUM_11A_EEPROM_CHANNELS; + ee->ee_numChannels2_4 = NUM_2_4_EEPROM_CHANNELS; + + for (i = 0; i < NUM_11A_EEPROM_CHANNELS; i ++) + ee->ee_dataPerChannel11a[i].numPcdacValues = NUM_PCDAC_VALUES; + + /* the channel list for 2.4 is fixed, fill this in here */ + for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) { + ee->ee_channels11b[i] = channels11b[i]; + /* XXX 5211 requires a hack though we don't support 11g */ + if (ah->ah_magic == 0x19570405) + ee->ee_channels11g[i] = channels11b[i]; + else + ee->ee_channels11g[i] = channels11g[i]; + ee->ee_dataPerChannel11b[i].numPcdacValues = NUM_PCDAC_VALUES; + ee->ee_dataPerChannel11g[i].numPcdacValues = NUM_PCDAC_VALUES; + } + + if (!legacyEepromReadContents(ah, ee)) { + /* XXX message */ + ath_hal_free(ee); + return HAL_EEREAD; /* XXX */ + } + + AH_PRIVATE(ah)->ah_eeprom = ee; + AH_PRIVATE(ah)->ah_eeversion = eeversion; + AH_PRIVATE(ah)->ah_eepromDetach = legacyEepromDetach; + AH_PRIVATE(ah)->ah_eepromGet = legacyEepromGet; + AH_PRIVATE(ah)->ah_eepromSet = legacyEepromSet; + AH_PRIVATE(ah)->ah_getSpurChan = legacyEepromGetSpurChan; + AH_PRIVATE(ah)->ah_eepromDiag = legacyEepromDiag; + return HAL_OK; +} diff --git a/sys/external/isc/atheros_hal/dist/ah_eeprom_v3.h b/sys/external/isc/atheros_hal/dist/ah_eeprom_v3.h new file mode 100644 index 0000000..cde9a10 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_eeprom_v3.h @@ -0,0 +1,462 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AH_EEPROM_V3_H_ +#define _ATH_AH_EEPROM_V3_H_ + +#include "ah_eeprom.h" + +/* EEPROM defines for Version 2 & 3 AR5211 chips */ +#define AR_EEPROM_RFSILENT 0x0f /* RF Silent/Clock Run Enable */ +#define AR_EEPROM_MAC(i) (0x1d+(i)) /* MAC address word */ +#define AR_EEPROM_MAGIC 0x3d /* magic number */ +#define AR_EEPROM_PROTECT 0x3f /* EEPROM protect bits */ +#define AR_EEPROM_PROTECT_PCIE 0x01 /* EEPROM protect bits for Condor/Swan*/ +#define AR_EEPROM_REG_DOMAIN 0xbf /* current regulatory domain */ +#define AR_EEPROM_ATHEROS_BASE 0xc0 /* Base of Atheros-specific data */ +#define AR_EEPROM_ATHEROS(i) (AR_EEPROM_ATHEROS_BASE+(i)) +#define AR_EEPROM_ATHEROS_MAX (0x400-AR_EEPROM_ATHEROS_BASE) +#define AR_EEPROM_VERSION AR_EEPROM_ATHEROS(1) + +/* FLASH(EEPROM) Defines for AR531X chips */ +#define AR_EEPROM_SIZE_LOWER 0x1b /* size info -- lower */ +#define AR_EEPROM_SIZE_UPPER 0x1c /* size info -- upper */ +#define AR_EEPROM_SIZE_UPPER_MASK 0xfff0 +#define AR_EEPROM_SIZE_UPPER_SHIFT 4 +#define AR_EEPROM_SIZE_ENDLOC_SHIFT 12 +#define AR_EEPROM_ATHEROS_MAX_LOC 0x400 +#define AR_EEPROM_ATHEROS_MAX_OFF (AR_EEPROM_ATHEROS_MAX_LOC-AR_EEPROM_ATHEROS_BASE) + +/* regulatory capabilities offsets */ +#define AR_EEPROM_REG_CAPABILITIES_OFFSET 0xCA +#define AR_EEPROM_REG_CAPABILITIES_OFFSET_PRE4_0 0xCF /* prior to 4.0 */ + +/* regulatory capabilities */ +#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040 +#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080 +#define AR_EEPROM_EEREGCAP_EN_KK_U2 0x0100 +#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200 +#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400 +#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800 + +/* regulatory capabilities prior to eeprom version 4.0 */ +#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0 0x4000 +#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000 + +/* + * AR2413 (includes AR5413) + */ +#define AR_EEPROM_SERIAL_NUM_OFFSET 0xB0 /* EEPROM serial number */ +#define AR_EEPROM_SERIAL_NUM_SIZE 12 /* EEPROM serial number size */ +#define AR_EEPROM_CAPABILITIES_OFFSET 0xC9 /* EEPROM Location of capabilities */ + +#define AR_EEPROM_EEPCAP_COMPRESS_DIS 0x0001 +#define AR_EEPROM_EEPCAP_AES_DIS 0x0002 +#define AR_EEPROM_EEPCAP_FASTFRAME_DIS 0x0004 +#define AR_EEPROM_EEPCAP_BURST_DIS 0x0008 +#define AR_EEPROM_EEPCAP_MAXQCU 0x01F0 +#define AR_EEPROM_EEPCAP_MAXQCU_S 4 +#define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN 0x0200 +#define AR_EEPROM_EEPCAP_KC_ENTRIES 0xF000 +#define AR_EEPROM_EEPCAP_KC_ENTRIES_S 12 + +/* XXX used to index various EEPROM-derived data structures */ +enum { + headerInfo11A = 0, + headerInfo11B = 1, + headerInfo11G = 2, +}; + +#define GROUPS_OFFSET3_2 0x100 /* groups offset for ver3.2 and earlier */ +#define GROUPS_OFFSET3_3 0x150 /* groups offset for ver3.3 */ +/* relative offset of GROUPi to GROUPS_OFFSET */ +#define GROUP1_OFFSET 0x0 +#define GROUP2_OFFSET 0x5 +#define GROUP3_OFFSET 0x37 +#define GROUP4_OFFSET 0x46 +#define GROUP5_OFFSET 0x55 +#define GROUP6_OFFSET 0x65 +#define GROUP7_OFFSET 0x69 +#define GROUP8_OFFSET 0x6f + +/* RF silent fields in EEPROM */ +#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c +#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 +#define AR_EEPROM_RFSILENT_POLARITY 0x0002 +#define AR_EEPROM_RFSILENT_POLARITY_S 1 + +/* Protect Bits RP is read protect, WP is write protect */ +#define AR_EEPROM_PROTECT_RP_0_31 0x0001 +#define AR_EEPROM_PROTECT_WP_0_31 0x0002 +#define AR_EEPROM_PROTECT_RP_32_63 0x0004 +#define AR_EEPROM_PROTECT_WP_32_63 0x0008 +#define AR_EEPROM_PROTECT_RP_64_127 0x0010 +#define AR_EEPROM_PROTECT_WP_64_127 0x0020 +#define AR_EEPROM_PROTECT_RP_128_191 0x0040 +#define AR_EEPROM_PROTECT_WP_128_191 0x0080 +#define AR_EEPROM_PROTECT_RP_192_207 0x0100 +#define AR_EEPROM_PROTECT_WP_192_207 0x0200 +#define AR_EEPROM_PROTECT_RP_208_223 0x0400 +#define AR_EEPROM_PROTECT_WP_208_223 0x0800 +#define AR_EEPROM_PROTECT_RP_224_239 0x1000 +#define AR_EEPROM_PROTECT_WP_224_239 0x2000 +#define AR_EEPROM_PROTECT_RP_240_255 0x4000 +#define AR_EEPROM_PROTECT_WP_240_255 0x8000 + +#define AR_EEPROM_MODAL_SPURS 5 +#define AR_SPUR_5413_1 1640 /* Freq 2464 */ +#define AR_SPUR_5413_2 1200 /* Freq 2420 */ + +/* + * EEPROM fixed point conversion scale factors. + * NB: if you change one be sure to keep the other in sync. + */ +#define EEP_SCALE 100 /* conversion scale to avoid fp arith */ +#define EEP_DELTA 10 /* SCALE/10, to avoid arith divide */ + +#define PWR_MIN 0 +#define PWR_MAX 3150 /* 31.5 * SCALE */ +#define PWR_STEP 50 /* 0.5 * SCALE */ +/* Keep 2 above defines together */ + +#define NUM_11A_EEPROM_CHANNELS 10 +#define NUM_2_4_EEPROM_CHANNELS 3 +#define NUM_PCDAC_VALUES 11 +#define NUM_TEST_FREQUENCIES 8 +#define NUM_EDGES 8 +#define NUM_INTERCEPTS 11 +#define FREQ_MASK 0x7f +#define FREQ_MASK_3_3 0xff /* expanded in version 3.3 */ +#define PCDAC_MASK 0x3f +#define POWER_MASK 0x3f +#define NON_EDGE_FLAG_MASK 0x40 +#define CHANNEL_POWER_INFO 8 +#define OBDB_UNSET 0xffff +#define CHANNEL_UNUSED 0xff +#define SCALE_OC_DELTA(_x) (((_x) * 2) / 10) + +/* Used during pcdac table construction */ +#define PCDAC_START 1 +#define PCDAC_STOP 63 +#define PCDAC_STEP 1 +#define PWR_TABLE_SIZE 64 +#define MAX_RATE_POWER 63 + +/* Used during power/rate table construction */ +#define NUM_CTLS 16 +#define NUM_CTLS_3_3 32 /* expanded in version 3.3 */ +#define NUM_CTLS_MAX NUM_CTLS_3_3 + +typedef struct fullPcdacStruct { + uint16_t channelValue; + uint16_t pcdacMin; + uint16_t pcdacMax; + uint16_t numPcdacValues; + uint16_t PcdacValues[64]; + /* power is 32bit since in dest it is scaled */ + int16_t PwrValues[64]; +} FULL_PCDAC_STRUCT; + +typedef struct dataPerChannel { + uint16_t channelValue; + uint16_t pcdacMin; + uint16_t pcdacMax; + uint16_t numPcdacValues; + uint16_t PcdacValues[NUM_PCDAC_VALUES]; + /* NB: power is 32bit since in dest it is scaled */ + int16_t PwrValues[NUM_PCDAC_VALUES]; +} DATA_PER_CHANNEL; + +/* points to the appropriate pcdac structs in the above struct based on mode */ +typedef struct pcdacsEeprom { + const uint16_t *pChannelList; + uint16_t numChannels; + const DATA_PER_CHANNEL *pDataPerChannel; +} PCDACS_EEPROM; + +typedef struct trgtPowerInfo { + uint16_t twicePwr54; + uint16_t twicePwr48; + uint16_t twicePwr36; + uint16_t twicePwr6_24; + uint16_t testChannel; +} TRGT_POWER_INFO; + +typedef struct trgtPowerAllModes { + uint16_t numTargetPwr_11a; + TRGT_POWER_INFO trgtPwr_11a[NUM_TEST_FREQUENCIES]; + uint16_t numTargetPwr_11g; + TRGT_POWER_INFO trgtPwr_11g[3]; + uint16_t numTargetPwr_11b; + TRGT_POWER_INFO trgtPwr_11b[2]; +} TRGT_POWER_ALL_MODES; + +typedef struct cornerCalInfo { + uint16_t gSel; + uint16_t pd84; + uint16_t pd90; + uint16_t clip; +} CORNER_CAL_INFO; + +/* + * EEPROM version 4 definitions + */ +#define NUM_XPD_PER_CHANNEL 4 +#define NUM_POINTS_XPD0 4 +#define NUM_POINTS_XPD3 3 +#define IDEAL_10dB_INTERCEPT_2G 35 +#define IDEAL_10dB_INTERCEPT_5G 55 + +#define TENX_OFDM_CCK_DELTA_INIT 15 /* power 1.5 dbm */ +#define TENX_CH14_FILTER_CCK_DELTA_INIT 15 /* power 1.5 dbm */ +#define CCK_OFDM_GAIN_DELTA 15 + +#define NUM_TARGET_POWER_LOCATIONS_11B 4 +#define NUM_TARGET_POWER_LOCATIONS_11G 6 + + +typedef struct { + uint16_t xpd_gain; + uint16_t numPcdacs; + uint16_t pcdac[NUM_POINTS_XPD0]; + int16_t pwr_t4[NUM_POINTS_XPD0]; /* or gainF */ +} EXPN_DATA_PER_XPD_5112; + +typedef struct { + uint16_t channelValue; + int16_t maxPower_t4; + EXPN_DATA_PER_XPD_5112 pDataPerXPD[NUM_XPD_PER_CHANNEL]; +} EXPN_DATA_PER_CHANNEL_5112; + +typedef struct { + uint16_t *pChannels; + uint16_t numChannels; + uint16_t xpdMask; /* mask of permitted xpd_gains */ + EXPN_DATA_PER_CHANNEL_5112 *pDataPerChannel; +} EEPROM_POWER_EXPN_5112; + +typedef struct { + uint16_t channelValue; + uint16_t pcd1_xg0; + int16_t pwr1_xg0; + uint16_t pcd2_delta_xg0; + int16_t pwr2_xg0; + uint16_t pcd3_delta_xg0; + int16_t pwr3_xg0; + uint16_t pcd4_delta_xg0; + int16_t pwr4_xg0; + int16_t maxPower_t4; + int16_t pwr1_xg3; /* pcdac = 20 */ + int16_t pwr2_xg3; /* pcdac = 35 */ + int16_t pwr3_xg3; /* pcdac = 63 */ + /* XXX - Should be pwr1_xg2, etc to agree with documentation */ +} EEPROM_DATA_PER_CHANNEL_5112; + +typedef struct { + uint16_t pChannels[NUM_11A_EEPROM_CHANNELS]; + uint16_t numChannels; + uint16_t xpdMask; /* mask of permitted xpd_gains */ + EEPROM_DATA_PER_CHANNEL_5112 pDataPerChannel[NUM_11A_EEPROM_CHANNELS]; +} EEPROM_POWER_5112; + +/* + * EEPROM version 5 definitions (Griffin, et. al.). + */ +#define NUM_2_4_EEPROM_CHANNELS_2413 4 +#define NUM_11A_EEPROM_CHANNELS_2413 10 +#define PWR_TABLE_SIZE_2413 128 + +/* Used during pdadc construction */ +#define MAX_NUM_PDGAINS_PER_CHANNEL 4 +#define NUM_PDGAINS_PER_CHANNEL 2 +#define NUM_POINTS_LAST_PDGAIN 5 +#define NUM_POINTS_OTHER_PDGAINS 4 +#define XPD_GAIN1_GEN5 3 +#define XPD_GAIN2_GEN5 1 +#define MAX_PWR_RANGE_IN_HALF_DB 64 +#define PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB 4 + +typedef struct { + uint16_t pd_gain; + uint16_t numVpd; + uint16_t Vpd[NUM_POINTS_LAST_PDGAIN]; + int16_t pwr_t4[NUM_POINTS_LAST_PDGAIN]; /* or gainF */ +} RAW_DATA_PER_PDGAIN_2413; + +typedef struct { + uint16_t channelValue; + int16_t maxPower_t4; + uint16_t numPdGains; /* # Pd Gains per channel */ + RAW_DATA_PER_PDGAIN_2413 pDataPerPDGain[MAX_NUM_PDGAINS_PER_CHANNEL]; +} RAW_DATA_PER_CHANNEL_2413; + +/* XXX: assumes NUM_11A_EEPROM_CHANNELS_2413 >= NUM_2_4_EEPROM_CHANNELS_2413 ??? */ +typedef struct { + uint16_t pChannels[NUM_11A_EEPROM_CHANNELS_2413]; + uint16_t numChannels; + uint16_t xpd_mask; /* mask of permitted xpd_gains */ + RAW_DATA_PER_CHANNEL_2413 pDataPerChannel[NUM_11A_EEPROM_CHANNELS_2413]; +} RAW_DATA_STRUCT_2413; + +typedef struct { + uint16_t channelValue; + uint16_t numPdGains; + uint16_t Vpd_I[MAX_NUM_PDGAINS_PER_CHANNEL]; + int16_t pwr_I[MAX_NUM_PDGAINS_PER_CHANNEL]; + uint16_t Vpd_delta[NUM_POINTS_LAST_PDGAIN] + [MAX_NUM_PDGAINS_PER_CHANNEL]; + int16_t pwr_delta_t2[NUM_POINTS_LAST_PDGAIN] + [MAX_NUM_PDGAINS_PER_CHANNEL]; + int16_t maxPower_t4; +} EEPROM_DATA_PER_CHANNEL_2413; + +typedef struct { + uint16_t pChannels[NUM_11A_EEPROM_CHANNELS_2413]; + uint16_t numChannels; + uint16_t xpd_mask; /* mask of permitted xpd_gains */ + EEPROM_DATA_PER_CHANNEL_2413 pDataPerChannel[NUM_11A_EEPROM_CHANNELS_2413]; +} EEPROM_DATA_STRUCT_2413; + +/* + * Information retrieved from EEPROM. + */ +typedef struct { + uint16_t ee_version; /* Version field */ + uint16_t ee_protect; /* EEPROM protect field */ + uint16_t ee_regdomain; /* Regulatory domain */ + + /* General Device Parameters */ + uint16_t ee_turbo5Disable; + uint16_t ee_turbo2Disable; + uint16_t ee_rfKill; + uint16_t ee_deviceType; + uint16_t ee_turbo2WMaxPower5; + uint16_t ee_turbo2WMaxPower2; + uint16_t ee_xrTargetPower5; + uint16_t ee_xrTargetPower2; + uint16_t ee_Amode; + uint16_t ee_regCap; + uint16_t ee_Bmode; + uint16_t ee_Gmode; + int8_t ee_antennaGainMax[2]; + uint16_t ee_xtnd5GSupport; + uint8_t ee_cckOfdmPwrDelta; + uint8_t ee_exist32kHzCrystal; + uint16_t ee_targetPowersStart; + uint16_t ee_fixedBias5; + uint16_t ee_fixedBias2; + uint16_t ee_cckOfdmGainDelta; + uint16_t ee_scaledCh14FilterCckDelta; + uint16_t ee_eepMap; + uint16_t ee_earStart; + + /* 5 GHz / 2.4 GHz CKK / 2.4 GHz OFDM common parameters */ + uint16_t ee_switchSettling[3]; + uint16_t ee_txrxAtten[3]; + uint16_t ee_txEndToXLNAOn[3]; + uint16_t ee_thresh62[3]; + uint16_t ee_txEndToXPAOff[3]; + uint16_t ee_txFrameToXPAOn[3]; + int8_t ee_adcDesiredSize[3]; /* 8-bit signed value */ + int8_t ee_pgaDesiredSize[3]; /* 8-bit signed value */ + int16_t ee_noiseFloorThresh[3]; + uint16_t ee_xlnaGain[3]; + uint16_t ee_xgain[3]; + uint16_t ee_xpd[3]; + uint16_t ee_antennaControl[11][3]; + uint16_t ee_falseDetectBackoff[3]; + uint16_t ee_gainI[3]; + uint16_t ee_rxtxMargin[3]; + + /* new parameters added for the AR2413 */ + HAL_BOOL ee_disableXr5; + HAL_BOOL ee_disableXr2; + uint16_t ee_eepMap2PowerCalStart; + uint16_t ee_capField; + + uint16_t ee_switchSettlingTurbo[2]; + uint16_t ee_txrxAttenTurbo[2]; + int8_t ee_adcDesiredSizeTurbo[2]; + int8_t ee_pgaDesiredSizeTurbo[2]; + uint16_t ee_rxtxMarginTurbo[2]; + + /* 5 GHz parameters */ + uint16_t ee_ob1; + uint16_t ee_db1; + uint16_t ee_ob2; + uint16_t ee_db2; + uint16_t ee_ob3; + uint16_t ee_db3; + uint16_t ee_ob4; + uint16_t ee_db4; + + /* 2.4 GHz parameters */ + uint16_t ee_obFor24; + uint16_t ee_dbFor24; + uint16_t ee_obFor24g; + uint16_t ee_dbFor24g; + uint16_t ee_ob2GHz[2]; + uint16_t ee_db2GHz[2]; + uint16_t ee_numCtls; + uint16_t ee_ctl[NUM_CTLS_MAX]; + uint16_t ee_iqCalI[2]; + uint16_t ee_iqCalQ[2]; + uint16_t ee_calPier11g[NUM_2_4_EEPROM_CHANNELS]; + uint16_t ee_calPier11b[NUM_2_4_EEPROM_CHANNELS]; + + /* corner calibration information */ + CORNER_CAL_INFO ee_cornerCal; + + uint16_t ee_opCap; + + /* 11a info */ + uint16_t ee_channels11a[NUM_11A_EEPROM_CHANNELS]; + uint16_t ee_numChannels11a; + DATA_PER_CHANNEL ee_dataPerChannel11a[NUM_11A_EEPROM_CHANNELS]; + + uint16_t ee_numChannels2_4; + uint16_t ee_channels11g[NUM_2_4_EEPROM_CHANNELS]; + uint16_t ee_channels11b[NUM_2_4_EEPROM_CHANNELS]; + uint16_t ee_spurChans[AR_EEPROM_MODAL_SPURS][2]; + + /* 11g info */ + DATA_PER_CHANNEL ee_dataPerChannel11g[NUM_2_4_EEPROM_CHANNELS]; + + /* 11b info */ + DATA_PER_CHANNEL ee_dataPerChannel11b[NUM_2_4_EEPROM_CHANNELS]; + + TRGT_POWER_ALL_MODES ee_tpow; + + RD_EDGES_POWER ee_rdEdgesPower[NUM_EDGES*NUM_CTLS_MAX]; + + union { + EEPROM_POWER_EXPN_5112 eu_modePowerArray5112[3]; + RAW_DATA_STRUCT_2413 eu_rawDataset2413[3]; + } ee_u; +} HAL_EEPROM; + +/* write-around defines */ +#define ee_numTargetPwr_11a ee_tpow.numTargetPwr_11a +#define ee_trgtPwr_11a ee_tpow.trgtPwr_11a +#define ee_numTargetPwr_11g ee_tpow.numTargetPwr_11g +#define ee_trgtPwr_11g ee_tpow.trgtPwr_11g +#define ee_numTargetPwr_11b ee_tpow.numTargetPwr_11b +#define ee_trgtPwr_11b ee_tpow.trgtPwr_11b +#define ee_modePowerArray5112 ee_u.eu_modePowerArray5112 +#define ee_rawDataset2413 ee_u.eu_rawDataset2413 +#endif /* _ATH_AH_EEPROM_V3_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ah_eeprom_v4k.c b/sys/external/isc/atheros_hal/dist/ah_eeprom_v4k.c new file mode 100644 index 0000000..12cb67e --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_eeprom_v4k.c @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2009 Rui Paulo + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_eeprom_v14.h" +#include "ah_eeprom_v4k.h" + +static HAL_STATUS +v4kEepromGet(struct ath_hal *ah, int param, void *val) +{ +#define CHAN_A_IDX 0 +#define CHAN_B_IDX 1 +#define IS_VERS(op, v) ((pBase->version & AR5416_EEP_VER_MINOR_MASK) op (v)) + HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + const MODAL_EEP4K_HEADER *pModal = &ee->ee_base.modalHeader; + const BASE_EEP4K_HEADER *pBase = &ee->ee_base.baseEepHeader; + uint32_t sum; + uint8_t *macaddr; + int i; + + switch (param) { + case AR_EEP_NFTHRESH_2: + *(int16_t *)val = pModal->noiseFloorThreshCh[0]; + return HAL_OK; + case AR_EEP_MACADDR: /* Get MAC Address */ + sum = 0; + macaddr = val; + for (i = 0; i < 6; i++) { + macaddr[i] = pBase->macAddr[i]; + sum += pBase->macAddr[i]; + } + if (sum == 0 || sum == 0xffff*3) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad mac address %s\n", + __func__, ath_hal_ether_sprintf(macaddr)); + return HAL_EEBADMAC; + } + return HAL_OK; + case AR_EEP_REGDMN_0: + return pBase->regDmn[0]; + case AR_EEP_REGDMN_1: + return pBase->regDmn[1]; + case AR_EEP_OPCAP: + return pBase->deviceCap; + case AR_EEP_OPMODE: + return pBase->opCapFlags; + case AR_EEP_RFSILENT: + return pBase->rfSilent; + case AR_EEP_OB_2: + return pModal->ob_0; + case AR_EEP_DB_2: + return pModal->db1_1; + case AR_EEP_TXMASK: + return pBase->txMask; + case AR_EEP_RXMASK: + return pBase->rxMask; + case AR_EEP_RXGAIN_TYPE: + return AR5416_EEP_RXGAIN_ORIG; + case AR_EEP_TXGAIN_TYPE: + return pBase->txGainType; + case AR_EEP_OL_PWRCTRL: + HALASSERT(val == AH_NULL); + return HAL_EIO; + case AR_EEP_AMODE: + HALASSERT(val == AH_NULL); + return pBase->opCapFlags & AR5416_OPFLAGS_11A ? + HAL_OK : HAL_EIO; + case AR_EEP_BMODE: + case AR_EEP_GMODE: + HALASSERT(val == AH_NULL); + return pBase->opCapFlags & AR5416_OPFLAGS_11G ? + HAL_OK : HAL_EIO; + case AR_EEP_32KHZCRYSTAL: + case AR_EEP_COMPRESS: + case AR_EEP_FASTFRAME: /* XXX policy decision, h/w can do it */ + case AR_EEP_WRITEPROTECT: /* NB: no write protect bit */ + HALASSERT(val == AH_NULL); + /* fall thru... */ + case AR_EEP_MAXQCU: /* NB: not in opCapFlags */ + case AR_EEP_KCENTRIES: /* NB: not in opCapFlags */ + return HAL_EIO; + case AR_EEP_AES: + case AR_EEP_BURST: + case AR_EEP_RFKILL: + case AR_EEP_TURBO2DISABLE: + HALASSERT(val == AH_NULL); + return HAL_OK; + case AR_EEP_ANTGAINMAX_2: + *(int8_t *) val = ee->ee_antennaGainMax; + return HAL_OK; + default: + HALASSERT(0); + return HAL_EINVAL; + } +#undef IS_VERS +#undef CHAN_A_IDX +#undef CHAN_B_IDX +} + +static HAL_STATUS +v4kEepromSet(struct ath_hal *ah, int param, int v) +{ + HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (param) { + case AR_EEP_ANTGAINMAX_2: + ee->ee_antennaGainMax = (int8_t) v; + return HAL_OK; + } + return HAL_EINVAL; +} + +static HAL_BOOL +v4kEepromDiag(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, void **result, uint32_t *resultsize) +{ + HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (request) { + case HAL_DIAG_EEPROM: + *result = ee; + *resultsize = sizeof(HAL_EEPROM_v4k); + return AH_TRUE; + } + return AH_FALSE; +} + +/* Do structure specific swaps if Eeprom format is non native to host */ +static void +eepromSwap(struct ar5416eeprom_4k *ee) +{ + uint32_t integer, i; + uint16_t word; + MODAL_EEP4K_HEADER *pModal; + + /* convert Base Eep header */ + word = __bswap16(ee->baseEepHeader.length); + ee->baseEepHeader.length = word; + + word = __bswap16(ee->baseEepHeader.checksum); + ee->baseEepHeader.checksum = word; + + word = __bswap16(ee->baseEepHeader.version); + ee->baseEepHeader.version = word; + + word = __bswap16(ee->baseEepHeader.regDmn[0]); + ee->baseEepHeader.regDmn[0] = word; + + word = __bswap16(ee->baseEepHeader.regDmn[1]); + ee->baseEepHeader.regDmn[1] = word; + + word = __bswap16(ee->baseEepHeader.rfSilent); + ee->baseEepHeader.rfSilent = word; + + word = __bswap16(ee->baseEepHeader.blueToothOptions); + ee->baseEepHeader.blueToothOptions = word; + + word = __bswap16(ee->baseEepHeader.deviceCap); + ee->baseEepHeader.deviceCap = word; + + /* convert Modal Eep header */ + pModal = &ee->modalHeader; + + /* XXX linux/ah_osdep.h only defines __bswap32 for BE */ + integer = __bswap32(pModal->antCtrlCommon); + pModal->antCtrlCommon = integer; + + for (i = 0; i < AR5416_4K_MAX_CHAINS; i++) { + integer = __bswap32(pModal->antCtrlChain[i]); + pModal->antCtrlChain[i] = integer; + } + + for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { + word = __bswap16(pModal->spurChans[i].spurChan); + pModal->spurChans[i].spurChan = word; + } +} + +static uint16_t +v4kEepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) +{ + HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + + HALASSERT(0 <= ix && ix < AR5416_EEPROM_MODAL_SPURS); + HALASSERT(is2GHz); + return ee->ee_base.modalHeader.spurChans[ix].spurChan; +} + +/************************************************************************** + * fbin2freq + * + * Get channel value from binary representation held in eeprom + * RETURNS: the frequency in MHz + */ +static uint16_t +fbin2freq(uint8_t fbin, HAL_BOOL is2GHz) +{ + /* + * Reserved value 0xFF provides an empty definition both as + * an fbin and as a frequency - do not convert + */ + if (fbin == AR5416_BCHAN_UNUSED) + return fbin; + return (uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); +} + +/* + * Copy EEPROM Conformance Testing Limits contents + * into the allocated space + */ +/* USE CTLS from chain zero */ +#define CTL_CHAIN 0 + +static void +v4kEepromReadCTLInfo(struct ath_hal *ah, HAL_EEPROM_v4k *ee) +{ + RD_EDGES_POWER *rep = ee->ee_rdEdgesPower; + int i, j; + + HALASSERT(AR5416_4K_NUM_CTLS <= sizeof(ee->ee_rdEdgesPower)/NUM_EDGES); + + for (i = 0; ee->ee_base.ctlIndex[i] != 0 && i < AR5416_4K_NUM_CTLS; i++) { + for (j = 0; j < NUM_EDGES; j ++) { + /* XXX Confirm this is the right thing to do when an invalid channel is stored */ + if (ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].bChannel == AR5416_BCHAN_UNUSED) { + rep[j].rdEdge = 0; + rep[j].twice_rdEdgePower = 0; + rep[j].flag = 0; + } else { + rep[j].rdEdge = fbin2freq( + ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].bChannel, + (ee->ee_base.ctlIndex[i] & CTL_MODE_M) != CTL_11A); + rep[j].twice_rdEdgePower = MS(ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].tPowerFlag, CAL_CTL_EDGES_POWER); + rep[j].flag = MS(ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].tPowerFlag, CAL_CTL_EDGES_FLAG) != 0; + } + } + rep += NUM_EDGES; + } + ee->ee_numCtls = i; + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "%s Numctls = %u\n",__func__,i); +} + +/* + * Reclaim any EEPROM-related storage. + */ +static void +v4kEepromDetach(struct ath_hal *ah) +{ + HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + + ath_hal_free(ee); + AH_PRIVATE(ah)->ah_eeprom = AH_NULL; +} + +#define owl_get_eep_ver(_ee) \ + (((_ee)->ee_base.baseEepHeader.version >> 12) & 0xF) +#define owl_get_eep_rev(_ee) \ + (((_ee)->ee_base.baseEepHeader.version) & 0xFFF) + +HAL_STATUS +ath_hal_v4kEepromAttach(struct ath_hal *ah) +{ +#define NW(a) (sizeof(a) / sizeof(uint16_t)) + HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t *eep_data, magic; + HAL_BOOL need_swap; + u_int w, off, len; + uint32_t sum; + + HALASSERT(ee == AH_NULL); + /* + * Don't check magic if we're supplied with an EEPROM block, + * typically this is from Howl but it may also be from later + * boards w/ an embedded WMAC. + */ + if (ah->ah_eepromdata == NULL) { + if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s Error reading Eeprom MAGIC\n", __func__); + return HAL_EEREAD; + } + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s Eeprom Magic = 0x%x\n", + __func__, magic); + if (magic != AR5416_EEPROM_MAGIC) { + HALDEBUG(ah, HAL_DEBUG_ANY, "Bad magic number\n"); + return HAL_EEMAGIC; + } + } + + ee = ath_hal_malloc(sizeof(HAL_EEPROM_v4k)); + if (ee == AH_NULL) { + /* XXX message */ + return HAL_ENOMEM; + } + + eep_data = (uint16_t *)&ee->ee_base; + for (w = 0; w < NW(struct ar5416eeprom_4k); w++) { + off = owl_eep_start_loc + w; /* NB: AP71 starts at 0 */ + if (!ath_hal_eepromRead(ah, off, &eep_data[w])) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s eeprom read error at offset 0x%x\n", + __func__, off); + return HAL_EEREAD; + } + } + /* Convert to eeprom native eeprom endian format */ + /* + * XXX this is likely incorrect but will do for now + * XXX to get embedded boards working. + */ + if (ah->ah_eepromdata == NULL && isBigEndian()) { + for (w = 0; w < NW(struct ar5416eeprom_4k); w++) + eep_data[w] = __bswap16(eep_data[w]); + } + + /* + * At this point, we're in the native eeprom endian format + * Now, determine the eeprom endian by looking at byte 26?? + */ + need_swap = ((ee->ee_base.baseEepHeader.eepMisc & AR5416_EEPMISC_BIG_ENDIAN) != 0) ^ isBigEndian(); + if (need_swap) { + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "Byte swap EEPROM contents.\n"); + len = __bswap16(ee->ee_base.baseEepHeader.length); + } else { + len = ee->ee_base.baseEepHeader.length; + } + len = AH_MIN(len, sizeof(struct ar5416eeprom_4k)) / sizeof(uint16_t); + + /* Apply the checksum, done in native eeprom format */ + /* XXX - Need to check to make sure checksum calculation is done + * in the correct endian format. Right now, it seems it would + * cast the raw data to host format and do the calculation, which may + * not be correct as the calculation may need to be done in the native + * eeprom format + */ + sum = 0; + for (w = 0; w < len; w++) { + sum ^= eep_data[w]; + } + /* Check CRC - Attach should fail on a bad checksum */ + if (sum != 0xffff) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "Bad EEPROM checksum 0x%x (Len=%u)\n", sum, len); + return HAL_EEBADSUM; + } + + if (need_swap) + eepromSwap(&ee->ee_base); /* byte swap multi-byte data */ + + /* swap words 0+2 so version is at the front */ + magic = eep_data[0]; + eep_data[0] = eep_data[2]; + eep_data[2] = magic; + + HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, + "%s Eeprom Version %u.%u\n", __func__, + owl_get_eep_ver(ee), owl_get_eep_rev(ee)); + + /* NB: must be after all byte swapping */ + if (owl_get_eep_ver(ee) != AR5416_EEP_VER) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "Bad EEPROM version 0x%x\n", owl_get_eep_ver(ee)); + return HAL_EEBADSUM; + } + + v4kEepromReadCTLInfo(ah, ee); /* Get CTLs */ + + AH_PRIVATE(ah)->ah_eeprom = ee; + AH_PRIVATE(ah)->ah_eeversion = ee->ee_base.baseEepHeader.version; + AH_PRIVATE(ah)->ah_eepromDetach = v4kEepromDetach; + AH_PRIVATE(ah)->ah_eepromGet = v4kEepromGet; + AH_PRIVATE(ah)->ah_eepromSet = v4kEepromSet; + AH_PRIVATE(ah)->ah_getSpurChan = v4kEepromGetSpurChan; + AH_PRIVATE(ah)->ah_eepromDiag = v4kEepromDiag; + return HAL_OK; +#undef NW +} diff --git a/sys/external/isc/atheros_hal/dist/ah_eeprom_v4k.h b/sys/external/isc/atheros_hal/dist/ah_eeprom_v4k.h new file mode 100644 index 0000000..3487de4 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_eeprom_v4k.h @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2009 Rui Paulo + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _AH_EEPROM_V4K_H_ +#define _AH_EEPROM_V4K_H_ + +#include "ah_eeprom.h" +#include "ah_eeprom_v14.h" + +#if _BYTE_ORDER == _BIG_ENDIAN +#define __BIG_ENDIAN_BITFIELD +#endif + +#define AR9285_RDEXT_DEFAULT 0x1F + +#define AR5416_4K_EEP_PD_GAIN_BOUNDARY_DEFAULT 58 + +#undef owl_eep_start_loc +#ifdef __LINUX_ARM_ARCH__ /* AP71 */ +#define owl_eep_start_loc 0 +#else +#define owl_eep_start_loc 64 +#endif + +// 16-bit offset location start of calibration struct +#define AR5416_4K_EEP_START_LOC 64 +#define AR5416_4K_NUM_2G_CAL_PIERS 3 +#define AR5416_4K_NUM_2G_CCK_TARGET_POWERS 3 +#define AR5416_4K_NUM_2G_20_TARGET_POWERS 3 +#define AR5416_4K_NUM_2G_40_TARGET_POWERS 3 +#define AR5416_4K_NUM_CTLS 12 +#define AR5416_4K_NUM_BAND_EDGES 4 +#define AR5416_4K_NUM_PD_GAINS 2 +#define AR5416_4K_MAX_CHAINS 1 + +/* + * NB: The format in EEPROM has words 0 and 2 swapped (i.e. version + * and length are swapped). We reverse their position after reading + * the data into host memory so the version field is at the same + * offset as in previous EEPROM layouts. This makes utilities that + * inspect the EEPROM contents work without looking at the PCI device + * id which may or may not be reliable. + */ +typedef struct BaseEepHeader4k { + uint16_t version; /* NB: length in EEPROM */ + uint16_t checksum; + uint16_t length; /* NB: version in EEPROM */ + uint8_t opCapFlags; + uint8_t eepMisc; + uint16_t regDmn[2]; + uint8_t macAddr[6]; + uint8_t rxMask; + uint8_t txMask; + uint16_t rfSilent; + uint16_t blueToothOptions; + uint16_t deviceCap; + uint32_t binBuildNumber; + uint8_t deviceType; + uint8_t txGainType; /* high power tx gain table support */ +} __packed BASE_EEP4K_HEADER; // 32 B + +typedef struct ModalEepHeader4k { + uint32_t antCtrlChain[AR5416_4K_MAX_CHAINS]; // 4 + uint32_t antCtrlCommon; // 4 + int8_t antennaGainCh[AR5416_4K_MAX_CHAINS]; // 1 + uint8_t switchSettling; // 1 + uint8_t txRxAttenCh[AR5416_4K_MAX_CHAINS]; // 1 + uint8_t rxTxMarginCh[AR5416_4K_MAX_CHAINS]; // 1 + uint8_t adcDesiredSize; // 1 + int8_t pgaDesiredSize; // 1 + uint8_t xlnaGainCh[AR5416_4K_MAX_CHAINS]; // 1 + uint8_t txEndToXpaOff; // 1 + uint8_t txEndToRxOn; // 1 + uint8_t txFrameToXpaOn; // 1 + uint8_t thresh62; // 1 + uint8_t noiseFloorThreshCh[AR5416_4K_MAX_CHAINS]; // 1 + uint8_t xpdGain; // 1 + uint8_t xpd; // 1 + int8_t iqCalICh[AR5416_4K_MAX_CHAINS]; // 1 + int8_t iqCalQCh[AR5416_4K_MAX_CHAINS]; // 1 + + uint8_t pdGainOverlap; // 1 + +#ifdef __BIG_ENDIAN_BITFIELD + uint8_t ob_1:4, ob_0:4; // 1 + uint8_t db1_1:4, db1_0:4; // 1 +#else + uint8_t ob_0:4, ob_1:4; + uint8_t db1_0:4, db1_1:4; +#endif + + uint8_t xpaBiasLvl; // 1 + uint8_t txFrameToDataStart; // 1 + uint8_t txFrameToPaOn; // 1 + uint8_t ht40PowerIncForPdadc; // 1 + uint8_t bswAtten[AR5416_4K_MAX_CHAINS]; // 1 + uint8_t bswMargin[AR5416_4K_MAX_CHAINS]; // 1 + uint8_t swSettleHt40; // 1 + uint8_t xatten2Db[AR5416_4K_MAX_CHAINS]; // 1 + uint8_t xatten2Margin[AR5416_4K_MAX_CHAINS]; // 1 + +#ifdef __BIG_ENDIAN_BITFIELD + uint8_t db2_1:4, db2_0:4; // 1 +#else + uint8_t db2_0:4, db2_1:4; // 1 +#endif + + uint8_t version; // 1 + +#ifdef __BIG_ENDIAN_BITFIELD + uint8_t ob_3:4, ob_2:4; // 1 + uint8_t antdiv_ctl1:4, ob_4:4; // 1 + uint8_t db1_3:4, db1_2:4; // 1 + uint8_t antdiv_ctl2:4, db1_4:4; // 1 + uint8_t db2_2:4, db2_3:4; // 1 + uint8_t reserved:4, db2_4:4; // 1 +#else + uint8_t ob_2:4, ob_3:4; + uint8_t ob_4:4, antdiv_ctl1:4; + uint8_t db1_2:4, db1_3:4; + uint8_t db1_4:4, antdiv_ctl2:4; + uint8_t db2_2:4, db2_3:4; + uint8_t db2_4:4, reserved:4; +#endif + uint8_t tx_diversity; + uint8_t flc_pwr_thresh; + uint8_t bb_scale_smrt_antenna; +#define EEP_4K_BB_DESIRED_SCALE_MASK 0x1f + uint8_t futureModal[1]; + + SPUR_CHAN spurChans[AR5416_EEPROM_MODAL_SPURS]; // 20 B +} __packed MODAL_EEP4K_HEADER; // == 68 B + +typedef struct CalCtlData4k { + CAL_CTL_EDGES ctlEdges[AR5416_4K_MAX_CHAINS][AR5416_4K_NUM_BAND_EDGES]; +} __packed CAL_CTL_DATA_4K; + +typedef struct calDataPerFreq4k { + uint8_t pwrPdg[AR5416_4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; + uint8_t vpdPdg[AR5416_4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; +} __packed CAL_DATA_PER_FREQ_4K; + +struct ar5416eeprom_4k { + BASE_EEP4K_HEADER baseEepHeader; // 32 B + uint8_t custData[20]; // 20 B + MODAL_EEP4K_HEADER modalHeader; // 68 B + uint8_t calFreqPier2G[AR5416_4K_NUM_2G_CAL_PIERS]; + CAL_DATA_PER_FREQ_4K calPierData2G[AR5416_4K_MAX_CHAINS][AR5416_4K_NUM_2G_CAL_PIERS]; + CAL_TARGET_POWER_LEG calTargetPowerCck[AR5416_4K_NUM_2G_CCK_TARGET_POWERS]; + CAL_TARGET_POWER_LEG calTargetPower2G[AR5416_4K_NUM_2G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT calTargetPower2GHT20[AR5416_4K_NUM_2G_20_TARGET_POWERS]; + CAL_TARGET_POWER_HT calTargetPower2GHT40[AR5416_4K_NUM_2G_40_TARGET_POWERS]; + uint8_t ctlIndex[AR5416_4K_NUM_CTLS]; + CAL_CTL_DATA_4K ctlData[AR5416_4K_NUM_CTLS]; + uint8_t padding; +} __packed; + +typedef struct { + struct ar5416eeprom_4k ee_base; +#define NUM_EDGES 8 + uint16_t ee_numCtls; + RD_EDGES_POWER ee_rdEdgesPower[NUM_EDGES*AR5416_4K_NUM_CTLS]; + /* XXX these are dynamically calculated for use by shared code */ + int8_t ee_antennaGainMax; +} HAL_EEPROM_v4k; +#endif /* _AH_EEPROM_V4K_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ah_internal.h b/sys/external/isc/atheros_hal/dist/ah_internal.h new file mode 100644 index 0000000..a4c7656 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_internal.h @@ -0,0 +1,1047 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AH_INTERAL_H_ +#define _ATH_AH_INTERAL_H_ +/* + * Atheros Device Hardware Access Layer (HAL). + * + * Internal definitions. + */ +#define AH_NULL 0 +#define AH_MIN(a,b) ((a)<(b)?(a):(b)) +#define AH_MAX(a,b) ((a)>(b)?(a):(b)) + +#include +#include "opt_ah.h" /* needed for AH_SUPPORT_AR5416 */ + +#ifndef AH_SUPPORT_AR5416 +#define AH_SUPPORT_AR5416 1 +#endif + +#ifndef NBBY +#define NBBY 8 /* number of bits/byte */ +#endif + +#ifndef roundup +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */ +#endif +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif + +#ifndef offsetof +#define offsetof(type, field) ((size_t)(&((type *)0)->field)) +#endif + +typedef struct { + uint32_t start; /* first register */ + uint32_t end; /* ending register or zero */ +} HAL_REGRANGE; + +typedef struct { + uint32_t addr; /* regiser address/offset */ + uint32_t value; /* value to write */ +} HAL_REGWRITE; + +/* + * Transmit power scale factor. + * + * NB: This is not public because we want to discourage the use of + * scaling; folks should use the tx power limit interface. + */ +typedef enum { + HAL_TP_SCALE_MAX = 0, /* no scaling (default) */ + HAL_TP_SCALE_50 = 1, /* 50% of max (-3 dBm) */ + HAL_TP_SCALE_25 = 2, /* 25% of max (-6 dBm) */ + HAL_TP_SCALE_12 = 3, /* 12% of max (-9 dBm) */ + HAL_TP_SCALE_MIN = 4, /* min, but still on */ +} HAL_TP_SCALE; + +typedef enum { + HAL_CAP_RADAR = 0, /* Radar capability */ + HAL_CAP_AR = 1, /* AR capability */ +} HAL_PHYDIAG_CAPS; + +/* + * Enable/disable strong signal fast diversity + */ +#define HAL_CAP_STRONG_DIV 2 + +/* + * Each chip or class of chips registers to offer support. + */ +struct ath_hal_chip { + const char *name; + const char *(*probe)(uint16_t vendorid, uint16_t devid); + struct ath_hal *(*attach)(uint16_t devid, HAL_SOFTC, + HAL_BUS_TAG, HAL_BUS_HANDLE, uint16_t *eepromdata, + HAL_OPS_CONFIG *ah, + HAL_STATUS *error); +}; +#ifndef AH_CHIP +#define AH_CHIP(_name, _probe, _attach) \ +static struct ath_hal_chip _name##_chip = { \ + .name = #_name, \ + .probe = _probe, \ + .attach = _attach \ +}; \ +OS_DATA_SET(ah_chips, _name##_chip) +#endif + +/* + * Each RF backend registers to offer support; this is mostly + * used by multi-chip 5212 solutions. Single-chip solutions + * have a fixed idea about which RF to use. + */ +struct ath_hal_rf { + const char *name; + HAL_BOOL (*probe)(struct ath_hal *ah); + HAL_BOOL (*attach)(struct ath_hal *ah, HAL_STATUS *ecode); +}; +#ifndef AH_RF +#define AH_RF(_name, _probe, _attach) \ +static struct ath_hal_rf _name##_rf = { \ + .name = __STRING(_name), \ + .probe = _probe, \ + .attach = _attach \ +}; \ +OS_DATA_SET(ah_rfs, _name##_rf) +#endif + +struct ath_hal_rf *ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode); + +/* + * Maximum number of internal channels. Entries are per unique + * frequency so this might be need to be increased to handle all + * usage cases; typically no more than 32 are really needed but + * dynamically allocating the data structures is a bit painful + * right now. + */ +#ifndef AH_MAXCHAN +#define AH_MAXCHAN 96 +#endif + +#define HAL_NF_CAL_HIST_LEN_FULL 5 +#define HAL_NF_CAL_HIST_LEN_SMALL 1 +#define HAL_NUM_NF_READINGS 6 /* 3 chains * (ctl + ext) */ +#define HAL_NF_LOAD_DELAY 1000 + +/* + * PER_CHAN doesn't work for now, as it looks like the device layer + * has to pre-populate the per-channel list with nominal values. + */ +//#define ATH_NF_PER_CHAN 1 + +typedef struct { + u_int8_t curr_index; + int8_t invalidNFcount; /* TO DO: REMOVE THIS! */ + int16_t priv_nf[HAL_NUM_NF_READINGS]; +} HAL_NFCAL_BASE; + +typedef struct { + HAL_NFCAL_BASE base; + int16_t nf_cal_buffer[HAL_NF_CAL_HIST_LEN_FULL][HAL_NUM_NF_READINGS]; +} HAL_NFCAL_HIST_FULL; + +typedef struct { + HAL_NFCAL_BASE base; + int16_t nf_cal_buffer[HAL_NF_CAL_HIST_LEN_SMALL][HAL_NUM_NF_READINGS]; +} HAL_NFCAL_HIST_SMALL; + +#ifdef ATH_NF_PER_CHAN +typedef HAL_NFCAL_HIST_FULL HAL_CHAN_NFCAL_HIST; +#define AH_HOME_CHAN_NFCAL_HIST(ah, ichan) (ichan ? &ichan->nf_cal_hist: NULL) +#else +typedef HAL_NFCAL_HIST_SMALL HAL_CHAN_NFCAL_HIST; +#define AH_HOME_CHAN_NFCAL_HIST(ah, ichan) (&AH_PRIVATE(ah)->nf_cal_hist) +#endif /* ATH_NF_PER_CHAN */ + +/* + * Internal per-channel state. These are found + * using ic_devdata in the ieee80211_channel. + */ +typedef struct { + uint16_t channel; /* h/w frequency, NB: may be mapped */ + uint8_t privFlags; +#define CHANNEL_IQVALID 0x01 /* IQ calibration valid */ +#define CHANNEL_ANI_INIT 0x02 /* ANI state initialized */ +#define CHANNEL_ANI_SETUP 0x04 /* ANI state setup */ +#define CHANNEL_MIMO_NF_VALID 0x04 /* Mimo NF values are valid */ + uint8_t calValid; /* bitmask of cal types */ + int8_t iCoff; + int8_t qCoff; + int16_t rawNoiseFloor; + int16_t noiseFloorAdjust; +#ifdef AH_SUPPORT_AR5416 + int16_t noiseFloorCtl[AH_MAX_CHAINS]; + int16_t noiseFloorExt[AH_MAX_CHAINS]; +#endif /* AH_SUPPORT_AR5416 */ + uint16_t mainSpur; /* cached spur value for this channel */ + + /*XXX TODO: make these part of privFlags */ + uint8_t paprd_done:1, /* 1: PAPRD DONE, 0: PAPRD Cal not done */ + paprd_table_write_done:1; /* 1: DONE, 0: Cal data write not done */ + int one_time_cals_done; + HAL_CHAN_NFCAL_HIST nf_cal_hist; +} HAL_CHANNEL_INTERNAL; + +/* channel requires noise floor check */ +#define CHANNEL_NFCREQUIRED IEEE80211_CHAN_PRIV0 + +/* all full-width channels */ +#define IEEE80211_CHAN_ALLFULL \ + (IEEE80211_CHAN_ALL - (IEEE80211_CHAN_HALF | IEEE80211_CHAN_QUARTER)) +#define IEEE80211_CHAN_ALLTURBOFULL \ + (IEEE80211_CHAN_ALLTURBO - \ + (IEEE80211_CHAN_HALF | IEEE80211_CHAN_QUARTER)) + +typedef struct { + uint32_t halChanSpreadSupport : 1, + halSleepAfterBeaconBroken : 1, + halCompressSupport : 1, + halBurstSupport : 1, + halFastFramesSupport : 1, + halChapTuningSupport : 1, + halTurboGSupport : 1, + halTurboPrimeSupport : 1, + halMicAesCcmSupport : 1, + halMicCkipSupport : 1, + halMicTkipSupport : 1, + halTkipMicTxRxKeySupport : 1, + halCipherAesCcmSupport : 1, + halCipherCkipSupport : 1, + halCipherTkipSupport : 1, + halPSPollBroken : 1, + halVEOLSupport : 1, + halBssIdMaskSupport : 1, + halMcastKeySrchSupport : 1, + halTsfAddSupport : 1, + halChanHalfRate : 1, + halChanQuarterRate : 1, + halHTSupport : 1, + halHTSGI20Support : 1, + halRfSilentSupport : 1, + halHwPhyCounterSupport : 1, + halWowSupport : 1, + halWowMatchPatternExact : 1, + halAutoSleepSupport : 1, + halFastCCSupport : 1, + halBtCoexSupport : 1; + uint32_t halRxStbcSupport : 1, + halTxStbcSupport : 1, + halGTTSupport : 1, + halCSTSupport : 1, + halRifsRxSupport : 1, + halRifsTxSupport : 1, + hal4AddrAggrSupport : 1, + halExtChanDfsSupport : 1, + halUseCombinedRadarRssi : 1, + halForcePpmSupport : 1, + halEnhancedPmSupport : 1, + halEnhancedDfsSupport : 1, + halMbssidAggrSupport : 1, + halBssidMatchSupport : 1, + hal4kbSplitTransSupport : 1, + halHasRxSelfLinkedTail : 1, + halSupportsFastClock5GHz : 1, + halHasLongRxDescTsf : 1, + halHasBBReadWar : 1, + halSerialiseRegWar : 1, + halMciSupport : 1, + halRxTxAbortSupport : 1, + halPaprdEnabled : 1, + halHasUapsdSupport : 1, + halWpsPushButtonSupport : 1, + halBtCoexApsmWar : 1, + halGenTimerSupport : 1, + halLDPCSupport : 1, + halHwBeaconProcSupport : 1, + halEnhancedDmaSupport : 1; + uint32_t halIsrRacSupport : 1, + halApmEnable : 1, + halIntrMitigation : 1, + hal49GhzSupport : 1, + halAntDivCombSupport : 1, + halAntDivCombSupportOrg : 1, + halRadioRetentionSupport : 1, + halSpectralScanSupport : 1, + halRxUsingLnaMixing : 1, + halRxDoMyBeacon : 1, + halHwUapsdTrig : 1; + + uint32_t halWirelessModes; + uint16_t halTotalQueues; + uint16_t halKeyCacheSize; + uint16_t halLow5GhzChan, halHigh5GhzChan; + uint16_t halLow2GhzChan, halHigh2GhzChan; + int halTstampPrecision; + int halRtsAggrLimit; + uint8_t halTxChainMask; + uint8_t halRxChainMask; + uint8_t halNumGpioPins; + uint8_t halNumAntCfg2GHz; + uint8_t halNumAntCfg5GHz; + uint32_t halIntrMask; + uint8_t halTxStreams; + uint8_t halRxStreams; + HAL_MFP_OPT_T halMfpSupport; + + /* AR9300 HAL porting capabilities */ + int hal_paprd_enabled; + int hal_pcie_lcr_offset; + int hal_pcie_lcr_extsync_en; + int halNumTxMaps; + int halTxDescLen; + int halTxStatusLen; + int halRxStatusLen; + int halRxHpFifoDepth; + int halRxLpFifoDepth; + uint32_t halRegCap; /* XXX needed? */ + int halNumMRRetries; + int hal_ani_poll_interval; + int hal_channel_switch_time_usec; +} HAL_CAPABILITIES; + +struct regDomain; + +/* + * Definitions for ah_flags in ath_hal_private + */ +#define AH_USE_EEPROM 0x1 +#define AH_IS_HB63 0x2 + +/* + * The ``private area'' follows immediately after the ``public area'' + * in the data structure returned by ath_hal_attach. Private data are + * used by device-independent code such as the regulatory domain support. + * In general, code within the HAL should never depend on data in the + * public area. Instead any public data needed internally should be + * shadowed here. + * + * When declaring a device-specific ath_hal data structure this structure + * is assumed to at the front; e.g. + * + * struct ath_hal_5212 { + * struct ath_hal_private ah_priv; + * ... + * }; + * + * It might be better to manage the method pointers in this structure + * using an indirect pointer to a read-only data structure but this would + * disallow class-style method overriding. + */ +struct ath_hal_private { + struct ath_hal h; /* public area */ + + /* NB: all methods go first to simplify initialization */ + HAL_BOOL (*ah_getChannelEdges)(struct ath_hal*, + uint16_t channelFlags, + uint16_t *lowChannel, uint16_t *highChannel); + u_int (*ah_getWirelessModes)(struct ath_hal*); + HAL_BOOL (*ah_eepromRead)(struct ath_hal *, u_int off, + uint16_t *data); + HAL_BOOL (*ah_eepromWrite)(struct ath_hal *, u_int off, + uint16_t data); + HAL_BOOL (*ah_getChipPowerLimits)(struct ath_hal *, + struct ieee80211_channel *); + int16_t (*ah_getNfAdjust)(struct ath_hal *, + const HAL_CHANNEL_INTERNAL*); + void (*ah_getNoiseFloor)(struct ath_hal *, + int16_t nfarray[]); + + void *ah_eeprom; /* opaque EEPROM state */ + uint16_t ah_eeversion; /* EEPROM version */ + void (*ah_eepromDetach)(struct ath_hal *); + HAL_STATUS (*ah_eepromGet)(struct ath_hal *, int, void *); + HAL_STATUS (*ah_eepromSet)(struct ath_hal *, int, int); + uint16_t (*ah_getSpurChan)(struct ath_hal *, int, HAL_BOOL); + HAL_BOOL (*ah_eepromDiag)(struct ath_hal *, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); + + /* + * Device revision information. + */ + uint16_t ah_devid; /* PCI device ID */ + uint16_t ah_subvendorid; /* PCI subvendor ID */ + uint32_t ah_macVersion; /* MAC version id */ + uint16_t ah_macRev; /* MAC revision */ + uint16_t ah_phyRev; /* PHY revision */ + uint16_t ah_analog5GhzRev; /* 2GHz radio revision */ + uint16_t ah_analog2GhzRev; /* 5GHz radio revision */ + uint32_t ah_flags; /* misc flags */ + uint8_t ah_ispcie; /* PCIE, special treatment */ + uint8_t ah_devType; /* card type - CB, PCI, PCIe */ + + HAL_OPMODE ah_opmode; /* operating mode from reset */ + const struct ieee80211_channel *ah_curchan;/* operating channel */ + HAL_CAPABILITIES ah_caps; /* device capabilities */ + uint32_t ah_diagreg; /* user-specified AR_DIAG_SW */ + int16_t ah_powerLimit; /* tx power cap */ + uint16_t ah_maxPowerLevel; /* calculated max tx power */ + u_int ah_tpScale; /* tx power scale factor */ + u_int16_t ah_extraTxPow; /* low rates extra-txpower */ + uint32_t ah_11nCompat; /* 11n compat controls */ + + /* + * State for regulatory domain handling. + */ + HAL_REG_DOMAIN ah_currentRD; /* EEPROM regulatory domain */ + HAL_REG_DOMAIN ah_currentRDext; /* EEPROM extended regdomain flags */ + HAL_DFS_DOMAIN ah_dfsDomain; /* current DFS domain */ + HAL_CHANNEL_INTERNAL ah_channels[AH_MAXCHAN]; /* private chan state */ + u_int ah_nchan; /* valid items in ah_channels */ + const struct regDomain *ah_rd2GHz; /* reg state for 2G band */ + const struct regDomain *ah_rd5GHz; /* reg state for 5G band */ + + uint8_t ah_coverageClass; /* coverage class */ + /* + * RF Silent handling; setup according to the EEPROM. + */ + uint16_t ah_rfsilent; /* GPIO pin + polarity */ + HAL_BOOL ah_rfkillEnabled; /* enable/disable RfKill */ + /* + * Diagnostic support for discriminating HIUERR reports. + */ + uint32_t ah_fatalState[6]; /* AR_ISR+shadow regs */ + int ah_rxornIsFatal; /* how to treat HAL_INT_RXORN */ + + /* Only used if ATH_NF_PER_CHAN is defined */ + HAL_NFCAL_HIST_FULL nf_cal_hist; + + /* + * Channel survey history - current channel only. + */ + HAL_CHANNEL_SURVEY ah_chansurvey; /* channel survey */ +}; + +#define AH_PRIVATE(_ah) ((struct ath_hal_private *)(_ah)) + +#define ath_hal_getChannelEdges(_ah, _cf, _lc, _hc) \ + AH_PRIVATE(_ah)->ah_getChannelEdges(_ah, _cf, _lc, _hc) +#define ath_hal_getWirelessModes(_ah) \ + AH_PRIVATE(_ah)->ah_getWirelessModes(_ah) +#define ath_hal_eepromRead(_ah, _off, _data) \ + AH_PRIVATE(_ah)->ah_eepromRead(_ah, _off, _data) +#define ath_hal_eepromWrite(_ah, _off, _data) \ + AH_PRIVATE(_ah)->ah_eepromWrite(_ah, _off, _data) +#define ath_hal_gpioCfgOutput(_ah, _gpio, _type) \ + (_ah)->ah_gpioCfgOutput(_ah, _gpio, _type) +#define ath_hal_gpioCfgInput(_ah, _gpio) \ + (_ah)->ah_gpioCfgInput(_ah, _gpio) +#define ath_hal_gpioGet(_ah, _gpio) \ + (_ah)->ah_gpioGet(_ah, _gpio) +#define ath_hal_gpioSet(_ah, _gpio, _val) \ + (_ah)->ah_gpioSet(_ah, _gpio, _val) +#define ath_hal_gpioSetIntr(_ah, _gpio, _ilevel) \ + (_ah)->ah_gpioSetIntr(_ah, _gpio, _ilevel) +#define ath_hal_getpowerlimits(_ah, _chan) \ + AH_PRIVATE(_ah)->ah_getChipPowerLimits(_ah, _chan) +#define ath_hal_getNfAdjust(_ah, _c) \ + AH_PRIVATE(_ah)->ah_getNfAdjust(_ah, _c) +#define ath_hal_getNoiseFloor(_ah, _nfArray) \ + AH_PRIVATE(_ah)->ah_getNoiseFloor(_ah, _nfArray) +#define ath_hal_configPCIE(_ah, _reset, _poweroff) \ + (_ah)->ah_configPCIE(_ah, _reset, _poweroff) +#define ath_hal_disablePCIE(_ah) \ + (_ah)->ah_disablePCIE(_ah) +#define ath_hal_setInterrupts(_ah, _mask) \ + (_ah)->ah_setInterrupts(_ah, _mask) + +#define ath_hal_isrfkillenabled(_ah) \ + (ath_hal_getcapability(_ah, HAL_CAP_RFSILENT, 1, AH_NULL) == HAL_OK) +#define ath_hal_enable_rfkill(_ah, _v) \ + ath_hal_setcapability(_ah, HAL_CAP_RFSILENT, 1, _v, AH_NULL) +#define ath_hal_hasrfkill_int(_ah) \ + (ath_hal_getcapability(_ah, HAL_CAP_RFSILENT, 3, AH_NULL) == HAL_OK) + +#define ath_hal_eepromDetach(_ah) do { \ + if (AH_PRIVATE(_ah)->ah_eepromDetach != AH_NULL) \ + AH_PRIVATE(_ah)->ah_eepromDetach(_ah); \ +} while (0) +#define ath_hal_eepromGet(_ah, _param, _val) \ + AH_PRIVATE(_ah)->ah_eepromGet(_ah, _param, _val) +#define ath_hal_eepromSet(_ah, _param, _val) \ + AH_PRIVATE(_ah)->ah_eepromSet(_ah, _param, _val) +#define ath_hal_eepromGetFlag(_ah, _param) \ + (AH_PRIVATE(_ah)->ah_eepromGet(_ah, _param, AH_NULL) == HAL_OK) +#define ath_hal_getSpurChan(_ah, _ix, _is2G) \ + AH_PRIVATE(_ah)->ah_getSpurChan(_ah, _ix, _is2G) +#define ath_hal_eepromDiag(_ah, _request, _a, _asize, _r, _rsize) \ + AH_PRIVATE(_ah)->ah_eepromDiag(_ah, _request, _a, _asize, _r, _rsize) + +#ifndef _NET_IF_IEEE80211_H_ +/* + * Stuff that would naturally come from _ieee80211.h + */ +#define IEEE80211_ADDR_LEN 6 + +#define IEEE80211_WEP_IVLEN 3 /* 24bit */ +#define IEEE80211_WEP_KIDLEN 1 /* 1 octet */ +#define IEEE80211_WEP_CRCLEN 4 /* CRC-32 */ + +#define IEEE80211_CRC_LEN 4 + +#define IEEE80211_MAX_LEN (2300 + IEEE80211_CRC_LEN + \ + (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN)) +#endif /* _NET_IF_IEEE80211_H_ */ + +#define HAL_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 + +#define INIT_AIFS 2 +#define INIT_CWMIN 15 +#define INIT_CWMIN_11B 31 +#define INIT_CWMAX 1023 +#define INIT_SH_RETRY 10 +#define INIT_LG_RETRY 10 +#define INIT_SSH_RETRY 32 +#define INIT_SLG_RETRY 32 + +typedef struct { + uint32_t tqi_ver; /* HAL TXQ verson */ + HAL_TX_QUEUE tqi_type; /* hw queue type*/ + HAL_TX_QUEUE_SUBTYPE tqi_subtype; /* queue subtype, if applicable */ + HAL_TX_QUEUE_FLAGS tqi_qflags; /* queue flags */ + uint32_t tqi_priority; + uint32_t tqi_aifs; /* aifs */ + uint32_t tqi_cwmin; /* cwMin */ + uint32_t tqi_cwmax; /* cwMax */ + uint16_t tqi_shretry; /* frame short retry limit */ + uint16_t tqi_lgretry; /* frame long retry limit */ + uint32_t tqi_cbrPeriod; + uint32_t tqi_cbrOverflowLimit; + uint32_t tqi_burstTime; + uint32_t tqi_readyTime; + uint32_t tqi_physCompBuf; + uint32_t tqi_intFlags; /* flags for internal use */ +} HAL_TX_QUEUE_INFO; + +extern HAL_BOOL ath_hal_setTxQProps(struct ath_hal *ah, + HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ath_hal_getTxQProps(struct ath_hal *ah, + HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi); + +#define HAL_SPUR_VAL_MASK 0x3FFF +#define HAL_SPUR_CHAN_WIDTH 87 +#define HAL_BIN_WIDTH_BASE_100HZ 3125 +#define HAL_BIN_WIDTH_TURBO_100HZ 6250 +#define HAL_MAX_BINS_ALLOWED 28 + +#define IS_CHAN_5GHZ(_c) ((_c)->channel > 4900) +#define IS_CHAN_2GHZ(_c) (!IS_CHAN_5GHZ(_c)) + +#define IS_CHAN_IN_PUBLIC_SAFETY_BAND(_c) ((_c) > 4940 && (_c) < 4990) + +/* + * Deduce if the host cpu has big- or litt-endian byte order. + */ +static __inline__ int +isBigEndian(void) +{ + union { + int32_t i; + char c[4]; + } u; + u.i = 1; + return (u.c[0] == 0); +} + +/* unalligned little endian access */ +#define LE_READ_2(p) \ + ((uint16_t) \ + ((((const uint8_t *)(p))[0] ) | (((const uint8_t *)(p))[1]<< 8))) +#define LE_READ_4(p) \ + ((uint32_t) \ + ((((const uint8_t *)(p))[0] ) | (((const uint8_t *)(p))[1]<< 8) |\ + (((const uint8_t *)(p))[2]<<16) | (((const uint8_t *)(p))[3]<<24))) + +/* + * Register manipulation macros that expect bit field defines + * to follow the convention that an _S suffix is appended for + * a shift count, while the field mask has no suffix. + */ +#define SM(_v, _f) (((_v) << _f##_S) & (_f)) +#define MS(_v, _f) (((_v) & (_f)) >> _f##_S) +#define OS_REG_RMW(_a, _r, _set, _clr) \ + OS_REG_WRITE(_a, _r, (OS_REG_READ(_a, _r) & ~(_clr)) | (_set)) +#define OS_REG_RMW_FIELD(_a, _r, _f, _v) \ + OS_REG_WRITE(_a, _r, \ + (OS_REG_READ(_a, _r) &~ (_f)) | (((_v) << _f##_S) & (_f))) +#define OS_REG_SET_BIT(_a, _r, _f) \ + OS_REG_WRITE(_a, _r, OS_REG_READ(_a, _r) | (_f)) +#define OS_REG_CLR_BIT(_a, _r, _f) \ + OS_REG_WRITE(_a, _r, OS_REG_READ(_a, _r) &~ (_f)) +#define OS_REG_IS_BIT_SET(_a, _r, _f) \ + ((OS_REG_READ(_a, _r) & (_f)) != 0) +#define OS_REG_RMW_FIELD_ALT(_a, _r, _f, _v) \ + OS_REG_WRITE(_a, _r, \ + (OS_REG_READ(_a, _r) &~(_f<<_f##_S)) | \ + (((_v) << _f##_S) & (_f<<_f##_S))) +#define OS_REG_READ_FIELD(_a, _r, _f) \ + (((OS_REG_READ(_a, _r) & _f) >> _f##_S)) +#define OS_REG_READ_FIELD_ALT(_a, _r, _f) \ + ((OS_REG_READ(_a, _r) >> (_f##_S))&(_f)) + +/* Analog register writes may require a delay between each one (eg Merlin?) */ +#define OS_A_REG_RMW_FIELD(_a, _r, _f, _v) \ + do { OS_REG_WRITE(_a, _r, (OS_REG_READ(_a, _r) &~ (_f)) | \ + (((_v) << _f##_S) & (_f))) ; OS_DELAY(100); } while (0) +#define OS_A_REG_WRITE(_a, _r, _v) \ + do { OS_REG_WRITE(_a, _r, _v); OS_DELAY(100); } while (0) + +/* wait for the register contents to have the specified value */ +extern HAL_BOOL ath_hal_wait(struct ath_hal *, u_int reg, + uint32_t mask, uint32_t val); +extern HAL_BOOL ath_hal_waitfor(struct ath_hal *, u_int reg, + uint32_t mask, uint32_t val, uint32_t timeout); + +/* return the first n bits in val reversed */ +extern uint32_t ath_hal_reverseBits(uint32_t val, uint32_t n); + +/* printf interfaces */ +extern void ath_hal_printf(struct ath_hal *, const char*, ...) + __printflike(2,3); +extern void ath_hal_vprintf(struct ath_hal *, const char*, __va_list) + __printflike(2, 0); +extern const char* ath_hal_ether_sprintf(const uint8_t *mac); + +/* allocate and free memory */ +extern void *ath_hal_malloc(size_t); +extern void ath_hal_free(void *); + +/* common debugging interfaces */ +#ifdef AH_DEBUG +#include "ah_debug.h" +extern int ath_hal_debug; /* Global debug flags */ + +/* + * The typecast is purely because some callers will pass in + * AH_NULL directly rather than using a NULL ath_hal pointer. + */ +#define HALDEBUG(_ah, __m, ...) \ + do { \ + if ((__m) == HAL_DEBUG_UNMASKABLE || \ + ath_hal_debug & (__m) || \ + ((_ah) != NULL && \ + ((struct ath_hal *) (_ah))->ah_config.ah_debug & (__m))) { \ + DO_HALDEBUG((_ah), (__m), __VA_ARGS__); \ + } \ + } while(0); + +extern void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) + __printflike(3,4); +#else +#define HALDEBUG(_ah, __m, ...) +#endif /* AH_DEBUG */ + +/* + * Register logging definitions shared with ardecode. + */ +#include "ah_decode.h" + +/* + * Common assertion interface. Note: it is a bad idea to generate + * an assertion failure for any recoverable event. Instead catch + * the violation and, if possible, fix it up or recover from it; either + * with an error return value or a diagnostic messages. System software + * does not panic unless the situation is hopeless. + */ +#ifdef AH_ASSERT +extern void ath_hal_assert_failed(const char* filename, + int lineno, const char* msg); + +#define HALASSERT(_x) do { \ + if (!(_x)) { \ + ath_hal_assert_failed(__FILE__, __LINE__, #_x); \ + } \ +} while (0) +#else +#define HALASSERT(_x) +#endif /* AH_ASSERT */ + +/* + * Regulatory domain support. + */ + +/* + * Return the max allowed antenna gain and apply any regulatory + * domain specific changes. + */ +u_int ath_hal_getantennareduction(struct ath_hal *ah, + const struct ieee80211_channel *chan, u_int twiceGain); + +/* + * Return the test group for the specific channel based on + * the current regulatory setup. + */ +u_int ath_hal_getctl(struct ath_hal *, const struct ieee80211_channel *); + +/* + * Map a public channel definition to the corresponding + * internal data structure. This implicitly specifies + * whether or not the specified channel is ok to use + * based on the current regulatory domain constraints. + */ +#ifndef AH_DEBUG +static OS_INLINE HAL_CHANNEL_INTERNAL * +ath_hal_checkchannel(struct ath_hal *ah, const struct ieee80211_channel *c) +{ + HAL_CHANNEL_INTERNAL *cc; + + HALASSERT(c->ic_devdata < AH_PRIVATE(ah)->ah_nchan); + cc = &AH_PRIVATE(ah)->ah_channels[c->ic_devdata]; + HALASSERT(c->ic_freq == cc->channel || IEEE80211_IS_CHAN_GSM(c)); + return cc; +} +#else +/* NB: non-inline version that checks state */ +HAL_CHANNEL_INTERNAL *ath_hal_checkchannel(struct ath_hal *, + const struct ieee80211_channel *); +#endif /* AH_DEBUG */ + +/* + * Return the h/w frequency for a channel. This may be + * different from ic_freq if this is a GSM device that + * takes 2.4GHz frequencies and down-converts them. + */ +static OS_INLINE uint16_t +ath_hal_gethwchannel(struct ath_hal *ah, const struct ieee80211_channel *c) +{ + return ath_hal_checkchannel(ah, c)->channel; +} + +/* + * Convert between microseconds and core system clocks. + */ +extern u_int ath_hal_mac_clks(struct ath_hal *ah, u_int usecs); +extern u_int ath_hal_mac_usec(struct ath_hal *ah, u_int clks); + +/* + * Generic get/set capability support. Each chip overrides + * this routine to support chip-specific capabilities. + */ +extern HAL_STATUS ath_hal_getcapability(struct ath_hal *ah, + HAL_CAPABILITY_TYPE type, uint32_t capability, + uint32_t *result); +extern HAL_BOOL ath_hal_setcapability(struct ath_hal *ah, + HAL_CAPABILITY_TYPE type, uint32_t capability, + uint32_t setting, HAL_STATUS *status); + +/* The diagnostic codes used to be internally defined here -adrian */ +#include "ah_diagcodes.h" + +/* + * The AR5416 and later HALs have MAC and baseband hang checking. + */ +typedef struct { + uint32_t hang_reg_offset; + uint32_t hang_val; + uint32_t hang_mask; + uint32_t hang_offset; +} hal_hw_hang_check_t; + +typedef struct { + uint32_t dma_dbg_3; + uint32_t dma_dbg_4; + uint32_t dma_dbg_5; + uint32_t dma_dbg_6; +} mac_dbg_regs_t; + +typedef enum { + dcu_chain_state = 0x1, + dcu_complete_state = 0x2, + qcu_state = 0x4, + qcu_fsp_ok = 0x8, + qcu_fsp_state = 0x10, + qcu_stitch_state = 0x20, + qcu_fetch_state = 0x40, + qcu_complete_state = 0x80 +} hal_mac_hangs_t; + +typedef struct { + int states; + uint8_t dcu_chain_state; + uint8_t dcu_complete_state; + uint8_t qcu_state; + uint8_t qcu_fsp_ok; + uint8_t qcu_fsp_state; + uint8_t qcu_stitch_state; + uint8_t qcu_fetch_state; + uint8_t qcu_complete_state; +} hal_mac_hang_check_t; + +enum { + HAL_BB_HANG_DFS = 0x0001, + HAL_BB_HANG_RIFS = 0x0002, + HAL_BB_HANG_RX_CLEAR = 0x0004, + HAL_BB_HANG_UNKNOWN = 0x0080, + + HAL_MAC_HANG_SIG1 = 0x0100, + HAL_MAC_HANG_SIG2 = 0x0200, + HAL_MAC_HANG_UNKNOWN = 0x8000, + + HAL_BB_HANGS = HAL_BB_HANG_DFS + | HAL_BB_HANG_RIFS + | HAL_BB_HANG_RX_CLEAR + | HAL_BB_HANG_UNKNOWN, + HAL_MAC_HANGS = HAL_MAC_HANG_SIG1 + | HAL_MAC_HANG_SIG2 + | HAL_MAC_HANG_UNKNOWN, +}; + +/* Merge these with above */ +typedef enum hal_hw_hangs { + HAL_DFS_BB_HANG_WAR = 0x1, + HAL_RIFS_BB_HANG_WAR = 0x2, + HAL_RX_STUCK_LOW_BB_HANG_WAR = 0x4, + HAL_MAC_HANG_WAR = 0x8, + HAL_PHYRESTART_CLR_WAR = 0x10, + HAL_MAC_HANG_DETECTED = 0x40000000, + HAL_BB_HANG_DETECTED = 0x80000000 +} hal_hw_hangs_t; + +/* + * Device revision information. + */ +typedef struct { + uint16_t ah_devid; /* PCI device ID */ + uint16_t ah_subvendorid; /* PCI subvendor ID */ + uint32_t ah_macVersion; /* MAC version id */ + uint16_t ah_macRev; /* MAC revision */ + uint16_t ah_phyRev; /* PHY revision */ + uint16_t ah_analog5GhzRev; /* 2GHz radio revision */ + uint16_t ah_analog2GhzRev; /* 5GHz radio revision */ +} HAL_REVS; + +/* + * Argument payload for HAL_DIAG_SETKEY. + */ +typedef struct { + HAL_KEYVAL dk_keyval; + uint16_t dk_keyix; /* key index */ + uint8_t dk_mac[IEEE80211_ADDR_LEN]; + int dk_xor; /* XOR key data */ +} HAL_DIAG_KEYVAL; + +/* + * Argument payload for HAL_DIAG_EEWRITE. + */ +typedef struct { + uint16_t ee_off; /* eeprom offset */ + uint16_t ee_data; /* write data */ +} HAL_DIAG_EEVAL; + + +typedef struct { + u_int offset; /* reg offset */ + uint32_t val; /* reg value */ +} HAL_DIAG_REGVAL; + +/* + * 11n compatibility tweaks. + */ +#define HAL_DIAG_11N_SERVICES 0x00000003 +#define HAL_DIAG_11N_SERVICES_S 0 +#define HAL_DIAG_11N_TXSTOMP 0x0000000c +#define HAL_DIAG_11N_TXSTOMP_S 2 + +typedef struct { + int maxNoiseImmunityLevel; /* [0..4] */ + int totalSizeDesired[5]; + int coarseHigh[5]; + int coarseLow[5]; + int firpwr[5]; + + int maxSpurImmunityLevel; /* [0..7] */ + int cycPwrThr1[8]; + + int maxFirstepLevel; /* [0..2] */ + int firstep[3]; + + uint32_t ofdmTrigHigh; + uint32_t ofdmTrigLow; + int32_t cckTrigHigh; + int32_t cckTrigLow; + int32_t rssiThrLow; + int32_t rssiThrHigh; + + int period; /* update listen period */ +} HAL_ANI_PARAMS; + +extern HAL_BOOL ath_hal_getdiagstate(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); + +/* + * Setup a h/w rate table for use. + */ +extern void ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt); + +/* + * Common routine for implementing getChanNoise api. + */ +int16_t ath_hal_getChanNoise(struct ath_hal *, const struct ieee80211_channel *); + +/* + * Initialization support. + */ +typedef struct { + const uint32_t *data; + int rows, cols; +} HAL_INI_ARRAY; + +#define HAL_INI_INIT(_ia, _data, _cols) do { \ + (_ia)->data = (const uint32_t *)(_data); \ + (_ia)->rows = sizeof(_data) / sizeof((_data)[0]); \ + (_ia)->cols = (_cols); \ +} while (0) +#define HAL_INI_VAL(_ia, _r, _c) \ + ((_ia)->data[((_r)*(_ia)->cols) + (_c)]) + +/* + * OS_DELAY() does a PIO READ on the PCI bus which allows + * other cards' DMA reads to complete in the middle of our reset. + */ +#define DMA_YIELD(x) do { \ + if ((++(x) % 64) == 0) \ + OS_DELAY(1); \ +} while (0) + +#define HAL_INI_WRITE_ARRAY(ah, regArray, col, regWr) do { \ + int r; \ + for (r = 0; r < N(regArray); r++) { \ + OS_REG_WRITE(ah, (regArray)[r][0], (regArray)[r][col]); \ + DMA_YIELD(regWr); \ + } \ +} while (0) + +#define HAL_INI_WRITE_BANK(ah, regArray, bankData, regWr) do { \ + int r; \ + for (r = 0; r < N(regArray); r++) { \ + OS_REG_WRITE(ah, (regArray)[r][0], (bankData)[r]); \ + DMA_YIELD(regWr); \ + } \ +} while (0) + +extern int ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, + int col, int regWr); +extern void ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, + int col); +extern int ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, + const uint32_t data[], int regWr); + +#define CCK_SIFS_TIME 10 +#define CCK_PREAMBLE_BITS 144 +#define CCK_PLCP_BITS 48 + +#define OFDM_SIFS_TIME 16 +#define OFDM_PREAMBLE_TIME 20 +#define OFDM_PLCP_BITS 22 +#define OFDM_SYMBOL_TIME 4 + +#define OFDM_HALF_SIFS_TIME 32 +#define OFDM_HALF_PREAMBLE_TIME 40 +#define OFDM_HALF_PLCP_BITS 22 +#define OFDM_HALF_SYMBOL_TIME 8 + +#define OFDM_QUARTER_SIFS_TIME 64 +#define OFDM_QUARTER_PREAMBLE_TIME 80 +#define OFDM_QUARTER_PLCP_BITS 22 +#define OFDM_QUARTER_SYMBOL_TIME 16 + +#define TURBO_SIFS_TIME 8 +#define TURBO_PREAMBLE_TIME 14 +#define TURBO_PLCP_BITS 22 +#define TURBO_SYMBOL_TIME 4 + +#define WLAN_CTRL_FRAME_SIZE (2+2+6+4) /* ACK+FCS */ + +/* Generic EEPROM board value functions */ +extern HAL_BOOL ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, + uint16_t listSize, uint16_t *indexL, uint16_t *indexR); +extern HAL_BOOL ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, + uint8_t *pPwrList, uint8_t *pVpdList, uint16_t numIntercepts, + uint8_t *pRetVpdList); +extern int16_t ath_ee_interpolate(uint16_t target, uint16_t srcLeft, + uint16_t srcRight, int16_t targetLeft, int16_t targetRight); + +/* Whether 5ghz fast clock is needed */ +/* + * The chipset (Merlin, AR9300/later) should set the capability flag below; + * this flag simply says that the hardware can do it, not that the EEPROM + * says it can. + * + * Merlin 2.0/2.1 chips with an EEPROM version > 16 do 5ghz fast clock + * if the relevant eeprom flag is set. + * Merlin 2.0/2.1 chips with an EEPROM version <= 16 do 5ghz fast clock + * by default. + */ +#define IS_5GHZ_FAST_CLOCK_EN(_ah, _c) \ + (IEEE80211_IS_CHAN_5GHZ(_c) && \ + AH_PRIVATE((_ah))->ah_caps.halSupportsFastClock5GHz && \ + ath_hal_eepromGetFlag((_ah), AR_EEP_FSTCLK_5G)) + +/* + * Fetch the maximum regulatory domain power for the given channel + * in 1/2dBm steps. + */ +static inline int +ath_hal_get_twice_max_regpower(struct ath_hal_private *ahp, + const HAL_CHANNEL_INTERNAL *ichan, const struct ieee80211_channel *chan) +{ + struct ath_hal *ah = &ahp->h; + + if (! chan) { + ath_hal_printf(ah, "%s: called with chan=NULL!\n", __func__); + return (0); + } + return (chan->ic_maxpower); +} + +/* + * Get the maximum antenna gain allowed, in 1/2dBm steps. + */ +static inline int +ath_hal_getantennaallowed(struct ath_hal *ah, + const struct ieee80211_channel *chan) +{ + + if (! chan) + return (0); + + return (chan->ic_maxantgain); +} + +/* + * Map the given 2GHz channel to an IEEE number. + */ +extern int ath_hal_mhz2ieee_2ghz(struct ath_hal *, int freq); + +/* + * Clear the channel survey data. + */ +extern void ath_hal_survey_clear(struct ath_hal *ah); + +/* + * Add a sample to the channel survey data. + */ +extern void ath_hal_survey_add_sample(struct ath_hal *ah, + HAL_SURVEY_SAMPLE *hs); + +#endif /* _ATH_AH_INTERAL_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ah_regdomain.c b/sys/external/isc/atheros_hal/dist/ah_regdomain.c new file mode 100644 index 0000000..fb0c841 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_regdomain.c @@ -0,0 +1,875 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2006 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" + +#include +#include + +#include "ah_internal.h" +#include "ah_eeprom.h" +#include "ah_devid.h" + +#include "ah_regdomain.h" + +/* + * XXX this code needs a audit+review + */ + +/* used throughout this file... */ +#define N(a) (sizeof (a) / sizeof (a[0])) + +#define HAL_MODE_11A_TURBO HAL_MODE_108A +#define HAL_MODE_11G_TURBO HAL_MODE_108G + +/* + * Mask to check whether a domain is a multidomain or a single domain + */ +#define MULTI_DOMAIN_MASK 0xFF00 + +/* + * Enumerated Regulatory Domain Information 8 bit values indicate that + * the regdomain is really a pair of unitary regdomains. 12 bit values + * are the real unitary regdomains and are the only ones which have the + * frequency bitmasks and flags set. + */ +#include "ah_regdomain/ah_rd_regenum.h" + +#define WORLD_SKU_MASK 0x00F0 +#define WORLD_SKU_PREFIX 0x0060 + +/* + * THE following table is the mapping of regdomain pairs specified by + * an 8 bit regdomain value to the individual unitary reg domains + */ +#include "ah_regdomain/ah_rd_regmap.h" + +/* + * The following tables are the master list for all different freqeuncy + * bands with the complete matrix of all possible flags and settings + * for each band if it is used in ANY reg domain. + */ + +#define COUNTRY_ERD_FLAG 0x8000 +#define WORLDWIDE_ROAMING_FLAG 0x4000 + +/* + * This table maps country ISO codes from net80211 into regulatory + * domains which the ath regulatory domain code understands. + */ +#include "ah_regdomain/ah_rd_ctry.h" + +/* + * The frequency band collections are a set of frequency ranges + * with shared properties - max tx power, max antenna gain, channel width, + * channel spacing, DFS requirements and passive scanning requirements. + * + * These are represented as entries in a frequency band bitmask. + * Each regulatory domain entry in ah_regdomain_domains.h uses one + * or more frequency band entries for each of the channel modes + * supported (11bg, 11a, half, quarter, turbo, etc.) + * + */ +#include "ah_regdomain/ah_rd_freqbands.h" + +/* + * This is the main regulatory database. It defines the supported + * set of features and requirements for each of the defined regulatory + * zones. It uses combinations of frequency ranges - represented in + * a bitmask - to determine the requirements and limitations needed. + */ +#include "ah_regdomain/ah_rd_domains.h" + +static const struct cmode modes[] = { + { HAL_MODE_TURBO, IEEE80211_CHAN_ST }, + { HAL_MODE_11A, IEEE80211_CHAN_A }, + { HAL_MODE_11B, IEEE80211_CHAN_B }, + { HAL_MODE_11G, IEEE80211_CHAN_G }, + { HAL_MODE_11G_TURBO, IEEE80211_CHAN_108G }, + { HAL_MODE_11A_TURBO, IEEE80211_CHAN_108A }, + { HAL_MODE_11A_QUARTER_RATE, + IEEE80211_CHAN_A | IEEE80211_CHAN_QUARTER }, + { HAL_MODE_11A_HALF_RATE, + IEEE80211_CHAN_A | IEEE80211_CHAN_HALF }, + { HAL_MODE_11G_QUARTER_RATE, + IEEE80211_CHAN_G | IEEE80211_CHAN_QUARTER }, + { HAL_MODE_11G_HALF_RATE, + IEEE80211_CHAN_G | IEEE80211_CHAN_HALF }, + { HAL_MODE_11NG_HT20, IEEE80211_CHAN_G | IEEE80211_CHAN_HT20 }, + { HAL_MODE_11NG_HT40PLUS, + IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U }, + { HAL_MODE_11NG_HT40MINUS, + IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D }, + { HAL_MODE_11NA_HT20, IEEE80211_CHAN_A | IEEE80211_CHAN_HT20 }, + { HAL_MODE_11NA_HT40PLUS, + IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U }, + { HAL_MODE_11NA_HT40MINUS, + IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D }, +}; + +static void ath_hal_update_dfsdomain(struct ath_hal *ah); + +static OS_INLINE uint16_t +getEepromRD(struct ath_hal *ah) +{ + return AH_PRIVATE(ah)->ah_currentRD &~ WORLDWIDE_ROAMING_FLAG; +} + +/* + * Test to see if the bitmask array is all zeros + */ +static HAL_BOOL +isChanBitMaskZero(const uint64_t *bitmask) +{ +#if BMLEN > 2 +#error "add more cases" +#endif +#if BMLEN > 1 + if (bitmask[1] != 0) + return AH_FALSE; +#endif + return (bitmask[0] == 0); +} + +/* + * Return whether or not the regulatory domain/country in EEPROM + * is acceptable. + */ +static HAL_BOOL +isEepromValid(struct ath_hal *ah) +{ + uint16_t rd = getEepromRD(ah); + int i; + + if (rd & COUNTRY_ERD_FLAG) { + uint16_t cc = rd &~ COUNTRY_ERD_FLAG; + for (i = 0; i < N(allCountries); i++) + if (allCountries[i].countryCode == cc) + return AH_TRUE; + } else { + for (i = 0; i < N(regDomainPairs); i++) + if (regDomainPairs[i].regDmnEnum == rd) + return AH_TRUE; + } + + if (rd == FCC_UBNT) { + return AH_TRUE; + } + + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: invalid regulatory domain/country code 0x%x\n", __func__, rd); + return AH_FALSE; +} + +/* + * Find the pointer to the country element in the country table + * corresponding to the country code + */ +static COUNTRY_CODE_TO_ENUM_RD* +findCountry(HAL_CTRY_CODE countryCode) +{ + int i; + + for (i = 0; i < N(allCountries); i++) { + if (allCountries[i].countryCode == countryCode) + return &allCountries[i]; + } + return AH_NULL; +} + +static REG_DOMAIN * +findRegDmn(int regDmn) +{ + int i; + + for (i = 0; i < N(regDomains); i++) { + if (regDomains[i].regDmnEnum == regDmn) + return ®Domains[i]; + } + return AH_NULL; +} + +static REG_DMN_PAIR_MAPPING * +findRegDmnPair(int regDmnPair) +{ + int i; + + if (regDmnPair != NO_ENUMRD) { + for (i = 0; i < N(regDomainPairs); i++) { + if (regDomainPairs[i].regDmnEnum == regDmnPair) + return ®DomainPairs[i]; + } + } + return AH_NULL; +} + +/* + * Calculate a default country based on the EEPROM setting. + */ +static HAL_CTRY_CODE +getDefaultCountry(struct ath_hal *ah) +{ + REG_DMN_PAIR_MAPPING *regpair; + uint16_t rd; + + rd = getEepromRD(ah); + if (rd & COUNTRY_ERD_FLAG) { + COUNTRY_CODE_TO_ENUM_RD *country; + uint16_t cc = rd & ~COUNTRY_ERD_FLAG; + country = findCountry(cc); + if (country != AH_NULL) + return cc; + } + /* + * Check reg domains that have only one country + */ + regpair = findRegDmnPair(rd); + return (regpair != AH_NULL) ? regpair->singleCC : CTRY_DEFAULT; +} + +static HAL_BOOL +IS_BIT_SET(int bit, const uint64_t bitmask[]) +{ + int byteOffset, bitnum; + uint64_t val; + + byteOffset = bit/64; + bitnum = bit - byteOffset*64; + val = ((uint64_t) 1) << bitnum; + return (bitmask[byteOffset] & val) != 0; +} + +static HAL_STATUS +getregstate(struct ath_hal *ah, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn, + COUNTRY_CODE_TO_ENUM_RD **pcountry, + REG_DOMAIN **prd2GHz, REG_DOMAIN **prd5GHz) +{ + COUNTRY_CODE_TO_ENUM_RD *country; + REG_DOMAIN *rd5GHz, *rd2GHz; + + if (cc == CTRY_DEFAULT && regDmn == SKU_NONE) { + /* + * Validate the EEPROM setting and setup defaults + */ + if (!isEepromValid(ah)) { + /* + * Don't return any channels if the EEPROM has an + * invalid regulatory domain/country code setting. + */ + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: invalid EEPROM contents\n",__func__); + return HAL_EEBADREG; + } + + cc = getDefaultCountry(ah); + country = findCountry(cc); + if (country == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "NULL Country!, cc %d\n", cc); + return HAL_EEBADCC; + } + regDmn = country->regDmnEnum; + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: EEPROM cc %u rd 0x%x\n", + __func__, cc, regDmn); + + if (country->countryCode == CTRY_DEFAULT) { + /* + * Check EEPROM; SKU may be for a country, single + * domain, or multiple domains (WWR). + */ + uint16_t rdnum = getEepromRD(ah); + if ((rdnum & COUNTRY_ERD_FLAG) == 0 && + (findRegDmn(rdnum) != AH_NULL || + findRegDmnPair(rdnum) != AH_NULL)) { + regDmn = rdnum; + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: EEPROM rd 0x%x\n", __func__, rdnum); + } + } + } else { + country = findCountry(cc); + if (country == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "unknown country, cc %d\n", cc); + return HAL_EINVAL; + } + if (regDmn == SKU_NONE) + regDmn = country->regDmnEnum; + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u rd 0x%x\n", + __func__, cc, regDmn); + } + + /* + * Setup per-band state. + */ + if ((regDmn & MULTI_DOMAIN_MASK) == 0) { + REG_DMN_PAIR_MAPPING *regpair = findRegDmnPair(regDmn); + if (regpair == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: no reg domain pair %u for country %u\n", + __func__, regDmn, country->countryCode); + return HAL_EINVAL; + } + rd5GHz = findRegDmn(regpair->regDmn5GHz); + if (rd5GHz == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: no 5GHz reg domain %u for country %u\n", + __func__, regpair->regDmn5GHz, country->countryCode); + return HAL_EINVAL; + } + rd2GHz = findRegDmn(regpair->regDmn2GHz); + if (rd2GHz == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: no 2GHz reg domain %u for country %u\n", + __func__, regpair->regDmn2GHz, country->countryCode); + return HAL_EINVAL; + } + } else { + rd5GHz = rd2GHz = findRegDmn(regDmn); + if (rd2GHz == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: no unitary reg domain %u for country %u\n", + __func__, regDmn, country->countryCode); + return HAL_EINVAL; + } + } + if (pcountry != AH_NULL) + *pcountry = country; + *prd2GHz = rd2GHz; + *prd5GHz = rd5GHz; + return HAL_OK; +} + +/* + * Construct the channel list for the specified regulatory config. + */ +static HAL_STATUS +getchannels(struct ath_hal *ah, + struct ieee80211_channel chans[], u_int maxchans, int *nchans, + u_int modeSelect, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn, + HAL_BOOL enableExtendedChannels, + COUNTRY_CODE_TO_ENUM_RD **pcountry, + REG_DOMAIN **prd2GHz, REG_DOMAIN **prd5GHz) +{ +#define CHANNEL_HALF_BW 10 +#define CHANNEL_QUARTER_BW 5 +#define HAL_MODE_11A_ALL \ + (HAL_MODE_11A | HAL_MODE_11A_TURBO | HAL_MODE_TURBO | \ + HAL_MODE_11A_QUARTER_RATE | HAL_MODE_11A_HALF_RATE) + REG_DOMAIN *rd5GHz, *rd2GHz; + u_int modesAvail; + const struct cmode *cm; + struct ieee80211_channel *ic; + int next, b; + HAL_STATUS status; + + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u regDmn 0x%x mode 0x%x%s\n", + __func__, cc, regDmn, modeSelect, + enableExtendedChannels ? " ecm" : ""); + + status = getregstate(ah, cc, regDmn, pcountry, &rd2GHz, &rd5GHz); + if (status != HAL_OK) + return status; + + /* get modes that HW is capable of */ + modesAvail = ath_hal_getWirelessModes(ah); + /* optimize work below if no 11a channels */ + if (isChanBitMaskZero(rd5GHz->chan11a) && + (modesAvail & HAL_MODE_11A_ALL)) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: disallow all 11a\n", __func__); + modesAvail &= ~HAL_MODE_11A_ALL; + } + + next = 0; + ic = &chans[0]; + for (cm = modes; cm < &modes[N(modes)]; cm++) { + uint16_t c, c_hi, c_lo; + uint64_t *channelBM = AH_NULL; + REG_DMN_FREQ_BAND *fband = AH_NULL,*freqs; + int low_adj, hi_adj, channelSep, lastc; + uint32_t rdflags; + uint64_t dfsMask; + uint64_t pscan; + + if ((cm->mode & modeSelect) == 0) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: skip mode 0x%x flags 0x%x\n", + __func__, cm->mode, cm->flags); + continue; + } + if ((cm->mode & modesAvail) == 0) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: !avail mode 0x%x (0x%x) flags 0x%x\n", + __func__, modesAvail, cm->mode, cm->flags); + continue; + } + if (!ath_hal_getChannelEdges(ah, cm->flags, &c_lo, &c_hi)) { + /* channel not supported by hardware, skip it */ + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: channels 0x%x not supported by hardware\n", + __func__,cm->flags); + continue; + } + switch (cm->mode) { + case HAL_MODE_TURBO: + case HAL_MODE_11A_TURBO: + rdflags = rd5GHz->flags; + dfsMask = rd5GHz->dfsMask; + pscan = rd5GHz->pscan; + if (cm->mode == HAL_MODE_TURBO) + channelBM = rd5GHz->chan11a_turbo; + else + channelBM = rd5GHz->chan11a_dyn_turbo; + freqs = ®Dmn5GhzTurboFreq[0]; + break; + case HAL_MODE_11G_TURBO: + rdflags = rd2GHz->flags; + dfsMask = rd2GHz->dfsMask; + pscan = rd2GHz->pscan; + channelBM = rd2GHz->chan11g_turbo; + freqs = ®Dmn2Ghz11gTurboFreq[0]; + break; + case HAL_MODE_11A: + case HAL_MODE_11A_HALF_RATE: + case HAL_MODE_11A_QUARTER_RATE: + case HAL_MODE_11NA_HT20: + case HAL_MODE_11NA_HT40PLUS: + case HAL_MODE_11NA_HT40MINUS: + rdflags = rd5GHz->flags; + dfsMask = rd5GHz->dfsMask; + pscan = rd5GHz->pscan; + if (cm->mode == HAL_MODE_11A_HALF_RATE) + channelBM = rd5GHz->chan11a_half; + else if (cm->mode == HAL_MODE_11A_QUARTER_RATE) + channelBM = rd5GHz->chan11a_quarter; + else + channelBM = rd5GHz->chan11a; + freqs = ®Dmn5GhzFreq[0]; + break; + case HAL_MODE_11B: + case HAL_MODE_11G: + case HAL_MODE_11G_HALF_RATE: + case HAL_MODE_11G_QUARTER_RATE: + case HAL_MODE_11NG_HT20: + case HAL_MODE_11NG_HT40PLUS: + case HAL_MODE_11NG_HT40MINUS: + rdflags = rd2GHz->flags; + dfsMask = rd2GHz->dfsMask; + pscan = rd2GHz->pscan; + if (cm->mode == HAL_MODE_11G_HALF_RATE) + channelBM = rd2GHz->chan11g_half; + else if (cm->mode == HAL_MODE_11G_QUARTER_RATE) + channelBM = rd2GHz->chan11g_quarter; + else if (cm->mode == HAL_MODE_11B) + channelBM = rd2GHz->chan11b; + else + channelBM = rd2GHz->chan11g; + if (cm->mode == HAL_MODE_11B) + freqs = ®Dmn2GhzFreq[0]; + else + freqs = ®Dmn2Ghz11gFreq[0]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: Unkonwn HAL mode 0x%x\n", __func__, cm->mode); + continue; + } + if (isChanBitMaskZero(channelBM)) + continue; + /* + * Setup special handling for HT40 channels; e.g. + * 5G HT40 channels require 40Mhz channel separation. + */ + hi_adj = (cm->mode == HAL_MODE_11NA_HT40PLUS || + cm->mode == HAL_MODE_11NG_HT40PLUS) ? -20 : 0; + low_adj = (cm->mode == HAL_MODE_11NA_HT40MINUS || + cm->mode == HAL_MODE_11NG_HT40MINUS) ? 20 : 0; + channelSep = (cm->mode == HAL_MODE_11NA_HT40PLUS || + cm->mode == HAL_MODE_11NA_HT40MINUS) ? 40 : 0; + + for (b = 0; b < 64*BMLEN; b++) { + if (!IS_BIT_SET(b, channelBM)) + continue; + fband = &freqs[b]; + lastc = 0; + + for (c = fband->lowChannel + low_adj; + c <= fband->highChannel + hi_adj; + c += fband->channelSep) { + if (!(c_lo <= c && c <= c_hi)) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: c %u out of range [%u..%u]\n", + __func__, c, c_lo, c_hi); + continue; + } + if (next >= maxchans){ + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: too many channels for channel table\n", + __func__); + goto done; + } + if ((fband->usePassScan & IS_ECM_CHAN) && + !enableExtendedChannels) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "skip ecm channel\n"); + continue; + } +#if 0 + if ((fband->useDfs & dfsMask) && + (cm->flags & IEEE80211_CHAN_HT40)) { + /* NB: DFS and HT40 don't mix */ + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "skip HT40 chan, DFS required\n"); + continue; + } +#endif + /* + * Make sure that channel separation + * meets the requirement. + */ + if (lastc && channelSep && + (c-lastc) < channelSep) + continue; + lastc = c; + + OS_MEMZERO(ic, sizeof(*ic)); + ic->ic_freq = c; + ic->ic_flags = cm->flags; + ic->ic_maxregpower = fband->powerDfs; + ath_hal_getpowerlimits(ah, ic); + ic->ic_maxantgain = fband->antennaMax; + if (fband->usePassScan & pscan) + ic->ic_flags |= IEEE80211_CHAN_PASSIVE; + if (fband->useDfs & dfsMask) + ic->ic_flags |= IEEE80211_CHAN_DFS; + if (IEEE80211_IS_CHAN_5GHZ(ic) && + (rdflags & DISALLOW_ADHOC_11A)) + ic->ic_flags |= IEEE80211_CHAN_NOADHOC; + if (IEEE80211_IS_CHAN_TURBO(ic) && + (rdflags & DISALLOW_ADHOC_11A_TURB)) + ic->ic_flags |= IEEE80211_CHAN_NOADHOC; + if (rdflags & NO_HOSTAP) + ic->ic_flags |= IEEE80211_CHAN_NOHOSTAP; + if (rdflags & LIMIT_FRAME_4MS) + ic->ic_flags |= IEEE80211_CHAN_4MSXMIT; + if (rdflags & NEED_NFC) + ic->ic_flags |= CHANNEL_NFCREQUIRED; + + ic++, next++; + } + } + } +done: + *nchans = next; + /* NB: pcountry set above by getregstate */ + if (prd2GHz != AH_NULL) + *prd2GHz = rd2GHz; + if (prd5GHz != AH_NULL) + *prd5GHz = rd5GHz; + return HAL_OK; +#undef HAL_MODE_11A_ALL +#undef CHANNEL_HALF_BW +#undef CHANNEL_QUARTER_BW +} + +/* + * Retrieve a channel list without affecting runtime state. + */ +HAL_STATUS +ath_hal_getchannels(struct ath_hal *ah, + struct ieee80211_channel chans[], u_int maxchans, int *nchans, + u_int modeSelect, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn, + HAL_BOOL enableExtendedChannels) +{ + return getchannels(ah, chans, maxchans, nchans, modeSelect, + cc, regDmn, enableExtendedChannels, AH_NULL, AH_NULL, AH_NULL); +} + +/* + * Handle frequency mapping from 900Mhz range to 2.4GHz range + * for GSM radios. This is done when we need the h/w frequency + * and the channel is marked IEEE80211_CHAN_GSM. + */ +static int +ath_hal_mapgsm(int sku, int freq) +{ + if (sku == SKU_XR9) + return 1520 + freq; + if (sku == SKU_GZ901) + return 1544 + freq; + if (sku == SKU_SR9) + return 3344 - freq; + if (sku == SKU_XC900M) + return 1517 + freq; + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot map freq %u unknown gsm sku %u\n", + __func__, freq, sku); + return freq; +} + +/* + * Setup the internal/private channel state given a table of + * net80211 channels. We collapse entries for the same frequency + * and record the frequency for doing noise floor processing + * where we don't have net80211 channel context. + */ +static HAL_BOOL +assignPrivateChannels(struct ath_hal *ah, + struct ieee80211_channel chans[], int nchans, int sku) +{ + HAL_CHANNEL_INTERNAL *ic; + int i, j, next, freq; + + next = 0; + for (i = 0; i < nchans; i++) { + struct ieee80211_channel *c = &chans[i]; + for (j = i-1; j >= 0; j--) + if (chans[j].ic_freq == c->ic_freq) { + c->ic_devdata = chans[j].ic_devdata; + break; + } + if (j < 0) { + /* new entry, assign a private channel entry */ + if (next >= N(AH_PRIVATE(ah)->ah_channels)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: too many channels, max %zu\n", + __func__, N(AH_PRIVATE(ah)->ah_channels)); + return AH_FALSE; + } + /* + * Handle frequency mapping for 900MHz devices. + * The hardware uses 2.4GHz frequencies that are + * down-converted. The 802.11 layer uses the + * true frequencies. + */ + freq = IEEE80211_IS_CHAN_GSM(c) ? + ath_hal_mapgsm(sku, c->ic_freq) : c->ic_freq; + + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: private[%3u] %u/0x%x -> channel %u\n", + __func__, next, c->ic_freq, c->ic_flags, freq); + + ic = &AH_PRIVATE(ah)->ah_channels[next]; + /* + * NB: This clears privFlags which means ancillary + * code like ANI and IQ calibration will be + * restarted and re-setup any per-channel state. + */ + OS_MEMZERO(ic, sizeof(*ic)); + ic->channel = freq; + c->ic_devdata = next; + next++; + } + } + AH_PRIVATE(ah)->ah_nchan = next; + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: %u public, %u private channels\n", + __func__, nchans, next); + return AH_TRUE; +} + +/* + * Setup the channel list based on the information in the EEPROM. + */ +HAL_STATUS +ath_hal_init_channels(struct ath_hal *ah, + struct ieee80211_channel chans[], u_int maxchans, int *nchans, + u_int modeSelect, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn, + HAL_BOOL enableExtendedChannels) +{ + COUNTRY_CODE_TO_ENUM_RD *country; + REG_DOMAIN *rd5GHz, *rd2GHz; + HAL_STATUS status; + + status = getchannels(ah, chans, maxchans, nchans, modeSelect, + cc, regDmn, enableExtendedChannels, &country, &rd2GHz, &rd5GHz); + if (status == HAL_OK && + assignPrivateChannels(ah, chans, *nchans, AH_PRIVATE(ah)->ah_currentRD)) { + AH_PRIVATE(ah)->ah_rd2GHz = rd2GHz; + AH_PRIVATE(ah)->ah_rd5GHz = rd5GHz; + + ah->ah_countryCode = country->countryCode; + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u\n", + __func__, ah->ah_countryCode); + + /* Update current DFS domain */ + ath_hal_update_dfsdomain(ah); + } else + status = HAL_EINVAL; + + return status; +} + +/* + * Set the channel list. + */ +HAL_STATUS +ath_hal_set_channels(struct ath_hal *ah, + struct ieee80211_channel chans[], int nchans, + HAL_CTRY_CODE cc, HAL_REG_DOMAIN rd) +{ + COUNTRY_CODE_TO_ENUM_RD *country; + REG_DOMAIN *rd5GHz, *rd2GHz; + HAL_STATUS status; + + switch (rd) { + case SKU_SR9: + case SKU_XR9: + case SKU_GZ901: + case SKU_XC900M: + /* + * Map 900MHz sku's. The frequencies will be mapped + * according to the sku to compensate for the down-converter. + * We use the FCC for these sku's as the mapped channel + * list is known compatible (will need to change if/when + * vendors do different mapping in different locales). + */ + status = getregstate(ah, CTRY_DEFAULT, SKU_FCC, + &country, &rd2GHz, &rd5GHz); + break; + default: + status = getregstate(ah, cc, rd, + &country, &rd2GHz, &rd5GHz); + rd = AH_PRIVATE(ah)->ah_currentRD; + break; + } + if (status == HAL_OK && assignPrivateChannels(ah, chans, nchans, rd)) { + AH_PRIVATE(ah)->ah_rd2GHz = rd2GHz; + AH_PRIVATE(ah)->ah_rd5GHz = rd5GHz; + + ah->ah_countryCode = country->countryCode; + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u\n", + __func__, ah->ah_countryCode); + } else + status = HAL_EINVAL; + + if (status == HAL_OK) { + /* Update current DFS domain */ + (void) ath_hal_update_dfsdomain(ah); + } + return status; +} + +#ifdef AH_DEBUG +/* + * Return the internal channel corresponding to a public channel. + * NB: normally this routine is inline'd (see ah_internal.h) + */ +HAL_CHANNEL_INTERNAL * +ath_hal_checkchannel(struct ath_hal *ah, const struct ieee80211_channel *c) +{ + HAL_CHANNEL_INTERNAL *cc = &AH_PRIVATE(ah)->ah_channels[c->ic_devdata]; + + if (c->ic_devdata < AH_PRIVATE(ah)->ah_nchan && + (c->ic_freq == cc->channel || IEEE80211_IS_CHAN_GSM(c))) + return cc; + if (c->ic_devdata >= AH_PRIVATE(ah)->ah_nchan) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: bad mapping, devdata %u nchans %u\n", + __func__, c->ic_devdata, AH_PRIVATE(ah)->ah_nchan); + HALASSERT(c->ic_devdata < AH_PRIVATE(ah)->ah_nchan); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: no match for %u/0x%x devdata %u channel %u\n", + __func__, c->ic_freq, c->ic_flags, c->ic_devdata, + cc->channel); + HALASSERT(c->ic_freq == cc->channel || IEEE80211_IS_CHAN_GSM(c)); + } + return AH_NULL; +} +#endif /* AH_DEBUG */ + +#define isWwrSKU(_ah) \ + ((getEepromRD((_ah)) & WORLD_SKU_MASK) == WORLD_SKU_PREFIX || \ + getEepromRD(_ah) == WORLD) + +/* + * Return the test group for the specific channel based on + * the current regulatory setup. + */ +u_int +ath_hal_getctl(struct ath_hal *ah, const struct ieee80211_channel *c) +{ + u_int ctl; + + if (AH_PRIVATE(ah)->ah_rd2GHz == AH_PRIVATE(ah)->ah_rd5GHz || + (ah->ah_countryCode == CTRY_DEFAULT && isWwrSKU(ah))) + ctl = SD_NO_CTL; + else if (IEEE80211_IS_CHAN_2GHZ(c)) + ctl = AH_PRIVATE(ah)->ah_rd2GHz->conformanceTestLimit; + else + ctl = AH_PRIVATE(ah)->ah_rd5GHz->conformanceTestLimit; + if (IEEE80211_IS_CHAN_B(c)) + return ctl | CTL_11B; + if (IEEE80211_IS_CHAN_G(c)) + return ctl | CTL_11G; + if (IEEE80211_IS_CHAN_108G(c)) + return ctl | CTL_108G; + if (IEEE80211_IS_CHAN_TURBO(c)) + return ctl | CTL_TURBO; + if (IEEE80211_IS_CHAN_A(c)) + return ctl | CTL_11A; + return ctl; +} + + +/* + * Update the current dfsDomain setting based on the given + * country code. + * + * Since FreeBSD/net80211 allows the channel set to change + * after the card has been setup (via ath_hal_init_channels()) + * this function method is needed to update ah_dfsDomain. + */ +void +ath_hal_update_dfsdomain(struct ath_hal *ah) +{ + const REG_DOMAIN *rd5GHz = AH_PRIVATE(ah)->ah_rd5GHz; + HAL_DFS_DOMAIN dfsDomain = HAL_DFS_UNINIT_DOMAIN; + + if (rd5GHz->dfsMask & DFS_FCC3) + dfsDomain = HAL_DFS_FCC_DOMAIN; + if (rd5GHz->dfsMask & DFS_ETSI) + dfsDomain = HAL_DFS_ETSI_DOMAIN; + if (rd5GHz->dfsMask & DFS_MKK4) + dfsDomain = HAL_DFS_MKK4_DOMAIN; + AH_PRIVATE(ah)->ah_dfsDomain = dfsDomain; + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s ah_dfsDomain: %d\n", + __func__, AH_PRIVATE(ah)->ah_dfsDomain); +} + + +/* + * Return the max allowed antenna gain and apply any regulatory + * domain specific changes. + * + * NOTE: a negative reduction is possible in RD's that only + * measure radiated power (e.g., ETSI) which would increase + * that actual conducted output power (though never beyond + * the calibrated target power). + */ +u_int +ath_hal_getantennareduction(struct ath_hal *ah, + const struct ieee80211_channel *chan, u_int twiceGain) +{ + int8_t antennaMax = twiceGain - chan->ic_maxantgain*2; + return (antennaMax < 0) ? 0 : antennaMax; +} diff --git a/sys/external/isc/atheros_hal/dist/ah_regdomain.h b/sys/external/isc/atheros_hal/dist/ah_regdomain.h new file mode 100644 index 0000000..e17e79a --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_regdomain.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2006 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef __AH_REGDOMAIN_H__ +#define __AH_REGDOMAIN_H__ + +/* + * BMLEN defines the size of the bitmask used to hold frequency + * band specifications. Note this must agree with the BM macro + * definition that's used to setup initializers. See also further + * comments below. + */ +#define BMLEN 2 /* 2 x 64 bits in each channel bitmask */ +typedef uint64_t chanbmask_t[BMLEN]; + +/* + * The following describe the bit masks for different passive scan + * capability/requirements per regdomain. + */ +#define NO_PSCAN 0x0ULL /* NB: must be zero */ +#define PSCAN_FCC 0x0000000000000001ULL +#define PSCAN_FCC_T 0x0000000000000002ULL +#define PSCAN_ETSI 0x0000000000000004ULL +#define PSCAN_MKK1 0x0000000000000008ULL +#define PSCAN_MKK2 0x0000000000000010ULL +#define PSCAN_MKKA 0x0000000000000020ULL +#define PSCAN_MKKA_G 0x0000000000000040ULL +#define PSCAN_ETSIA 0x0000000000000080ULL +#define PSCAN_ETSIB 0x0000000000000100ULL +#define PSCAN_ETSIC 0x0000000000000200ULL +#define PSCAN_WWR 0x0000000000000400ULL +#define PSCAN_MKKA1 0x0000000000000800ULL +#define PSCAN_MKKA1_G 0x0000000000001000ULL +#define PSCAN_MKKA2 0x0000000000002000ULL +#define PSCAN_MKKA2_G 0x0000000000004000ULL +#define PSCAN_MKK3 0x0000000000008000ULL +#define PSCAN_DEFER 0x7FFFFFFFFFFFFFFFULL +#define IS_ECM_CHAN 0x8000000000000000ULL + +/* + * The following are flags for different requirements per reg domain. + * These requirements are either inhereted from the reg domain pair or + * from the unitary reg domain if the reg domain pair flags value is 0 + */ +enum { + NO_REQ = 0x00000000, /* NB: must be zero */ + DISALLOW_ADHOC_11A = 0x00000001, /* adhoc not allowed in 5GHz */ + DISALLOW_ADHOC_11A_TURB = 0x00000002, /* not allowed w/ 5GHz turbo */ + NEED_NFC = 0x00000004, /* need noise floor check */ + ADHOC_PER_11D = 0x00000008, /* must receive 11d beacon */ + LIMIT_FRAME_4MS = 0x00000020, /* 4msec tx burst limit */ + NO_HOSTAP = 0x00000040, /* No HOSTAP mode opereation */ +}; + +/* Bit masks for DFS per regdomain */ +enum { + NO_DFS = 0x0000000000000000ULL, /* NB: must be zero */ + DFS_FCC3 = 0x0000000000000001ULL, + DFS_ETSI = 0x0000000000000002ULL, + DFS_MKK4 = 0x0000000000000004ULL, +}; + +enum { /* conformance test limits */ + FCC = 0x10, + MKK = 0x40, + ETSI = 0x30, +}; + +/* + * THE following table is the mapping of regdomain pairs specified by + * an 8 bit regdomain value to the individual unitary reg domains + */ +typedef struct regDomainPair { + HAL_REG_DOMAIN regDmnEnum; /* 16 bit reg domain pair */ + HAL_REG_DOMAIN regDmn5GHz; /* 5GHz reg domain */ + HAL_REG_DOMAIN regDmn2GHz; /* 2GHz reg domain */ + uint32_t flags5GHz; /* Requirements flags (AdHoc + disallow, noise floor cal needed, + etc) */ + uint32_t flags2GHz; /* Requirements flags (AdHoc + disallow, noise floor cal needed, + etc) */ + uint64_t pscanMask; /* Passive Scan flags which + can override unitary domain + passive scan flags. This + value is used as a mask on + the unitary flags*/ + uint16_t singleCC; /* Country code of single country if + a one-on-one mapping exists */ +} REG_DMN_PAIR_MAPPING; + +typedef struct { + HAL_CTRY_CODE countryCode; + HAL_REG_DOMAIN regDmnEnum; +} COUNTRY_CODE_TO_ENUM_RD; + +/* + * Frequency band collections are defined using bitmasks. Each bit + * in a mask is the index of an entry in one of the following tables. + * Bitmasks are BMLEN*64 bits so if a table grows beyond that the bit + * vectors must be enlarged or the tables split somehow (e.g. split + * 1/2 and 1/4 rate channels into a separate table). + * + * Beware of ordering; the indices are defined relative to the preceding + * entry so if things get off there will be confusion. A good way to + * check the indices is to collect them in a switch statement in a stub + * function so the compiler checks for duplicates. + */ +typedef struct { + uint16_t lowChannel; /* Low channel center in MHz */ + uint16_t highChannel; /* High Channel center in MHz */ + uint8_t powerDfs; /* Max power (dBm) for channel + range when using DFS */ + uint8_t antennaMax; /* Max allowed antenna gain */ + uint8_t channelBW; /* Bandwidth of the channel */ + uint8_t channelSep; /* Channel separation within + the band */ + uint64_t useDfs; /* Use DFS in the RegDomain + if corresponding bit is set */ + uint64_t usePassScan; /* Use Passive Scan in the RegDomain + if corresponding bit is set */ +} REG_DMN_FREQ_BAND; + +typedef struct regDomain { + uint16_t regDmnEnum; /* value from EnumRd table */ + uint8_t conformanceTestLimit; + uint32_t flags; /* Requirement flags (AdHoc disallow, + noise floor cal needed, etc) */ + uint64_t dfsMask; /* DFS bitmask for 5Ghz tables */ + uint64_t pscan; /* Bitmask for passive scan */ + chanbmask_t chan11a; /* 11a channels */ + chanbmask_t chan11a_turbo; /* 11a static turbo channels */ + chanbmask_t chan11a_dyn_turbo; /* 11a dynamic turbo channels */ + chanbmask_t chan11a_half; /* 11a 1/2 width channels */ + chanbmask_t chan11a_quarter; /* 11a 1/4 width channels */ + chanbmask_t chan11b; /* 11b channels */ + chanbmask_t chan11g; /* 11g channels */ + chanbmask_t chan11g_turbo; /* 11g dynamic turbo channels */ + chanbmask_t chan11g_half; /* 11g 1/2 width channels */ + chanbmask_t chan11g_quarter; /* 11g 1/4 width channels */ +} REG_DOMAIN; + +struct cmode { + u_int mode; + u_int flags; +}; +#endif diff --git a/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_ctry.h b/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_ctry.h new file mode 100644 index 0000000..af4824c --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_ctry.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2011 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AH_REGDOMAIN_CTRY_H__ +#define __AH_REGDOMAIN_CTRY_H__ + +#define DEF_REGDMN FCC1_FCCA + +/* + * This table maps country ISO codes from net80211 into regulatory + * domains which the ath regulatory domain code understands. + */ +static COUNTRY_CODE_TO_ENUM_RD allCountries[] = { + { CTRY_DEBUG, NO_ENUMRD }, + { CTRY_DEFAULT, DEF_REGDMN }, + { CTRY_ALBANIA, NULL1_WORLD }, + { CTRY_ALGERIA, NULL1_WORLD }, + { CTRY_ARGENTINA, APL3_WORLD }, + { CTRY_ARMENIA, ETSI4_WORLD }, + { CTRY_AUSTRALIA, FCC3_WORLD }, + { CTRY_AUSTRIA, ETSI1_WORLD }, + { CTRY_AZERBAIJAN, ETSI4_WORLD }, + { CTRY_BAHRAIN, APL6_WORLD }, + { CTRY_BELARUS, NULL1_WORLD }, + { CTRY_BELGIUM, ETSI1_WORLD }, + { CTRY_BELIZE, APL1_ETSIC }, + { CTRY_BOLIVIA, APL1_ETSIC }, + { CTRY_BRAZIL, FCC3_WORLD }, + { CTRY_BRUNEI_DARUSSALAM,APL1_WORLD }, + { CTRY_BULGARIA, ETSI6_WORLD }, + { CTRY_CANADA, FCC2_FCCA }, + { CTRY_CHILE, APL6_WORLD }, + { CTRY_CHINA, APL1_WORLD }, + { CTRY_COLOMBIA, FCC1_FCCA }, + { CTRY_COSTA_RICA, NULL1_WORLD }, + { CTRY_CROATIA, ETSI3_WORLD }, + { CTRY_CYPRUS, ETSI1_WORLD }, + { CTRY_CZECH, ETSI1_WORLD }, + { CTRY_DENMARK, ETSI1_WORLD }, + { CTRY_DOMINICAN_REPUBLIC,FCC1_FCCA }, + { CTRY_ECUADOR, NULL1_WORLD }, + { CTRY_EGYPT, ETSI3_WORLD }, + { CTRY_EL_SALVADOR, NULL1_WORLD }, + { CTRY_ESTONIA, ETSI1_WORLD }, + { CTRY_FINLAND, ETSI1_WORLD }, + { CTRY_FRANCE, ETSI1_WORLD }, + { CTRY_FRANCE2, ETSI3_WORLD }, + { CTRY_GEORGIA, ETSI4_WORLD }, + { CTRY_GERMANY, ETSI1_WORLD }, + { CTRY_GREECE, ETSI1_WORLD }, + { CTRY_GUATEMALA, FCC1_FCCA }, + { CTRY_HONDURAS, NULL1_WORLD }, + { CTRY_HONG_KONG, FCC2_WORLD }, + { CTRY_HUNGARY, ETSI1_WORLD }, + { CTRY_ICELAND, ETSI1_WORLD }, + { CTRY_INDIA, APL6_WORLD }, + { CTRY_INDONESIA, APL1_WORLD }, + { CTRY_IRAN, APL1_WORLD }, + { CTRY_IRELAND, ETSI1_WORLD }, + { CTRY_ISRAEL, NULL1_WORLD }, + { CTRY_ITALY, ETSI1_WORLD }, + { CTRY_JAPAN, MKK1_MKKA }, + { CTRY_JAPAN1, MKK1_MKKB }, + { CTRY_JAPAN2, MKK1_FCCA }, + { CTRY_JAPAN3, MKK2_MKKA }, + { CTRY_JAPAN4, MKK1_MKKA1 }, + { CTRY_JAPAN5, MKK1_MKKA2 }, + { CTRY_JAPAN6, MKK1_MKKC }, + + { CTRY_JAPAN7, MKK3_MKKB }, + { CTRY_JAPAN8, MKK3_MKKA2 }, + { CTRY_JAPAN9, MKK3_MKKC }, + + { CTRY_JAPAN10, MKK4_MKKB }, + { CTRY_JAPAN11, MKK4_MKKA2 }, + { CTRY_JAPAN12, MKK4_MKKC }, + + { CTRY_JAPAN13, MKK5_MKKB }, + { CTRY_JAPAN14, MKK5_MKKA2 }, + { CTRY_JAPAN15, MKK5_MKKC }, + + { CTRY_JAPAN16, MKK6_MKKB }, + { CTRY_JAPAN17, MKK6_MKKA2 }, + { CTRY_JAPAN18, MKK6_MKKC }, + + { CTRY_JAPAN19, MKK7_MKKB }, + { CTRY_JAPAN20, MKK7_MKKA2 }, + { CTRY_JAPAN21, MKK7_MKKC }, + + { CTRY_JAPAN22, MKK8_MKKB }, + { CTRY_JAPAN23, MKK8_MKKA2 }, + { CTRY_JAPAN24, MKK8_MKKC }, + + { CTRY_JORDAN, APL4_WORLD }, + { CTRY_KAZAKHSTAN, NULL1_WORLD }, + { CTRY_KOREA_NORTH, APL2_WORLD }, + { CTRY_KOREA_ROC, APL2_WORLD }, + { CTRY_KOREA_ROC2, APL2_WORLD }, + { CTRY_KOREA_ROC3, APL9_WORLD }, + { CTRY_KUWAIT, NULL1_WORLD }, + { CTRY_LATVIA, ETSI1_WORLD }, + { CTRY_LEBANON, NULL1_WORLD }, + { CTRY_LIECHTENSTEIN,ETSI1_WORLD }, + { CTRY_LITHUANIA, ETSI1_WORLD }, + { CTRY_LUXEMBOURG, ETSI1_WORLD }, + { CTRY_MACAU, FCC2_WORLD }, + { CTRY_MACEDONIA, NULL1_WORLD }, + { CTRY_MALAYSIA, APL8_WORLD }, + { CTRY_MALTA, ETSI1_WORLD }, + { CTRY_MEXICO, FCC1_FCCA }, + { CTRY_MONACO, ETSI4_WORLD }, + { CTRY_MOROCCO, NULL1_WORLD }, + { CTRY_NETHERLANDS, ETSI1_WORLD }, + { CTRY_NEW_ZEALAND, FCC2_ETSIC }, + { CTRY_NORWAY, ETSI1_WORLD }, + { CTRY_OMAN, APL6_WORLD }, + { CTRY_PAKISTAN, NULL1_WORLD }, + { CTRY_PANAMA, FCC1_FCCA }, + { CTRY_PERU, APL1_WORLD }, + { CTRY_PHILIPPINES, FCC3_WORLD }, + { CTRY_POLAND, ETSI1_WORLD }, + { CTRY_PORTUGAL, ETSI1_WORLD }, + { CTRY_PUERTO_RICO, FCC1_FCCA }, + { CTRY_QATAR, NULL1_WORLD }, + { CTRY_ROMANIA, NULL1_WORLD }, + { CTRY_RUSSIA, NULL1_WORLD }, + { CTRY_SAUDI_ARABIA,FCC2_WORLD }, + { CTRY_SINGAPORE, APL6_WORLD }, + { CTRY_SLOVAKIA, ETSI1_WORLD }, + { CTRY_SLOVENIA, ETSI1_WORLD }, + { CTRY_SOUTH_AFRICA,FCC3_WORLD }, + { CTRY_SPAIN, ETSI1_WORLD }, + { CTRY_SWEDEN, ETSI1_WORLD }, + { CTRY_SWITZERLAND, ETSI1_WORLD }, + { CTRY_SYRIA, NULL1_WORLD }, + { CTRY_TAIWAN, APL3_FCCA }, + { CTRY_THAILAND, FCC3_WORLD }, + { CTRY_TRINIDAD_Y_TOBAGO,ETSI4_WORLD }, + { CTRY_TUNISIA, ETSI3_WORLD }, + { CTRY_TURKEY, ETSI3_WORLD }, + { CTRY_UKRAINE, NULL1_WORLD }, + { CTRY_UAE, NULL1_WORLD }, + { CTRY_UNITED_KINGDOM, ETSI1_WORLD }, + { CTRY_UNITED_STATES, FCC1_FCCA }, + { CTRY_UNITED_STATES_FCC49,FCC4_FCCA }, + { CTRY_URUGUAY, FCC1_WORLD }, + { CTRY_UZBEKISTAN, FCC3_FCCA }, + { CTRY_VENEZUELA, APL2_ETSIC }, + { CTRY_VIET_NAM, NULL1_WORLD }, + { CTRY_ZIMBABWE, NULL1_WORLD } +}; + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_domains.h b/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_domains.h new file mode 100644 index 0000000..04a6ccd --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_domains.h @@ -0,0 +1,774 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2006 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AH_REGDOMAIN_DOMAINS_H__ +#define __AH_REGDOMAIN_DOMAINS_H__ + +/* + * BMLEN defines the size of the bitmask used to hold frequency + * band specifications. Note this must agree with the BM macro + * definition that's used to setup initializers. See also further + * comments below. + */ +/* BMLEN is now defined in ah_regdomain.h */ +#define W0(_a) \ + (((_a) >= 0 && (_a) < 64 ? (((uint64_t) 1)<<(_a)) : (uint64_t) 0)) +#define W1(_a) \ + (((_a) > 63 && (_a) < 128 ? (((uint64_t) 1)<<((_a)-64)) : (uint64_t) 0)) +#define BM1(_fa) { W0(_fa), W1(_fa) } +#define BM2(_fa, _fb) { W0(_fa) | W0(_fb), W1(_fa) | W1(_fb) } +#define BM3(_fa, _fb, _fc) \ + { W0(_fa) | W0(_fb) | W0(_fc), W1(_fa) | W1(_fb) | W1(_fc) } +#define BM4(_fa, _fb, _fc, _fd) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd), \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) } +#define BM5(_fa, _fb, _fc, _fd, _fe) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe), \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) } +#define BM6(_fa, _fb, _fc, _fd, _fe, _ff) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff), \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) } +#define BM7(_fa, _fb, _fc, _fd, _fe, _ff, _fg) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) | \ + W0(_fg),\ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) | \ + W1(_fg) } +#define BM8(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) | \ + W0(_fg) | W0(_fh) , \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) | \ + W1(_fg) | W1(_fh) } +#define BM9(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh, _fi) \ + { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) | \ + W0(_fg) | W0(_fh) | W0(_fi) , \ + W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) | \ + W1(_fg) | W1(_fh) | W1(_fi) } + +static REG_DOMAIN regDomains[] = { + + {.regDmnEnum = DEBUG_REG_DMN, + .conformanceTestLimit = FCC, + .dfsMask = DFS_FCC3, + .chan11a = BM4(F1_4950_4980, + F1_5120_5240, + F1_5260_5700, + F1_5745_5825), + .chan11a_half = BM4(F1_4945_4985, + F2_5120_5240, + F2_5260_5700, + F7_5745_5825), + .chan11a_quarter = BM4(F1_4942_4987, + F3_5120_5240, + F3_5260_5700, + F8_5745_5825), + .chan11a_turbo = BM8(T1_5130_5210, + T1_5250_5330, + T1_5370_5490, + T1_5530_5650, + T1_5150_5190, + T1_5230_5310, + T1_5350_5470, + T1_5510_5670), + .chan11a_dyn_turbo = BM4(T1_5200_5240, + T1_5280_5280, + T1_5540_5660, + T1_5765_5805), + .chan11b = BM4(F1_2312_2372, + F1_2412_2472, + F1_2484_2484, + F1_2512_2732), + .chan11g = BM3(G1_2312_2372, G1_2412_2472, G1_2512_2732), + .chan11g_turbo = BM3(T1_2312_2372, T1_2437_2437, T1_2512_2732), + .chan11g_half = BM3(G2_2312_2372, G4_2412_2472, G2_2512_2732), + .chan11g_quarter = BM3(G3_2312_2372, G5_2412_2472, G3_2512_2732), + }, + + {.regDmnEnum = APL1, + .conformanceTestLimit = FCC, + .chan11a = BM1(F4_5745_5825), + }, + + {.regDmnEnum = APL2, + .conformanceTestLimit = FCC, + .chan11a = BM1(F1_5745_5805), + }, + + {.regDmnEnum = APL3, + .conformanceTestLimit = FCC, + .chan11a = BM2(F1_5280_5320, F2_5745_5805), + }, + + {.regDmnEnum = APL4, + .conformanceTestLimit = FCC, + .chan11a = BM2(F4_5180_5240, F3_5745_5825), + }, + + {.regDmnEnum = APL5, + .conformanceTestLimit = FCC, + .chan11a = BM1(F2_5745_5825), + }, + + {.regDmnEnum = APL6, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_FCC_T | PSCAN_FCC, + .chan11a = BM3(F4_5180_5240, F2_5260_5320, F3_5745_5825), + .chan11a_turbo = BM3(T2_5210_5210, T1_5250_5290, T1_5760_5800), + }, + + {.regDmnEnum = APL8, + .conformanceTestLimit = ETSI, + .flags = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(F6_5260_5320, F4_5745_5825), + }, + + {.regDmnEnum = APL9, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F1_5180_5320, F1_5500_5620, F3_5745_5805), + }, + + {.regDmnEnum = ETSI1, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(W2_5180_5240, F2_5260_5320, F2_5500_5700), + }, + + {.regDmnEnum = ETSI2, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F3_5180_5240), + }, + + {.regDmnEnum = ETSI3, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(W2_5180_5240, F2_5260_5320), + }, + + {.regDmnEnum = ETSI4, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(F3_5180_5240, F1_5260_5320), + }, + + {.regDmnEnum = ETSI5, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F1_5180_5240), + }, + + {.regDmnEnum = ETSI6, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F5_5180_5240, F1_5260_5280, F3_5500_5700), + }, + + {.regDmnEnum = FCC1, + .conformanceTestLimit = FCC, + .chan11a = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825), + .chan11a_turbo = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800), + .chan11a_dyn_turbo = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805), + }, + + {.regDmnEnum = FCC2, + .conformanceTestLimit = FCC, + .chan11a = BM3(F6_5180_5240, F5_5260_5320, F6_5745_5825), + .chan11a_dyn_turbo = BM3(T2_5200_5240, T1_5280_5280, T1_5765_5805), + }, + + {.regDmnEnum = FCC3, + .conformanceTestLimit = FCC, + .dfsMask = DFS_FCC3, + .pscan = PSCAN_FCC | PSCAN_FCC_T, + .chan11a = BM4(F2_5180_5240, + F3_5260_5320, + F1_5500_5700, + F5_5745_5825), + .chan11a_turbo = BM4(T1_5210_5210, + T1_5250_5250, + T1_5290_5290, + T2_5760_5800), + .chan11a_dyn_turbo = BM3(T1_5200_5240, T2_5280_5280, T1_5540_5660), + }, + + {.regDmnEnum = FCC4, + .conformanceTestLimit = FCC, + .dfsMask = DFS_FCC3, + .pscan = PSCAN_FCC | PSCAN_FCC_T, + .chan11a = BM1(F1_4950_4980), + .chan11a_half = BM1(F1_4945_4985), + .chan11a_quarter = BM1(F1_4942_4987), + }, + + /* FCC1 w/ 1/2 and 1/4 width channels */ + {.regDmnEnum = FCC5, + .conformanceTestLimit = FCC, + .chan11a = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825), + .chan11a_turbo = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800), + .chan11a_dyn_turbo = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805), + .chan11a_half = BM3(F7_5180_5240, F7_5260_5320, F9_5745_5825), + .chan11a_quarter = BM3(F8_5180_5240, F8_5260_5320,F10_5745_5825), + }, + + {.regDmnEnum = MKK1, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK1, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F1_5170_5230), + }, + + {.regDmnEnum = MKK2, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK2, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F1_4920_4980, F1_5040_5080, F1_5170_5230), + .chan11a_half = BM4(F1_4915_4925, + F1_4935_4945, + F1_5035_5040, + F1_5055_5055), + }, + + /* UNI-1 even */ + {.regDmnEnum = MKK3, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F4_5180_5240), + }, + + /* UNI-1 even + UNI-2 */ + {.regDmnEnum = MKK4, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(F4_5180_5240, F2_5260_5320), + }, + + /* UNI-1 even + UNI-2 + mid-band */ + {.regDmnEnum = MKK5, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F4_5180_5240, F2_5260_5320, F4_5500_5700), + }, + + /* UNI-1 odd + even */ + {.regDmnEnum = MKK6, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK1, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(F2_5170_5230, F4_5180_5240), + }, + + /* UNI-1 odd + UNI-1 even + UNI-2 */ + {.regDmnEnum = MKK7, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK1 | PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM3(F1_5170_5230, F4_5180_5240, F2_5260_5320), + }, + + /* UNI-1 odd + UNI-1 even + UNI-2 + mid-band */ + {.regDmnEnum = MKK8, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK1 | PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM4(F1_5170_5230, + F4_5180_5240, + F2_5260_5320, + F4_5500_5700), + }, + + /* UNI-1 even + 4.9 GHZ */ + {.regDmnEnum = MKK9, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM7(F1_4915_4925, + F1_4935_4945, + F1_4920_4980, + F1_5035_5040, + F1_5055_5055, + F1_5040_5080, + F4_5180_5240), + }, + + /* UNI-1 even + UNI-2 + 4.9 GHZ */ + {.regDmnEnum = MKK10, + .conformanceTestLimit = MKK, + .dfsMask = DFS_MKK4, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM8(F1_4915_4925, + F1_4935_4945, + F1_4920_4980, + F1_5035_5040, + F1_5055_5055, + F1_5040_5080, + F4_5180_5240, + F2_5260_5320), + }, + + /* Defined here to use when 2G channels are authorised for country K2 */ + {.regDmnEnum = APLD, + .conformanceTestLimit = NO_CTL, + .chan11b = BM2(F2_2312_2372,F2_2412_2472), + .chan11g = BM2(G2_2312_2372,G2_2412_2472), + }, + + {.regDmnEnum = ETSIA, + .conformanceTestLimit = NO_CTL, + .pscan = PSCAN_ETSIA, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11b = BM1(F1_2457_2472), + .chan11g = BM1(G1_2457_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = ETSIB, + .conformanceTestLimit = ETSI, + .pscan = PSCAN_ETSIB, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11b = BM1(F1_2432_2442), + .chan11g = BM1(G1_2432_2442), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = ETSIC, + .conformanceTestLimit = ETSI, + .pscan = PSCAN_ETSIC, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11b = BM1(F3_2412_2472), + .chan11g = BM1(G3_2412_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = FCCA, + .conformanceTestLimit = FCC, + .chan11b = BM1(F1_2412_2462), + .chan11g = BM1(G1_2412_2462), + .chan11g_turbo = BM1(T2_2437_2437), + }, + + /* FCCA w/ 1/2 and 1/4 width channels */ + {.regDmnEnum = FCCB, + .conformanceTestLimit = FCC, + .chan11b = BM1(F1_2412_2462), + .chan11g = BM1(G1_2412_2462), + .chan11g_turbo = BM1(T2_2437_2437), + .chan11g_half = BM1(G3_2412_2462), + .chan11g_quarter = BM1(G4_2412_2462), + }, + + {.regDmnEnum = MKKA, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKKA | PSCAN_MKKA_G + | PSCAN_MKKA1 | PSCAN_MKKA1_G + | PSCAN_MKKA2 | PSCAN_MKKA2_G, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11b = BM3(F2_2412_2462, F1_2467_2472, F2_2484_2484), + .chan11g = BM2(G2_2412_2462, G1_2467_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = MKKC, + .conformanceTestLimit = MKK, + .chan11b = BM1(F2_2412_2472), + .chan11g = BM1(G2_2412_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = WORLD, + .conformanceTestLimit = ETSI, + .chan11b = BM1(F2_2412_2472), + .chan11g = BM1(G2_2412_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, + + {.regDmnEnum = WOR0_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM8(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467, + W1_2484_2484), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437) + }, + + {.regDmnEnum = WOR01_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM5(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2417_2432, + W1_2447_2457), + .chan11g = BM5(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2417_2432, + WG1_2447_2457), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR02_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = EU1_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W2_2472_2472, + W1_2417_2432, + W1_2447_2457, + W2_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG2_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG2_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR1_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11b = BM8(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467, + W1_2484_2484), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437) + }, + + {.regDmnEnum = WOR2_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM5(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM8(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467, + W1_2484_2484), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR3_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM4(W1_5260_5320, + W1_5180_5240, + W1_5170_5230, + W1_5745_5825), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR4_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM4(W2_5260_5320, + W2_5180_5240, + F2_5745_5805, + W2_5825_5825), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM5(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2417_2432, + W1_2447_2457), + .chan11g = BM5(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2417_2432, + WG1_2447_2457), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR5_ETSIC, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM3(W1_5260_5320, W2_5180_5240, F6_5745_5825), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W2_2472_2472, + W1_2417_2432, + W1_2447_2457, + W2_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG2_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG2_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WOR9_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM4(W1_5260_5320, + W1_5180_5240, + W1_5745_5825, + W1_5500_5700), + .chan11a_turbo = BM3(WT1_5210_5250, + WT1_5290_5290, + WT1_5760_5800), + .chan11b = BM5(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2417_2432, + W1_2447_2457), + .chan11g = BM5(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2417_2432, + WG1_2447_2457), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WORA_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM4(W1_5260_5320, + W1_5180_5240, + W1_5745_5825, + W1_5500_5700), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WORB_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = DISALLOW_ADHOC_11A, + .chan11a = BM4(W1_5260_5320, + W1_5180_5240, + W1_5745_5825, + W1_5500_5700), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = WORC_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_PER_11D, + .chan11a = BM4(W1_5260_5320, + W1_5180_5240, + W1_5745_5825, + W1_5500_5700), + .chan11b = BM7(W1_2412_2412, + W1_2437_2442, + W1_2462_2462, + W1_2472_2472, + W1_2417_2432, + W1_2447_2457, + W1_2467_2467), + .chan11g = BM7(WG1_2412_2412, + WG1_2437_2442, + WG1_2462_2462, + WG1_2472_2472, + WG1_2417_2432, + WG1_2447_2457, + WG1_2467_2467), + .chan11g_turbo = BM1(T3_2437_2437)}, + + {.regDmnEnum = NULL1, + .conformanceTestLimit = NO_CTL, + } +}; + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_freqbands.h b/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_freqbands.h new file mode 100644 index 0000000..79d418f --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_freqbands.h @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2006 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AH_REGDOMAIN_FREQBANDS_H__ +#define __AH_REGDOMAIN_FREQBANDS_H__ + +#define AFTER(x) ((x)+1) + +/* + * Frequency band collections are defined using bitmasks. Each bit + * in a mask is the index of an entry in one of the following tables. + * Bitmasks are BMLEN*64 bits so if a table grows beyond that the bit + * vectors must be enlarged or the tables split somehow (e.g. split + * 1/2 and 1/4 rate channels into a separate table). + * + * Beware of ordering; the indices are defined relative to the preceding + * entry so if things get off there will be confusion. A good way to + * check the indices is to collect them in a switch statement in a stub + * function so the compiler checks for duplicates. + */ + +/* + * 5GHz 11A channel tags + */ +static REG_DMN_FREQ_BAND regDmn5GhzFreq[] = { + { 4915, 4925, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2 }, +#define F1_4915_4925 0 + { 4935, 4945, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2 }, +#define F1_4935_4945 AFTER(F1_4915_4925) + { 4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2 }, +#define F1_4920_4980 AFTER(F1_4935_4945) + { 4942, 4987, 27, 6, 5, 5, NO_DFS, PSCAN_FCC }, +#define F1_4942_4987 AFTER(F1_4920_4980) + { 4945, 4985, 30, 6, 10, 5, NO_DFS, PSCAN_FCC }, +#define F1_4945_4985 AFTER(F1_4942_4987) + { 4950, 4980, 33, 6, 20, 5, NO_DFS, PSCAN_FCC }, +#define F1_4950_4980 AFTER(F1_4945_4985) + { 5035, 5040, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2 }, +#define F1_5035_5040 AFTER(F1_4950_4980) + { 5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2 }, +#define F1_5040_5080 AFTER(F1_5035_5040) + { 5055, 5055, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2 }, +#define F1_5055_5055 AFTER(F1_5040_5080) + + { 5120, 5240, 5, 6, 20, 20, NO_DFS, NO_PSCAN }, +#define F1_5120_5240 AFTER(F1_5055_5055) + { 5120, 5240, 5, 6, 10, 10, NO_DFS, NO_PSCAN }, +#define F2_5120_5240 AFTER(F1_5120_5240) + { 5120, 5240, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, +#define F3_5120_5240 AFTER(F2_5120_5240) + + { 5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2 }, +#define F1_5170_5230 AFTER(F3_5120_5240) + { 5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2 }, +#define F2_5170_5230 AFTER(F1_5170_5230) + + { 5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI }, +#define F1_5180_5240 AFTER(F2_5170_5230) + { 5180, 5240, 17, 6, 20, 20, NO_DFS, PSCAN_FCC }, +#define F2_5180_5240 AFTER(F1_5180_5240) + { 5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI }, +#define F3_5180_5240 AFTER(F2_5180_5240) + { 5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI }, +#define F4_5180_5240 AFTER(F3_5180_5240) + { 5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI }, +#define F5_5180_5240 AFTER(F4_5180_5240) + { 5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC }, +#define F6_5180_5240 AFTER(F5_5180_5240) + { 5180, 5240, 17, 6, 20, 10, NO_DFS, PSCAN_FCC }, +#define F7_5180_5240 AFTER(F6_5180_5240) + { 5180, 5240, 17, 6, 20, 5, NO_DFS, PSCAN_FCC }, +#define F8_5180_5240 AFTER(F7_5180_5240) + { 5180, 5320, 20, 6, 20, 20, DFS_ETSI, PSCAN_ETSI }, + +#define F1_5180_5320 AFTER(F8_5180_5240) + { 5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI }, + +#define F1_5240_5280 AFTER(F1_5180_5320) + { 5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI }, + +#define F1_5260_5280 AFTER(F1_5240_5280) + { 5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI }, + +#define F1_5260_5320 AFTER(F1_5260_5280) + { 5260, 5320, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3 }, +#define F2_5260_5320 AFTER(F1_5260_5320) + + { 5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F3_5260_5320 AFTER(F2_5260_5320) + { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F4_5260_5320 AFTER(F3_5260_5320) + { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F5_5260_5320 AFTER(F4_5260_5320) + { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define F6_5260_5320 AFTER(F5_5260_5320) + { 5260, 5320, 23, 6, 20, 10, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F7_5260_5320 AFTER(F6_5260_5320) + { 5260, 5320, 23, 6, 20, 5, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F8_5260_5320 AFTER(F7_5260_5320) + + { 5260, 5700, 5, 6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN }, +#define F1_5260_5700 AFTER(F8_5260_5320) + { 5260, 5700, 5, 6, 10, 10, DFS_FCC3 | DFS_ETSI, NO_PSCAN }, +#define F2_5260_5700 AFTER(F1_5260_5700) + { 5260, 5700, 5, 6, 5, 5, DFS_FCC3 | DFS_ETSI, NO_PSCAN }, +#define F3_5260_5700 AFTER(F2_5260_5700) + + { 5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F1_5280_5320 AFTER(F3_5260_5700) + + { 5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI }, +#define F1_5500_5620 AFTER(F1_5280_5320) + + { 5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC }, +#define F1_5500_5700 AFTER(F1_5500_5620) + { 5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI }, +#define F2_5500_5700 AFTER(F1_5500_5700) + { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI }, +#define F3_5500_5700 AFTER(F2_5500_5700) + { 5500, 5700, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_MKK3 | PSCAN_FCC }, +#define F4_5500_5700 AFTER(F3_5500_5700) + + { 5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define F1_5745_5805 AFTER(F4_5500_5700) + { 5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN }, +#define F2_5745_5805 AFTER(F1_5745_5805) + { 5745, 5805, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI }, +#define F3_5745_5805 AFTER(F2_5745_5805) + { 5745, 5825, 5, 6, 20, 20, NO_DFS, NO_PSCAN }, +#define F1_5745_5825 AFTER(F3_5745_5805) + { 5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define F2_5745_5825 AFTER(F1_5745_5825) + { 5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define F3_5745_5825 AFTER(F2_5745_5825) + { 5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define F4_5745_5825 AFTER(F3_5745_5825) + { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN }, +#define F5_5745_5825 AFTER(F4_5745_5825) + { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN }, +#define F6_5745_5825 AFTER(F5_5745_5825) + { 5745, 5825, 5, 6, 10, 10, NO_DFS, NO_PSCAN }, +#define F7_5745_5825 AFTER(F6_5745_5825) + { 5745, 5825, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, +#define F8_5745_5825 AFTER(F7_5745_5825) + { 5745, 5825, 30, 6, 20, 10, NO_DFS, NO_PSCAN }, +#define F9_5745_5825 AFTER(F8_5745_5825) + { 5745, 5825, 30, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define F10_5745_5825 AFTER(F9_5745_5825) + + /* + * Below are the world roaming channels + * All WWR domains have no power limit, instead use the card's CTL + * or max power settings. + */ + { 4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR }, +#define W1_4920_4980 AFTER(F10_5745_5825) + { 5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR }, +#define W1_5040_5080 AFTER(W1_4920_4980) + { 5170, 5230, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define W1_5170_5230 AFTER(W1_5040_5080) + { 5180, 5240, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define W1_5180_5240 AFTER(W1_5170_5230) + { 5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define W1_5260_5320 AFTER(W1_5180_5240) + { 5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR }, +#define W1_5745_5825 AFTER(W1_5260_5320) + { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define W1_5500_5700 AFTER(W1_5745_5825) + { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define W2_5260_5320 AFTER(W1_5500_5700) + { 5180, 5240, 30, 0, 20, 20, NO_DFS, NO_PSCAN }, +#define W2_5180_5240 AFTER(W2_5260_5320) + { 5825, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR }, +#define W2_5825_5825 AFTER(W2_5180_5240) +}; + +/* + * 5GHz Turbo (dynamic & static) tags + */ +static REG_DMN_FREQ_BAND regDmn5GhzTurboFreq[] = { + { 5130, 5210, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5130_5210 0 + { 5250, 5330, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN }, +#define T1_5250_5330 AFTER(T1_5130_5210) + { 5370, 5490, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5370_5490 AFTER(T1_5250_5330) + { 5530, 5650, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN }, +#define T1_5530_5650 AFTER(T1_5370_5490) + + { 5150, 5190, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5150_5190 AFTER(T1_5530_5650) + { 5230, 5310, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN }, +#define T1_5230_5310 AFTER(T1_5150_5190) + { 5350, 5470, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5350_5470 AFTER(T1_5230_5310) + { 5510, 5670, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN }, +#define T1_5510_5670 AFTER(T1_5350_5470) + + { 5200, 5240, 17, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5200_5240 AFTER(T1_5510_5670) + { 5200, 5240, 23, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T2_5200_5240 AFTER(T1_5200_5240) + { 5210, 5210, 17, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5210_5210 AFTER(T2_5200_5240) + { 5210, 5210, 23, 0, 40, 40, NO_DFS, NO_PSCAN }, +#define T2_5210_5210 AFTER(T1_5210_5210) + + { 5280, 5280, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T1_5280_5280 AFTER(T2_5210_5210) + { 5280, 5280, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T2_5280_5280 AFTER(T1_5280_5280) + { 5250, 5250, 17, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T1_5250_5250 AFTER(T2_5280_5280) + { 5290, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T1_5290_5290 AFTER(T1_5250_5250) + { 5250, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T1_5250_5290 AFTER(T1_5290_5290) + { 5250, 5290, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T2_5250_5290 AFTER(T1_5250_5290) + + { 5540, 5660, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T }, +#define T1_5540_5660 AFTER(T2_5250_5290) + { 5760, 5800, 20, 0, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5760_5800 AFTER(T1_5540_5660) + { 5760, 5800, 30, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T2_5760_5800 AFTER(T1_5760_5800) + + { 5765, 5805, 30, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_5765_5805 AFTER(T2_5760_5800) + + /* + * Below are the WWR frequencies + */ + { 5210, 5250, 15, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define WT1_5210_5250 AFTER(T1_5765_5805) + { 5290, 5290, 18, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define WT1_5290_5290 AFTER(WT1_5210_5250) + { 5540, 5660, 20, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR }, +#define WT1_5540_5660 AFTER(WT1_5290_5290) + { 5760, 5800, 20, 0, 40, 40, NO_DFS, PSCAN_WWR }, +#define WT1_5760_5800 AFTER(WT1_5540_5660) +}; + +/* + * 2GHz 11b channel tags + */ +static REG_DMN_FREQ_BAND regDmn2GhzFreq[] = { + { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2312_2372 0 + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define F2_2312_2372 AFTER(F1_2312_2372) + + { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2412_2472 AFTER(F2_2312_2372) + { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA }, +#define F2_2412_2472 AFTER(F1_2412_2472) + { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define F3_2412_2472 AFTER(F2_2412_2472) + + { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2412_2462 AFTER(F3_2412_2472) + { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA }, +#define F2_2412_2462 AFTER(F1_2412_2462) + + { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2432_2442 AFTER(F2_2412_2462) + + { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2457_2472 AFTER(F1_2432_2442) + + { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA }, +#define F1_2467_2472 AFTER(F1_2457_2472) + + { 2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2484_2484 AFTER(F1_2467_2472) + { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2 }, +#define F2_2484_2484 AFTER(F1_2484_2484) + + { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define F1_2512_2732 AFTER(F2_2484_2484) + + /* + * WWR have powers opened up to 20dBm. + * Limits should often come from CTL/Max powers + */ + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define W1_2312_2372 AFTER(F1_2512_2732) + { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define W1_2412_2412 AFTER(W1_2312_2372) + { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define W1_2417_2432 AFTER(W1_2412_2412) + { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define W1_2437_2442 AFTER(W1_2417_2432) + { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define W1_2447_2457 AFTER(W1_2437_2442) + { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define W1_2462_2462 AFTER(W1_2447_2457) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, +#define W1_2467_2467 AFTER(W1_2462_2462) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, +#define W2_2467_2467 AFTER(W1_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, +#define W1_2472_2472 AFTER(W2_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, +#define W2_2472_2472 AFTER(W1_2472_2472) + { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, +#define W1_2484_2484 AFTER(W2_2472_2472) + { 2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, +#define W2_2484_2484 AFTER(W1_2484_2484) +}; + +/* + * 2GHz 11g channel tags + */ +static REG_DMN_FREQ_BAND regDmn2Ghz11gFreq[] = { + { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define G1_2312_2372 0 + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define G2_2312_2372 AFTER(G1_2312_2372) + { 2312, 2372, 5, 6, 10, 5, NO_DFS, NO_PSCAN }, +#define G3_2312_2372 AFTER(G2_2312_2372) + { 2312, 2372, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, +#define G4_2312_2372 AFTER(G3_2312_2372) + + { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define G1_2412_2472 AFTER(G4_2312_2372) + { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G }, +#define G2_2412_2472 AFTER(G1_2412_2472) + { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define G3_2412_2472 AFTER(G2_2412_2472) + { 2412, 2472, 5, 6, 10, 5, NO_DFS, NO_PSCAN }, +#define G4_2412_2472 AFTER(G3_2412_2472) + { 2412, 2472, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, +#define G5_2412_2472 AFTER(G4_2412_2472) + + { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define G1_2412_2462 AFTER(G5_2412_2472) + { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G }, +#define G2_2412_2462 AFTER(G1_2412_2462) + { 2412, 2462, 27, 6, 10, 5, NO_DFS, NO_PSCAN }, +#define G3_2412_2462 AFTER(G2_2412_2462) + { 2412, 2462, 27, 6, 5, 5, NO_DFS, NO_PSCAN }, +#define G4_2412_2462 AFTER(G3_2412_2462) + + { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define G1_2432_2442 AFTER(G4_2412_2462) + + { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define G1_2457_2472 AFTER(G1_2432_2442) + + { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN }, +#define G1_2512_2732 AFTER(G1_2457_2472) + { 2512, 2732, 5, 6, 10, 5, NO_DFS, NO_PSCAN }, +#define G2_2512_2732 AFTER(G1_2512_2732) + { 2512, 2732, 5, 6, 5, 5, NO_DFS, NO_PSCAN }, +#define G3_2512_2732 AFTER(G2_2512_2732) + + { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA }, +#define G1_2467_2472 AFTER(G3_2512_2732) + + /* + * WWR open up the power to 20dBm + */ + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define WG1_2312_2372 AFTER(G1_2467_2472) + { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define WG1_2412_2412 AFTER(WG1_2312_2372) + { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define WG1_2417_2432 AFTER(WG1_2412_2412) + { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define WG1_2437_2442 AFTER(WG1_2417_2432) + { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define WG1_2447_2457 AFTER(WG1_2437_2442) + { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, +#define WG1_2462_2462 AFTER(WG1_2447_2457) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, +#define WG1_2467_2467 AFTER(WG1_2462_2462) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, +#define WG2_2467_2467 AFTER(WG1_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN }, +#define WG1_2472_2472 AFTER(WG2_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN }, +#define WG2_2472_2472 AFTER(WG1_2472_2472) +}; + +/* + * 2GHz Dynamic turbo tags + */ +static REG_DMN_FREQ_BAND regDmn2Ghz11gTurboFreq[] = { + { 2312, 2372, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_2312_2372 0 + { 2437, 2437, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_2437_2437 AFTER(T1_2312_2372) + { 2437, 2437, 20, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T2_2437_2437 AFTER(T1_2437_2437) + { 2437, 2437, 18, 6, 40, 40, NO_DFS, PSCAN_WWR }, +#define T3_2437_2437 AFTER(T2_2437_2437) + { 2512, 2732, 5, 6, 40, 40, NO_DFS, NO_PSCAN }, +#define T1_2512_2732 AFTER(T3_2437_2437) +}; + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_regenum.h b/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_regenum.h new file mode 100644 index 0000000..d8d211e --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_regenum.h @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2011 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AH_REGDOMAIN_REGENUM_H__ +#define __AH_REGDOMAIN_REGENUM_H__ + +/* + * Enumerated Regulatory Domain Information 8 bit values indicate that + * the regdomain is really a pair of unitary regdomains. 12 bit values + * are the real unitary regdomains and are the only ones which have the + * frequency bitmasks and flags set. + */ +enum { + /* + * The following regulatory domain definitions are + * found in the EEPROM. Each regulatory domain + * can operate in either a 5GHz or 2.4GHz wireless mode or + * both 5GHz and 2.4GHz wireless modes. + * In general, the value holds no special + * meaning and is used to decode into either specific + * 2.4GHz or 5GHz wireless mode for that particular + * regulatory domain. + */ + NO_ENUMRD = 0x00, + NULL1_WORLD = 0x03, /* For 11b-only countries (no 11a allowed) */ + NULL1_ETSIB = 0x07, /* Israel */ + NULL1_ETSIC = 0x08, + FCC1_FCCA = 0x10, /* USA */ + FCC1_WORLD = 0x11, /* Hong Kong */ + FCC4_FCCA = 0x12, /* USA - Public Safety */ + FCC5_FCCB = 0x13, /* USA w/ 1/2 and 1/4 width channels */ + FCC6_FCCA = 0x14, /* Canada for AP only */ + + FCC2_FCCA = 0x20, /* Canada */ + FCC2_WORLD = 0x21, /* Australia & HK */ + FCC2_ETSIC = 0x22, + FCC_UBNT = 0x2A, /* Ubiquity PicoStation M2HP */ + FRANCE_RES = 0x31, /* Legacy France for OEM */ + FCC3_FCCA = 0x3A, /* USA & Canada w/5470 band, 11h, DFS enabled */ + FCC3_WORLD = 0x3B, /* USA & Canada w/5470 band, 11h, DFS enabled */ + + ETSI1_WORLD = 0x37, + ETSI3_ETSIA = 0x32, /* France (optional) */ + ETSI2_WORLD = 0x35, /* Hungary & others */ + ETSI3_WORLD = 0x36, /* France & others */ + ETSI4_WORLD = 0x30, + ETSI4_ETSIC = 0x38, + ETSI5_WORLD = 0x39, + ETSI6_WORLD = 0x34, /* Bulgaria */ + ETSI8_WORLD = 0x3D, /* Russia */ + ETSI9_WORLD = 0x3E, /* Ukraine */ + ETSI_RESERVED = 0x33, /* Reserved (Do not used) */ + + MKK1_MKKA = 0x40, /* Japan (JP1) */ + MKK1_MKKB = 0x41, /* Japan (JP0) */ + APL4_WORLD = 0x42, /* Singapore */ + MKK2_MKKA = 0x43, /* Japan with 4.9G channels */ + APL_RESERVED = 0x44, /* Reserved (Do not used) */ + APL2_WORLD = 0x45, /* Korea */ + APL2_APLC = 0x46, + APL3_WORLD = 0x47, + MKK1_FCCA = 0x48, /* Japan (JP1-1) */ + APL2_APLD = 0x49, /* Korea with 2.3G channels */ + MKK1_MKKA1 = 0x4A, /* Japan (JE1) */ + MKK1_MKKA2 = 0x4B, /* Japan (JE2) */ + MKK1_MKKC = 0x4C, /* Japan (MKK1_MKKA,except Ch14) */ + APL2_FCCA = 0x4D, /* Mobile customer */ + + APL3_FCCA = 0x50, + APL1_WORLD = 0x52, /* Latin America */ + APL1_FCCA = 0x53, + APL1_APLA = 0x54, + APL1_ETSIC = 0x55, + APL2_ETSIC = 0x56, /* Venezuela */ + APL5_WORLD = 0x58, /* Chile */ + APL6_WORLD = 0x5B, /* Singapore */ + APL7_FCCA = 0x5C, /* Taiwan 5.47 Band */ + APL8_WORLD = 0x5D, /* Malaysia 5GHz */ + APL9_WORLD = 0x5E, /* Korea 5GHz; before 11/2007; now APs only */ + APL10_WORLD = 0x5F, /* Korea 5GHz; After 11/2007; STAs only */ + + /* + * World mode SKUs + */ + WOR0_WORLD = 0x60, /* World0 (WO0 SKU) */ + WOR1_WORLD = 0x61, /* World1 (WO1 SKU) */ + WOR2_WORLD = 0x62, /* World2 (WO2 SKU) */ + WOR3_WORLD = 0x63, /* World3 (WO3 SKU) */ + WOR4_WORLD = 0x64, /* World4 (WO4 SKU) */ + WOR5_ETSIC = 0x65, /* World5 (WO5 SKU) */ + + WOR01_WORLD = 0x66, /* World0-1 (WW0-1 SKU) */ + WOR02_WORLD = 0x67, /* World0-2 (WW0-2 SKU) */ + EU1_WORLD = 0x68, /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */ + + WOR9_WORLD = 0x69, /* World9 (WO9 SKU) */ + WORA_WORLD = 0x6A, /* WorldA (WOA SKU) */ + WORB_WORLD = 0x6B, /* WorldB (WOB SKU) */ + WORC_WORLD = 0x6C, /* WorldC (WOC SKU) */ + + MKK3_MKKB = 0x80, /* Japan UNI-1 even + MKKB */ + MKK3_MKKA2 = 0x81, /* Japan UNI-1 even + MKKA2 */ + MKK3_MKKC = 0x82, /* Japan UNI-1 even + MKKC */ + + MKK4_MKKB = 0x83, /* Japan UNI-1 even + UNI-2 + MKKB */ + MKK4_MKKA2 = 0x84, /* Japan UNI-1 even + UNI-2 + MKKA2 */ + MKK4_MKKC = 0x85, /* Japan UNI-1 even + UNI-2 + MKKC */ + + MKK5_MKKB = 0x86, /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */ + MKK5_MKKA2 = 0x87, /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */ + MKK5_MKKC = 0x88, /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */ + + MKK6_MKKB = 0x89, /* Japan UNI-1 even + UNI-1 odd MKKB */ + MKK6_MKKA2 = 0x8A, /* Japan UNI-1 even + UNI-1 odd + MKKA2 */ + MKK6_MKKC = 0x8B, /* Japan UNI-1 even + UNI-1 odd + MKKC */ + + MKK7_MKKB = 0x8C, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */ + MKK7_MKKA2 = 0x8D, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */ + MKK7_MKKC = 0x8E, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */ + + MKK8_MKKB = 0x8F, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */ + MKK8_MKKA2 = 0x90, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */ + MKK8_MKKC = 0x91, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */ + + MKK14_MKKA1 = 0x92, /* Japan UNI-1 even + UNI-1 odd + 4.9GHz + MKKA1 */ + MKK15_MKKA1 = 0x93, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + 4.9GHz + MKKA1 */ + + MKK10_FCCA = 0xD0, /* Japan UNI-1 even + UNI-2 + 4.9GHz + FCCA */ + MKK10_MKKA1 = 0xD1, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKA1 */ + MKK10_MKKC = 0xD2, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKC */ + MKK10_MKKA2 = 0xD3, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKA2 */ + + MKK11_MKKA = 0xD4, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA */ + MKK11_FCCA = 0xD5, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + FCCA */ + MKK11_MKKA1 = 0xD6, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA1 */ + MKK11_MKKC = 0xD7, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKC */ + MKK11_MKKA2 = 0xD8, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA2 */ + + MKK12_MKKA = 0xD9, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA */ + MKK12_FCCA = 0xDA, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + FCCA */ + MKK12_MKKA1 = 0xDB, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA1 */ + MKK12_MKKC = 0xDC, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKC */ + MKK12_MKKA2 = 0xDD, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA2 */ + + MKK13_MKKB = 0xDE, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB + All passive + no adhoc */ + + /* + * Following definitions are used only by s/w to map old + * Japan SKUs. + */ + MKK3_MKKA = 0xF0, /* Japan UNI-1 even + MKKA */ + MKK3_MKKA1 = 0xF1, /* Japan UNI-1 even + MKKA1 */ + MKK3_FCCA = 0xF2, /* Japan UNI-1 even + FCCA */ + MKK4_MKKA = 0xF3, /* Japan UNI-1 even + UNI-2 + MKKA */ + MKK4_MKKA1 = 0xF4, /* Japan UNI-1 even + UNI-2 + MKKA1 */ + MKK4_FCCA = 0xF5, /* Japan UNI-1 even + UNI-2 + FCCA */ + MKK9_MKKA = 0xF6, /* Japan UNI-1 even + 4.9GHz */ + MKK10_MKKA = 0xF7, /* Japan UNI-1 even + UNI-2 + 4.9GHz */ + MKK6_MKKA1 = 0xF8, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA1 */ + MKK6_FCCA = 0xF9, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + FCCA */ + MKK7_MKKA1 = 0xFA, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA1 */ + MKK7_FCCA = 0xFB, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + FCCA */ + MKK9_FCCA = 0xFC, /* Japan UNI-1 even + 4.9GHz + FCCA */ + MKK9_MKKA1 = 0xFD, /* Japan UNI-1 even + 4.9GHz + MKKA1 */ + MKK9_MKKC = 0xFE, /* Japan UNI-1 even + 4.9GHz + MKKC */ + MKK9_MKKA2 = 0xFF, /* Japan UNI-1 even + 4.9GHz + MKKA2 */ + + /* + * Regulator domains ending in a number (e.g. APL1, + * MK1, ETSI4, etc) apply to 5GHz channel and power + * information. Regulator domains ending in a letter + * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and + * power information. + */ + APL1 = 0x0150, /* LAT & Asia */ + APL2 = 0x0250, /* LAT & Asia */ + APL3 = 0x0350, /* Taiwan */ + APL4 = 0x0450, /* Jordan */ + APL5 = 0x0550, /* Chile */ + APL6 = 0x0650, /* Singapore */ + APL7 = 0x0750, /* Taiwan, disable ch52 */ + APL8 = 0x0850, /* Malaysia */ + APL9 = 0x0950, /* Korea. Before 11/2007. Now used only by APs */ + APL10 = 0x1050, /* Korea. After 11/2007. For STAs only */ + + ETSI1 = 0x0130, /* Europe & others */ + ETSI2 = 0x0230, /* Europe & others */ + ETSI3 = 0x0330, /* Europe & others */ + ETSI4 = 0x0430, /* Europe & others */ + ETSI5 = 0x0530, /* Europe & others */ + ETSI6 = 0x0630, /* Europe & others */ + ETSI8 = 0x0830, /* Russia */ + ETSI9 = 0x0930, /* Ukraine */ + ETSIA = 0x0A30, /* France */ + ETSIB = 0x0B30, /* Israel */ + ETSIC = 0x0C30, /* Latin America */ + + FCC1 = 0x0110, /* US & others */ + FCC2 = 0x0120, /* Canada, Australia & New Zealand */ + FCC3 = 0x0160, /* US w/new middle band & DFS */ + FCC4 = 0x0165, /* US Public Safety */ + FCC5 = 0x0166, /* US w/ 1/2 and 1/4 width channels */ + FCC6 = 0x0610, /* Canada and Australia */ + FCCA = 0x0A10, + FCCB = 0x0A11, /* US w/ 1/2 and 1/4 width channels */ + + APLD = 0x0D50, /* South Korea */ + + MKK1 = 0x0140, /* Japan (UNI-1 odd)*/ + MKK2 = 0x0240, /* Japan (4.9 GHz + UNI-1 odd) */ + MKK3 = 0x0340, /* Japan (UNI-1 even) */ + MKK4 = 0x0440, /* Japan (UNI-1 even + UNI-2) */ + MKK5 = 0x0540, /* Japan (UNI-1 even + UNI-2 + mid-band) */ + MKK6 = 0x0640, /* Japan (UNI-1 odd + UNI-1 even) */ + MKK7 = 0x0740, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */ + MKK8 = 0x0840, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */ + MKK9 = 0x0940, /* Japan (UNI-1 even + 4.9 GHZ) */ + MKK10 = 0x0B40, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKK11 = 0x1140, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKK12 = 0x1240, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKK13 = 0x0C40, /* Same as MKK8 but all passive and no adhoc 11a */ + MKK14 = 0x1440, /* Japan UNI-1 even + UNI-1 odd + 4.9GHz */ + MKK15 = 0x1540, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + 4.9GHz */ + + MKKA = 0x0A40, /* Japan */ + MKKC = 0x0A50, + + NULL1 = 0x0198, + WORLD = 0x0199, + DEBUG_REG_DMN = 0x01ff, +}; + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_regmap.h b/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_regmap.h new file mode 100644 index 0000000..f77be22 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_regdomain/ah_rd_regmap.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2006 Atheros Communications, Inc. + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AH_REGDOMAIN_REGMAP_H__ +#define __AH_REGDOMAIN_REGMAP_H__ + +/* + * THE following table is the mapping of regdomain pairs specified by + * an 8 bit regdomain value to the individual unitary reg domains + */ + +/* regdomain 5ghz 2ghz 5ghz 2ghz pscan mask single */ +/* enum regdomain regdomain flags flags country? */ +static REG_DMN_PAIR_MAPPING regDomainPairs[] = { + {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {NULL1_WORLD, NULL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {NULL1_ETSIB, NULL1, ETSIB, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {NULL1_ETSIC, NULL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + + {FCC2_FCCA, FCC2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC2_WORLD, FCC2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC2_ETSIC, FCC2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC3_FCCA, FCC3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC3_WORLD, FCC3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC4_FCCA, FCC4, FCCA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC5_FCCB, FCC5, FCCB, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + + {ETSI1_WORLD, ETSI1, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {ETSI2_WORLD, ETSI2, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {ETSI3_WORLD, ETSI3, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {ETSI4_WORLD, ETSI4, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {ETSI5_WORLD, ETSI5, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {ETSI6_WORLD, ETSI6, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + + {ETSI3_ETSIA, ETSI3, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FRANCE_RES, ETSI3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + + {FCC1_WORLD, FCC1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {FCC1_FCCA, FCC1, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL1_WORLD, APL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL2_WORLD, APL2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL3_WORLD, APL3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL4_WORLD, APL4, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL5_WORLD, APL5, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL6_WORLD, APL6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL8_WORLD, APL8, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL9_WORLD, APL9, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + + {APL3_FCCA, APL3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL1_ETSIC, APL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL2_ETSIC, APL2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {APL2_APLD, APL2, APLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + + {MKK1_MKKA, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA, CTRY_JAPAN }, + {MKK1_MKKB, MKK1, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN1 }, + {MKK1_FCCA, MKK1, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN2 }, + {MKK1_MKKA1, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN4 }, + {MKK1_MKKA2, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN5 }, + {MKK1_MKKC, MKK1, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN6 }, + + /* MKK2 */ + {MKK2_MKKA, MKK2, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN3 }, + + /* MKK3 */ + {MKK3_MKKA, MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC , PSCAN_MKKA, CTRY_DEFAULT }, + {MKK3_MKKB, MKK3, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN7 }, + {MKK3_MKKA1, MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_DEFAULT }, + {MKK3_MKKA2,MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN8 }, + {MKK3_MKKC, MKK3, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_JAPAN9 }, + {MKK3_FCCA, MKK3, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_DEFAULT }, + + /* MKK4 */ + {MKK4_MKKB, MKK4, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN10 }, + {MKK4_MKKA1, MKK4, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_DEFAULT }, + {MKK4_MKKA2, MKK4, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 |PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN11 }, + {MKK4_MKKC, MKK4, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN12 }, + {MKK4_FCCA, MKK4, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_DEFAULT }, + + /* MKK5 */ + {MKK5_MKKB, MKK5, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN13 }, + {MKK5_MKKA2,MKK5, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN14 }, + {MKK5_MKKC, MKK5, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN15 }, + + /* MKK6 */ + {MKK6_MKKB, MKK6, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN16 }, + {MKK6_MKKA2, MKK6, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN17 }, + {MKK6_MKKC, MKK6, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN18 }, + + /* MKK7 */ + {MKK7_MKKB, MKK7, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN19 }, + {MKK7_MKKA2, MKK7, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN20 }, + {MKK7_MKKC, MKK7, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN21 }, + + /* MKK8 */ + {MKK8_MKKB, MKK8, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN22 }, + {MKK8_MKKA2,MKK8, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN23 }, + {MKK8_MKKC, MKK8, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 , CTRY_JAPAN24 }, + + {MKK9_MKKA, MKK9, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_DEFAULT }, + {MKK10_MKKA, MKK10, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_DEFAULT }, + + /* These are super domains */ + {WOR0_WORLD, WOR0_WORLD, WOR0_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR1_WORLD, WOR1_WORLD, WOR1_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR2_WORLD, WOR2_WORLD, WOR2_WORLD, DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR3_WORLD, WOR3_WORLD, WOR3_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR4_WORLD, WOR4_WORLD, WOR4_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR5_ETSIC, WOR5_ETSIC, WOR5_ETSIC, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR01_WORLD, WOR01_WORLD, WOR01_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR02_WORLD, WOR02_WORLD, WOR02_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {EU1_WORLD, EU1_WORLD, EU1_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WOR9_WORLD, WOR9_WORLD, WOR9_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WORA_WORLD, WORA_WORLD, WORA_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WORB_WORLD, WORB_WORLD, WORB_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, + {WORC_WORLD, WORC_WORLD, WORC_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT }, +}; + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ah_soc.h b/sys/external/isc/atheros_hal/dist/ah_soc.h new file mode 100644 index 0000000..ca75ae9 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ah_soc.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AH_SOC_H_ +#define _ATH_AH_SOC_H_ +/* + * Atheros System on Chip (SoC) public definitions. + */ + +/* + * This is board-specific data that is stored in a "known" + * location in flash. To find the start of this data search + * back from the (aliased) end of flash by 0x1000 bytes at a + * time until you find the string "5311", which marks the + * start of Board Configuration. Typically one gives up if + * more than 500KB is searched. + */ +struct ar531x_boarddata { + uint32_t magic; /* board data is valid */ +#define AR531X_BD_MAGIC 0x35333131 /* "5311", for all 531x platforms */ + uint16_t cksum; /* checksum (starting with BD_REV 2) */ + uint16_t rev; /* revision of this struct */ +#define BD_REV 4 + char boardName[64]; /* Name of board */ + uint16_t major; /* Board major number */ + uint16_t minor; /* Board minor number */ + uint32_t config; /* Board configuration */ +#define BD_ENET0 0x00000001 /* ENET0 is stuffed */ +#define BD_ENET1 0x00000002 /* ENET1 is stuffed */ +#define BD_UART1 0x00000004 /* UART1 is stuffed */ +#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */ +#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */ +#define BD_SYSLED 0x00000020 /* System LED stuffed */ +#define BD_EXTUARTCLK 0x00000040 /* External UART clock */ +#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */ +#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */ +#define BD_WLAN0 0x00000200 /* Enable WLAN0 */ +#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ memCap for testing */ +#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */ +#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */ +#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */ +#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */ +#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */ +#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */ +#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */ + uint16_t resetConfigGpio; /* Reset factory GPIO pin */ + uint16_t sysLedGpio; /* System LED GPIO pin */ + + uint32_t cpuFreq; /* CPU core frequency in Hz */ + uint32_t sysFreq; /* System frequency in Hz */ + uint32_t cntFreq; /* Calculated C0_COUNT frequency */ + + uint8_t wlan0Mac[6]; + uint8_t enet0Mac[6]; + uint8_t enet1Mac[6]; + + uint16_t pciId; /* Pseudo PCIID for common code */ + uint16_t memCap; /* cap bank1 in MB */ + + /* version 3 */ + uint8_t wlan1Mac[6]; /* (ar5212) */ +}; + +/* + * Board support data. The driver is required to locate + * and fill-in this information before passing a reference to + * this structure as the HAL_BUS_TAG parameter supplied to + * ath_hal_attach. + */ +struct ar531x_config { + const struct ar531x_boarddata *board; /* board config data */ + const char *radio; /* radio config data */ + int unit; /* unit number [0, 1] */ + void *tag; /* bus space tag */ +}; +#endif /* _ATH_AH_SOC_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210.h b/sys/external/isc/atheros_hal/dist/ar5210/ar5210.h new file mode 100644 index 0000000..71d78b5 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210.h @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AR5210_H_ +#define _ATH_AR5210_H_ + +#define AR5210_MAGIC 0x19980124 + +#if 0 +/* + * RTS_ENABLE includes LONG_PKT because they essentially + * imply the same thing, and are set or not set together + * for this chip + */ +#define AR5210_TXD_CTRL_A_HDR_LEN(_val) (((_val) ) & 0x0003f) +#define AR5210_TXD_CTRL_A_TX_RATE(_val) (((_val) << 6) & 0x003c0) +#define AR5210_TXD_CTRL_A_RTS_ENABLE ( 0x00c00) +#define AR5210_TXD_CTRL_A_CLEAR_DEST_MASK(_val) (((_val) << 12) & 0x01000) +#define AR5210_TXD_CTRL_A_ANT_MODE(_val) (((_val) << 13) & 0x02000) +#define AR5210_TXD_CTRL_A_PKT_TYPE(_val) (((_val) << 14) & 0x1c000) +#define AR5210_TXD_CTRL_A_INT_REQ ( 0x20000) +#define AR5210_TXD_CTRL_A_KEY_VALID ( 0x40000) +#define AR5210_TXD_CTRL_B_KEY_ID(_val) (((_val) ) & 0x0003f) +#define AR5210_TXD_CTRL_B_RTS_DURATION(_val) (((_val) << 6) & 0x7ffc0) +#endif + +#define INIT_CONFIG_STATUS 0x00000000 +#define INIT_ACKTOPS 0x00000008 +#define INIT_BCON_CNTRL_REG 0x00000000 +#define INIT_SLOT_TIME 0x00000168 +#define INIT_SLOT_TIME_TURBO 0x000001e0 /* More aggressive turbo slot timing = 6 us */ +#define INIT_ACK_CTS_TIMEOUT 0x04000400 +#define INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800 + +#define INIT_USEC 0x27 +#define INIT_USEC_TURBO 0x4f +#define INIT_USEC_32 0x1f +#define INIT_TX_LATENCY 0x36 +#define INIT_RX_LATENCY 0x1D +#define INIT_TRANSMIT_LATENCY \ + ((INIT_RX_LATENCY << AR_USEC_RX_LATENCY_S) | \ + (INIT_TX_LATENCY << AR_USEC_TX_LATENCY_S) | \ + (INIT_USEC_32 << 7) | INIT_USEC ) +#define INIT_TRANSMIT_LATENCY_TURBO \ + ((INIT_RX_LATENCY << AR_USEC_RX_LATENCY_S) | \ + (INIT_TX_LATENCY << AR_USEC_TX_LATENCY_S) | \ + (INIT_USEC_32 << 7) | INIT_USEC_TURBO) + +#define INIT_SIFS 0x230 /* = 16 us - 2 us */ +#define INIT_SIFS_TURBO 0x1E0 /* More aggressive turbo SIFS timing - 8 us - 2 us */ + +/* + * Various fifo fill before Tx start, in 64-byte units + * i.e. put the frame in the air while still DMAing + */ +#define MIN_TX_FIFO_THRESHOLD 0x1 +#define MAX_TX_FIFO_THRESHOLD ((IEEE80211_MAX_LEN / 64) + 1) + +#define INIT_NEXT_CFP_START 0xffffffff + +#define INIT_BEACON_PERIOD 0xffff +#define INIT_BEACON_EN 0 /* this should be set by AP only when it's ready */ +#define INIT_BEACON_CONTROL \ + ((INIT_RESET_TSF << 24) | (INIT_BEACON_EN << 23) | \ + (INIT_TIM_OFFSET<<16) | INIT_BEACON_PERIOD) + +#define INIT_RSSI_THR 0x00000700 /* Missed beacon counter initialized to max value of 7 */ +#define INIT_ProgIFS 0x398 /* PIFS - 2us */ +#define INIT_ProgIFS_TURBO 0x3C0 +#define INIT_EIFS 0xd70 +#define INIT_EIFS_TURBO 0x1ae0 +#define INIT_CARR_SENSE_EN 1 +#define INIT_PROTO_TIME_CNTRL ( (INIT_CARR_SENSE_EN << 26) | (INIT_EIFS << 12) | \ + (INIT_ProgIFS) ) +#define INIT_PROTO_TIME_CNTRL_TURBO ( (INIT_CARR_SENSE_EN << 26) | (INIT_EIFS_TURBO << 12) | \ + (INIT_ProgIFS_TURBO) ) + +#define AR5210_MAX_RATE_POWER 60 + +#undef HAL_NUM_TX_QUEUES /* from ah.h */ +#define HAL_NUM_TX_QUEUES 3 + +struct ath_hal_5210 { + struct ath_hal_private ah_priv; /* base definitions */ + + uint8_t ah_macaddr[IEEE80211_ADDR_LEN]; + /* + * Runtime state. + */ + uint32_t ah_maskReg; /* shadow of IMR+IER regs */ + uint32_t ah_txOkInterruptMask; + uint32_t ah_txErrInterruptMask; + uint32_t ah_txDescInterruptMask; + uint32_t ah_txEolInterruptMask; + uint32_t ah_txUrnInterruptMask; + uint8_t ah_bssid[IEEE80211_ADDR_LEN]; + HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; /* beacon+cab+data */ + /* + * Station mode support. + */ + uint32_t ah_staId1Defaults; /* STA_ID1 default settings */ + uint32_t ah_rssiThr; /* RSSI_THR settings */ + + u_int ah_sifstime; /* user-specified sifs time */ + u_int ah_slottime; /* user-specified slot time */ + u_int ah_acktimeout; /* user-specified ack timeout */ + u_int ah_ctstimeout; /* user-specified cts timeout */ + + uint16_t ah_associd; /* association id */ +}; +#define AH5210(ah) ((struct ath_hal_5210 *)(ah)) + +struct ath_hal; + +extern void ar5210Detach(struct ath_hal *ah); +extern HAL_BOOL ar5210Reset(struct ath_hal *, HAL_OPMODE, + struct ieee80211_channel *, HAL_BOOL bChannelChange, + HAL_RESET_TYPE, HAL_STATUS *); +extern void ar5210SetPCUConfig(struct ath_hal *); +extern HAL_BOOL ar5210PhyDisable(struct ath_hal *); +extern HAL_BOOL ar5210Disable(struct ath_hal *); +extern HAL_BOOL ar5210ChipReset(struct ath_hal *, struct ieee80211_channel *); +extern HAL_BOOL ar5210PerCalibration(struct ath_hal *, struct ieee80211_channel *, HAL_BOOL *); +extern HAL_BOOL ar5210PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); +extern HAL_BOOL ar5210ResetCalValid(struct ath_hal *ah, const struct ieee80211_channel *); +extern int16_t ar5210GetNoiseFloor(struct ath_hal *); +extern int16_t ar5210GetNfAdjust(struct ath_hal *, + const HAL_CHANNEL_INTERNAL *); +extern HAL_BOOL ar5210SetTxPowerLimit(struct ath_hal *, uint32_t limit); +extern HAL_BOOL ar5210SetTransmitPower(struct ath_hal *, + const struct ieee80211_channel *); +extern HAL_BOOL ar5210CalNoiseFloor(struct ath_hal *, HAL_CHANNEL_INTERNAL *); +extern HAL_BOOL ar5210ResetDma(struct ath_hal *, HAL_OPMODE); + +extern HAL_BOOL ar5210SetTxQueueProps(struct ath_hal *ah, int q, + const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ar5210GetTxQueueProps(struct ath_hal *ah, int q, + HAL_TXQ_INFO *qInfo); +extern int ar5210SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ar5210ReleaseTxQueue(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5210ResetTxQueue(struct ath_hal *ah, u_int q); +extern uint32_t ar5210GetTxDP(struct ath_hal *, u_int); +extern HAL_BOOL ar5210SetTxDP(struct ath_hal *, u_int, uint32_t txdp); +extern HAL_BOOL ar5210UpdateTxTrigLevel(struct ath_hal *, HAL_BOOL); +extern uint32_t ar5210NumTxPending(struct ath_hal *, u_int); +extern HAL_BOOL ar5210StartTxDma(struct ath_hal *, u_int); +extern HAL_BOOL ar5210StopTxDma(struct ath_hal *, u_int); +extern HAL_BOOL ar5210SetupTxDesc(struct ath_hal *, struct ath_desc *, + u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, + u_int txRate0, u_int txRetries0, + u_int keyIx, u_int antMode, u_int flags, + u_int rtsctsRate, u_int rtsctsDuration, + u_int compicvLen, u_int compivLen, u_int comp); +extern HAL_BOOL ar5210SetupXTxDesc(struct ath_hal *, struct ath_desc *, + u_int txRate1, u_int txRetries1, + u_int txRate2, u_int txRetries2, + u_int txRate3, u_int txRetries3); +extern HAL_BOOL ar5210FillTxDesc(struct ath_hal *, struct ath_desc *, + HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, + u_int descId, u_int qcuId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0); +extern HAL_STATUS ar5210ProcTxDesc(struct ath_hal *, + struct ath_desc *, struct ath_tx_status *); +extern void ar5210GetTxIntrQueue(struct ath_hal *ah, uint32_t *); +extern void ar5210IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); +extern HAL_BOOL ar5210GetTxCompletionRates(struct ath_hal *ah, + const struct ath_desc *, int *rates, int *tries); +extern void ar5210SetTxDescLink(struct ath_hal *ah, void *ds, + uint32_t link); +extern void ar5210GetTxDescLink(struct ath_hal *ah, void *ds, + uint32_t *link); +extern void ar5210GetTxDescLinkPtr(struct ath_hal *ah, void *ds, + uint32_t **linkptr); + +extern uint32_t ar5210GetRxDP(struct ath_hal *, HAL_RX_QUEUE); +extern void ar5210SetRxDP(struct ath_hal *, uint32_t rxdp, HAL_RX_QUEUE); +extern void ar5210EnableReceive(struct ath_hal *); +extern HAL_BOOL ar5210StopDmaReceive(struct ath_hal *); +extern void ar5210StartPcuReceive(struct ath_hal *); +extern void ar5210StopPcuReceive(struct ath_hal *); +extern void ar5210SetMulticastFilter(struct ath_hal *, + uint32_t filter0, uint32_t filter1); +extern HAL_BOOL ar5210ClrMulticastFilterIndex(struct ath_hal *, uint32_t); +extern HAL_BOOL ar5210SetMulticastFilterIndex(struct ath_hal *, uint32_t); +extern uint32_t ar5210GetRxFilter(struct ath_hal *); +extern void ar5210SetRxFilter(struct ath_hal *, uint32_t); +extern HAL_BOOL ar5210SetupRxDesc(struct ath_hal *, struct ath_desc *, + uint32_t, u_int flags); +extern HAL_STATUS ar5210ProcRxDesc(struct ath_hal *, struct ath_desc *, + uint32_t, struct ath_desc *, uint64_t, + struct ath_rx_status *); + +extern void ar5210GetMacAddress(struct ath_hal *, uint8_t *); +extern HAL_BOOL ar5210SetMacAddress(struct ath_hal *ah, const uint8_t *); +extern void ar5210GetBssIdMask(struct ath_hal *, uint8_t *); +extern HAL_BOOL ar5210SetBssIdMask(struct ath_hal *, const uint8_t *); +extern HAL_BOOL ar5210EepromRead(struct ath_hal *, u_int off, uint16_t *data); +extern HAL_BOOL ar5210EepromWrite(struct ath_hal *, u_int off, uint16_t data); +extern HAL_BOOL ar5210SetRegulatoryDomain(struct ath_hal *, + uint16_t, HAL_STATUS *); +extern u_int ar5210GetWirelessModes(struct ath_hal *ah); +extern void ar5210EnableRfKill(struct ath_hal *); +extern HAL_BOOL ar5210GpioCfgInput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5210GpioCfgOutput(struct ath_hal *, uint32_t gpio, + HAL_GPIO_MUX_TYPE); +extern uint32_t ar5210GpioGet(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5210GpioSet(struct ath_hal *, uint32_t gpio, uint32_t); +extern void ar5210Gpio0SetIntr(struct ath_hal *, u_int, uint32_t ilevel); +extern void ar5210SetLedState(struct ath_hal *, HAL_LED_STATE); +extern u_int ar5210GetDefAntenna(struct ath_hal *); +extern void ar5210SetDefAntenna(struct ath_hal *, u_int); +extern HAL_ANT_SETTING ar5210GetAntennaSwitch(struct ath_hal *); +extern HAL_BOOL ar5210SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); +extern void ar5210WriteAssocid(struct ath_hal *, + const uint8_t *bssid, uint16_t assocId); +extern uint32_t ar5210GetTsf32(struct ath_hal *); +extern uint64_t ar5210GetTsf64(struct ath_hal *); +extern void ar5210ResetTsf(struct ath_hal *); +extern uint32_t ar5210GetRandomSeed(struct ath_hal *); +extern HAL_BOOL ar5210DetectCardPresent(struct ath_hal *); +extern void ar5210UpdateMibCounters(struct ath_hal *, HAL_MIB_STATS *); +extern void ar5210EnableHwEncryption(struct ath_hal *); +extern void ar5210DisableHwEncryption(struct ath_hal *); +extern HAL_RFGAIN ar5210GetRfgain(struct ath_hal *); +extern HAL_BOOL ar5210SetSifsTime(struct ath_hal *, u_int); +extern u_int ar5210GetSifsTime(struct ath_hal *); +extern HAL_BOOL ar5210SetSlotTime(struct ath_hal *, u_int); +extern u_int ar5210GetSlotTime(struct ath_hal *); +extern HAL_BOOL ar5210SetAckTimeout(struct ath_hal *, u_int); +extern u_int ar5210GetAckTimeout(struct ath_hal *); +extern HAL_BOOL ar5210SetAckCTSRate(struct ath_hal *, u_int); +extern u_int ar5210GetAckCTSRate(struct ath_hal *); +extern HAL_BOOL ar5210SetCTSTimeout(struct ath_hal *, u_int); +extern u_int ar5210GetCTSTimeout(struct ath_hal *); +extern HAL_BOOL ar5210SetDecompMask(struct ath_hal *, uint16_t, int); +void ar5210SetCoverageClass(struct ath_hal *, uint8_t, int); +extern HAL_STATUS ar5210GetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, + uint32_t, uint32_t *); +extern HAL_BOOL ar5210SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, + uint32_t, uint32_t, HAL_STATUS *); +extern HAL_BOOL ar5210GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); +extern uint32_t ar5210Get11nExtBusy(struct ath_hal *); +extern HAL_BOOL ar5210GetMibCycleCounts(struct ath_hal *, + HAL_SURVEY_SAMPLE *); +extern void ar5210SetChainMasks(struct ath_hal *, uint32_t, uint32_t); +extern void ar5210EnableDfs(struct ath_hal *, HAL_PHYERR_PARAM *); +extern void ar5210GetDfsThresh(struct ath_hal *, HAL_PHYERR_PARAM *); +extern void ar5210UpdateDiagReg(struct ath_hal *ah, uint32_t val); + +extern u_int ar5210GetKeyCacheSize(struct ath_hal *); +extern HAL_BOOL ar5210IsKeyCacheEntryValid(struct ath_hal *, uint16_t); +extern HAL_BOOL ar5210ResetKeyCacheEntry(struct ath_hal *, uint16_t entry); +extern HAL_BOOL ar5210SetKeyCacheEntry(struct ath_hal *, uint16_t entry, + const HAL_KEYVAL *, const uint8_t *mac, int xorKey); +extern HAL_BOOL ar5210SetKeyCacheEntryMac(struct ath_hal *, + uint16_t, const uint8_t *); + +extern HAL_BOOL ar5210SetPowerMode(struct ath_hal *, uint32_t powerRequest, + int setChip); +extern HAL_POWER_MODE ar5210GetPowerMode(struct ath_hal *); + +extern void ar5210SetBeaconTimers(struct ath_hal *, + const HAL_BEACON_TIMERS *); +extern void ar5210BeaconInit(struct ath_hal *, uint32_t, uint32_t); +extern void ar5210SetStaBeaconTimers(struct ath_hal *, + const HAL_BEACON_STATE *); +extern void ar5210ResetStaBeaconTimers(struct ath_hal *); +extern uint64_t ar5210GetNextTBTT(struct ath_hal *); + +extern HAL_BOOL ar5210IsInterruptPending(struct ath_hal *); +extern HAL_BOOL ar5210GetPendingInterrupts(struct ath_hal *, HAL_INT *); +extern HAL_INT ar5210GetInterrupts(struct ath_hal *); +extern HAL_INT ar5210SetInterrupts(struct ath_hal *, HAL_INT ints); + +extern const HAL_RATE_TABLE *ar5210GetRateTable(struct ath_hal *, u_int mode); + +extern HAL_BOOL ar5210AniControl(struct ath_hal *, HAL_ANI_CMD, int ); +extern void ar5210AniPoll(struct ath_hal *, const struct ieee80211_channel *); +extern void ar5210RxMonitor(struct ath_hal *, const HAL_NODE_STATS *, + const struct ieee80211_channel *); +extern void ar5210MibEvent(struct ath_hal *, const HAL_NODE_STATS *); +#endif /* _ATH_AR5210_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210_attach.c b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_attach.c new file mode 100644 index 0000000..ceafa99 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_attach.c @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210phy.h" + +#include "ah_eeprom_v1.h" + +static HAL_BOOL ar5210GetChannelEdges(struct ath_hal *, + uint16_t flags, uint16_t *low, uint16_t *high); +static HAL_BOOL ar5210GetChipPowerLimits(struct ath_hal *ah, + struct ieee80211_channel *chan); + +static void ar5210ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, + HAL_BOOL power_on); +static void ar5210DisablePCIE(struct ath_hal *ah); + +static const struct ath_hal_private ar5210hal = {{ + .ah_magic = AR5210_MAGIC, + + .ah_getRateTable = ar5210GetRateTable, + .ah_detach = ar5210Detach, + + /* Reset Functions */ + .ah_reset = ar5210Reset, + .ah_phyDisable = ar5210PhyDisable, + .ah_disable = ar5210Disable, + .ah_configPCIE = ar5210ConfigPCIE, + .ah_disablePCIE = ar5210DisablePCIE, + .ah_setPCUConfig = ar5210SetPCUConfig, + .ah_perCalibration = ar5210PerCalibration, + .ah_perCalibrationN = ar5210PerCalibrationN, + .ah_resetCalValid = ar5210ResetCalValid, + .ah_setTxPowerLimit = ar5210SetTxPowerLimit, + .ah_getChanNoise = ath_hal_getChanNoise, + + /* Transmit functions */ + .ah_updateTxTrigLevel = ar5210UpdateTxTrigLevel, + .ah_setupTxQueue = ar5210SetupTxQueue, + .ah_setTxQueueProps = ar5210SetTxQueueProps, + .ah_getTxQueueProps = ar5210GetTxQueueProps, + .ah_releaseTxQueue = ar5210ReleaseTxQueue, + .ah_resetTxQueue = ar5210ResetTxQueue, + .ah_getTxDP = ar5210GetTxDP, + .ah_setTxDP = ar5210SetTxDP, + .ah_numTxPending = ar5210NumTxPending, + .ah_startTxDma = ar5210StartTxDma, + .ah_stopTxDma = ar5210StopTxDma, + .ah_setupTxDesc = ar5210SetupTxDesc, + .ah_setupXTxDesc = ar5210SetupXTxDesc, + .ah_fillTxDesc = ar5210FillTxDesc, + .ah_procTxDesc = ar5210ProcTxDesc, + .ah_getTxIntrQueue = ar5210GetTxIntrQueue, + .ah_reqTxIntrDesc = ar5210IntrReqTxDesc, + .ah_getTxCompletionRates = ar5210GetTxCompletionRates, + .ah_setTxDescLink = ar5210SetTxDescLink, + .ah_getTxDescLink = ar5210GetTxDescLink, + .ah_getTxDescLinkPtr = ar5210GetTxDescLinkPtr, + + /* RX Functions */ + .ah_getRxDP = ar5210GetRxDP, + .ah_setRxDP = ar5210SetRxDP, + .ah_enableReceive = ar5210EnableReceive, + .ah_stopDmaReceive = ar5210StopDmaReceive, + .ah_startPcuReceive = ar5210StartPcuReceive, + .ah_stopPcuReceive = ar5210StopPcuReceive, + .ah_setMulticastFilter = ar5210SetMulticastFilter, + .ah_setMulticastFilterIndex = ar5210SetMulticastFilterIndex, + .ah_clrMulticastFilterIndex = ar5210ClrMulticastFilterIndex, + .ah_getRxFilter = ar5210GetRxFilter, + .ah_setRxFilter = ar5210SetRxFilter, + .ah_setupRxDesc = ar5210SetupRxDesc, + .ah_procRxDesc = ar5210ProcRxDesc, + .ah_rxMonitor = ar5210RxMonitor, + .ah_aniPoll = ar5210AniPoll, + .ah_procMibEvent = ar5210MibEvent, + + /* Misc Functions */ + .ah_getCapability = ar5210GetCapability, + .ah_setCapability = ar5210SetCapability, + .ah_getDiagState = ar5210GetDiagState, + .ah_getMacAddress = ar5210GetMacAddress, + .ah_setMacAddress = ar5210SetMacAddress, + .ah_getBssIdMask = ar5210GetBssIdMask, + .ah_setBssIdMask = ar5210SetBssIdMask, + .ah_setRegulatoryDomain = ar5210SetRegulatoryDomain, + .ah_setLedState = ar5210SetLedState, + .ah_writeAssocid = ar5210WriteAssocid, + .ah_gpioCfgInput = ar5210GpioCfgInput, + .ah_gpioCfgOutput = ar5210GpioCfgOutput, + .ah_gpioGet = ar5210GpioGet, + .ah_gpioSet = ar5210GpioSet, + .ah_gpioSetIntr = ar5210Gpio0SetIntr, + .ah_getTsf32 = ar5210GetTsf32, + .ah_getTsf64 = ar5210GetTsf64, + .ah_resetTsf = ar5210ResetTsf, + .ah_detectCardPresent = ar5210DetectCardPresent, + .ah_updateMibCounters = ar5210UpdateMibCounters, + .ah_getRfGain = ar5210GetRfgain, + .ah_getDefAntenna = ar5210GetDefAntenna, + .ah_setDefAntenna = ar5210SetDefAntenna, + .ah_getAntennaSwitch = ar5210GetAntennaSwitch, + .ah_setAntennaSwitch = ar5210SetAntennaSwitch, + .ah_setSifsTime = ar5210SetSifsTime, + .ah_getSifsTime = ar5210GetSifsTime, + .ah_setSlotTime = ar5210SetSlotTime, + .ah_getSlotTime = ar5210GetSlotTime, + .ah_setAckTimeout = ar5210SetAckTimeout, + .ah_getAckTimeout = ar5210GetAckTimeout, + .ah_setAckCTSRate = ar5210SetAckCTSRate, + .ah_getAckCTSRate = ar5210GetAckCTSRate, + .ah_setCTSTimeout = ar5210SetCTSTimeout, + .ah_getCTSTimeout = ar5210GetCTSTimeout, + .ah_setDecompMask = ar5210SetDecompMask, + .ah_setCoverageClass = ar5210SetCoverageClass, + .ah_get11nExtBusy = ar5210Get11nExtBusy, + .ah_getMibCycleCounts = ar5210GetMibCycleCounts, + .ah_setChainMasks = ar5210SetChainMasks, + .ah_enableDfs = ar5210EnableDfs, + .ah_getDfsThresh = ar5210GetDfsThresh, + /* XXX procRadarEvent */ + /* XXX isFastClockEnabled */ + + /* Key Cache Functions */ + .ah_getKeyCacheSize = ar5210GetKeyCacheSize, + .ah_resetKeyCacheEntry = ar5210ResetKeyCacheEntry, + .ah_isKeyCacheEntryValid = ar5210IsKeyCacheEntryValid, + .ah_setKeyCacheEntry = ar5210SetKeyCacheEntry, + .ah_setKeyCacheEntryMac = ar5210SetKeyCacheEntryMac, + + /* Power Management Functions */ + .ah_setPowerMode = ar5210SetPowerMode, + .ah_getPowerMode = ar5210GetPowerMode, + + /* Beacon Functions */ + .ah_setBeaconTimers = ar5210SetBeaconTimers, + .ah_beaconInit = ar5210BeaconInit, + .ah_setStationBeaconTimers = ar5210SetStaBeaconTimers, + .ah_resetStationBeaconTimers = ar5210ResetStaBeaconTimers, + .ah_getNextTBTT = ar5210GetNextTBTT, + + /* Interrupt Functions */ + .ah_isInterruptPending = ar5210IsInterruptPending, + .ah_getPendingInterrupts = ar5210GetPendingInterrupts, + .ah_getInterrupts = ar5210GetInterrupts, + .ah_setInterrupts = ar5210SetInterrupts }, + + .ah_getChannelEdges = ar5210GetChannelEdges, + .ah_getWirelessModes = ar5210GetWirelessModes, + .ah_eepromRead = ar5210EepromRead, +#ifdef AH_SUPPORT_WRITE_EEPROM + .ah_eepromWrite = ar5210EepromWrite, +#endif + .ah_getChipPowerLimits = ar5210GetChipPowerLimits, +}; + +static HAL_BOOL ar5210FillCapabilityInfo(struct ath_hal *ah); + +/* + * Attach for an AR5210 part. + */ +static struct ath_hal * +ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, + uint16_t *eepromdata, HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + struct ath_hal_5210 *ahp; + struct ath_hal *ah; + uint32_t revid, pcicfg; + uint16_t eeval; + HAL_STATUS ecode; + int i; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, + "%s: devid 0x%x sc %p st %p sh %p\n", __func__, devid, + sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp = ath_hal_malloc(sizeof (struct ath_hal_5210)); + if (ahp == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: no memory for state block\n", __func__); + ecode = HAL_ENOMEM; + goto bad; + } + ah = &ahp->ah_priv.h; + /* set initial values */ + OS_MEMCPY(&ahp->ah_priv, &ar5210hal, sizeof(struct ath_hal_private)); + ah->ah_sc = sc; + ah->ah_st = st; + ah->ah_sh = sh; + + ah->ah_devid = devid; /* NB: for AH_DEBUG_ALQ */ + AH_PRIVATE(ah)->ah_devid = devid; + AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */ + + AH_PRIVATE(ah)->ah_powerLimit = AR5210_MAX_RATE_POWER; + AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ + + ah->ah_powerMode = HAL_PM_UNDEFINED; + ahp->ah_staId1Defaults = 0; + ahp->ah_rssiThr = INIT_RSSI_THR; + ahp->ah_sifstime = (u_int) -1; + ahp->ah_slottime = (u_int) -1; + ahp->ah_acktimeout = (u_int) -1; + ahp->ah_ctstimeout = (u_int) -1; + + if (!ar5210ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + + /* Read Revisions from Chips */ + AH_PRIVATE(ah)->ah_macVersion = 1; + AH_PRIVATE(ah)->ah_macRev = OS_REG_READ(ah, AR_SREV) & 0xff; + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIPID); + AH_PRIVATE(ah)->ah_analog2GhzRev = 0; + + /* Read Radio Chip Rev Extract */ + OS_REG_WRITE(ah, (AR_PHY_BASE + (0x34 << 2)), 0x00001c16); + for (i = 0; i < 4; i++) + OS_REG_WRITE(ah, (AR_PHY_BASE + (0x20 << 2)), 0x00010000); + revid = (OS_REG_READ(ah, AR_PHY_BASE + (256 << 2)) >> 28) & 0xf; + + /* Chip labelling is 1 greater than revision register for AR5110 */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ath_hal_reverseBits(revid, 4) + 1; + + /* + * Read all the settings from the EEPROM and stash + * ones we'll use later. + */ + pcicfg = OS_REG_READ(ah, AR_PCICFG); + OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL); + ecode = ath_hal_v1EepromAttach(ah); + if (ecode != HAL_OK) { + goto eebad; + } + ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read regulatory domain from EEPROM\n", + __func__); + goto eebad; + } + AH_PRIVATE(ah)->ah_currentRD = eeval; + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto eebad; + } + OS_REG_WRITE(ah, AR_PCICFG, pcicfg); /* disable EEPROM access */ + + AH_PRIVATE(ah)->ah_getNfAdjust = ar5210GetNfAdjust; + + /* + * Got everything we need now to setup the capabilities. + */ + (void) ar5210FillCapabilityInfo(ah); + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +eebad: + OS_REG_WRITE(ah, AR_PCICFG, pcicfg); /* disable EEPROM access */ +bad: + if (ahp) + ath_hal_free(ahp); + if (status) + *status = ecode; + return AH_NULL; +#undef N +} + +void +ar5210Detach(struct ath_hal *ah) +{ + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); + + HALASSERT(ah != AH_NULL); + HALASSERT(ah->ah_magic == AR5210_MAGIC); + + ath_hal_eepromDetach(ah); + ath_hal_free(ah); +} + +/* + * Store the channel edges for the requested operational mode + */ +static HAL_BOOL +ar5210GetChannelEdges(struct ath_hal *ah, + uint16_t flags, uint16_t *low, uint16_t *high) +{ + if (flags & IEEE80211_CHAN_5GHZ) { + *low = 5120; + *high = 5430; + return AH_TRUE; + } else { + return AH_FALSE; + } +} + +static HAL_BOOL +ar5210GetChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan) +{ + /* XXX fill in, this is just a placeholder */ + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: no min/max power for %u/0x%x\n", + __func__, chan->ic_freq, chan->ic_flags); + chan->ic_maxpower = AR5210_MAX_RATE_POWER; + chan->ic_minpower = 0; + return AH_TRUE; +} + +static void +ar5210ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) +{ +} + +static void +ar5210DisablePCIE(struct ath_hal *ah) +{ +} + +/* + * Fill all software cached or static hardware state information. + */ +static HAL_BOOL +ar5210FillCapabilityInfo(struct ath_hal *ah) +{ + struct ath_hal_private *ahpriv = AH_PRIVATE(ah); + HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; + + pCap->halWirelessModes |= HAL_MODE_11A; + + pCap->halLow5GhzChan = 5120; + pCap->halHigh5GhzChan = 5430; + + pCap->halSleepAfterBeaconBroken = AH_TRUE; + pCap->halPSPollBroken = AH_FALSE; + pCap->halNumMRRetries = 1; /* No hardware MRR support */ + pCap->halNumTxMaps = 1; /* Single TX ptr per descr */ + + pCap->halTotalQueues = HAL_NUM_TX_QUEUES; + pCap->halKeyCacheSize = 64; + + /* XXX not needed */ + pCap->halChanHalfRate = AH_FALSE; + pCap->halChanQuarterRate = AH_FALSE; + + /* + * RSSI uses the combined field; some 11n NICs may use + * the control chain RSSI. + */ + pCap->halUseCombinedRadarRssi = AH_TRUE; + + if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL)) { + /* + * Setup initial rfsilent settings based on the EEPROM + * contents. Pin 0, polarity 0 is fixed; record this + * using the EEPROM format found in later parts. + */ + ahpriv->ah_rfsilent = SM(0, AR_EEPROM_RFSILENT_GPIO_SEL) + | SM(0, AR_EEPROM_RFSILENT_POLARITY); + ahpriv->ah_rfkillEnabled = AH_TRUE; + pCap->halRfSilentSupport = AH_TRUE; + } + + pCap->halTstampPrecision = 15; /* NB: s/w extended from 13 */ + pCap->halIntrMask = (HAL_INT_COMMON - HAL_INT_BNR) + | HAL_INT_RX + | HAL_INT_TX + | HAL_INT_FATAL + ; + + pCap->hal4kbSplitTransSupport = AH_TRUE; + pCap->halHasRxSelfLinkedTail = AH_TRUE; + + ahpriv->ah_rxornIsFatal = AH_TRUE; + return AH_TRUE; +} + +static const char* +ar5210Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID && + (devid == AR5210_PROD || devid == AR5210_DEFAULT)) + return "Atheros 5210"; + return AH_NULL; +} +AH_CHIP(AR5210, ar5210Probe, ar5210Attach); diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210_beacon.c b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_beacon.c new file mode 100644 index 0000000..e12b039 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_beacon.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210desc.h" + +/* + * Return the hardware NextTBTT in TSF + */ +uint64_t +ar5210GetNextTBTT(struct ath_hal *ah) +{ +#define TU_TO_TSF(_tu) (((uint64_t)(_tu)) << 10) + return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0)); +#undef TU_TO_TSF +} + +/* + * Initialize all of the hardware registers used to send beacons. + */ +void +ar5210SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt) +{ + + OS_REG_WRITE(ah, AR_TIMER0, bt->bt_nexttbtt); + OS_REG_WRITE(ah, AR_TIMER1, bt->bt_nextdba); + OS_REG_WRITE(ah, AR_TIMER2, bt->bt_nextswba); + OS_REG_WRITE(ah, AR_TIMER3, bt->bt_nextatim); + /* + * Set the Beacon register after setting all timers. + */ + OS_REG_WRITE(ah, AR_BEACON, bt->bt_intval); +} + +/* + * Legacy api to Initialize all of the beacon registers. + */ +void +ar5210BeaconInit(struct ath_hal *ah, + uint32_t next_beacon, uint32_t beacon_period) +{ + HAL_BEACON_TIMERS bt; + + bt.bt_nexttbtt = next_beacon; + + if (AH_PRIVATE(ah)->ah_opmode != HAL_M_STA) { + bt.bt_nextdba = (next_beacon - + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ + bt.bt_nextswba = (next_beacon - + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ + /* + * The SWBA interrupt is not used for beacons in ad hoc mode + * as we don't yet support ATIMs. So since the beacon never + * changes, the beacon descriptor is set up once and read + * into a special HW buffer, from which it will be + * automagically retrieved at each DMA Beacon Alert (DBA). + */ + + /* Set the ATIM window */ + bt.bt_nextatim = next_beacon + 0; /* NB: no ATIMs */ + } else { + bt.bt_nextdba = ~0; + bt.bt_nextswba = ~0; + bt.bt_nextatim = 1; + } + bt.bt_intval = beacon_period & + (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN); + ar5210SetBeaconTimers(ah, &bt); +} + +void +ar5210ResetStaBeaconTimers(struct ath_hal *ah) +{ + uint32_t val; + + OS_REG_WRITE(ah, AR_TIMER0, 0); /* no beacons */ + val = OS_REG_READ(ah, AR_STA_ID1); + val |= AR_STA_ID1_NO_PSPOLL; /* XXX */ + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + val & ~(AR_STA_ID1_DEFAULT_ANTENNA | AR_STA_ID1_PCF)); + OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_PERIOD); +} + +/* + * Set all the beacon related bits on the h/w for stations + * i.e. initializes the corresponding h/w timers; + * also tells the h/w whether to anticipate PCF beacons + * + * dtim_count and cfp_count from the current beacon - their current + * values aren't necessarily maintained in the device struct + */ +void +ar5210SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: setting beacon timers\n", __func__); + + HALASSERT(bs->bs_intval != 0); + /* if the AP will do PCF */ + if (bs->bs_cfpmaxduration != 0) { + /* tell the h/w that the associated AP is PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + (OS_REG_READ(ah, AR_STA_ID1) &~ AR_STA_ID1_DEFAULT_ANTENNA) + | AR_STA_ID1_PCF); + + /* set CFP_PERIOD(1.024ms) register */ + OS_REG_WRITE(ah, AR_CFP_PERIOD, bs->bs_cfpperiod); + + /* set CFP_DUR(1.024ms) register to max cfp duration */ + OS_REG_WRITE(ah, AR_CFP_DUR, bs->bs_cfpmaxduration); + + /* set TIMER2(128us) to anticipated time of next CFP */ + OS_REG_WRITE(ah, AR_TIMER2, bs->bs_cfpnext << 3); + } else { + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + OS_REG_READ(ah, AR_STA_ID1) &~ (AR_STA_ID1_DEFAULT_ANTENNA | AR_STA_ID1_PCF)); + } + + /* + * Set TIMER0(1.024ms) to the anticipated time of the next beacon. + */ + OS_REG_WRITE(ah, AR_TIMER0, bs->bs_nexttbtt); + + /* + * Start the beacon timers by setting the BEACON register + * to the beacon interval; also write the tim offset which + * we should know by now. The code, in ar5211WriteAssocid, + * also sets the tim offset once the AID is known which can + * be left as such for now. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_PERIOD|AR_BEACON_TIM)) + | SM(bs->bs_intval, AR_BEACON_PERIOD) + | SM(bs->bs_timoffset ? bs->bs_timoffset + 4 : 0, AR_BEACON_TIM) + ); + + /* + * Configure the BMISS interrupt. Note that we + * assume the caller blocks interrupts while enabling + * the threshold. + */ + + /* + * Interrupt works only on Crete. + */ + if (AH_PRIVATE(ah)->ah_macRev < AR_SREV_CRETE) + return; + /* + * Counter is only 3-bits. + * Count of 0 with BMISS interrupt enabled will hang the system + * with too many interrupts + */ + if (AH_PRIVATE(ah)->ah_macRev >= AR_SREV_CRETE && + (bs->bs_bmissthreshold&7) == 0) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: invalid beacon miss threshold %u\n", + __func__, bs->bs_bmissthreshold); +#endif + return; + } +#define BMISS_MAX (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S) + /* + * Configure the BMISS interrupt. Note that we + * assume the caller blocks interrupts while enabling + * the threshold. + * + * NB: the beacon miss count field is only 3 bits which + * is much smaller than what's found on later parts; + * clamp overflow values as a safeguard. + */ + ahp->ah_rssiThr = (ahp->ah_rssiThr &~ AR_RSSI_THR_BM_THR) + | SM(bs->bs_bmissthreshold > BMISS_MAX ? + BMISS_MAX : bs->bs_bmissthreshold, + AR_RSSI_THR_BM_THR); + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); +#undef BMISS_MAX +} diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210_interrupts.c b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_interrupts.c new file mode 100644 index 0000000..96b1a2c --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_interrupts.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" + +/* + * Return non-zero if an interrupt is pending. + */ +HAL_BOOL +ar5210IsInterruptPending(struct ath_hal *ah) +{ + return (OS_REG_READ(ah, AR_INTPEND) ? AH_TRUE : AH_FALSE); +} + +/* + * Read the Interrupt Status Register value and return + * an abstracted bitmask of the data found in the ISR. + * Note that reading the ISR clear pending interrupts. + */ +HAL_BOOL +ar5210GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) +{ +#define AR_FATAL_INT \ + (AR_ISR_MCABT_INT | AR_ISR_SSERR_INT | AR_ISR_DPERR_INT | AR_ISR_RXORN_INT) + struct ath_hal_5210 *ahp = AH5210(ah); + uint32_t isr; + + isr = OS_REG_READ(ah, AR_ISR); + if (isr == 0xffffffff) { + *masked = 0; + return AH_FALSE; + } + + /* + * Mask interrupts that have no device-independent + * representation; these are added back below. We + * also masked with the abstracted IMR to insure no + * status bits leak through that weren't requested + * (e.g. RXNOFRM) and that might confuse the caller. + */ + *masked = (isr & (HAL_INT_COMMON - HAL_INT_BNR)) & ahp->ah_maskReg; + + if (isr & AR_FATAL_INT) + *masked |= HAL_INT_FATAL; + if (isr & (AR_ISR_RXOK_INT | AR_ISR_RXERR_INT)) + *masked |= HAL_INT_RX; + if (isr & (AR_ISR_TXOK_INT | AR_ISR_TXDESC_INT | AR_ISR_TXERR_INT | AR_ISR_TXEOL_INT)) + *masked |= HAL_INT_TX; + + /* + * On fatal errors collect ISR state for debugging. + */ + if (*masked & HAL_INT_FATAL) { + AH_PRIVATE(ah)->ah_fatalState[0] = isr; + } + + return AH_TRUE; +#undef AR_FATAL_INT +} + +HAL_INT +ar5210GetInterrupts(struct ath_hal *ah) +{ + return AH5210(ah)->ah_maskReg; +} + +HAL_INT +ar5210SetInterrupts(struct ath_hal *ah, HAL_INT ints) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + uint32_t omask = ahp->ah_maskReg; + uint32_t mask; + + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n", + __func__, omask, ints); + + /* + * Disable interrupts here before reading & modifying + * the mask so that the ISR does not modify the mask + * out from under us. + */ + if (omask & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + } + + mask = ints & (HAL_INT_COMMON - HAL_INT_BNR); + if (ints & HAL_INT_RX) + mask |= AR_IMR_RXOK_INT | AR_IMR_RXERR_INT; + if (ints & HAL_INT_TX) { + if (ahp->ah_txOkInterruptMask) + mask |= AR_IMR_TXOK_INT; + if (ahp->ah_txErrInterruptMask) + mask |= AR_IMR_TXERR_INT; + if (ahp->ah_txDescInterruptMask) + mask |= AR_IMR_TXDESC_INT; + if (ahp->ah_txEolInterruptMask) + mask |= AR_IMR_TXEOL_INT; + } + + /* Write the new IMR and store off our SW copy. */ + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); + OS_REG_WRITE(ah, AR_IMR, mask); + ahp->ah_maskReg = ints; + + /* Re-enable interrupts as appropriate. */ + if (ints & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + } + + return omask; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210_keycache.c b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_keycache.c new file mode 100644 index 0000000..87fb067 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_keycache.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" + +#define AR_KEYTABLE_SIZE 64 +#define KEY_XOR 0xaa + +/* + * Return the size of the hardware key cache. + */ +u_int +ar5210GetKeyCacheSize(struct ath_hal *ah) +{ + return AR_KEYTABLE_SIZE; +} + +/* + * Return the size of the hardware key cache. + */ +HAL_BOOL +ar5210IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry) +{ + if (entry < AR_KEYTABLE_SIZE) { + uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry)); + if (val & AR_KEYTABLE_VALID) + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Clear the specified key cache entry. + */ +HAL_BOOL +ar5210ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry) +{ + if (entry < AR_KEYTABLE_SIZE) { + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Sets the mac part of the specified key cache entry and mark it valid. + */ +HAL_BOOL +ar5210SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac) +{ + uint32_t macHi, macLo; + + if (entry < AR_KEYTABLE_SIZE) { + /* + * Set MAC address -- shifted right by 1. MacLo is + * the 4 MSBs, and MacHi is the 2 LSBs. + */ + if (mac != AH_NULL) { + macHi = (mac[5] << 8) | mac[4]; + macLo = (mac[3] << 24)| (mac[2] << 16) + | (mac[1] << 8) | mac[0]; + macLo >>= 1; + macLo |= (macHi & 1) << 31; /* carry */ + macHi >>= 1; + } else { + macLo = macHi = 0; + } + + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), + macHi | AR_KEYTABLE_VALID); + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Sets the contents of the specified key cache entry. + */ +HAL_BOOL +ar5210SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, + const HAL_KEYVAL *k, const uint8_t *mac, int xorKey) +{ + uint32_t key0, key1, key2, key3, key4; + uint32_t keyType; + uint32_t xorMask= xorKey ? + (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0; + + if (entry >= AR_KEYTABLE_SIZE) + return AH_FALSE; + if (k->kv_type != HAL_CIPHER_WEP) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n", + __func__, k->kv_type); + return AH_FALSE; + } + + /* NB: only WEP supported */ + if (k->kv_len < 40 / NBBY) + return AH_FALSE; + if (k->kv_len <= 40 / NBBY) + keyType = AR_KEYTABLE_TYPE_40; + else if (k->kv_len <= 104 / NBBY) + keyType = AR_KEYTABLE_TYPE_104; + else + keyType = AR_KEYTABLE_TYPE_128; + + key0 = LE_READ_4(k->kv_val+0) ^ xorMask; + key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff; + key2 = LE_READ_4(k->kv_val+6) ^ xorMask; + key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff; + key4 = LE_READ_4(k->kv_val+12) ^ xorMask; + if (k->kv_len <= 104 / NBBY) + key4 &= 0xff; + + /* + * Note: WEP key cache hardware requires that each double-word + * pair be written in even/odd order (since the destination is + * a 64-bit register). Don't reorder these writes w/o + * understanding this! + */ + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); + return ar5210SetKeyCacheEntryMac(ah, entry, mac); +} diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210_misc.c b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_misc.c new file mode 100644 index 0000000..5eaa18e --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_misc.c @@ -0,0 +1,703 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210phy.h" + +#include "ah_eeprom_v1.h" + +#define AR_NUM_GPIO 6 /* 6 GPIO bits */ +#define AR_GPIOD_MASK 0x2f /* 6-bit mask */ + +void +ar5210GetMacAddress(struct ath_hal *ah, uint8_t *mac) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5210SetMacAddress(struct ath_hal *ah, const uint8_t *mac) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); + return AH_TRUE; +} + +void +ar5210GetBssIdMask(struct ath_hal *ah, uint8_t *mask) +{ + static const uint8_t ones[IEEE80211_ADDR_LEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5210SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) +{ + return AH_FALSE; +} + +/* + * Read 16 bits of data from the specified EEPROM offset. + */ +HAL_BOOL +ar5210EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) +{ + (void) OS_REG_READ(ah, AR_EP_AIR(off)); /* activate read op */ + if (!ath_hal_wait(ah, AR_EP_STA, + AR_EP_STA_RDCMPLT | AR_EP_STA_RDERR, AR_EP_STA_RDCMPLT)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n", + __func__, AR_EP_AIR(off)); + return AH_FALSE; + } + *data = OS_REG_READ(ah, AR_EP_RDATA) & 0xffff; + return AH_TRUE; +} + +#ifdef AH_SUPPORT_WRITE_EEPROM +/* + * Write 16 bits of data to the specified EEPROM offset. + */ +HAL_BOOL +ar5210EepromWrite(struct ath_hal *ah, u_int off, uint16_t data) +{ + return AH_FALSE; +} +#endif /* AH_SUPPORT_WRITE_EEPROM */ + +/* + * Attempt to change the cards operating regulatory domain to the given value + */ +HAL_BOOL +ar5210SetRegulatoryDomain(struct ath_hal *ah, + uint16_t regDomain, HAL_STATUS *status) +{ + HAL_STATUS ecode; + + if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { + ecode = HAL_EINVAL; + goto bad; + } + /* + * Check if EEPROM is configured to allow this; must + * be a proper version and the protection bits must + * permit re-writing that segment of the EEPROM. + */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { + ecode = HAL_EEWRITE; + goto bad; + } + ecode = HAL_EIO; /* disallow all writes */ +bad: + if (status) + *status = ecode; + return AH_FALSE; +} + +/* + * Return the wireless modes (a,b,g,t) supported by hardware. + * + * This value is what is actually supported by the hardware + * and is unaffected by regulatory/country code settings. + * + */ +u_int +ar5210GetWirelessModes(struct ath_hal *ah) +{ + /* XXX could enable turbo mode but can't do all rates */ + return HAL_MODE_11A; +} + +/* + * Called if RfKill is supported (according to EEPROM). Set the interrupt and + * GPIO values so the ISR and can disable RF on a switch signal + */ +void +ar5210EnableRfKill(struct ath_hal *ah) +{ + uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; + int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); + int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); + + /* + * If radio disable switch connection to GPIO bit 0 is enabled + * program GPIO interrupt. + * If rfkill bit on eeprom is 1, setupeeprommap routine has already + * verified that it is a later version of eeprom, it has a place for + * rfkill bit and it is set to 1, indicating that GPIO bit 0 hardware + * connection is present. + */ + ar5210Gpio0SetIntr(ah, select, (ar5210GpioGet(ah, select) == polarity)); +} + +/* + * Configure GPIO Output lines + */ +HAL_BOOL +ar5210GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) +{ + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, AR_GPIOCR, + (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio)) + | AR_GPIOCR_OUT1(gpio)); + + return AH_TRUE; +} + +/* + * Configure GPIO Input lines + */ +HAL_BOOL +ar5210GpioCfgInput(struct ath_hal *ah, uint32_t gpio) +{ + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, AR_GPIOCR, + (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio)) + | AR_GPIOCR_IN(gpio)); + + return AH_TRUE; +} + +/* + * Once configured for I/O - set output lines + */ +HAL_BOOL +ar5210GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) +{ + uint32_t reg; + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, AR_GPIODO); + reg &= ~(1 << gpio); + reg |= (val&1) << gpio; + + OS_REG_WRITE(ah, AR_GPIODO, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - get input lines + */ +uint32_t +ar5210GpioGet(struct ath_hal *ah, uint32_t gpio) +{ + if (gpio < AR_NUM_GPIO) { + uint32_t val = OS_REG_READ(ah, AR_GPIODI); + val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1; + return val; + } else { + return 0xffffffff; + } +} + +/* + * Set the GPIO 0 Interrupt + */ +void +ar5210Gpio0SetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) +{ + uint32_t val = OS_REG_READ(ah, AR_GPIOCR); + + /* Clear the bits that we will modify. */ + val &= ~(AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA | + AR_GPIOCR_ALL(gpio)); + + val |= AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_ENA; + if (ilevel) + val |= AR_GPIOCR_INT_SELH; + + /* Don't need to change anything for low level interrupt. */ + OS_REG_WRITE(ah, AR_GPIOCR, val); + + /* Change the interrupt mask. */ + ar5210SetInterrupts(ah, AH5210(ah)->ah_maskReg | HAL_INT_GPIO); +} + +/* + * Change the LED blinking pattern to correspond to the connectivity + */ +void +ar5210SetLedState(struct ath_hal *ah, HAL_LED_STATE state) +{ + uint32_t val; + + val = OS_REG_READ(ah, AR_PCICFG); + switch (state) { + case HAL_LED_INIT: + val &= ~(AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT); + break; + case HAL_LED_RUN: + /* normal blink when connected */ + val &= ~AR_PCICFG_LED_PEND; + val |= AR_PCICFG_LED_ACT; + break; + default: + val |= AR_PCICFG_LED_PEND; + val &= ~AR_PCICFG_LED_ACT; + break; + } + OS_REG_WRITE(ah, AR_PCICFG, val); +} + +/* + * Return 1 or 2 for the corresponding antenna that is in use + */ +u_int +ar5210GetDefAntenna(struct ath_hal *ah) +{ + uint32_t val = OS_REG_READ(ah, AR_STA_ID1); + return (val & AR_STA_ID1_DEFAULT_ANTENNA ? 2 : 1); +} + +void +ar5210SetDefAntenna(struct ath_hal *ah, u_int antenna) +{ + uint32_t val = OS_REG_READ(ah, AR_STA_ID1); + + if (antenna != (val & AR_STA_ID1_DEFAULT_ANTENNA ? 2 : 1)) { + /* + * Antenna change requested, force a toggle of the default. + */ + OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_DEFAULT_ANTENNA); + } +} + +HAL_ANT_SETTING +ar5210GetAntennaSwitch(struct ath_hal *ah) +{ + return HAL_ANT_VARIABLE; +} + +HAL_BOOL +ar5210SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) +{ + /* XXX not sure how to fix antenna */ + return (settings == HAL_ANT_VARIABLE); +} + +/* + * Change association related fields programmed into the hardware. + * Writing a valid BSSID to the hardware effectively enables the hardware + * to synchronize its TSF to the correct beacons and receive frames coming + * from that BSSID. It is called by the SME JOIN operation. + */ +void +ar5210WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + /* XXX save bssid for possible re-use on reset */ + OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); + ahp->ah_associd = assocId; + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | + ((assocId & 0x3fff)<> 19) & 0x1ff; + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + return (OS_REG_READ(ah, AR_TSF_U32) ^ + OS_REG_READ(ah, AR_TSF_L32) ^ nf); +} + +/* + * Detect if our card is present + */ +HAL_BOOL +ar5210DetectCardPresent(struct ath_hal *ah) +{ + /* + * Read the Silicon Revision register and compare that + * to what we read at attach time. If the same, we say + * a card/device is present. + */ + return (AH_PRIVATE(ah)->ah_macRev == (OS_REG_READ(ah, AR_SREV) & 0xff)); +} + +/* + * Update MIB Counters + */ +void +ar5210UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats) +{ + stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); + stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); + stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); + stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); + stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); +} + +HAL_BOOL +ar5210SetSifsTime(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (us > ath_hal_mac_usec(ah, 0x7ff)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", + __func__, us); + ahp->ah_sifstime = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_IFS0, AR_IFS0_SIFS, + ath_hal_mac_clks(ah, us)); + ahp->ah_sifstime = us; + return AH_TRUE; + } +} + +u_int +ar5210GetSifsTime(struct ath_hal *ah) +{ + u_int clks = OS_REG_READ(ah, AR_IFS0) & 0x7ff; + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5210SetSlotTime(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", + __func__, us); + ahp->ah_slottime = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_WRITE(ah, AR_SLOT_TIME, ath_hal_mac_clks(ah, us)); + ahp->ah_slottime = us; + return AH_TRUE; + } +} + +u_int +ar5210GetSlotTime(struct ath_hal *ah) +{ + u_int clks = OS_REG_READ(ah, AR_SLOT_TIME) & 0xffff; + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5210SetAckTimeout(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", + __func__, us); + ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); + ahp->ah_acktimeout = us; + return AH_TRUE; + } +} + +u_int +ar5210GetAckTimeout(struct ath_hal *ah) +{ + u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +u_int +ar5210GetAckCTSRate(struct ath_hal *ah) +{ + return ((AH5210(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); +} + +HAL_BOOL +ar5210SetAckCTSRate(struct ath_hal *ah, u_int high) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (high) { + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); + ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; + } else { + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); + ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; + } + return AH_TRUE; +} + +HAL_BOOL +ar5210SetCTSTimeout(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", + __func__, us); + ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); + ahp->ah_ctstimeout = us; + return AH_TRUE; + } +} + +u_int +ar5210GetCTSTimeout(struct ath_hal *ah) +{ + u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5210SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) +{ + /* nothing to do */ + return AH_TRUE; +} + +void +ar5210SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) +{ +} + +/* + * Control Adaptive Noise Immunity Parameters + */ +HAL_BOOL +ar5210AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) +{ + return AH_FALSE; +} + +void +ar5210RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats, + const struct ieee80211_channel *chan) +{ +} + +void +ar5210AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +} + +void +ar5210MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats) +{ +} + +HAL_STATUS +ar5210GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t *result) +{ + + switch (type) { + case HAL_CAP_CIPHER: /* cipher handled in hardware */ +#if 0 + return (capability == HAL_CIPHER_WEP ? HAL_OK : HAL_ENOTSUPP); +#else + return HAL_ENOTSUPP; +#endif + default: + return ath_hal_getcapability(ah, type, capability, result); + } +} + +HAL_BOOL +ar5210SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t setting, HAL_STATUS *status) +{ + + switch (type) { + case HAL_CAP_DIAG: /* hardware diagnostic support */ + /* + * NB: could split this up into virtual capabilities, + * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly + * seems worth the additional complexity. + */ +#ifdef AH_DEBUG + AH_PRIVATE(ah)->ah_diagreg = setting; +#else + AH_PRIVATE(ah)->ah_diagreg = setting & 0x6; /* ACK+CTS */ +#endif + ar5210UpdateDiagReg(ah, AH_PRIVATE(ah)->ah_diagreg); + return AH_TRUE; + case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ + return AH_FALSE; /* NB: disallow */ + default: + return ath_hal_setcapability(ah, type, capability, + setting, status); + } +} + +HAL_BOOL +ar5210GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize) +{ +#ifdef AH_PRIVATE_DIAG + uint32_t pcicfg; + HAL_BOOL ok; + + switch (request) { + case HAL_DIAG_EEPROM: + /* XXX */ + break; + case HAL_DIAG_EEREAD: + if (argsize != sizeof(uint16_t)) + return AH_FALSE; + pcicfg = OS_REG_READ(ah, AR_PCICFG); + OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL); + ok = ath_hal_eepromRead(ah, *(const uint16_t *)args, *result); + OS_REG_WRITE(ah, AR_PCICFG, pcicfg); + if (ok) + *resultsize = sizeof(uint16_t); + return ok; + } +#endif + return ath_hal_getdiagstate(ah, request, + args, argsize, result, resultsize); +} + +/* + * Return what percentage of the extension channel is busy. + * This is always disabled for AR5210 series NICs. + */ +uint32_t +ar5210Get11nExtBusy(struct ath_hal *ah) +{ + + return (0); +} + +/* + * There's no channel survey support for the AR5210. + */ +HAL_BOOL +ar5210GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) +{ + + return (AH_FALSE); +} + +void +ar5210SetChainMasks(struct ath_hal *ah, uint32_t txchainmask, + uint32_t rxchainmask) +{ +} + +void +ar5210EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ +} + +void +ar5210GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ +} + +/* + * Update the diagnostic register. + * + * This merges in the diagnostic register setting with the default + * value, which may or may not involve disabling hardware encryption. + */ +void +ar5210UpdateDiagReg(struct ath_hal *ah, uint32_t val) +{ + + /* Disable all hardware encryption */ + val |= AR_DIAG_SW_DIS_CRYPTO; + OS_REG_WRITE(ah, AR_DIAG_SW, val); +} diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210_phy.c b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_phy.c new file mode 100644 index 0000000..0455d65 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_phy.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" + +/* shorthands to compact tables for readability */ +#define OFDM IEEE80211_T_OFDM +#define TURBO IEEE80211_T_TURBO + +HAL_RATE_TABLE ar5210_11a_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 } + }, +}; + +HAL_RATE_TABLE ar5210_turbo_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, TURBO, 12000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, TURBO, 18000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, TURBO, 24000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, TURBO, 36000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, TURBO, 48000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, TURBO, 72000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, TURBO, 96000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, TURBO, 108000, 0x0c, 0x00, 108, 4 } + }, +}; + +#undef OFDM +#undef TURBO + +const HAL_RATE_TABLE * +ar5210GetRateTable(struct ath_hal *ah, u_int mode) +{ + HAL_RATE_TABLE *rt; + switch (mode) { + case HAL_MODE_11A: + rt = &ar5210_11a_table; + break; + case HAL_MODE_TURBO: + rt = &ar5210_turbo_table; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", + __func__, mode); + return AH_NULL; + } + ath_hal_setupratetable(ah, rt); + return rt; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210_power.c b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_power.c new file mode 100644 index 0000000..ec5e75d --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_power.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, set Power Mode of chip to auto/normal. + */ +static void +ar5210SetPowerModeAuto(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_ALLOW); +} + +/* + * Notify Power Mgt is enabled in self-generated frames. + * If requested, force chip awake. + * + * Returns A_OK if chip is awake or successfully forced awake. + * + * WARNING WARNING WARNING + * There is a problem with the chip where sometimes it will not wake up. + */ +static HAL_BOOL +ar5210SetPowerModeAwake(struct ath_hal *ah, int setChip) +{ +#define POWER_UP_TIME 2000 + uint32_t val; + int i; + + if (setChip) { + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_WAKE); + OS_DELAY(2000); /* Give chip the chance to awake */ + + for (i = POWER_UP_TIME / 200; i != 0; i--) { + val = OS_REG_READ(ah, AR_PCICFG); + if ((val & AR_PCICFG_SPWR_DN) == 0) + break; + OS_DELAY(200); + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, + AR_SCR_SLE_WAKE); + } + if (i == 0) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n", + __func__, POWER_UP_TIME/20); +#endif + return AH_FALSE; + } + } + + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV); + return AH_TRUE; +#undef POWER_UP_TIME +} + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, force chip to sleep. + */ +static void +ar5210SetPowerModeSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_SLP); +} + +HAL_BOOL +ar5210SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) +{ +#ifdef AH_DEBUG + static const char* modes[] = { + "AWAKE", + "FULL-SLEEP", + "NETWORK SLEEP", + "UNDEFINED" + }; +#endif + int status = AH_TRUE; + + HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, + modes[ah->ah_powerMode], modes[mode], + setChip ? "set chip " : ""); + switch (mode) { + case HAL_PM_AWAKE: + if (setChip) + ah->ah_powerMode = mode; + status = ar5210SetPowerModeAwake(ah, setChip); + break; + case HAL_PM_FULL_SLEEP: + ar5210SetPowerModeSleep(ah, setChip); + if (setChip) + ah->ah_powerMode = mode; + break; + case HAL_PM_NETWORK_SLEEP: + ar5210SetPowerModeAuto(ah, setChip); + if (setChip) + ah->ah_powerMode = mode; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n", + __func__, mode); + return AH_FALSE; + } + return status; +} + +HAL_POWER_MODE +ar5210GetPowerMode(struct ath_hal *ah) +{ + /* Just so happens the h/w maps directly to the abstracted value */ + return MS(OS_REG_READ(ah, AR_SCR), AR_SCR_SLE); +} diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210_recv.c b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_recv.c new file mode 100644 index 0000000..b43d807 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_recv.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210desc.h" + +/* + * Get the RXDP. + */ +uint32_t +ar5210GetRxDP(struct ath_hal *ah, HAL_RX_QUEUE qtype) +{ + + HALASSERT(qtype == HAL_RX_QUEUE_HP); + return OS_REG_READ(ah, AR_RXDP); +} + +/* + * Set the RxDP. + */ +void +ar5210SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE qtype) +{ + + HALASSERT(qtype == HAL_RX_QUEUE_HP); + OS_REG_WRITE(ah, AR_RXDP, rxdp); +} + + +/* + * Set Receive Enable bits. + */ +void +ar5210EnableReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_CR, AR_CR_RXE); +} + +/* + * Stop Receive at the DMA engine + */ +HAL_BOOL +ar5210StopDmaReceive(struct ath_hal *ah) +{ + int i; + + OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */ + for (i = 0; i < 1000; i++) { + if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) + return AH_TRUE; + OS_DELAY(10); + } +#ifdef AH_DEBUG + ath_hal_printf(ah, "ar5210: dma receive failed to stop in 10ms\n"); + ath_hal_printf(ah, "AR_CR=0x%x\n", OS_REG_READ(ah, AR_CR)); + ath_hal_printf(ah, "AR_DIAG_SW=0x%x\n", OS_REG_READ(ah, AR_DIAG_SW)); +#endif + return AH_FALSE; +} + +/* + * Start Transmit at the PCU engine (unpause receive) + */ +void +ar5210StartPcuReceive(struct ath_hal *ah) +{ + ar5210UpdateDiagReg(ah, + OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_RX)); +} + +/* + * Stop Transmit at the PCU engine (pause receive) + */ +void +ar5210StopPcuReceive(struct ath_hal *ah) +{ + ar5210UpdateDiagReg(ah, + OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_SW_DIS_RX); +} + +/* + * Set multicast filter 0 (lower 32-bits) + * filter 1 (upper 32-bits) + */ +void +ar5210SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1) +{ + OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0); + OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1); +} + +/* + * Clear multicast filter by index + */ +HAL_BOOL +ar5210ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix) +{ + uint32_t val; + + if (ix >= 64) + return AH_FALSE; + if (ix >= 32) { + val = OS_REG_READ(ah, AR_MCAST_FIL1); + OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32)))); + } else { + val = OS_REG_READ(ah, AR_MCAST_FIL0); + OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<= 64) + return AH_FALSE; + if (ix >= 32) { + val = OS_REG_READ(ah, AR_MCAST_FIL1); + OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32)))); + } else { + val = OS_REG_READ(ah, AR_MCAST_FIL0); + OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<ds_ctl0 = 0; + ads->ds_ctl1 = size & AR_BufLen; + if (ads->ds_ctl1 != size) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: buffer size %u too large\n", + __func__, size); + return AH_FALSE; + } + if (flags & HAL_RXDESC_INTREQ) + ads->ds_ctl1 |= AR_RxInterReq; + ads->ds_status0 = ads->ds_status1 = 0; + + return AH_TRUE; +} + +/* + * Process an RX descriptor, and return the status to the caller. + * Copy some hardware specific items into the software portion + * of the descriptor. + * + * NB: the caller is responsible for validating the memory contents + * of the descriptor (e.g. flushing any cached copy). + */ +HAL_STATUS +ar5210ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, + uint32_t pa, struct ath_desc *nds, uint64_t tsf, + struct ath_rx_status *rs) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + struct ar5210_desc *ands = AR5210DESC(nds); + uint32_t now, rstamp; + + if ((ads->ds_status1 & AR_Done) == 0) + return HAL_EINPROGRESS; + /* + * Given the use of a self-linked tail be very sure that the hw is + * done with this descriptor; the hw may have done this descriptor + * once and picked it up again...make sure the hw has moved on. + */ + if ((ands->ds_status1 & AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa) + return HAL_EINPROGRESS; + + rs->rs_datalen = ads->ds_status0 & AR_DataLen; + rstamp = MS(ads->ds_status1, AR_RcvTimestamp); + /* + * Convert timestamp. The value in the + * descriptor is bits [10..22] of the TSF. + */ + now = (OS_REG_READ(ah, AR_TSF_L32) >> 10) & 0xffff; + if ((now & 0x1fff) < rstamp) + rstamp |= (now - 0x2000) & 0xffff; + else + rstamp |= now; + /* NB: keep only 15 bits for consistency w/ other chips */ + rs->rs_tstamp = rstamp & 0x7fff; + rs->rs_status = 0; + if ((ads->ds_status1 & AR_FrmRcvOK) == 0) { + if (ads->ds_status1 & AR_CRCErr) + rs->rs_status |= HAL_RXERR_CRC; + else if (ads->ds_status1 & AR_DecryptCRCErr) + rs->rs_status |= HAL_RXERR_DECRYPT; + else if (ads->ds_status1 & AR_FIFOOverrun) + rs->rs_status |= HAL_RXERR_FIFO; + else { + rs->rs_status |= HAL_RXERR_PHY; + rs->rs_phyerr = + (ads->ds_status1 & AR_PHYErr) >> AR_PHYErr_S; + } + } + /* XXX what about KeyCacheMiss? */ + rs->rs_rssi = MS(ads->ds_status0, AR_RcvSigStrength); + if (ads->ds_status1 & AR_KeyIdxValid) + rs->rs_keyix = MS(ads->ds_status1, AR_KeyIdx); + else + rs->rs_keyix = HAL_RXKEYIX_INVALID; + /* NB: caller expected to do rate table mapping */ + rs->rs_rate = MS(ads->ds_status0, AR_RcvRate); + rs->rs_antenna = (ads->ds_status0 & AR_RcvAntenna) ? 1 : 0; + rs->rs_more = (ads->ds_status0 & AR_More) ? 1 : 0; + + return HAL_OK; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210_reset.c b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_reset.c new file mode 100644 index 0000000..6029bff --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_reset.c @@ -0,0 +1,1006 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210phy.h" + +#include "ah_eeprom_v1.h" + +typedef struct { + uint32_t Offset; + uint32_t Value; +} REGISTER_VAL; + +static const REGISTER_VAL ar5k0007_init[] = { +#include "ar5210/ar5k_0007.ini" +}; + +/* Default Power Settings for channels outside of EEPROM range */ +static const uint8_t ar5k0007_pwrSettings[17] = { +/* gain delta pc dac */ +/* 54 48 36 24 18 12 9 54 48 36 24 18 12 9 6 ob db */ + 9, 9, 0, 0, 0, 0, 0, 2, 2, 6, 6, 6, 6, 6, 6, 2, 2 +}; + +/* + * The delay, in usecs, between writing AR_RC with a reset + * request and waiting for the chip to settle. If this is + * too short then the chip does not come out of sleep state. + * Note this value was empirically derived and may be dependent + * on the host machine (don't know--the problem was identified + * on an IBM 570e laptop; 10us delays worked on other systems). + */ +#define AR_RC_SETTLE_TIME 20000 + +static HAL_BOOL ar5210SetResetReg(struct ath_hal *, + uint32_t resetMask, u_int delay); +static HAL_BOOL ar5210SetChannel(struct ath_hal *, struct ieee80211_channel *); +static void ar5210SetOperatingMode(struct ath_hal *, int opmode); + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + * + * bChannelChange is used to preserve DMA/PCU registers across + * a HW Reset during channel change. + */ +HAL_BOOL +ar5210Reset(struct ath_hal *ah, HAL_OPMODE opmode, + struct ieee80211_channel *chan, HAL_BOOL bChannelChange, + HAL_RESET_TYPE resetType, + HAL_STATUS *status) +{ +#define N(a) (sizeof (a) /sizeof (a[0])) +#define FAIL(_code) do { ecode = _code; goto bad; } while (0) + struct ath_hal_5210 *ahp = AH5210(ah); + const HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + HAL_CHANNEL_INTERNAL *ichan; + HAL_STATUS ecode; + uint32_t ledstate; + int i, q; + + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: opmode %u channel %u/0x%x %s channel\n", __func__, + opmode, chan->ic_freq, chan->ic_flags, + bChannelChange ? "change" : "same"); + + if (!IEEE80211_IS_CHAN_5GHZ(chan)) { + /* Only 11a mode */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: channel not 5GHz\n", __func__); + FAIL(HAL_EINVAL); + } + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->ic_freq, chan->ic_flags); + FAIL(HAL_EINVAL); + } + switch (opmode) { + case HAL_M_STA: + case HAL_M_IBSS: + case HAL_M_HOSTAP: + case HAL_M_MONITOR: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n", + __func__, opmode); + FAIL(HAL_EINVAL); + break; + } + + ledstate = OS_REG_READ(ah, AR_PCICFG) & + (AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT); + + if (!ar5210ChipReset(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", + __func__); + FAIL(HAL_EIO); + } + + OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); + OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)); + ar5210SetOperatingMode(ah, opmode); + + switch (opmode) { + case HAL_M_HOSTAP: + OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG); + OS_REG_WRITE(ah, AR_PCICFG, + AR_PCICFG_LED_ACT | AR_PCICFG_LED_BCTL); + break; + case HAL_M_IBSS: + OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG | AR_BCR_BCMD); + OS_REG_WRITE(ah, AR_PCICFG, + AR_PCICFG_CLKRUNEN | AR_PCICFG_LED_PEND | AR_PCICFG_LED_BCTL); + break; + case HAL_M_STA: + OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG); + OS_REG_WRITE(ah, AR_PCICFG, + AR_PCICFG_CLKRUNEN | AR_PCICFG_LED_PEND | AR_PCICFG_LED_BCTL); + break; + case HAL_M_MONITOR: + OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG); + OS_REG_WRITE(ah, AR_PCICFG, + AR_PCICFG_LED_ACT | AR_PCICFG_LED_BCTL); + break; + } + + /* Restore previous led state */ + OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate); + +#if 0 + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4)); +#endif + /* BSSID, association id, ps-poll */ + ar5210WriteAssocid(ah, ahp->ah_bssid, ahp->ah_associd); + + OS_REG_WRITE(ah, AR_TXDP0, 0); + OS_REG_WRITE(ah, AR_TXDP1, 0); + OS_REG_WRITE(ah, AR_RXDP, 0); + + /* + * Initialize interrupt state. + */ + (void) OS_REG_READ(ah, AR_ISR); /* cleared on read */ + OS_REG_WRITE(ah, AR_IMR, 0); + OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + ahp->ah_maskReg = 0; + + (void) OS_REG_READ(ah, AR_BSR); /* cleared on read */ + OS_REG_WRITE(ah, AR_TXCFG, AR_DMASIZE_128B); + OS_REG_WRITE(ah, AR_RXCFG, AR_DMASIZE_128B); + + OS_REG_WRITE(ah, AR_TOPS, 8); /* timeout prescale */ + OS_REG_WRITE(ah, AR_RXNOFRM, 8); /* RX no frame timeout */ + OS_REG_WRITE(ah, AR_RPGTO, 0); /* RX frame gap timeout */ + OS_REG_WRITE(ah, AR_TXNOFRM, 0); /* TX no frame timeout */ + + OS_REG_WRITE(ah, AR_SFR, 0); + OS_REG_WRITE(ah, AR_MIBC, 0); /* unfreeze ctrs + clr state */ + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + OS_REG_WRITE(ah, AR_CFP_DUR, 0); + + ar5210SetRxFilter(ah, 0); /* nothing for now */ + OS_REG_WRITE(ah, AR_MCAST_FIL0, 0); /* multicast filter */ + OS_REG_WRITE(ah, AR_MCAST_FIL1, 0); /* XXX was 2 */ + + OS_REG_WRITE(ah, AR_TX_MASK0, 0); + OS_REG_WRITE(ah, AR_TX_MASK1, 0); + OS_REG_WRITE(ah, AR_CLR_TMASK, 1); + OS_REG_WRITE(ah, AR_TRIG_LEV, 1); /* minimum */ + + ar5210UpdateDiagReg(ah, 0); + + OS_REG_WRITE(ah, AR_CFP_PERIOD, 0); + OS_REG_WRITE(ah, AR_TIMER0, 0); /* next beacon time */ + OS_REG_WRITE(ah, AR_TSF_L32, 0); /* local clock */ + OS_REG_WRITE(ah, AR_TIMER1, ~0); /* next DMA beacon alert */ + OS_REG_WRITE(ah, AR_TIMER2, ~0); /* next SW beacon alert */ + OS_REG_WRITE(ah, AR_TIMER3, 1); /* next ATIM window */ + + /* Write the INI values for PHYreg initialization */ + for (i = 0; i < N(ar5k0007_init); i++) { + uint32_t reg = ar5k0007_init[i].Offset; + /* On channel change, don't reset the PCU registers */ + if (!(bChannelChange && (0x8000 <= reg && reg < 0x9000))) + OS_REG_WRITE(ah, reg, ar5k0007_init[i].Value); + } + + /* Setup the transmit power values for cards since 0x0[0-2]05 */ + if (!ar5210SetTransmitPower(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + FAIL(HAL_EIO); + } + + OS_REG_WRITE(ah, AR_PHY(10), + (OS_REG_READ(ah, AR_PHY(10)) & 0xFFFF00FF) | + (ee->ee_xlnaOn << 8)); + OS_REG_WRITE(ah, AR_PHY(13), + (ee->ee_xpaOff << 24) | (ee->ee_xpaOff << 16) | + (ee->ee_xpaOn << 8) | ee->ee_xpaOn); + OS_REG_WRITE(ah, AR_PHY(17), + (OS_REG_READ(ah, AR_PHY(17)) & 0xFFFFC07F) | + ((ee->ee_antenna >> 1) & 0x3F80)); + OS_REG_WRITE(ah, AR_PHY(18), + (OS_REG_READ(ah, AR_PHY(18)) & 0xFFFC0FFF) | + ((ee->ee_antenna << 10) & 0x3F000)); + OS_REG_WRITE(ah, AR_PHY(25), + (OS_REG_READ(ah, AR_PHY(25)) & 0xFFF80FFF) | + ((ee->ee_thresh62 << 12) & 0x7F000)); + OS_REG_WRITE(ah, AR_PHY(68), + (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFFFC) | + (ee->ee_antenna & 0x3)); + + if (!ar5210SetChannel(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set channel\n", + __func__); + FAIL(HAL_EIO); + } + if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan)) + chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT; + + /* Activate the PHY */ + OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ENABLE); + + OS_DELAY(1000); /* Wait a bit (1 msec) */ + + /* calibrate the HW and poll the bit going to 0 for completion */ + OS_REG_WRITE(ah, AR_PHY_AGCCTL, + OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_CAL); + (void) ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_CAL, 0); + + /* Perform noise floor calibration and set status */ + if (!ar5210CalNoiseFloor(ah, ichan)) { + chan->ic_state |= IEEE80211_CHANSTATE_CWINT; + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: noise floor calibration failed\n", __func__); + FAIL(HAL_EIO); + } + + for (q = 0; q < HAL_NUM_TX_QUEUES; q++) + ar5210ResetTxQueue(ah, q); + + if (AH_PRIVATE(ah)->ah_rfkillEnabled) + ar5210EnableRfKill(ah); + + /* + * Writing to AR_BEACON will start timers. Hence it should be + * the last register to be written. Do not reset tsf, do not + * enable beacons at this point, but preserve other values + * like beaconInterval. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) & + ~(AR_BEACON_EN | AR_BEACON_RESET_TSF))); + + /* Restore user-specified slot time and timeouts */ + if (ahp->ah_sifstime != (u_int) -1) + ar5210SetSifsTime(ah, ahp->ah_sifstime); + if (ahp->ah_slottime != (u_int) -1) + ar5210SetSlotTime(ah, ahp->ah_slottime); + if (ahp->ah_acktimeout != (u_int) -1) + ar5210SetAckTimeout(ah, ahp->ah_acktimeout); + if (ahp->ah_ctstimeout != (u_int) -1) + ar5210SetCTSTimeout(ah, ahp->ah_ctstimeout); + if (AH_PRIVATE(ah)->ah_diagreg != 0) + ar5210UpdateDiagReg(ah, AH_PRIVATE(ah)->ah_diagreg); + + AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); + + return AH_TRUE; +bad: + if (status != AH_NULL) + *status = ecode; + return AH_FALSE; +#undef FAIL +#undef N +} + +static void +ar5210SetOperatingMode(struct ath_hal *ah, int opmode) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + uint32_t val; + + val = OS_REG_READ(ah, AR_STA_ID1) & 0xffff; + switch (opmode) { + case HAL_M_HOSTAP: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_AP + | AR_STA_ID1_NO_PSPOLL + | AR_STA_ID1_DESC_ANTENNA + | ahp->ah_staId1Defaults); + break; + case HAL_M_IBSS: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_ADHOC + | AR_STA_ID1_NO_PSPOLL + | AR_STA_ID1_DESC_ANTENNA + | ahp->ah_staId1Defaults); + break; + case HAL_M_STA: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_NO_PSPOLL + | AR_STA_ID1_PWR_SV + | ahp->ah_staId1Defaults); + break; + case HAL_M_MONITOR: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_NO_PSPOLL + | ahp->ah_staId1Defaults); + break; + } +} + +void +ar5210SetPCUConfig(struct ath_hal *ah) +{ + ar5210SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode); +} + +/* + * Places the PHY and Radio chips into reset. A full reset + * must be called to leave this state. The PCI/MAC/PCU are + * not placed into reset as we must receive interrupt to + * re-enable the hardware. + */ +HAL_BOOL +ar5210PhyDisable(struct ath_hal *ah) +{ + return ar5210SetResetReg(ah, AR_RC_RPHY, 10); +} + +/* + * Places all of hardware into reset + */ +HAL_BOOL +ar5210Disable(struct ath_hal *ah) +{ +#define AR_RC_HW (AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC) + if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* + * Reset the HW - PCI must be reset after the rest of the + * device has been reset + */ + if (!ar5210SetResetReg(ah, AR_RC_HW, AR_RC_SETTLE_TIME)) + return AH_FALSE; + OS_DELAY(1000); + (void) ar5210SetResetReg(ah, AR_RC_HW | AR_RC_RPCI, AR_RC_SETTLE_TIME); + OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */ + + return AH_TRUE; +#undef AR_RC_HW +} + +/* + * Places the hardware into reset and then pulls it out of reset + */ +HAL_BOOL +ar5210ChipReset(struct ath_hal *ah, struct ieee80211_channel *chan) +{ +#define AR_RC_HW (AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC) + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s turbo %s\n", __func__, + chan && IEEE80211_IS_CHAN_TURBO(chan) ? + "enabled" : "disabled"); + + if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* Place chip in turbo before reset to cleanly reset clocks */ + OS_REG_WRITE(ah, AR_PHY_FRCTL, + chan && IEEE80211_IS_CHAN_TURBO(chan) ? AR_PHY_TURBO_MODE : 0); + + /* + * Reset the HW. + * PCI must be reset after the rest of the device has been reset. + */ + if (!ar5210SetResetReg(ah, AR_RC_HW, AR_RC_SETTLE_TIME)) + return AH_FALSE; + OS_DELAY(1000); + if (!ar5210SetResetReg(ah, AR_RC_HW | AR_RC_RPCI, AR_RC_SETTLE_TIME)) + return AH_FALSE; + OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */ + + /* + * Bring out of sleep mode (AGAIN) + * + * WARNING WARNING WARNING + * + * There is a problem with the chip where it doesn't always indicate + * that it's awake, so initializePowerUp() will fail. + */ + if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* Clear warm reset reg */ + return ar5210SetResetReg(ah, 0, 10); +#undef AR_RC_HW +} + +enum { + FIRPWR_M = 0x03fc0000, + FIRPWR_S = 18, + KCOARSEHIGH_M = 0x003f8000, + KCOARSEHIGH_S = 15, + KCOARSELOW_M = 0x00007f80, + KCOARSELOW_S = 7, + ADCSAT_ICOUNT_M = 0x0001f800, + ADCSAT_ICOUNT_S = 11, + ADCSAT_THRESH_M = 0x000007e0, + ADCSAT_THRESH_S = 5 +}; + +/* + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +HAL_BOOL +ar5210PerCalibrationN(struct ath_hal *ah, + struct ieee80211_channel *chan, u_int chainMask, + HAL_BOOL longCal, HAL_BOOL *isCalDone) +{ + uint32_t regBeacon; + uint32_t reg9858, reg985c, reg9868; + HAL_CHANNEL_INTERNAL *ichan; + + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) + return AH_FALSE; + /* Disable tx and rx */ + ar5210UpdateDiagReg(ah, + OS_REG_READ(ah, AR_DIAG_SW) | (AR_DIAG_SW_DIS_TX | AR_DIAG_SW_DIS_RX)); + + /* Disable Beacon Enable */ + regBeacon = OS_REG_READ(ah, AR_BEACON); + OS_REG_WRITE(ah, AR_BEACON, regBeacon & ~AR_BEACON_EN); + + /* Delay 4ms to ensure that all tx and rx activity has ceased */ + OS_DELAY(4000); + + /* Disable AGC to radio traffic */ + OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) | 0x08000000); + /* Wait for the AGC traffic to cease. */ + OS_DELAY(10); + + /* Change Channel to relock synth */ + if (!ar5210SetChannel(ah, chan)) + return AH_FALSE; + + /* wait for the synthesizer lock to stabilize */ + OS_DELAY(1000); + + /* Re-enable AGC to radio traffic */ + OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) & (~0x08000000)); + + /* + * Configure the AGC so that it is highly unlikely (if not + * impossible) for it to send any gain changes to the analog + * chip. We store off the current values so that they can + * be rewritten below. Setting the following values: + * firpwr = -1 + * Kcoursehigh = -1 + * Kcourselow = -127 + * ADCsat_icount = 2 + * ADCsat_thresh = 12 + */ + reg9858 = OS_REG_READ(ah, 0x9858); + reg985c = OS_REG_READ(ah, 0x985c); + reg9868 = OS_REG_READ(ah, 0x9868); + + OS_REG_WRITE(ah, 0x9858, (reg9858 & ~FIRPWR_M) | + ((-1 << FIRPWR_S) & FIRPWR_M)); + OS_REG_WRITE(ah, 0x985c, + (reg985c & ~(KCOARSEHIGH_M | KCOARSELOW_M)) | + ((-1 << KCOARSEHIGH_S) & KCOARSEHIGH_M) | + ((-127 << KCOARSELOW_S) & KCOARSELOW_M)); + OS_REG_WRITE(ah, 0x9868, + (reg9868 & ~(ADCSAT_ICOUNT_M | ADCSAT_THRESH_M)) | + ((2 << ADCSAT_ICOUNT_S) & ADCSAT_ICOUNT_M) | + ((12 << ADCSAT_THRESH_S) & ADCSAT_THRESH_M)); + + /* Wait for AGC changes to be enacted */ + OS_DELAY(20); + + /* + * We disable RF mix/gain stages for the PGA to avoid a + * race condition that will occur with receiving a frame + * and performing the AGC calibration. This will be + * re-enabled at the end of offset cal. We turn off AGC + * writes during this write as it will go over the analog bus. + */ + OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) | 0x08000000); + OS_DELAY(10); /* wait for the AGC traffic to cease */ + OS_REG_WRITE(ah, 0x98D4, 0x21); + OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) & (~0x08000000)); + + /* wait to make sure that additional AGC traffic has quiesced */ + OS_DELAY(1000); + + /* AGC calibration (this was added to make the NF threshold check work) */ + OS_REG_WRITE(ah, AR_PHY_AGCCTL, + OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_CAL); + if (!ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: AGC calibration timeout\n", + __func__); + } + + /* Rewrite our AGC values we stored off earlier (return AGC to normal operation) */ + OS_REG_WRITE(ah, 0x9858, reg9858); + OS_REG_WRITE(ah, 0x985c, reg985c); + OS_REG_WRITE(ah, 0x9868, reg9868); + + /* Perform noise floor and set status */ + if (!ar5210CalNoiseFloor(ah, ichan)) { + /* + * Delay 5ms before retrying the noise floor - + * just to make sure. We're in an error + * condition here + */ + HALDEBUG(ah, HAL_DEBUG_NFCAL | HAL_DEBUG_PERCAL, + "%s: Performing 2nd Noise Cal\n", __func__); + OS_DELAY(5000); + if (!ar5210CalNoiseFloor(ah, ichan)) + chan->ic_state |= IEEE80211_CHANSTATE_CWINT; + } + + /* Clear tx and rx disable bit */ + ar5210UpdateDiagReg(ah, + OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_TX | AR_DIAG_SW_DIS_RX)); + + /* Re-enable Beacons */ + OS_REG_WRITE(ah, AR_BEACON, regBeacon); + + *isCalDone = AH_TRUE; + + return AH_TRUE; +} + +HAL_BOOL +ar5210PerCalibration(struct ath_hal *ah, struct ieee80211_channel *chan, + HAL_BOOL *isIQdone) +{ + return ar5210PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone); +} + +HAL_BOOL +ar5210ResetCalValid(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + return AH_TRUE; +} + +/* + * Writes the given reset bit mask into the reset register + */ +static HAL_BOOL +ar5210SetResetReg(struct ath_hal *ah, uint32_t resetMask, u_int delay) +{ + uint32_t mask = resetMask ? resetMask : ~0; + HAL_BOOL rt; + + OS_REG_WRITE(ah, AR_RC, resetMask); + /* need to wait at least 128 clocks when reseting PCI before read */ + OS_DELAY(delay); + + resetMask &= AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC; + mask &= AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC; + rt = ath_hal_wait(ah, AR_RC, mask, resetMask); + if ((resetMask & AR_RC_RMAC) == 0) { + if (isBigEndian()) { + /* + * Set CFG, little-endian for descriptor accesses. + */ + mask = INIT_CONFIG_STATUS | AR_CFG_SWTD | AR_CFG_SWRD; + OS_REG_WRITE(ah, AR_CFG, mask); + } else + OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS); + } + return rt; +} + + +/* + * Returns: the pcdac value + */ +static uint8_t +getPcdac(struct ath_hal *ah, const struct tpcMap *pRD, uint8_t dBm) +{ + int32_t i; + int useNextEntry = AH_FALSE; + uint32_t interp; + + for (i = AR_TP_SCALING_ENTRIES - 1; i >= 0; i--) { + /* Check for exact entry */ + if (dBm == AR_I2DBM(i)) { + if (pRD->pcdac[i] != 63) + return pRD->pcdac[i]; + useNextEntry = AH_TRUE; + } else if (dBm + 1 == AR_I2DBM(i) && i > 0) { + /* Interpolate for between entry with a logish scale */ + if (pRD->pcdac[i] != 63 && pRD->pcdac[i-1] != 63) { + interp = (350 * (pRD->pcdac[i] - pRD->pcdac[i-1])) + 999; + interp = (interp / 1000) + pRD->pcdac[i-1]; + return interp; + } + useNextEntry = AH_TRUE; + } else if (useNextEntry == AH_TRUE) { + /* Grab the next lowest */ + if (pRD->pcdac[i] != 63) + return pRD->pcdac[i]; + } + } + + /* Return the lowest Entry if we haven't returned */ + for (i = 0; i < AR_TP_SCALING_ENTRIES; i++) + if (pRD->pcdac[i] != 63) + return pRD->pcdac[i]; + + /* No value to return from table */ +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: empty transmit power table?\n", __func__); +#endif + return 1; +} + +/* + * Find or interpolates the gainF value from the table ptr. + */ +static uint8_t +getGainF(struct ath_hal *ah, const struct tpcMap *pRD, + uint8_t pcdac, uint8_t *dBm) +{ + uint32_t interp; + int low, high, i; + + low = high = -1; + + for (i = 0; i < AR_TP_SCALING_ENTRIES; i++) { + if(pRD->pcdac[i] == 63) + continue; + if (pcdac == pRD->pcdac[i]) { + *dBm = AR_I2DBM(i); + return pRD->gainF[i]; /* Exact Match */ + } + if (pcdac > pRD->pcdac[i]) + low = i; + if (pcdac < pRD->pcdac[i]) { + high = i; + if (low == -1) { + *dBm = AR_I2DBM(i); + /* PCDAC is lower than lowest setting */ + return pRD->gainF[i]; + } + break; + } + } + if (i >= AR_TP_SCALING_ENTRIES && low == -1) { + /* No settings were found */ +#ifdef AH_DEBUG + ath_hal_printf(ah, + "%s: no valid entries in the pcdac table: %d\n", + __func__, pcdac); +#endif + return 63; + } + if (i >= AR_TP_SCALING_ENTRIES) { + /* PCDAC setting was above the max setting in the table */ + *dBm = AR_I2DBM(low); + return pRD->gainF[low]; + } + /* Only exact if table has no missing entries */ + *dBm = (low + high) + 3; + + /* + * Perform interpolation between low and high values to find gainF + * linearly scale the pcdac between low and high + */ + interp = ((pcdac - pRD->pcdac[low]) * 1000) / + (pRD->pcdac[high] - pRD->pcdac[low]); + /* + * Multiply the scale ratio by the gainF difference + * (plus a rnd up factor) + */ + interp = ((interp * (pRD->gainF[high] - pRD->gainF[low])) + 999) / 1000; + + /* Add ratioed gain_f to low gain_f value */ + return interp + pRD->gainF[low]; +} + +HAL_BOOL +ar5210SetTxPowerLimit(struct ath_hal *ah, uint32_t limit) +{ + AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, AR5210_MAX_RATE_POWER); + /* XXX flush to h/w */ + return AH_TRUE; +} + +/* + * Get TXPower values and set them in the radio + */ +static HAL_BOOL +setupPowerSettings(struct ath_hal *ah, const struct ieee80211_channel *chan, + uint8_t cp[17]) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + const HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + uint8_t gainFRD, gainF36, gainF48, gainF54; + uint8_t dBmRD, dBm36, dBm48, dBm54, dontcare; + uint32_t rd, group; + const struct tpcMap *pRD; + + /* Set OB/DB Values regardless of channel */ + cp[15] = (ee->ee_biasCurrents >> 4) & 0x7; + cp[16] = ee->ee_biasCurrents & 0x7; + + if (freq < 5170 || freq > 5320) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u\n", + __func__, freq); + return AH_FALSE; + } + + HALASSERT(ee->ee_version >= AR_EEPROM_VER1 && + ee->ee_version < AR_EEPROM_VER3); + + /* Match regulatory domain */ + for (rd = 0; rd < AR_REG_DOMAINS_MAX; rd++) + if (AH_PRIVATE(ah)->ah_currentRD == ee->ee_regDomain[rd]) + break; + if (rd == AR_REG_DOMAINS_MAX) { +#ifdef AH_DEBUG + ath_hal_printf(ah, + "%s: no calibrated regulatory domain matches the " + "current regularly domain (0x%0x)\n", __func__, + AH_PRIVATE(ah)->ah_currentRD); +#endif + return AH_FALSE; + } + group = ((freq - 5170) / 10); + + if (group > 11) { + /* Pull 5.29 into the 5.27 group */ + group--; + } + + /* Integer divide will set group from 0 to 4 */ + group = group / 3; + pRD = &ee->ee_tpc[group]; + + /* Set PC DAC Values */ + cp[14] = pRD->regdmn[rd]; + cp[9] = AH_MIN(pRD->regdmn[rd], pRD->rate36); + cp[8] = AH_MIN(pRD->regdmn[rd], pRD->rate48); + cp[7] = AH_MIN(pRD->regdmn[rd], pRD->rate54); + + /* Find Corresponding gainF values for RD, 36, 48, 54 */ + gainFRD = getGainF(ah, pRD, pRD->regdmn[rd], &dBmRD); + gainF36 = getGainF(ah, pRD, cp[9], &dBm36); + gainF48 = getGainF(ah, pRD, cp[8], &dBm48); + gainF54 = getGainF(ah, pRD, cp[7], &dBm54); + + /* Power Scale if requested */ + if (AH_PRIVATE(ah)->ah_tpScale != HAL_TP_SCALE_MAX) { + static const uint16_t tpcScaleReductionTable[5] = + { 0, 3, 6, 9, AR5210_MAX_RATE_POWER }; + uint16_t tpScale; + + tpScale = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale]; + if (dBmRD < tpScale+3) + dBmRD = 3; /* min */ + else + dBmRD -= tpScale; + cp[14] = getPcdac(ah, pRD, dBmRD); + gainFRD = getGainF(ah, pRD, cp[14], &dontcare); + dBm36 = AH_MIN(dBm36, dBmRD); + cp[9] = getPcdac(ah, pRD, dBm36); + gainF36 = getGainF(ah, pRD, cp[9], &dontcare); + dBm48 = AH_MIN(dBm48, dBmRD); + cp[8] = getPcdac(ah, pRD, dBm48); + gainF48 = getGainF(ah, pRD, cp[8], &dontcare); + dBm54 = AH_MIN(dBm54, dBmRD); + cp[7] = getPcdac(ah, pRD, dBm54); + gainF54 = getGainF(ah, pRD, cp[7], &dontcare); + } + /* Record current dBm at rate 6 */ + AH_PRIVATE(ah)->ah_maxPowerLevel = 2*dBmRD; + + cp[13] = cp[12] = cp[11] = cp[10] = cp[14]; + + /* Set GainF Values */ + cp[0] = gainFRD - gainF54; + cp[1] = gainFRD - gainF48; + cp[2] = gainFRD - gainF36; + /* 9, 12, 18, 24 have no gain_delta from 6 */ + cp[3] = cp[4] = cp[5] = cp[6] = 0; + return AH_TRUE; +} + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + */ +HAL_BOOL +ar5210SetTransmitPower(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) + static const uint32_t pwr_regs_start[17] = { + 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xf0000000, + 0xcc000000, 0x00000000, 0x00000000, + 0x00000000, 0x0a000000, 0x000000e2, + 0x0a000020, 0x01000002, 0x01000018, + 0x40000000, 0x00000418 + }; + uint16_t i; + uint8_t cp[sizeof(ar5k0007_pwrSettings)]; + uint32_t pwr_regs[17]; + + OS_MEMCPY(pwr_regs, pwr_regs_start, sizeof(pwr_regs)); + OS_MEMCPY(cp, ar5k0007_pwrSettings, sizeof(cp)); + + /* Check the EEPROM tx power calibration settings */ + if (!setupPowerSettings(ah, chan, cp)) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: unable to setup power settings\n", + __func__); +#endif + return AH_FALSE; + } + if (cp[15] < 1 || cp[15] > 5) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: OB out of range (%u)\n", + __func__, cp[15]); +#endif + return AH_FALSE; + } + if (cp[16] < 1 || cp[16] > 5) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: DB out of range (%u)\n", + __func__, cp[16]); +#endif + return AH_FALSE; + } + + /* reverse bits of the transmit power array */ + for (i = 0; i < 7; i++) + cp[i] = ath_hal_reverseBits(cp[i], 5); + for (i = 7; i < 15; i++) + cp[i] = ath_hal_reverseBits(cp[i], 6); + + /* merge transmit power values into the register - quite gross */ + pwr_regs[0] |= ((cp[1] << 5) & 0xE0) | (cp[0] & 0x1F); + pwr_regs[1] |= ((cp[3] << 7) & 0x80) | ((cp[2] << 2) & 0x7C) | + ((cp[1] >> 3) & 0x03); + pwr_regs[2] |= ((cp[4] << 4) & 0xF0) | ((cp[3] >> 1) & 0x0F); + pwr_regs[3] |= ((cp[6] << 6) & 0xC0) | ((cp[5] << 1) & 0x3E) | + ((cp[4] >> 4) & 0x01); + pwr_regs[4] |= ((cp[7] << 3) & 0xF8) | ((cp[6] >> 2) & 0x07); + pwr_regs[5] |= ((cp[9] << 7) & 0x80) | ((cp[8] << 1) & 0x7E) | + ((cp[7] >> 5) & 0x01); + pwr_regs[6] |= ((cp[10] << 5) & 0xE0) | ((cp[9] >> 1) & 0x1F); + pwr_regs[7] |= ((cp[11] << 3) & 0xF8) | ((cp[10] >> 3) & 0x07); + pwr_regs[8] |= ((cp[12] << 1) & 0x7E) | ((cp[11] >> 5) & 0x01); + pwr_regs[9] |= ((cp[13] << 5) & 0xE0); + pwr_regs[10] |= ((cp[14] << 3) & 0xF8) | ((cp[13] >> 3) & 0x07); + pwr_regs[11] |= ((cp[14] >> 5) & 0x01); + + /* Set OB */ + pwr_regs[8] |= (ath_hal_reverseBits(cp[15], 3) << 7) & 0x80; + pwr_regs[9] |= (ath_hal_reverseBits(cp[15], 3) >> 1) & 0x03; + + /* Set DB */ + pwr_regs[9] |= (ath_hal_reverseBits(cp[16], 3) << 2) & 0x1C; + + /* Write the registers */ + for (i = 0; i < N(pwr_regs)-1; i++) + OS_REG_WRITE(ah, 0x0000989c, pwr_regs[i]); + /* last write is a flush */ + OS_REG_WRITE(ah, 0x000098d4, pwr_regs[i]); + + return AH_TRUE; +#undef N +} + +/* + * Takes the MHz channel value and sets the Channel value + * + * ASSUMES: Writes enabled to analog bus before AGC is active + * or by disabling the AGC. + */ +static HAL_BOOL +ar5210SetChannel(struct ath_hal *ah, struct ieee80211_channel *chan) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + uint32_t data; + + /* Set the Channel */ + data = ath_hal_reverseBits((freq - 5120)/10, 5); + data = (data << 1) | 0x41; + OS_REG_WRITE(ah, AR_PHY(0x27), data); + OS_REG_WRITE(ah, AR_PHY(0x30), 0); + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +int16_t +ar5210GetNoiseFloor(struct ath_hal *ah) +{ + int16_t nf; + + nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + return nf; +} + +#define NORMAL_NF_THRESH (-72) +/* + * Peform the noisefloor calibration and check for + * any constant channel interference + * + * Returns: TRUE for a successful noise floor calibration; else FALSE + */ +HAL_BOOL +ar5210CalNoiseFloor(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan) +{ + int32_t nf, nfLoops; + + /* Calibrate the noise floor */ + OS_REG_WRITE(ah, AR_PHY_AGCCTL, + OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_NF); + + /* Do not read noise floor until it has done the first update */ + if (!ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_NF, 0)) { +#ifdef ATH_HAL_DEBUG + ath_hal_printf(ah, " -PHY NF Reg state: 0x%x\n", + OS_REG_READ(ah, AR_PHY_AGCCTL)); + ath_hal_printf(ah, " -MAC Reset Reg state: 0x%x\n", + OS_REG_READ(ah, AR_RC)); + ath_hal_printf(ah, " -PHY Active Reg state: 0x%x\n", + OS_REG_READ(ah, AR_PHY_ACTIVE)); +#endif /* ATH_HAL_DEBUG */ + return AH_FALSE; + } + + nf = 0; + /* Keep checking until the floor is below the threshold or the nf is done */ + for (nfLoops = 0; ((nfLoops < 21) && (nf > NORMAL_NF_THRESH)); nfLoops++) { + OS_DELAY(1000); /* Sleep for 1 ms */ + nf = ar5210GetNoiseFloor(ah); + } + + if (nf > NORMAL_NF_THRESH) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Bad noise cal %d\n", + __func__, nf); + ichan->rawNoiseFloor = 0; + return AH_FALSE; + } + ichan->rawNoiseFloor = nf; + return AH_TRUE; +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + */ +int16_t +ar5210GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + return 0; +} + +HAL_RFGAIN +ar5210GetRfgain(struct ath_hal *ah) +{ + return HAL_RFGAIN_INACTIVE; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210_xmit.c b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_xmit.c new file mode 100644 index 0000000..d376996 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210_xmit.c @@ -0,0 +1,670 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210phy.h" +#include "ar5210/ar5210desc.h" + +/* + * Set the properties of the tx queue with the parameters + * from qInfo. The queue must previously have been setup + * with a call to ar5210SetupTxQueue. + */ +HAL_BOOL +ar5210SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo); +} + +/* + * Return the properties for the specified tx queue. + */ +HAL_BOOL +ar5210GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]); +} + +/* + * Allocate and initialize a tx DCU/QCU combination. + */ +int +ar5210SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + int q; + + switch (type) { + case HAL_TX_QUEUE_BEACON: + q = 2; + break; + case HAL_TX_QUEUE_CAB: + q = 1; + break; + case HAL_TX_QUEUE_DATA: + q = 0; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad tx queue type %u\n", + __func__, type); + return -1; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + + qi = &ahp->ah_txq[q]; + if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n", + __func__, q); + return -1; + } + OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); + qi->tqi_type = type; + if (qInfo == AH_NULL) { + /* by default enable OK+ERR+DESC+URN interrupts */ + qi->tqi_qflags = + HAL_TXQ_TXOKINT_ENABLE + | HAL_TXQ_TXERRINT_ENABLE + | HAL_TXQ_TXDESCINT_ENABLE + | HAL_TXQ_TXURNINT_ENABLE + ; + qi->tqi_aifs = INIT_AIFS; + qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ + qi->tqi_shretry = INIT_SH_RETRY; + qi->tqi_lgretry = INIT_LG_RETRY; + } else + (void) ar5210SetTxQueueProps(ah, q, qInfo); + /* NB: must be followed by ar5210ResetTxQueue */ + return q; +} + +/* + * Free a tx DCU/QCU combination. + */ +HAL_BOOL +ar5210ReleaseTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_FALSE; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q); + + qi->tqi_type = HAL_TX_QUEUE_INACTIVE; + ahp->ah_txOkInterruptMask &= ~(1 << q); + ahp->ah_txErrInterruptMask &= ~(1 << q); + ahp->ah_txDescInterruptMask &= ~(1 << q); + ahp->ah_txEolInterruptMask &= ~(1 << q); + ahp->ah_txUrnInterruptMask &= ~(1 << q); + + return AH_TRUE; +#undef N +} + +HAL_BOOL +ar5210ResetTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + HAL_TX_QUEUE_INFO *qi; + uint32_t cwMin; + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_FALSE; + } + + /* + * Ignore any non-data queue(s). + */ + if (qi->tqi_type != HAL_TX_QUEUE_DATA) + return AH_TRUE; + + /* Set turbo mode / base mode parameters on or off */ + if (IEEE80211_IS_CHAN_TURBO(chan)) { + OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME_TURBO); + OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT_TURBO); + OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY_TURBO); + OS_REG_WRITE(ah, AR_IFS0, + ((INIT_SIFS_TURBO + qi->tqi_aifs * INIT_SLOT_TIME_TURBO) + << AR_IFS0_DIFS_S) + | INIT_SIFS_TURBO); + OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL_TURBO); + OS_REG_WRITE(ah, AR_PHY(17), + (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x38); + OS_REG_WRITE(ah, AR_PHY_FRCTL, + AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | + AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | + AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | + 0x2020 | + AR_PHY_TURBO_MODE | AR_PHY_TURBO_SHORT); + } else { + OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME); + OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT); + OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY); + OS_REG_WRITE(ah, AR_IFS0, + ((INIT_SIFS + qi->tqi_aifs * INIT_SLOT_TIME) + << AR_IFS0_DIFS_S) + | INIT_SIFS); + OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL); + OS_REG_WRITE(ah, AR_PHY(17), + (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x1C); + OS_REG_WRITE(ah, AR_PHY_FRCTL, + AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | + AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | + AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | 0x1020); + } + + if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) + cwMin = INIT_CWMIN; + else + cwMin = qi->tqi_cwmin; + + /* Set cwmin and retry limit values */ + OS_REG_WRITE(ah, AR_RETRY_LMT, + (cwMin << AR_RETRY_LMT_CW_MIN_S) + | SM(INIT_SLG_RETRY, AR_RETRY_LMT_SLG_RETRY) + | SM(INIT_SSH_RETRY, AR_RETRY_LMT_SSH_RETRY) + | SM(qi->tqi_lgretry, AR_RETRY_LMT_LG_RETRY) + | SM(qi->tqi_shretry, AR_RETRY_LMT_SH_RETRY) + ); + + if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) + ahp->ah_txOkInterruptMask |= 1 << q; + else + ahp->ah_txOkInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) + ahp->ah_txErrInterruptMask |= 1 << q; + else + ahp->ah_txErrInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE) + ahp->ah_txDescInterruptMask |= 1 << q; + else + ahp->ah_txDescInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) + ahp->ah_txEolInterruptMask |= 1 << q; + else + ahp->ah_txEolInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) + ahp->ah_txUrnInterruptMask |= 1 << q; + else + ahp->ah_txUrnInterruptMask &= ~(1 << q); + + return AH_TRUE; +} + +/* + * Get the TXDP for the "main" data queue. Needs to be extended + * for multiple Q functionality + */ +uint32_t +ar5210GetTxDP(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + + HALASSERT(q < HAL_NUM_TX_QUEUES); + + qi = &ahp->ah_txq[q]; + switch (qi->tqi_type) { + case HAL_TX_QUEUE_DATA: + return OS_REG_READ(ah, AR_TXDP0); + case HAL_TX_QUEUE_INACTIVE: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", + __func__, q); + /* fall thru... */ + default: + break; + } + return 0xffffffff; +} + +/* + * Set the TxDP for the "main" data queue. + */ +HAL_BOOL +ar5210SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + + HALASSERT(q < HAL_NUM_TX_QUEUES); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u 0x%x\n", + __func__, q, txdp); + qi = &ahp->ah_txq[q]; + switch (qi->tqi_type) { + case HAL_TX_QUEUE_DATA: +#ifdef AH_DEBUG + /* + * Make sure that TXE is deasserted before setting the + * TXDP. If TXE is still asserted, setting TXDP will + * have no effect. + */ + if (OS_REG_READ(ah, AR_CR) & AR_CR_TXE0) + ath_hal_printf(ah, "%s: TXE asserted; AR_CR=0x%x\n", + __func__, OS_REG_READ(ah, AR_CR)); +#endif + OS_REG_WRITE(ah, AR_TXDP0, txdp); + break; + case HAL_TX_QUEUE_BEACON: + case HAL_TX_QUEUE_CAB: + OS_REG_WRITE(ah, AR_TXDP1, txdp); + break; + case HAL_TX_QUEUE_INACTIVE: + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + /* fall thru... */ + default: + return AH_FALSE; + } + return AH_TRUE; +} + +/* + * Update Tx FIFO trigger level. + * + * Set bIncTrigLevel to TRUE to increase the trigger level. + * Set bIncTrigLevel to FALSE to decrease the trigger level. + * + * Returns TRUE if the trigger level was updated + */ +HAL_BOOL +ar5210UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel) +{ + uint32_t curTrigLevel; + HAL_INT ints = ar5210GetInterrupts(ah); + + /* + * Disable chip interrupts. This is because halUpdateTxTrigLevel + * is called from both ISR and non-ISR contexts. + */ + (void) ar5210SetInterrupts(ah, ints &~ HAL_INT_GLOBAL); + curTrigLevel = OS_REG_READ(ah, AR_TRIG_LEV); + if (bIncTrigLevel){ + /* increase the trigger level */ + curTrigLevel = curTrigLevel + + ((MAX_TX_FIFO_THRESHOLD - curTrigLevel) / 2); + } else { + /* decrease the trigger level if not already at the minimum */ + if (curTrigLevel > MIN_TX_FIFO_THRESHOLD) { + /* decrease the trigger level */ + curTrigLevel--; + } else { + /* no update to the trigger level */ + /* re-enable chip interrupts */ + ar5210SetInterrupts(ah, ints); + return AH_FALSE; + } + } + /* Update the trigger level */ + OS_REG_WRITE(ah, AR_TRIG_LEV, curTrigLevel); + /* re-enable chip interrupts */ + ar5210SetInterrupts(ah, ints); + return AH_TRUE; +} + +/* + * Set Transmit Enable bits for the specified queues. + */ +HAL_BOOL +ar5210StartTxDma(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + + HALASSERT(q < HAL_NUM_TX_QUEUES); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + qi = &ahp->ah_txq[q]; + switch (qi->tqi_type) { + case HAL_TX_QUEUE_DATA: + OS_REG_WRITE(ah, AR_CR, AR_CR_TXE0); + break; + case HAL_TX_QUEUE_CAB: + OS_REG_WRITE(ah, AR_CR, AR_CR_TXE1); /* enable altq xmit */ + OS_REG_WRITE(ah, AR_BCR, + AR_BCR_TQ1V | AR_BCR_BDMAE | AR_BCR_TQ1FV); + break; + case HAL_TX_QUEUE_BEACON: + /* XXX add CR_BCR_BCMD if IBSS mode */ + OS_REG_WRITE(ah, AR_BCR, AR_BCR_TQ1V | AR_BCR_BDMAE); + break; + case HAL_TX_QUEUE_INACTIVE: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", + __func__, q); + /* fal thru... */ + default: + return AH_FALSE; + } + return AH_TRUE; +} + +uint32_t +ar5210NumTxPending(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + uint32_t v; + + HALASSERT(q < HAL_NUM_TX_QUEUES); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + qi = &ahp->ah_txq[q]; + switch (qi->tqi_type) { + case HAL_TX_QUEUE_DATA: + v = OS_REG_READ(ah, AR_CFG); + return MS(v, AR_CFG_TXCNT); + case HAL_TX_QUEUE_INACTIVE: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", + __func__, q); + /* fall thru... */ + default: + break; + } + return 0; +} + +/* + * Stop transmit on the specified queue + */ +HAL_BOOL +ar5210StopTxDma(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + + HALASSERT(q < HAL_NUM_TX_QUEUES); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + qi = &ahp->ah_txq[q]; + switch (qi->tqi_type) { + case HAL_TX_QUEUE_DATA: { + int i; + OS_REG_WRITE(ah, AR_CR, AR_CR_TXD0); + for (i = 0; i < 1000; i++) { + if ((OS_REG_READ(ah, AR_CFG) & AR_CFG_TXCNT) == 0) + break; + OS_DELAY(10); + } + OS_REG_WRITE(ah, AR_CR, 0); + return (i < 1000); + } + case HAL_TX_QUEUE_BEACON: + return ath_hal_wait(ah, AR_BSR, AR_BSR_TXQ1F, 0); + case HAL_TX_QUEUE_INACTIVE: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", + __func__, q); + /* fall thru... */ + default: + break; + } + return AH_FALSE; +} + +/* + * Descriptor Access Functions + */ + +#define VALID_PKT_TYPES \ + ((1<ds_ctl0 = (pktLen & AR_FrameLen) + | (txRate0 << AR_XmitRate_S) + | ((hdrLen << AR_HdrLen_S) & AR_HdrLen) + | frtype + | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0) + | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0) + | (antMode ? AR_AntModeXmit : 0) + ; + if (keyIx != HAL_TXKEYIX_INVALID) { + ads->ds_ctl1 = (keyIx << AR_EncryptKeyIdx_S) & AR_EncryptKeyIdx; + ads->ds_ctl0 |= AR_EncryptKeyValid; + } else + ads->ds_ctl1 = 0; + if (flags & HAL_TXDESC_RTSENA) { + ads->ds_ctl0 |= AR_RTSCTSEnable; + ads->ds_ctl1 |= (rtsctsDuration << AR_RTSDuration_S) + & AR_RTSDuration; + } + return AH_TRUE; +} + +HAL_BOOL +ar5210SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int txRate1, u_int txTries1, + u_int txRate2, u_int txTries2, + u_int txRate3, u_int txTries3) +{ + (void) ah; (void) ds; + (void) txRate1; (void) txTries1; + (void) txRate2; (void) txTries2; + (void) txRate3; (void) txTries3; + return AH_FALSE; +} + +void +ar5210IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + ads->ds_ctl0 |= AR_TxInterReq; +} + +HAL_BOOL +ar5210FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, + HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, u_int descId, + u_int qcuId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + uint32_t segLen = segLenList[0]; + + HALASSERT((segLen &~ AR_BufLen) == 0); + + ds->ds_data = bufAddrList[0]; + + if (firstSeg) { + /* + * First descriptor, don't clobber xmit control data + * setup by ar5210SetupTxDesc. + */ + ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More); + } else if (lastSeg) { /* !firstSeg && lastSeg */ + /* + * Last descriptor in a multi-descriptor frame, + * copy the transmit parameters from the first + * frame for processing on completion. + */ + ads->ds_ctl0 = AR5210DESC_CONST(ds0)->ds_ctl0; + ads->ds_ctl1 = segLen; + } else { /* !firstSeg && !lastSeg */ + /* + * Intermediate descriptor in a multi-descriptor frame. + */ + ads->ds_ctl0 = 0; + ads->ds_ctl1 = segLen | AR_More; + } + ads->ds_status0 = ads->ds_status1 = 0; + return AH_TRUE; +} + +/* + * Processing of HW TX descriptor. + */ +HAL_STATUS +ar5210ProcTxDesc(struct ath_hal *ah, + struct ath_desc *ds, struct ath_tx_status *ts) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + if ((ads->ds_status1 & AR_Done) == 0) + return HAL_EINPROGRESS; + + /* Update software copies of the HW status */ + ts->ts_seqnum = ads->ds_status1 & AR_SeqNum; + ts->ts_tstamp = MS(ads->ds_status0, AR_SendTimestamp); + ts->ts_status = 0; + if ((ads->ds_status0 & AR_FrmXmitOK) == 0) { + if (ads->ds_status0 & AR_ExcessiveRetries) + ts->ts_status |= HAL_TXERR_XRETRY; + if (ads->ds_status0 & AR_Filtered) + ts->ts_status |= HAL_TXERR_FILT; + if (ads->ds_status0 & AR_FIFOUnderrun) + ts->ts_status |= HAL_TXERR_FIFO; + } + ts->ts_rate = MS(ads->ds_ctl0, AR_XmitRate); + ts->ts_rssi = MS(ads->ds_status1, AR_AckSigStrength); + ts->ts_shortretry = MS(ads->ds_status0, AR_ShortRetryCnt); + ts->ts_longretry = MS(ads->ds_status0, AR_LongRetryCnt); + ts->ts_antenna = 0; /* NB: don't know */ + ts->ts_finaltsi = 0; + + return HAL_OK; +} + +/* + * Determine which tx queues need interrupt servicing. + * STUB. + */ +void +ar5210GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs) +{ + return; +} + +/* + * Retrieve the rate table from the given TX completion descriptor + */ +HAL_BOOL +ar5210GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries) +{ + return AH_FALSE; +} + +/* + * Set the TX descriptor link pointer + */ +void +ar5210SetTxDescLink(struct ath_hal *ah, void *ds, uint32_t link) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + ads->ds_link = link; +} + +/* + * Get the TX descriptor link pointer + */ +void +ar5210GetTxDescLink(struct ath_hal *ah, void *ds, uint32_t *link) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + *link = ads->ds_link; +} + +/* + * Get a pointer to the TX descriptor link pointer + */ +void +ar5210GetTxDescLinkPtr(struct ath_hal *ah, void *ds, uint32_t **linkptr) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + *linkptr = &ads->ds_link; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210desc.h b/sys/external/isc/atheros_hal/dist/ar5210/ar5210desc.h new file mode 100644 index 0000000..da5c51f --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210desc.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _DEV_ATH_AR5210DESC_H +#define _DEV_ATH_AR5210DESC_H + +/* + * Defintions for the DMA descriptors used by the Atheros + * AR5210/AR5211 and AR5110 Wireless Lan controller parts. + */ + +/* DMA descriptors */ +struct ar5210_desc { + uint32_t ds_link; /* link pointer */ + uint32_t ds_data; /* data buffer pointer */ + uint32_t ds_ctl0; /* DMA control 0 */ + uint32_t ds_ctl1; /* DMA control 1 */ + uint32_t ds_status0; /* DMA status 0 */ + uint32_t ds_status1; /* DMA status 1 */ +} __packed; +#define AR5210DESC(_ds) ((struct ar5210_desc *)(_ds)) +#define AR5210DESC_CONST(_ds) ((const struct ar5210_desc *)(_ds)) + +/* TX ds_ctl0 */ +#define AR_FrameLen 0x00000fff /* frame length */ +#define AR_HdrLen 0x0003f000 /* header length */ +#define AR_HdrLen_S 12 +#define AR_XmitRate 0x003c0000 /* txrate */ +#define AR_XmitRate_S 18 +#define AR_Rate_6M 0xb +#define AR_Rate_9M 0xf +#define AR_Rate_12M 0xa +#define AR_Rate_18M 0xe +#define AR_Rate_24M 0x9 +#define AR_Rate_36M 0xd +#define AR_Rate_48M 0x8 +#define AR_Rate_54M 0xc +#define AR_RTSCTSEnable 0x00400000 /* RTS/CTS enable */ +#define AR_LongPkt 0x00800000 /* long packet indication */ +#define AR_ClearDestMask 0x01000000 /* Clear destination mask bit */ +#define AR_AntModeXmit 0x02000000 /* TX antenna seslection */ +#define AR_FrmType 0x1c000000 /* frame type indication */ +#define AR_FrmType_S 26 +#define AR_Frm_Normal 0x00000000 /* normal frame */ +#define AR_Frm_ATIM 0x04000000 /* ATIM frame */ +#define AR_Frm_PSPOLL 0x08000000 /* PS poll frame */ +#define AR_Frm_NoDelay 0x0c000000 /* no delay data */ +#define AR_Frm_PIFS 0x10000000 /* PIFS data */ +#define AR_TxInterReq 0x20000000 /* TX interrupt request */ +#define AR_EncryptKeyValid 0x40000000 /* EncryptKeyIdx is valid */ + +/* TX ds_ctl1 */ +#define AR_BufLen 0x00000fff /* data buffer length */ +#define AR_More 0x00001000 /* more desc in this frame */ +#define AR_EncryptKeyIdx 0x0007e000 /* ecnrypt key table index */ +#define AR_EncryptKeyIdx_S 13 +#define AR_RTSDuration 0xfff80000 /* lower 13bit of duration */ +#define AR_RTSDuration_S 19 + +/* RX ds_ctl1 */ +/* AR_BufLen 0x00000fff data buffer length */ +#define AR_RxInterReq 0x00002000 /* RX interrupt request */ + +/* TX ds_status0 */ +#define AR_FrmXmitOK 0x00000001 /* TX success */ +#define AR_ExcessiveRetries 0x00000002 /* excessive retries */ +#define AR_FIFOUnderrun 0x00000004 /* TX FIFO underrun */ +#define AR_Filtered 0x00000008 /* TX filter indication */ +/* NB: the spec has the Short+Long retry counts reversed */ +#define AR_LongRetryCnt 0x000000f0 /* long retry count */ +#define AR_LongRetryCnt_S 4 +#define AR_ShortRetryCnt 0x00000f00 /* short retry count */ +#define AR_ShortRetryCnt_S 8 +#define AR_SendTimestamp 0xffff0000 /* TX timestamp */ +#define AR_SendTimestamp_S 16 + +/* RX ds_status0 */ +#define AR_DataLen 0x00000fff /* RX data length */ +/* AR_More 0x00001000 more desc in this frame */ +#define AR_RcvAntenna 0x00004000 /* received on ant 1 */ +#define AR_RcvRate 0x00078000 /* reception rate */ +#define AR_RcvRate_S 15 +#define AR_RcvSigStrength 0x07f80000 /* receive signal strength */ +#define AR_RcvSigStrength_S 19 + +/* TX ds_status1 */ +#define AR_Done 0x00000001 /* descripter complete */ +#define AR_SeqNum 0x00001ffe /* TX sequence number */ +#define AR_AckSigStrength 0x001fe000 /* strength of ACK */ +#define AR_AckSigStrength_S 13 + +/* RX ds_status1 */ +/* AR_Done 0x00000001 descripter complete */ +#define AR_FrmRcvOK 0x00000002 /* frame reception success */ +#define AR_CRCErr 0x00000004 /* CRC error */ +#define AR_FIFOOverrun 0x00000008 /* RX FIFO overrun */ +#define AR_DecryptCRCErr 0x00000010 /* Decryption CRC fiailure */ +#define AR_PHYErr 0x000000e0 /* PHY error */ +#define AR_PHYErr_S 5 +#define AR_PHYErr_NoErr 0x00000000 /* No error */ +#define AR_PHYErr_Tim 0x00000020 /* Timing error */ +#define AR_PHYErr_Par 0x00000040 /* Parity error */ +#define AR_PHYErr_Rate 0x00000060 /* Illegal rate */ +#define AR_PHYErr_Len 0x00000080 /* Illegal length */ +#define AR_PHYErr_QAM 0x000000a0 /* 64 QAM rate */ +#define AR_PHYErr_Srv 0x000000c0 /* Service bit error */ +#define AR_PHYErr_TOR 0x000000e0 /* Transmit override receive */ +#define AR_KeyIdxValid 0x00000100 /* decryption key index valid */ +#define AR_KeyIdx 0x00007e00 /* Decryption key index */ +#define AR_KeyIdx_S 9 +#define AR_RcvTimestamp 0x0fff8000 /* timestamp */ +#define AR_RcvTimestamp_S 15 +#define AR_KeyCacheMiss 0x10000000 /* key cache miss indication */ + +#endif /* _DEV_ATH_AR5210DESC_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210phy.h b/sys/external/isc/atheros_hal/dist/ar5210/ar5210phy.h new file mode 100644 index 0000000..4ab3025 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210phy.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _DEV_ATH_AR5210PHY_H +#define _DEV_ATH_AR5210PHY_H + +/* + * Definitions for the PHY on the Atheros AR5210 parts. + */ + +/* PHY Registers */ +#define AR_PHY_BASE 0x9800 /* PHY register base */ +#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) + +#define AR_PHY_FRCTL 0x9804 /* PHY frame control */ +#define AR_PHY_TURBO_MODE 0x00000001 /* PHY turbo mode */ +#define AR_PHY_TURBO_SHORT 0x00000002 /* PHY turbo short symbol */ +#define AR_PHY_TIMING_ERR 0x01000000 /* Detect PHY timing error */ +#define AR_PHY_PARITY_ERR 0x02000000 /* Detect signal parity err */ +#define AR_PHY_ILLRATE_ERR 0x04000000 /* Detect PHY illegal rate */ +#define AR_PHY_ILLLEN_ERR 0x08000000 /* Detect PHY illegal length */ +#define AR_PHY_SERVICE_ERR 0x20000000 /* Detect PHY nonzero service */ +#define AR_PHY_TXURN_ERR 0x40000000 /* DetectPHY TX underrun */ +#define AR_PHY_FRCTL_BITS \ + "\20\1TURBO_MODE\2TURBO_SHORT\30TIMING_ERR\31PARITY_ERR\32ILLRATE_ERR"\ + "\33ILLEN_ERR\35SERVICE_ERR\36TXURN_ERR" + +#define AR_PHY_AGC 0x9808 /* PHY AGC command */ +#define AR_PHY_AGC_DISABLE 0x08000000 /* Disable PHY AGC */ +#define AR_PHY_AGC_BITS "\20\33DISABLE" + +#define AR_PHY_CHIPID 0x9818 /* PHY chip revision */ + +#define AR_PHY_ACTIVE 0x981c /* PHY activation */ +#define AR_PHY_ENABLE 0x00000001 /* activate PHY */ +#define AR_PHY_DISABLE 0x00000002 /* deactivate PHY */ +#define AR_PHY_ACTIVE_BITS "\20\1ENABLE\2DISABLE" + +#define AR_PHY_AGCCTL 0x9860 /* PHY calibration and noise floor */ +#define AR_PHY_AGC_CAL 0x00000001 /* PHY internal calibration */ +#define AR_PHY_AGC_NF 0x00000002 /* calc PHY noise-floor */ +#define AR_PHY_AGCCTL_BITS "\20\1CAL\2NF" + +#endif /* _DEV_ATH_AR5210PHY_H */ diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5210reg.h b/sys/external/isc/atheros_hal/dist/ar5210/ar5210reg.h new file mode 100644 index 0000000..16cd74e --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5210reg.h @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _DEV_ATH_AR5210REG_H +#define _DEV_ATH_AR5210REG_H + +/* + * Register defintions for the Atheros AR5210/5110 MAC/Basedband + * Processor for IEEE 802.11a 5-GHz Wireless LANs. + */ + +#ifndef PCI_VENDOR_ATHEROS +#define PCI_VENDOR_ATHEROS 0x168c +#endif +#define PCI_PRODUCT_ATHEROS_AR5210 0x0007 +#define PCI_PRODUCT_ATHEROS_AR5210_OLD 0x0004 + +/* DMA Registers */ +#define AR_TXDP0 0x0000 /* TX queue pointer 0 register */ +#define AR_TXDP1 0x0004 /* TX queue pointer 1 register */ +#define AR_CR 0x0008 /* Command register */ +#define AR_RXDP 0x000c /* RX queue descriptor ptr register */ +#define AR_CFG 0x0014 /* Configuration and status register */ +#define AR_ISR 0x001c /* Interrupt status register */ +#define AR_IMR 0x0020 /* Interrupt mask register */ +#define AR_IER 0x0024 /* Interrupt global enable register */ +#define AR_BCR 0x0028 /* Beacon control register */ +#define AR_BSR 0x002c /* Beacon status register */ +#define AR_TXCFG 0x0030 /* TX configuration register */ +#define AR_RXCFG 0x0034 /* RX configuration register */ +#define AR_MIBC 0x0040 /* MIB control register */ +#define AR_TOPS 0x0044 /* Timeout prescale register */ +#define AR_RXNOFRM 0x0048 /* RX no frame timeout register */ +#define AR_TXNOFRM 0x004c /* TX no frame timeout register */ +#define AR_RPGTO 0x0050 /* RX frame gap timeout register */ +#define AR_RFCNT 0x0054 /* RX frame count limit register */ +#define AR_MISC 0x0058 /* Misc control and status register */ +#define AR_RC 0x4000 /* Reset control */ +#define AR_SCR 0x4004 /* Sleep control */ +#define AR_INTPEND 0x4008 /* Interrupt pending */ +#define AR_SFR 0x400c /* Force sleep */ +#define AR_PCICFG 0x4010 /* PCI configuration */ +#define AR_GPIOCR 0x4014 /* GPIO configuration */ +#define AR_GPIODO 0x4018 /* GPIO data output */ +#define AR_GPIODI 0x401c /* GPIO data input */ +#define AR_SREV 0x4020 /* Silicon revision */ +/* EEPROM Access Registers */ +#define AR_EP_AIR_BASE 0x6000 /* EEPROM access initiation regs base */ +#define AR_EP_AIR(n) (AR_EP_AIR_BASE + (n)*4) +#define AR_EP_RDATA 0x6800 /* EEPROM read data register */ +#define AR_EP_STA 0x6c00 /* EEPROM access status register */ +/* PCU Registers */ +#define AR_STA_ID0 0x8000 /* Lower 32bits of MAC address */ +#define AR_STA_ID1 0x8004 /* Upper 16bits of MAC address */ +#define AR_BSS_ID0 0x8008 /* Lower 32bits of BSSID */ +#define AR_BSS_ID1 0x800c /* Upper 16bits of BSSID */ +#define AR_SLOT_TIME 0x8010 /* Length of a back-off */ +#define AR_TIME_OUT 0x8014 /* Timeout to wait for ACK and CTS */ +#define AR_RSSI_THR 0x8018 /* Beacon RSSI warning threshold */ +#define AR_RETRY_LMT 0x801c /* Short and long frame retry limit */ +#define AR_USEC 0x8020 /* Transmit latency */ +#define AR_BEACON 0x8024 /* Beacon control */ +#define AR_CFP_PERIOD 0x8028 /* CFP period */ +#define AR_TIMER0 0x802c /* Next beacon time */ +#define AR_TIMER1 0x8030 /* Next DMA beacon alert time */ +#define AR_TIMER2 0x8034 /* Next software beacon alert time */ +#define AR_TIMER3 0x8038 /* Next ATIM window time */ +#define AR_IFS0 0x8040 /* Protocol timers */ +#define AR_IFS1 0x8044 /* Protocol time and control */ +#define AR_CFP_DUR 0x8048 /* Maximum CFP duration */ +#define AR_RX_FILTER 0x804c /* Receive filter */ +#define AR_MCAST_FIL0 0x8050 /* Lower 32bits of mcast filter mask */ +#define AR_MCAST_FIL1 0x8054 /* Upper 16bits of mcast filter mask */ +#define AR_TX_MASK0 0x8058 /* Lower 32bits of TX mask */ +#define AR_TX_MASK1 0x805c /* Upper 16bits of TX mask */ +#define AR_CLR_TMASK 0x8060 /* Clear TX mask */ +#define AR_TRIG_LEV 0x8064 /* Minimum FIFO fill level before TX */ +#define AR_DIAG_SW 0x8068 /* PCU control */ +#define AR_TSF_L32 0x806c /* Lower 32bits of local clock */ +#define AR_TSF_U32 0x8070 /* Upper 32bits of local clock */ +#define AR_LAST_TSTP 0x8080 /* Lower 32bits of last beacon tstamp */ +#define AR_RETRY_CNT 0x8084 /* Current short or long retry cnt */ +#define AR_BACKOFF 0x8088 /* Back-off status */ +#define AR_NAV 0x808c /* Current NAV value */ +#define AR_RTS_OK 0x8090 /* RTS success counter */ +#define AR_RTS_FAIL 0x8094 /* RTS failure counter */ +#define AR_ACK_FAIL 0x8098 /* ACK failure counter */ +#define AR_FCS_FAIL 0x809c /* FCS failure counter */ +#define AR_BEACON_CNT 0x80a0 /* Valid beacon counter */ +#define AR_KEYTABLE_0 0x9000 /* Encryption key table */ +#define AR_KEYTABLE(n) (AR_KEYTABLE_0 + ((n)*32)) + +#define AR_CR_TXE0 0x00000001 /* TX queue 0 enable */ +#define AR_CR_TXE1 0x00000002 /* TX queue 1 enable */ +#define AR_CR_RXE 0x00000004 /* RX enable */ +#define AR_CR_TXD0 0x00000008 /* TX queue 0 disable */ +#define AR_CR_TXD1 0x00000010 /* TX queue 1 disable */ +#define AR_CR_RXD 0x00000020 /* RX disable */ +#define AR_CR_SWI 0x00000040 /* software interrupt */ +#define AR_CR_BITS \ + "\20\1TXE0\2TXE1\3RXE\4TXD0\5TXD1\6RXD\7SWI" + +#define AR_CFG_SWTD 0x00000001 /* BE for TX desc */ +#define AR_CFG_SWTB 0x00000002 /* BE for TX data */ +#define AR_CFG_SWRD 0x00000004 /* BE for RX desc */ +#define AR_CFG_SWRB 0x00000008 /* BE for RX data */ +#define AR_CFG_SWRG 0x00000010 /* BE for registers */ +#define AR_CFG_EEBS 0x00000200 /* EEPROM busy */ +#define AR_CFG_TXCNT 0x00007800 /* number of TX desc in Q */ +#define AR_CFG_TXCNT_S 11 +#define AR_CFG_TXFSTAT 0x00008000 /* TX DMA status */ +#define AR_CFG_TXFSTRT 0x00010000 /* re-enable TX DMA */ +#define AR_CFG_BITS \ + "\20\1SWTD\2SWTB\3SWRD\4SWRB\5SWRG\14EEBS\17TXFSTAT\20TXFSTRT" + +#define AR_ISR_RXOK_INT 0x00000001 /* RX frame OK */ +#define AR_ISR_RXDESC_INT 0x00000002 /* RX intr request */ +#define AR_ISR_RXERR_INT 0x00000004 /* RX error */ +#define AR_ISR_RXNOFRM_INT 0x00000008 /* no frame received */ +#define AR_ISR_RXEOL_INT 0x00000010 /* RX desc empty */ +#define AR_ISR_RXORN_INT 0x00000020 /* RX fifo overrun */ +#define AR_ISR_TXOK_INT 0x00000040 /* TX frame OK */ +#define AR_ISR_TXDESC_INT 0x00000080 /* TX intr request */ +#define AR_ISR_TXERR_INT 0x00000100 /* TX error */ +#define AR_ISR_TXNOFRM_INT 0x00000200 /* no frame transmitted */ +#define AR_ISR_TXEOL_INT 0x00000400 /* TX desc empty */ +#define AR_ISR_TXURN_INT 0x00000800 /* TX fifo underrun */ +#define AR_ISR_MIB_INT 0x00001000 /* MIB interrupt */ +#define AR_ISR_SWI_INT 0x00002000 /* software interrupt */ +#define AR_ISR_RXPHY_INT 0x00004000 /* PHY RX error */ +#define AR_ISR_RXKCM_INT 0x00008000 /* Key cache miss */ +#define AR_ISR_SWBA_INT 0x00010000 /* software beacon alert */ +#define AR_ISR_BRSSI_INT 0x00020000 /* beacon threshold */ +#define AR_ISR_BMISS_INT 0x00040000 /* beacon missed */ +#define AR_ISR_MCABT_INT 0x00100000 /* master cycle abort */ +#define AR_ISR_SSERR_INT 0x00200000 /* SERR on PCI */ +#define AR_ISR_DPERR_INT 0x00400000 /* Parity error on PCI */ +#define AR_ISR_GPIO_INT 0x01000000 /* GPIO interrupt */ +#define AR_ISR_BITS \ + "\20\1RXOK\2RXDESC\3RXERR\4RXNOFM\5RXEOL\6RXORN\7TXOK\10TXDESC"\ + "\11TXERR\12TXNOFRM\13TXEOL\14TXURN\15MIB\16SWI\17RXPHY\20RXKCM"\ + "\21SWBA\22BRSSI\23BMISS\24MCABT\25SSERR\26DPERR\27GPIO" + +#define AR_IMR_RXOK_INT 0x00000001 /* RX frame OK */ +#define AR_IMR_RXDESC_INT 0x00000002 /* RX intr request */ +#define AR_IMR_RXERR_INT 0x00000004 /* RX error */ +#define AR_IMR_RXNOFRM_INT 0x00000008 /* no frame received */ +#define AR_IMR_RXEOL_INT 0x00000010 /* RX desc empty */ +#define AR_IMR_RXORN_INT 0x00000020 /* RX fifo overrun */ +#define AR_IMR_TXOK_INT 0x00000040 /* TX frame OK */ +#define AR_IMR_TXDESC_INT 0x00000080 /* TX intr request */ +#define AR_IMR_TXERR_INT 0x00000100 /* TX error */ +#define AR_IMR_TXNOFRM_INT 0x00000200 /* no frame transmitted */ +#define AR_IMR_TXEOL_INT 0x00000400 /* TX desc empty */ +#define AR_IMR_TXURN_INT 0x00000800 /* TX fifo underrun */ +#define AR_IMR_MIB_INT 0x00001000 /* MIB interrupt */ +#define AR_IMR_SWI_INT 0x00002000 /* software interrupt */ +#define AR_IMR_RXPHY_INT 0x00004000 /* PHY RX error */ +#define AR_IMR_RXKCM_INT 0x00008000 /* Key cache miss */ +#define AR_IMR_SWBA_INT 0x00010000 /* software beacon alert */ +#define AR_IMR_BRSSI_INT 0x00020000 /* beacon threshold */ +#define AR_IMR_BMISS_INT 0x00040000 /* beacon missed */ +#define AR_IMR_MCABT_INT 0x00100000 /* master cycle abort */ +#define AR_IMR_SSERR_INT 0x00200000 /* SERR on PCI */ +#define AR_IMR_DPERR_INT 0x00400000 /* Parity error on PCI */ +#define AR_IMR_GPIO_INT 0x01000000 /* GPIO interrupt */ +#define AR_IMR_BITS AR_ISR_BITS + +#define AR_IER_DISABLE 0x00000000 /* pseudo-flag */ +#define AR_IER_ENABLE 0x00000001 /* global interrupt enable */ +#define AR_IER_BITS "\20\1ENABLE" + +#define AR_BCR_BCMD 0x00000001 /* ad hoc beacon mode */ +#define AR_BCR_BDMAE 0x00000002 /* beacon DMA enable */ +#define AR_BCR_TQ1FV 0x00000004 /* use TXQ1 for non-beacon */ +#define AR_BCR_TQ1V 0x00000008 /* TXQ1 valid for beacon */ +#define AR_BCR_BCGET 0x00000010 /* force a beacon fetch */ +#define AR_BCR_BITS "\20\1BCMD\2BDMAE\3TQ1FV\4TQ1V\5BCGET" + +#define AR_BSR_BDLYSW 0x00000001 /* software beacon delay */ +#define AR_BSR_BDLYDMA 0x00000002 /* DMA beacon delay */ +#define AR_BSR_TXQ1F 0x00000004 /* TXQ1 fetch */ +#define AR_BSR_ATIMDLY 0x00000008 /* ATIM delay */ +#define AR_BSR_SNPBCMD 0x00000100 /* snapshot of BCMD */ +#define AR_BSR_SNPBDMAE 0x00000200 /* snapshot of BDMAE */ +#define AR_BSR_SNPTQ1FV 0x00000400 /* snapshot of TQ1FV */ +#define AR_BSR_SNPTQ1V 0x00000800 /* snapshot of TQ1V */ +#define AR_BSR_SNAPPEDBCRVALID 0x00001000 /* snapshot of BCR are valid */ +#define AR_BSR_SWBA_CNT 0x00ff0000 /* software beacon alert cnt */ +#define AR_BSR_BITS \ + "\20\1BDLYSW\2BDLYDMA\3TXQ1F\4ATIMDLY\11SNPBCMD\12SNPBDMAE"\ + "\13SNPTQ1FV\14SNPTQ1V\15SNAPPEDBCRVALID" + +#define AR_TXCFG_SDMAMR 0x00000007 /* DMA burst size 2^(2+x) */ +#define AR_TXCFG_TXFSTP 0x00000008 /* Stop TX DMA on filtered */ +#define AR_TXCFG_TXFULL 0x00000070 /* TX DMA desc Q full thresh */ +#define AR_TXCFG_TXCONT_EN 0x00000080 /* Enable continuous TX mode */ +#define AR_TXCFG_BITS "\20\3TXFSTP\7TXCONT_EN" + +#define AR_RXCFG_SDMAMW 0x00000007 /* DMA burst size 2^(2+x) */ +#define AR_RXCFG_ZLFDMA 0x00000010 /* enable zero length DMA */ + +/* DMA sizes used for both AR_TXCFG_SDMAMR and AR_RXCFG_SDMAMW */ +#define AR_DMASIZE_4B 0 /* DMA size 4 bytes */ +#define AR_DMASIZE_8B 1 /* DMA size 8 bytes */ +#define AR_DMASIZE_16B 2 /* DMA size 16 bytes */ +#define AR_DMASIZE_32B 3 /* DMA size 32 bytes */ +#define AR_DMASIZE_64B 4 /* DMA size 64 bytes */ +#define AR_DMASIZE_128B 5 /* DMA size 128 bytes */ +#define AR_DMASIZE_256B 6 /* DMA size 256 bytes */ +#define AR_DMASIZE_512B 7 /* DMA size 512 bytes */ + +#define AR_MIBC_COW 0x00000001 /* counter overflow warning */ +#define AR_MIBC_FMC 0x00000002 /* freeze MIB counters */ +#define AR_MIBC_CMC 0x00000004 /* clear MIB counters */ +#define AR_MIBC_MCS 0x00000008 /* MIB counter strobe */ + +#define AR_RFCNT_RFCL 0x0000000f /* RX frame count limit */ + +#define AR_MISC_LED_DECAY 0x001c0000 /* LED decay rate */ +#define AR_MISC_LED_BLINK 0x00e00000 /* LED blink rate */ + +#define AR_RC_RPCU 0x00000001 /* PCU Warm Reset */ +#define AR_RC_RDMA 0x00000002 /* DMA Warm Reset */ +#define AR_RC_RMAC 0x00000004 /* MAC Warm Reset */ +#define AR_RC_RPHY 0x00000008 /* PHY Warm Reset */ +#define AR_RC_RPCI 0x00000010 /* PCI Core Warm Reset */ +#define AR_RC_BITS "\20\1RPCU\2RDMA\3RMAC\4RPHY\5RPCI" + +#define AR_SCR_SLDUR 0x0000ffff /* sleep duration */ +#define AR_SCR_SLE 0x00030000 /* sleep enable */ +#define AR_SCR_SLE_S 16 +/* + * The previous values for the following three defines were: + * + * AR_SCR_SLE_WAKE 0x00000000 + * AR_SCR_SLE_SLP 0x00010000 + * AR_SCR_SLE_ALLOW 0x00020000 + * + * However, these have been pre-shifted with AR_SCR_SLE_S. The + * OS_REG_READ() macro would attempt to shift them again, effectively + * shifting out any of the set bits completely. + */ +#define AR_SCR_SLE_WAKE 0 /* force wake */ +#define AR_SCR_SLE_SLP 1 /* force sleep */ +#define AR_SCR_SLE_ALLOW 2 /* allow to control sleep */ +#define AR_SCR_BITS "\20\20SLE_SLP\21SLE_ALLOW" + +#define AR_INTPEND_IP 0x00000001 /* interrupt pending */ +#define AR_INTPEND_BITS "\20\1IP" + +#define AR_SFR_SF 0x00000001 /* force sleep immediately */ + +#define AR_PCICFG_EEPROMSEL 0x00000001 /* EEPROM access enable */ +#define AR_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable */ +#define AR_PCICFG_LED_PEND 0x00000020 /* LED for assoc pending */ +#define AR_PCICFG_LED_ACT 0x00000040 /* LED for assoc active */ +#define AR_PCICFG_SL_INTEN 0x00000800 /* Enable sleep intr */ +#define AR_PCICFG_LED_BCTL 0x00001000 /* LED blink for local act */ +#define AR_PCICFG_SL_INPEN 0x00002800 /* sleep even intr pending */ +#define AR_PCICFG_SPWR_DN 0x00010000 /* sleep indication */ +#define AR_PCICFG_BITS \ + "\20\1EEPROMSEL\3CLKRUNEN\5LED_PEND\6LED_ACT\13SL_INTEN"\ + "\14LED_BCTL\20SPWR_DN" + +#define AR_GPIOCR_IN(n) (0<<((n)*2)) /* input-only */ +#define AR_GPIOCR_OUT0(n) (1<<((n)*2)) /* output-only if GPIODO = 0 */ +#define AR_GPIOCR_OUT1(n) (2<<((n)*2)) /* output-only if GPIODO = 1 */ +#define AR_GPIOCR_OUT(n) (3<<((n)*2)) /* always output */ +#define AR_GPIOCR_ALL(n) (3<<((n)*2)) /* all bits for pin */ +#define AR_GPIOCR_INT_SEL(n) ((n)<<12) /* GPIO interrupt pin select */ +#define AR_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */ +#define AR_GPIOCR_INT_SELL 0x00000000 /* Interrupt if pin is low */ +#define AR_GPIOCR_INT_SELH 0x00010000 /* Interrupt if pin is high */ + +#define AR_SREV_CRETE 4 /* Crete 1st version */ +#define AR_SREV_CRETE_MS 5 /* Crete FCS version */ +#define AR_SREV_CRETE_23 8 /* Crete version 2.3 */ + +#define AR_EP_STA_RDERR 0x00000001 /* read error */ +#define AR_EP_STA_RDCMPLT 0x00000002 /* read complete */ +#define AR_EP_STA_WRERR 0x00000004 /* write error */ +#define AR_EP_STA_WRCMPLT 0x00000008 /* write complete */ +#define AR_EP_STA_BITS \ + "\20\1RDERR\2RDCMPLT\3WRERR\4WRCMPLT" + +#define AR_STA_ID1_AP 0x00010000 /* Access Point Operation */ +#define AR_STA_ID1_ADHOC 0x00020000 /* ad hoc Operation */ +#define AR_STA_ID1_PWR_SV 0x00040000 /* power save report enable */ +#define AR_STA_ID1_NO_KEYSRCH 0x00080000 /* key table search disable */ +#define AR_STA_ID1_NO_PSPOLL 0x00100000 /* auto PS-POLL disable */ +#define AR_STA_ID1_PCF 0x00200000 /* PCF observation enable */ +#define AR_STA_ID1_DESC_ANTENNA 0x00400000 /* use antenna in TX desc */ +#define AR_STA_ID1_DEFAULT_ANTENNA 0x00800000 /* toggle default antenna */ +#define AR_STA_ID1_ACKCTS_6MB 0x01000000 /* use 6Mbps for ACK/CTS */ +#define AR_STA_ID1_BITS \ + "\20\20AP\21ADHOC\22PWR_SV\23NO_KEYSRCH\24NO_PSPOLL\25PCF"\ + "\26DESC_ANTENNA\27DEFAULT_ANTENNA\30ACKCTS_6MB" + +#define AR_BSS_ID1_AID 0xffff0000 /* association ID */ +#define AR_BSS_ID1_AID_S 16 + +#define AR_TIME_OUT_ACK 0x00001fff /* ACK timeout */ +#define AR_TIME_OUT_ACK_S 0 +#define AR_TIME_OUT_CTS 0x1fff0000 /* CTS timeout */ +#define AR_TIME_OUT_CTS_S 16 + +#define AR_RSSI_THR_BM_THR 0x00000700 /* missed beacon threshold */ +#define AR_RSSI_THR_BM_THR_S 8 + +#define AR_RETRY_LMT_SH_RETRY 0x0000000f /* short frame retry limit */ +#define AR_RETRY_LMT_SH_RETRY_S 0 +#define AR_RETRY_LMT_LG_RETRY 0x000000f0 /* long frame retry limit */ +#define AR_RETRY_LMT_LG_RETRY_S 4 +#define AR_RETRY_LMT_SSH_RETRY 0x00003f00 /* short station retry limit */ +#define AR_RETRY_LMT_SSH_RETRY_S 8 +#define AR_RETRY_LMT_SLG_RETRY 0x000fc000 /* long station retry limit */ +#define AR_RETRY_LMT_SLG_RETRY_S 14 +#define AR_RETRY_LMT_CW_MIN 0x3ff00000 /* minimum contention window */ +#define AR_RETRY_LMT_CW_MIN_S 20 + +#define AR_USEC_1 0x0000007f /* number of clk in 1us */ +#define AR_USEC_1_S 0 +#define AR_USEC_32 0x00003f80 /* number of 32MHz clk in 1us */ +#define AR_USEC_32_S 7 +#define AR_USEC_TX_LATENCY 0x000fc000 /* transmit latency in us */ +#define AR_USEC_TX_LATENCY_S 14 +#define AR_USEC_RX_LATENCY 0x03f00000 /* receive latency in us */ +#define AR_USEC_RX_LATENCY_S 20 + +#define AR_BEACON_PERIOD 0x0000ffff /* beacon period in TU/ms */ +#define AR_BEACON_PERIOD_S 0 +#define AR_BEACON_TIM 0x007f0000 /* byte offset */ +#define AR_BEACON_TIM_S 16 +#define AR_BEACON_EN 0x00800000 /* beacon transmission enable */ +#define AR_BEACON_RESET_TSF 0x01000000 /* TSF reset oneshot */ +#define AR_BEACON_BITS "\20\27ENABLE\30RESET_TSF" + +#define AR_IFS0_SIFS 0x000007ff /* SIFS in core clock cycles */ +#define AR_IFS0_SIFS_S 0 +#define AR_IFS0_DIFS 0x007ff800 /* DIFS in core clock cycles */ +#define AR_IFS0_DIFS_S 11 + +#define AR_IFS1_PIFS 0x00000fff /* Programmable IFS */ +#define AR_IFS1_PIFS_S 0 +#define AR_IFS1_EIFS 0x03fff000 /* EIFS in core clock cycles */ +#define AR_IFS1_EIFS_S 12 +#define AR_IFS1_CS_EN 0x04000000 /* carrier sense enable */ + +#define AR_RX_FILTER_UNICAST 0x00000001 /* unicast frame enable */ +#define AR_RX_FILTER_MULTICAST 0x00000002 /* multicast frame enable */ +#define AR_RX_FILTER_BROADCAST 0x00000004 /* broadcast frame enable */ +#define AR_RX_FILTER_CONTROL 0x00000008 /* control frame enable */ +#define AR_RX_FILTER_BEACON 0x00000010 /* beacon frame enable */ +#define AR_RX_FILTER_PROMISCUOUS 0x00000020 /* promiscuous receive enable */ +#define AR_RX_FILTER_BITS \ + "\20\1UCAST\2MCAST\3BCAST\4CONTROL\5BEACON\6PROMISC" + +#define AR_DIAG_SW_DIS_WEP_ACK 0x00000001 /* disable ACK if no key found*/ +#define AR_DIAG_SW_DIS_ACK 0x00000002 /* disable ACK generation */ +#define AR_DIAG_SW_DIS_CTS 0x00000004 /* disable CTS generation */ +#define AR_DIAG_SW_DIS_ENC 0x00000008 /* encryption disable */ +#define AR_DIAG_SW_DIS_DEC 0x00000010 /* decryption disable */ +#define AR_DIAG_SW_DIS_TX 0x00000020 /* TX disable */ +#define AR_DIAG_SW_DIS_RX 0x00000040 /* RX disable */ +#define AR_DIAG_SW_LOOP_BACK 0x00000080 /* TX data loopback enable */ +#define AR_DIAG_SW_CORR_FCS 0x00000100 /* corrupt FCS enable */ +#define AR_DIAG_SW_CHAN_INFO 0x00000200 /* channel information enable */ +#define AR_DIAG_SW_EN_SCRAM_SEED 0x00000400 /* use fixed scrambler seed */ +#define AR_DIAG_SW_SCVRAM_SEED 0x0003f800 /* fixed scrambler seed */ +#define AR_DIAG_SW_DIS_SEQ_INC 0x00040000 /* seq increment disable */ +#define AR_DIAG_SW_FRAME_NV0 0x00080000 /* accept frame vers != 0 */ +#define AR_DIAG_SW_DIS_CRYPTO (AR_DIAG_SW_DIS_ENC | AR_DIAG_SW_DIS_DEC) +#define AR_DIAG_SW_BITS \ + "\20\1DIS_WEP_ACK\2DIS_ACK\3DIS_CTS\4DIS_ENC\5DIS_DEC\6DIS_TX"\ + "\7DIS_RX\10LOOP_BACK\11CORR_FCS\12CHAN_INFO\13EN_SCRAM_SEED"\ + "\22DIS_SEQ_INC\24FRAME_NV0" + +#define AR_RETRY_CNT_SSH 0x0000003f /* current short retry count */ +#define AR_RETRY_CNT_SLG 0x00000fc0 /* current long retry count */ + +#define AR_BACKOFF_CW 0x000003ff /* current contention window */ +#define AR_BACKOFF_CNT 0x03ff0000 /* backoff count */ + +#define AR_KEYTABLE_KEY0(n) (AR_KEYTABLE(n) + 0) /* key bit 0-31 */ +#define AR_KEYTABLE_KEY1(n) (AR_KEYTABLE(n) + 4) /* key bit 32-47 */ +#define AR_KEYTABLE_KEY2(n) (AR_KEYTABLE(n) + 8) /* key bit 48-79 */ +#define AR_KEYTABLE_KEY3(n) (AR_KEYTABLE(n) + 12) /* key bit 80-95 */ +#define AR_KEYTABLE_KEY4(n) (AR_KEYTABLE(n) + 16) /* key bit 96-127 */ +#define AR_KEYTABLE_TYPE(n) (AR_KEYTABLE(n) + 20) /* key type */ +#define AR_KEYTABLE_TYPE_40 0x00000000 /* 40 bit key */ +#define AR_KEYTABLE_TYPE_104 0x00000001 /* 104 bit key */ +#define AR_KEYTABLE_TYPE_128 0x00000003 /* 128 bit key */ +#define AR_KEYTABLE_MAC0(n) (AR_KEYTABLE(n) + 24) /* MAC address 1-32 */ +#define AR_KEYTABLE_MAC1(n) (AR_KEYTABLE(n) + 28) /* MAC address 33-47 */ +#define AR_KEYTABLE_VALID 0x00008000 /* key and MAC address valid */ + +#endif /* _DEV_ATH_AR5210REG_H */ diff --git a/sys/external/isc/atheros_hal/dist/ar5210/ar5k_0007.ini b/sys/external/isc/atheros_hal/dist/ar5210/ar5k_0007.ini new file mode 100644 index 0000000..b536483 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5210/ar5k_0007.ini @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2004 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + + /* crete register init */ + { 0x00009800, 0x00000047 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0x09848ea6 }, + { 0x00009810, 0x3d32e000 }, + { 0x00009814, 0x0000076b }, + { 0x0000981c, 0x00000000 }, + { 0x00009820, 0x02020200 }, + { 0x00009824, 0x00000e0e }, + { 0x00009828, 0x0a020201 }, + { 0x0000982c, 0x00036ffc }, + { 0x00009830, 0x00000000 }, + { 0x00009834, 0x00000e0e }, + { 0x00009838, 0x00000007 }, + { 0x0000983c, 0x00020100 }, + { 0x00009840, 0x89630000 }, + { 0x00009844, 0x1372169c }, + { 0x00009848, 0x0018b633 }, + { 0x0000984c, 0x1284613c }, + { 0x00009850, 0x0de8b8e0 }, + { 0x00009854, 0x00074859 }, + { 0x00009858, 0x7e80beba }, + { 0x0000985c, 0x313a665e }, + { 0x00009860, 0x00001d08 }, + { 0x00009864, 0x0001ce00 }, + { 0x00009868, 0x409a4190 }, + { 0x00009870, 0x0000000f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x00000004 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00800000 }, + { 0x00009910, 0x00000003 }, + + + /* bb gain table */ + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000020 }, + { 0x00009b08, 0x00000010 }, + { 0x00009b0c, 0x00000030 }, + { 0x00009b10, 0x00000008 }, + { 0x00009b14, 0x00000028 }, + { 0x00009b18, 0x00000028 }, + { 0x00009b1c, 0x00000004 }, + { 0x00009b20, 0x00000024 }, + { 0x00009b24, 0x00000014 }, + { 0x00009b28, 0x00000034 }, + { 0x00009b2c, 0x0000000c }, + { 0x00009b30, 0x0000002c }, + { 0x00009b34, 0x00000002 }, + { 0x00009b38, 0x00000022 }, + { 0x00009b3c, 0x00000012 }, + { 0x00009b40, 0x00000032 }, + { 0x00009b44, 0x0000000a }, + { 0x00009b48, 0x0000002a }, + { 0x00009b4c, 0x00000001 }, + { 0x00009b50, 0x00000021 }, + { 0x00009b54, 0x00000011 }, + { 0x00009b58, 0x00000031 }, + { 0x00009b5c, 0x00000009 }, + { 0x00009b60, 0x00000029 }, + { 0x00009b64, 0x00000005 }, + { 0x00009b68, 0x00000025 }, + { 0x00009b6c, 0x00000015 }, + { 0x00009b70, 0x00000035 }, + { 0x00009b74, 0x0000000d }, + { 0x00009b78, 0x0000002d }, + { 0x00009b7c, 0x00000003 }, + { 0x00009b80, 0x00000023 }, + { 0x00009b84, 0x00000013 }, + { 0x00009b88, 0x00000033 }, + { 0x00009b8c, 0x0000000b }, + { 0x00009b90, 0x0000002b }, + { 0x00009b94, 0x00000007 }, + { 0x00009b98, 0x00000027 }, + { 0x00009b9c, 0x00000017 }, + { 0x00009ba0, 0x00000037 }, + { 0x00009ba4, 0x0000000f }, + { 0x00009ba8, 0x0000002f }, + { 0x00009bac, 0x0000002f }, + { 0x00009bb0, 0x0000002f }, + { 0x00009bb4, 0x0000002f }, + { 0x00009bb8, 0x0000002f }, + { 0x00009bbc, 0x0000002f }, + { 0x00009bc0, 0x0000002f }, + { 0x00009bc4, 0x0000002f }, + { 0x00009bc8, 0x0000002f }, + { 0x00009bcc, 0x0000002f }, + { 0x00009bd0, 0x0000002f }, + { 0x00009bd4, 0x0000002f }, + { 0x00009bd8, 0x0000002f }, + { 0x00009bdc, 0x0000002f }, + { 0x00009be0, 0x0000002f }, + { 0x00009be4, 0x0000002f }, + { 0x00009be8, 0x0000002f }, + { 0x00009bec, 0x0000002f }, + { 0x00009bf0, 0x0000002f }, + { 0x00009bf4, 0x0000002f }, + { 0x00009bf8, 0x0000002f }, + { 0x00009bfc, 0x0000002f }, + + /* rf gain table */ + { 0x00009a00, 0x0000001d }, + { 0x00009a04, 0x0000005d }, + { 0x00009a08, 0x0000009d }, + { 0x00009a0c, 0x000000dd }, + { 0x00009a10, 0x0000011d }, + { 0x00009a14, 0x00000021 }, + { 0x00009a18, 0x00000061 }, + { 0x00009a1c, 0x000000a1 }, + { 0x00009a20, 0x000000e1 }, + { 0x00009a24, 0x00000031 }, + { 0x00009a28, 0x00000071 }, + { 0x00009a2c, 0x000000b1 }, + { 0x00009a30, 0x0000001c }, + { 0x00009a34, 0x0000005c }, + { 0x00009a38, 0x00000029 }, + { 0x00009a3c, 0x00000069 }, + { 0x00009a40, 0x000000a9 }, + { 0x00009a44, 0x00000020 }, + { 0x00009a48, 0x00000019 }, + { 0x00009a4c, 0x00000059 }, + { 0x00009a50, 0x00000099 }, + { 0x00009a54, 0x00000030 }, + { 0x00009a58, 0x00000005 }, + { 0x00009a5c, 0x00000025 }, + { 0x00009a60, 0x00000065 }, + { 0x00009a64, 0x000000a5 }, + { 0x00009a68, 0x00000028 }, + { 0x00009a6c, 0x00000068 }, + { 0x00009a70, 0x0000001f }, + { 0x00009a74, 0x0000001e }, + { 0x00009a78, 0x00000018 }, + { 0x00009a7c, 0x00000058 }, + { 0x00009a80, 0x00000098 }, + { 0x00009a84, 0x00000003 }, + { 0x00009a88, 0x00000004 }, + { 0x00009a8c, 0x00000044 }, + { 0x00009a90, 0x00000084 }, + { 0x00009a94, 0x00000013 }, + { 0x00009a98, 0x00000012 }, + { 0x00009a9c, 0x00000052 }, + { 0x00009aa0, 0x00000092 }, + { 0x00009aa4, 0x000000d2 }, + { 0x00009aa8, 0x0000002b }, + { 0x00009aac, 0x0000002a }, + { 0x00009ab0, 0x0000006a }, + { 0x00009ab4, 0x000000aa }, + { 0x00009ab8, 0x0000001b }, + { 0x00009abc, 0x0000001a }, + { 0x00009ac0, 0x0000005a }, + { 0x00009ac4, 0x0000009a }, + { 0x00009ac8, 0x000000da }, + { 0x00009acc, 0x00000006 }, + { 0x00009ad0, 0x00000006 }, + { 0x00009ad4, 0x00000006 }, + { 0x00009ad8, 0x00000006 }, + { 0x00009adc, 0x00000006 }, + { 0x00009ae0, 0x00000006 }, + { 0x00009ae4, 0x00000006 }, + { 0x00009ae8, 0x00000006 }, + { 0x00009aec, 0x00000006 }, + { 0x00009af0, 0x00000006 }, + { 0x00009af4, 0x00000006 }, + { 0x00009af8, 0x00000006 }, + { 0x00009afc, 0x00000006 }, + + /* fez register init */ + { 0x000098d4, 0x00000020 }, + { 0x000098cc, 0x00000004 }, + { 0x000098c8, 0x00060106 }, + { 0x0000989c, 0x0000006d }, + { 0x000098c0, 0x00000000 }, + { 0x000098d0, 0x00000014 }, diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211.h b/sys/external/isc/atheros_hal/dist/ar5211/ar5211.h new file mode 100644 index 0000000..cdc33e1 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211.h @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AR5211_H_ +#define _ATH_AR5211_H_ + +#include "ah_eeprom.h" + +#define AR5211_MAGIC 0x19570405 + +/* Classes for WME streams */ +#define AC_BK 0 +#define AC_BE 1 +#define AC_VI 2 +#define AC_VO 3 + +/* DCU Transmit Filter macros */ +#define CALC_MMR(dcu, idx) \ + ( (4 * dcu) + (idx < 32 ? 0 : (idx < 64 ? 1 : (idx < 96 ? 2 : 3))) ) +#define TXBLK_FROM_MMR(mmr) \ + (AR_D_TXBLK_BASE + ((mmr & 0x1f) << 6) + ((mmr & 0x20) >> 3)) +#define CALC_TXBLK_ADDR(dcu, idx) (TXBLK_FROM_MMR(CALC_MMR(dcu, idx))) +#define CALC_TXBLK_VALUE(idx) (1 << (idx & 0x1f)) + +/* MAC register values */ + +#define INIT_INTERRUPT_MASK \ + ( AR_IMR_TXERR | AR_IMR_TXOK | AR_IMR_RXORN | \ + AR_IMR_RXERR | AR_IMR_RXOK | AR_IMR_TXURN | \ + AR_IMR_HIUERR ) +#define INIT_BEACON_CONTROL \ + ( (INIT_RESET_TSF << 24) | (INIT_BEACON_EN << 23) | \ + (INIT_TIM_OFFSET << 16) | INIT_BEACON_PERIOD ) + +#define INIT_CONFIG_STATUS 0x00000000 +#define INIT_RSSI_THR 0x00000700 /* Missed beacon counter initialized to 0x7 (max is 0xff) */ +#define INIT_IQCAL_LOG_COUNT_MAX 0xF +#define INIT_BCON_CNTRL_REG 0x00000000 + +#define INIT_BEACON_PERIOD 0xffff +#define INIT_TIM_OFFSET 0 +#define INIT_BEACON_EN 0 /* this should be set by AP only when it's ready */ +#define INIT_RESET_TSF 0 + +/* + * Various fifo fill before Tx start, in 64-byte units + * i.e. put the frame in the air while still DMAing + */ +#define MIN_TX_FIFO_THRESHOLD 0x1 +#define MAX_TX_FIFO_THRESHOLD ((IEEE80211_MAX_LEN / 64) + 1) +#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD + +/* + * Gain support. + */ +typedef struct _gainOptStep { + int16_t paramVal[4]; + int32_t stepGain; + int8_t stepName[16]; +} GAIN_OPTIMIZATION_STEP; + +typedef struct { + uint32_t numStepsInLadder; + uint32_t defaultStepNum; + GAIN_OPTIMIZATION_STEP optStep[10]; +} GAIN_OPTIMIZATION_LADDER; + +typedef struct { + uint32_t currStepNum; + uint32_t currGain; + uint32_t targetGain; + uint32_t loTrig; + uint32_t hiTrig; + uint32_t active; + const GAIN_OPTIMIZATION_STEP *currStep; +} GAIN_VALUES; + +enum { + RFGAIN_INACTIVE, + RFGAIN_READ_REQUESTED, + RFGAIN_NEED_CHANGE +}; + +/* + * Header Info - general parameters and + * values set for each chipset board solution + * that are programmed every reset + */ +struct ath_hal_5211 { + struct ath_hal_private ah_priv; /* base class */ + + GAIN_VALUES ah_gainValues; + + uint8_t ah_macaddr[IEEE80211_ADDR_LEN]; + uint8_t ah_bssid[IEEE80211_ADDR_LEN]; + + /* + * Runtime state. + */ + uint32_t ah_maskReg; /* copy of AR_IMR */ + uint32_t ah_txOkInterruptMask; + uint32_t ah_txErrInterruptMask; + uint32_t ah_txDescInterruptMask; + uint32_t ah_txEolInterruptMask; + uint32_t ah_txUrnInterruptMask; + HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; + HAL_ANT_SETTING ah_diversityControl; /* antenna setting */ + uint32_t ah_calibrationTime; + HAL_BOOL ah_bIQCalibration; + int ah_rfgainState; + uint32_t ah_tx6PowerInHalfDbm; /* power output for 6Mb tx */ + uint32_t ah_staId1Defaults; /* STA_ID1 default settings */ + uint32_t ah_beaconInterval; + uint32_t ah_rssiThr; /* RSSI_THR settings */ + + u_int ah_sifstime; /* user-specified sifs time */ + u_int ah_slottime; /* user-specified slot time */ + u_int ah_acktimeout; /* user-specified ack timeout */ + u_int ah_ctstimeout; /* user-specified cts timeout */ + /* + * RF Silent handling. + */ + uint32_t ah_gpioSelect; /* GPIO pin to use */ + uint32_t ah_polarity; /* polarity to disable RF */ + uint32_t ah_gpioBit; /* after init, prev value */ +}; +#define AH5211(ah) ((struct ath_hal_5211 *)(ah)) + +struct ath_hal; + +extern void ar5211Detach(struct ath_hal *); + +extern HAL_BOOL ar5211Reset(struct ath_hal *, HAL_OPMODE, + struct ieee80211_channel *, HAL_BOOL bChannelChange, + HAL_RESET_TYPE, + HAL_STATUS *); +extern HAL_BOOL ar5211PhyDisable(struct ath_hal *); +extern HAL_BOOL ar5211Disable(struct ath_hal *); +extern HAL_BOOL ar5211ChipReset(struct ath_hal *, + const struct ieee80211_channel *); +extern HAL_BOOL ar5211PerCalibration(struct ath_hal *, struct ieee80211_channel *, HAL_BOOL *); +extern HAL_BOOL ar5211PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); +extern HAL_BOOL ar5211ResetCalValid(struct ath_hal *ah, const struct ieee80211_channel *); +extern HAL_BOOL ar5211SetTxPowerLimit(struct ath_hal *, uint32_t limit); +extern HAL_BOOL ar5211CalNoiseFloor(struct ath_hal *, + const struct ieee80211_channel *); +extern HAL_BOOL ar5211SetAntennaSwitchInternal(struct ath_hal *, + HAL_ANT_SETTING, const struct ieee80211_channel *); +extern int16_t ar5211GetNfAdjust(struct ath_hal *, + const HAL_CHANNEL_INTERNAL *); +extern HAL_BOOL ar5211ResetDma(struct ath_hal *, HAL_OPMODE); +extern void ar5211InitializeGainValues(struct ath_hal *); +extern HAL_RFGAIN ar5211GetRfgain(struct ath_hal *); +extern void ar5211SetPCUConfig(struct ath_hal *); + +extern HAL_BOOL ar5211SetTxQueueProps(struct ath_hal *ah, int q, + const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ar5211GetTxQueueProps(struct ath_hal *ah, int q, + HAL_TXQ_INFO *qInfo); +extern int ar5211SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ar5211ReleaseTxQueue(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5211ResetTxQueue(struct ath_hal *ah, u_int q); +extern uint32_t ar5211GetTxDP(struct ath_hal *, u_int); +extern HAL_BOOL ar5211SetTxDP(struct ath_hal *, u_int, uint32_t txdp); +extern HAL_BOOL ar5211UpdateTxTrigLevel(struct ath_hal *, HAL_BOOL); +extern HAL_BOOL ar5211StartTxDma(struct ath_hal *, u_int); +extern HAL_BOOL ar5211StopTxDma(struct ath_hal *, u_int); +extern uint32_t ar5211NumTxPending(struct ath_hal *, u_int qnum); +extern HAL_BOOL ar5211IsTxQueueStopped(struct ath_hal *, u_int); +extern HAL_BOOL ar5211GetTransmitFilterIndex(struct ath_hal *, uint32_t); +extern HAL_BOOL ar5211SetupTxDesc(struct ath_hal *, struct ath_desc *, + u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, + u_int txRate0, u_int txTries0, + u_int keyIx, u_int antMode, u_int flags, + u_int rtsctsRate, u_int rtsctsDuration, + u_int compicvLen, u_int compivLen, u_int comp); +extern HAL_BOOL ar5211SetupXTxDesc(struct ath_hal *, struct ath_desc *, + u_int txRate1, u_int txRetries1, + u_int txRate2, u_int txRetries2, + u_int txRate3, u_int txRetries3); +extern HAL_BOOL ar5211FillTxDesc(struct ath_hal *, struct ath_desc *, + HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, + u_int descId, u_int qcuId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0); +extern HAL_STATUS ar5211ProcTxDesc(struct ath_hal *, + struct ath_desc *, struct ath_tx_status *); +extern void ar5211GetTxIntrQueue(struct ath_hal *ah, uint32_t *); +extern void ar5211IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); +extern HAL_BOOL ar5211GetTxCompletionRates(struct ath_hal *ah, + const struct ath_desc *ds0, int *rates, int *tries); +extern void ar5211SetTxDescLink(struct ath_hal *ah, void *ds, + uint32_t link); +extern void ar5211GetTxDescLink(struct ath_hal *ah, void *ds, + uint32_t *link); +extern void ar5211GetTxDescLinkPtr(struct ath_hal *ah, void *ds, + uint32_t **linkptr); + +extern uint32_t ar5211GetRxDP(struct ath_hal *, HAL_RX_QUEUE); +extern void ar5211SetRxDP(struct ath_hal *, uint32_t rxdp, HAL_RX_QUEUE); +extern void ar5211EnableReceive(struct ath_hal *); +extern HAL_BOOL ar5211StopDmaReceive(struct ath_hal *); +extern void ar5211StartPcuReceive(struct ath_hal *); +extern void ar5211StopPcuReceive(struct ath_hal *); +extern void ar5211SetMulticastFilter(struct ath_hal *, + uint32_t filter0, uint32_t filter1); +extern HAL_BOOL ar5211ClrMulticastFilterIndex(struct ath_hal *, uint32_t); +extern HAL_BOOL ar5211SetMulticastFilterIndex(struct ath_hal *, uint32_t); +extern uint32_t ar5211GetRxFilter(struct ath_hal *); +extern void ar5211SetRxFilter(struct ath_hal *, uint32_t); +extern HAL_BOOL ar5211SetupRxDesc(struct ath_hal *, struct ath_desc *, + uint32_t, u_int flags); +extern HAL_STATUS ar5211ProcRxDesc(struct ath_hal *, struct ath_desc *, + uint32_t, struct ath_desc *, uint64_t, + struct ath_rx_status *); + +extern void ar5211GetMacAddress(struct ath_hal *, uint8_t *); +extern HAL_BOOL ar5211SetMacAddress(struct ath_hal *ah, const uint8_t *); +extern void ar5211GetBssIdMask(struct ath_hal *, uint8_t *); +extern HAL_BOOL ar5211SetBssIdMask(struct ath_hal *, const uint8_t *); +extern HAL_BOOL ar5211EepromRead(struct ath_hal *, u_int off, uint16_t *data); +extern HAL_BOOL ar5211EepromWrite(struct ath_hal *, u_int off, uint16_t data); +extern HAL_BOOL ar5211SetRegulatoryDomain(struct ath_hal *, + uint16_t, HAL_STATUS *); +extern u_int ar5211GetWirelessModes(struct ath_hal *); +extern void ar5211EnableRfKill(struct ath_hal *); +extern uint32_t ar5211GpioGet(struct ath_hal *, uint32_t gpio); +extern void ar5211GpioSetIntr(struct ath_hal *, u_int, uint32_t ilevel); +extern HAL_BOOL ar5211GpioCfgOutput(struct ath_hal *, uint32_t gpio, + HAL_GPIO_MUX_TYPE); +extern HAL_BOOL ar5211GpioCfgInput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5211GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val); +extern void ar5211SetLedState(struct ath_hal *, HAL_LED_STATE); +extern u_int ar5211AntennaGet(struct ath_hal *); +extern void ar5211WriteAssocid(struct ath_hal *, + const uint8_t *bssid, uint16_t assocId); +extern uint64_t ar5211GetTsf64(struct ath_hal *); +extern uint32_t ar5211GetTsf32(struct ath_hal *); +extern void ar5211ResetTsf(struct ath_hal *); +extern uint32_t ar5211GetMaxTurboRate(struct ath_hal *); +extern uint32_t ar5211GetRandomSeed(struct ath_hal *); +extern HAL_BOOL ar5211DetectCardPresent(struct ath_hal *); +extern void ar5211UpdateMibCounters(struct ath_hal *, HAL_MIB_STATS *); +extern void ar5211EnableHwEncryption(struct ath_hal *); +extern void ar5211DisableHwEncryption(struct ath_hal *); +extern HAL_BOOL ar5211SetSlotTime(struct ath_hal *, u_int); +extern u_int ar5211GetSlotTime(struct ath_hal *); +extern HAL_BOOL ar5211SetAckTimeout(struct ath_hal *, u_int); +extern u_int ar5211GetAckTimeout(struct ath_hal *); +extern HAL_BOOL ar5211SetAckCTSRate(struct ath_hal *, u_int); +extern u_int ar5211GetAckCTSRate(struct ath_hal *); +extern HAL_BOOL ar5211SetCTSTimeout(struct ath_hal *, u_int); +extern u_int ar5211GetCTSTimeout(struct ath_hal *); +extern HAL_BOOL ar5211SetSifsTime(struct ath_hal *, u_int); +extern u_int ar5211GetSifsTime(struct ath_hal *); +extern HAL_BOOL ar5211SetDecompMask(struct ath_hal *, uint16_t, int); +extern void ar5211SetCoverageClass(struct ath_hal *, uint8_t, int); +extern uint32_t ar5211GetCurRssi(struct ath_hal *); +extern u_int ar5211GetDefAntenna(struct ath_hal *); +extern void ar5211SetDefAntenna(struct ath_hal *ah, u_int antenna); +extern HAL_ANT_SETTING ar5211GetAntennaSwitch(struct ath_hal *); +extern HAL_BOOL ar5211SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); +extern HAL_STATUS ar5211GetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, + uint32_t, uint32_t *); +extern HAL_BOOL ar5211SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, + uint32_t, uint32_t, HAL_STATUS *); +extern HAL_BOOL ar5211GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); +extern uint32_t ar5211Get11nExtBusy(struct ath_hal *); +extern HAL_BOOL ar5211GetMibCycleCounts(struct ath_hal *, + HAL_SURVEY_SAMPLE *); +extern void ar5211SetChainMasks(struct ath_hal *ah, uint32_t, uint32_t); + +extern void ar5211EnableDfs(struct ath_hal *, HAL_PHYERR_PARAM *); +extern void ar5211GetDfsThresh(struct ath_hal *, HAL_PHYERR_PARAM *); + +extern u_int ar5211GetKeyCacheSize(struct ath_hal *); +extern HAL_BOOL ar5211IsKeyCacheEntryValid(struct ath_hal *, uint16_t); +extern HAL_BOOL ar5211ResetKeyCacheEntry(struct ath_hal *, uint16_t entry); +extern HAL_BOOL ar5211SetKeyCacheEntry(struct ath_hal *, uint16_t entry, + const HAL_KEYVAL *, const uint8_t *mac, + int xorKey); +extern HAL_BOOL ar5211SetKeyCacheEntryMac(struct ath_hal *, + uint16_t, const uint8_t *); + +extern HAL_BOOL ar5211SetPowerMode(struct ath_hal *, uint32_t powerRequest, + int setChip); +extern HAL_POWER_MODE ar5211GetPowerMode(struct ath_hal *); + +extern void ar5211SetBeaconTimers(struct ath_hal *, + const HAL_BEACON_TIMERS *); +extern void ar5211BeaconInit(struct ath_hal *, uint32_t, uint32_t); +extern void ar5211SetStaBeaconTimers(struct ath_hal *, + const HAL_BEACON_STATE *); +extern void ar5211ResetStaBeaconTimers(struct ath_hal *); +extern uint64_t ar5211GetNextTBTT(struct ath_hal *); + +extern HAL_BOOL ar5211IsInterruptPending(struct ath_hal *); +extern HAL_BOOL ar5211GetPendingInterrupts(struct ath_hal *, HAL_INT *); +extern HAL_INT ar5211GetInterrupts(struct ath_hal *); +extern HAL_INT ar5211SetInterrupts(struct ath_hal *, HAL_INT ints); + +extern const HAL_RATE_TABLE *ar5211GetRateTable(struct ath_hal *, u_int mode); + +extern HAL_BOOL ar5211AniControl(struct ath_hal *, HAL_ANI_CMD, int ); +extern void ar5211RxMonitor(struct ath_hal *, const HAL_NODE_STATS *, + const struct ieee80211_channel *); +extern void ar5211AniPoll(struct ath_hal *, const struct ieee80211_channel *); +extern void ar5211MibEvent(struct ath_hal *, const HAL_NODE_STATS *); +#endif /* _ATH_AR5211_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211_attach.c b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_attach.c new file mode 100644 index 0000000..3416dc0 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_attach.c @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211phy.h" + +#include "ah_eeprom_v3.h" + +static HAL_BOOL ar5211GetChannelEdges(struct ath_hal *ah, + uint16_t flags, uint16_t *low, uint16_t *high); +static HAL_BOOL ar5211GetChipPowerLimits(struct ath_hal *ah, + struct ieee80211_channel *chan); + +static void ar5211ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, + HAL_BOOL power_off); +static void ar5211DisablePCIE(struct ath_hal *ah); + +static const struct ath_hal_private ar5211hal = {{ + .ah_magic = AR5211_MAGIC, + + .ah_getRateTable = ar5211GetRateTable, + .ah_detach = ar5211Detach, + + /* Reset Functions */ + .ah_reset = ar5211Reset, + .ah_phyDisable = ar5211PhyDisable, + .ah_disable = ar5211Disable, + .ah_configPCIE = ar5211ConfigPCIE, + .ah_disablePCIE = ar5211DisablePCIE, + .ah_setPCUConfig = ar5211SetPCUConfig, + .ah_perCalibration = ar5211PerCalibration, + .ah_perCalibrationN = ar5211PerCalibrationN, + .ah_resetCalValid = ar5211ResetCalValid, + .ah_setTxPowerLimit = ar5211SetTxPowerLimit, + .ah_getChanNoise = ath_hal_getChanNoise, + + /* Transmit functions */ + .ah_updateTxTrigLevel = ar5211UpdateTxTrigLevel, + .ah_setupTxQueue = ar5211SetupTxQueue, + .ah_setTxQueueProps = ar5211SetTxQueueProps, + .ah_getTxQueueProps = ar5211GetTxQueueProps, + .ah_releaseTxQueue = ar5211ReleaseTxQueue, + .ah_resetTxQueue = ar5211ResetTxQueue, + .ah_getTxDP = ar5211GetTxDP, + .ah_setTxDP = ar5211SetTxDP, + .ah_numTxPending = ar5211NumTxPending, + .ah_startTxDma = ar5211StartTxDma, + .ah_stopTxDma = ar5211StopTxDma, + .ah_setupTxDesc = ar5211SetupTxDesc, + .ah_setupXTxDesc = ar5211SetupXTxDesc, + .ah_fillTxDesc = ar5211FillTxDesc, + .ah_procTxDesc = ar5211ProcTxDesc, + .ah_getTxIntrQueue = ar5211GetTxIntrQueue, + .ah_reqTxIntrDesc = ar5211IntrReqTxDesc, + .ah_getTxCompletionRates = ar5211GetTxCompletionRates, + .ah_setTxDescLink = ar5211SetTxDescLink, + .ah_getTxDescLink = ar5211GetTxDescLink, + .ah_getTxDescLinkPtr = ar5211GetTxDescLinkPtr, + + /* RX Functions */ + .ah_getRxDP = ar5211GetRxDP, + .ah_setRxDP = ar5211SetRxDP, + .ah_enableReceive = ar5211EnableReceive, + .ah_stopDmaReceive = ar5211StopDmaReceive, + .ah_startPcuReceive = ar5211StartPcuReceive, + .ah_stopPcuReceive = ar5211StopPcuReceive, + .ah_setMulticastFilter = ar5211SetMulticastFilter, + .ah_setMulticastFilterIndex = ar5211SetMulticastFilterIndex, + .ah_clrMulticastFilterIndex = ar5211ClrMulticastFilterIndex, + .ah_getRxFilter = ar5211GetRxFilter, + .ah_setRxFilter = ar5211SetRxFilter, + .ah_setupRxDesc = ar5211SetupRxDesc, + .ah_procRxDesc = ar5211ProcRxDesc, + .ah_rxMonitor = ar5211RxMonitor, + .ah_aniPoll = ar5211AniPoll, + .ah_procMibEvent = ar5211MibEvent, + + /* Misc Functions */ + .ah_getCapability = ar5211GetCapability, + .ah_setCapability = ar5211SetCapability, + .ah_getDiagState = ar5211GetDiagState, + .ah_getMacAddress = ar5211GetMacAddress, + .ah_setMacAddress = ar5211SetMacAddress, + .ah_getBssIdMask = ar5211GetBssIdMask, + .ah_setBssIdMask = ar5211SetBssIdMask, + .ah_setRegulatoryDomain = ar5211SetRegulatoryDomain, + .ah_setLedState = ar5211SetLedState, + .ah_writeAssocid = ar5211WriteAssocid, + .ah_gpioCfgInput = ar5211GpioCfgInput, + .ah_gpioCfgOutput = ar5211GpioCfgOutput, + .ah_gpioGet = ar5211GpioGet, + .ah_gpioSet = ar5211GpioSet, + .ah_gpioSetIntr = ar5211GpioSetIntr, + .ah_getTsf32 = ar5211GetTsf32, + .ah_getTsf64 = ar5211GetTsf64, + .ah_resetTsf = ar5211ResetTsf, + .ah_detectCardPresent = ar5211DetectCardPresent, + .ah_updateMibCounters = ar5211UpdateMibCounters, + .ah_getRfGain = ar5211GetRfgain, + .ah_getDefAntenna = ar5211GetDefAntenna, + .ah_setDefAntenna = ar5211SetDefAntenna, + .ah_getAntennaSwitch = ar5211GetAntennaSwitch, + .ah_setAntennaSwitch = ar5211SetAntennaSwitch, + .ah_setSifsTime = ar5211SetSifsTime, + .ah_getSifsTime = ar5211GetSifsTime, + .ah_setSlotTime = ar5211SetSlotTime, + .ah_getSlotTime = ar5211GetSlotTime, + .ah_setAckTimeout = ar5211SetAckTimeout, + .ah_getAckTimeout = ar5211GetAckTimeout, + .ah_setAckCTSRate = ar5211SetAckCTSRate, + .ah_getAckCTSRate = ar5211GetAckCTSRate, + .ah_setCTSTimeout = ar5211SetCTSTimeout, + .ah_getCTSTimeout = ar5211GetCTSTimeout, + .ah_setDecompMask = ar5211SetDecompMask, + .ah_setCoverageClass = ar5211SetCoverageClass, + .ah_get11nExtBusy = ar5211Get11nExtBusy, + .ah_getMibCycleCounts = ar5211GetMibCycleCounts, + .ah_setChainMasks = ar5211SetChainMasks, + .ah_enableDfs = ar5211EnableDfs, + .ah_getDfsThresh = ar5211GetDfsThresh, + /* XXX procRadarEvent */ + /* XXX isFastClockEnabled */ + + /* Key Cache Functions */ + .ah_getKeyCacheSize = ar5211GetKeyCacheSize, + .ah_resetKeyCacheEntry = ar5211ResetKeyCacheEntry, + .ah_isKeyCacheEntryValid = ar5211IsKeyCacheEntryValid, + .ah_setKeyCacheEntry = ar5211SetKeyCacheEntry, + .ah_setKeyCacheEntryMac = ar5211SetKeyCacheEntryMac, + + /* Power Management Functions */ + .ah_setPowerMode = ar5211SetPowerMode, + .ah_getPowerMode = ar5211GetPowerMode, + + /* Beacon Functions */ + .ah_setBeaconTimers = ar5211SetBeaconTimers, + .ah_beaconInit = ar5211BeaconInit, + .ah_setStationBeaconTimers = ar5211SetStaBeaconTimers, + .ah_resetStationBeaconTimers = ar5211ResetStaBeaconTimers, + .ah_getNextTBTT = ar5211GetNextTBTT, + + /* Interrupt Functions */ + .ah_isInterruptPending = ar5211IsInterruptPending, + .ah_getPendingInterrupts = ar5211GetPendingInterrupts, + .ah_getInterrupts = ar5211GetInterrupts, + .ah_setInterrupts = ar5211SetInterrupts }, + + .ah_getChannelEdges = ar5211GetChannelEdges, + .ah_getWirelessModes = ar5211GetWirelessModes, + .ah_eepromRead = ar5211EepromRead, +#ifdef AH_SUPPORT_WRITE_EEPROM + .ah_eepromWrite = ar5211EepromWrite, +#endif + .ah_getChipPowerLimits = ar5211GetChipPowerLimits, +}; + +static HAL_BOOL ar5211ChipTest(struct ath_hal *); +static HAL_BOOL ar5211FillCapabilityInfo(struct ath_hal *ah); + +/* + * Return the revsion id for the radio chip. This + * fetched via the PHY. + */ +static uint32_t +ar5211GetRadioRev(struct ath_hal *ah) +{ + uint32_t val; + int i; + + OS_REG_WRITE(ah, (AR_PHY_BASE + (0x34 << 2)), 0x00001c16); + for (i = 0; i < 8; i++) + OS_REG_WRITE(ah, (AR_PHY_BASE + (0x20 << 2)), 0x00010000); + val = (OS_REG_READ(ah, AR_PHY_BASE + (256 << 2)) >> 24) & 0xff; + val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); + return ath_hal_reverseBits(val, 8); +} + +/* + * Attach for an AR5211 part. + */ +static struct ath_hal * +ar5211Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + struct ath_hal_5211 *ahp; + struct ath_hal *ah; + uint32_t val; + uint16_t eeval; + HAL_STATUS ecode; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp = ath_hal_malloc(sizeof (struct ath_hal_5211)); + if (ahp == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + ecode = HAL_ENOMEM; + goto bad; + } + ah = &ahp->ah_priv.h; + /* set initial values */ + OS_MEMCPY(&ahp->ah_priv, &ar5211hal, sizeof(struct ath_hal_private)); + ah->ah_sc = sc; + ah->ah_st = st; + ah->ah_sh = sh; + + ah->ah_devid = devid; /* NB: for AH_DEBUG_ALQ */ + AH_PRIVATE(ah)->ah_devid = devid; + AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */ + + AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER; + AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ + + ahp->ah_diversityControl = HAL_ANT_VARIABLE; + ahp->ah_staId1Defaults = 0; + ahp->ah_rssiThr = INIT_RSSI_THR; + ahp->ah_sifstime = (u_int) -1; + ahp->ah_slottime = (u_int) -1; + ahp->ah_acktimeout = (u_int) -1; + ahp->ah_ctstimeout = (u_int) -1; + + if (!ar5211ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + ecode = HAL_EIO; + goto bad; + } + if (AH_PRIVATE(ah)->ah_devid == AR5211_FPGA11B) { + /* set it back to OFDM mode to be able to read analog rev id */ + OS_REG_WRITE(ah, AR5211_PHY_MODE, AR5211_PHY_MODE_OFDM); + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_44); + OS_DELAY(1000); + } + + /* Read Revisions from Chips */ + val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M; + AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S; + AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION_M; + + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_MAUI_2 || + AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_OAHU) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Mac Chip Rev 0x%x is not supported by this driver\n", + __func__, AH_PRIVATE(ah)->ah_macVersion); + ecode = HAL_ENOTSUPP; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5211ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* Set correct Baseband to analog shift setting to access analog chips. */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) { + OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007); + } else { + OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000047); + } + OS_DELAY(2000); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5211GetRadioRev(ah); + if ((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xf0) != RAD5_SREV_MAJOR) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by this " + "driver\n", __func__, AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; + } + + val = (OS_REG_READ(ah, AR_PCICFG) & AR_PCICFG_EEPROM_SIZE_M) >> + AR_PCICFG_EEPROM_SIZE_S; + if (val != AR_PCICFG_EEPROM_SIZE_16K) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM size " + "%u (0x%x) found\n", __func__, val, val); + ecode = HAL_EESIZE; + goto bad; + } + ecode = ath_hal_legacyEepromAttach(ah); + if (ecode != HAL_OK) { + goto bad; + } + + /* If Bmode and AR5211, verify 2.4 analog exists */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU && + ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) { + /* Set correct Baseband to analog shift setting to access analog chips. */ + OS_REG_WRITE(ah, AR_PHY_BASE, 0x00004007); + OS_DELAY(2000); + AH_PRIVATE(ah)->ah_analog2GhzRev = ar5211GetRadioRev(ah); + + /* Set baseband for 5GHz chip */ + OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007); + OS_DELAY(2000); + if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != RAD2_SREV_MAJOR) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 2G Radio Chip Rev 0x%x is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog2GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; + } + } else { + ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_FALSE); + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read regulatory domain from EEPROM\n", + __func__); + goto bad; + } + AH_PRIVATE(ah)->ah_currentRD = eeval; + AH_PRIVATE(ah)->ah_getNfAdjust = ar5211GetNfAdjust; + + /* + * Got everything we need now to setup the capabilities. + */ + (void) ar5211FillCapabilityInfo(ah); + + /* Initialize gain ladder thermal calibration structure */ + ar5211InitializeGainValues(ah); + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +bad: + if (ahp) + ar5211Detach((struct ath_hal *) ahp); + if (status) + *status = ecode; + return AH_NULL; +#undef N +} + +void +ar5211Detach(struct ath_hal *ah) +{ + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); + + HALASSERT(ah != AH_NULL); + HALASSERT(ah->ah_magic == AR5211_MAGIC); + + ath_hal_eepromDetach(ah); + ath_hal_free(ah); +} + +static HAL_BOOL +ar5211ChipTest(struct ath_hal *ah) +{ + uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) }; + uint32_t regHold[2]; + uint32_t patternData[4] = + { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 }; + int i, j; + + /* Test PHY & MAC registers */ + for (i = 0; i < 2; i++) { + uint32_t addr = regAddr[i]; + uint32_t wrData, rdData; + + regHold[i] = OS_REG_READ(ah, addr); + for (j = 0; j < 0x100; j++) { + wrData = (j << 16) | j; + OS_REG_WRITE(ah, addr, wrData); + rdData = OS_REG_READ(ah, addr); + if (rdData != wrData) { + HALDEBUG(ah, HAL_DEBUG_ANY, +"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", + __func__, addr, wrData, rdData); + return AH_FALSE; + } + } + for (j = 0; j < 4; j++) { + wrData = patternData[j]; + OS_REG_WRITE(ah, addr, wrData); + rdData = OS_REG_READ(ah, addr); + if (wrData != rdData) { + HALDEBUG(ah, HAL_DEBUG_ANY, +"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", + __func__, addr, wrData, rdData); + return AH_FALSE; + } + } + OS_REG_WRITE(ah, regAddr[i], regHold[i]); + } + OS_DELAY(100); + return AH_TRUE; +} + +/* + * Store the channel edges for the requested operational mode + */ +static HAL_BOOL +ar5211GetChannelEdges(struct ath_hal *ah, + uint16_t flags, uint16_t *low, uint16_t *high) +{ + if (flags & IEEE80211_CHAN_5GHZ) { + *low = 4920; + *high = 6100; + return AH_TRUE; + } + if (flags & IEEE80211_CHAN_2GHZ && + ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) { + *low = 2312; + *high = 2732; + return AH_TRUE; + } + return AH_FALSE; +} + +static HAL_BOOL +ar5211GetChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan) +{ + /* XXX fill in, this is just a placeholder */ + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: no min/max power for %u/0x%x\n", + __func__, chan->ic_freq, chan->ic_flags); + chan->ic_maxpower = MAX_RATE_POWER; + chan->ic_minpower = 0; + return AH_TRUE; +} + +static void +ar5211ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) +{ +} + +static void +ar5211DisablePCIE(struct ath_hal *ah) +{ +} + +/* + * Fill all software cached or static hardware state information. + */ +static HAL_BOOL +ar5211FillCapabilityInfo(struct ath_hal *ah) +{ + struct ath_hal_private *ahpriv = AH_PRIVATE(ah); + HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; + + /* Construct wireless mode from EEPROM */ + pCap->halWirelessModes = 0; + if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { + pCap->halWirelessModes |= HAL_MODE_11A; + if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) + pCap->halWirelessModes |= HAL_MODE_TURBO; + } + if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) + pCap->halWirelessModes |= HAL_MODE_11B; + + pCap->halLow2GhzChan = 2312; + pCap->halHigh2GhzChan = 2732; + pCap->halLow5GhzChan = 4920; + pCap->halHigh5GhzChan = 6100; + + pCap->halChanSpreadSupport = AH_TRUE; + pCap->halSleepAfterBeaconBroken = AH_TRUE; + pCap->halPSPollBroken = AH_TRUE; + pCap->halVEOLSupport = AH_TRUE; + pCap->halNumMRRetries = 1; /* No hardware MRR support */ + pCap->halNumTxMaps = 1; /* Single TX ptr per descr */ + + pCap->halTotalQueues = HAL_NUM_TX_QUEUES; + pCap->halKeyCacheSize = 128; + + /* XXX not needed */ + pCap->halChanHalfRate = AH_FALSE; + pCap->halChanQuarterRate = AH_FALSE; + + /* + * RSSI uses the combined field; some 11n NICs may use + * the control chain RSSI. + */ + pCap->halUseCombinedRadarRssi = AH_TRUE; + + if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) && + ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) { + /* NB: enabled by default */ + ahpriv->ah_rfkillEnabled = AH_TRUE; + pCap->halRfSilentSupport = AH_TRUE; + } + + pCap->halTstampPrecision = 13; + pCap->halIntrMask = HAL_INT_COMMON + | HAL_INT_RX + | HAL_INT_TX + | HAL_INT_FATAL + | HAL_INT_BNR + | HAL_INT_TIM + ; + + pCap->hal4kbSplitTransSupport = AH_TRUE; + pCap->halHasRxSelfLinkedTail = AH_TRUE; + + /* XXX might be ok w/ some chip revs */ + ahpriv->ah_rxornIsFatal = AH_TRUE; + return AH_TRUE; +} + +static const char* +ar5211Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID) { + if (devid == AR5211_DEVID || devid == AR5311_DEVID || + devid == AR5211_DEFAULT) + return "Atheros 5211"; + if (devid == AR5211_FPGA11B) + return "Atheros 5211 (FPGA)"; + } + return AH_NULL; +} +AH_CHIP(AR5211, ar5211Probe, ar5211Attach); diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211_beacon.c b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_beacon.c new file mode 100644 index 0000000..b2775d0 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_beacon.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211desc.h" + +/* + * Routines used to initialize and generated beacons for the AR5211/AR5311. + */ + +/* + * Return the hardware NextTBTT in TSF + */ +uint64_t +ar5211GetNextTBTT(struct ath_hal *ah) +{ +#define TU_TO_TSF(_tu) (((uint64_t)(_tu)) << 10) + return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0)); +#undef TU_TO_TSF +} + +/* + * Initialize all of the hardware registers used to send beacons. + */ +void +ar5211SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt) +{ + + OS_REG_WRITE(ah, AR_TIMER0, bt->bt_nexttbtt); + OS_REG_WRITE(ah, AR_TIMER1, bt->bt_nextdba); + OS_REG_WRITE(ah, AR_TIMER2, bt->bt_nextswba); + OS_REG_WRITE(ah, AR_TIMER3, bt->bt_nextatim); + /* + * Set the Beacon register after setting all timers. + */ + OS_REG_WRITE(ah, AR_BEACON, bt->bt_intval); +} + +/* + * Legacy api to initialize all of the beacon registers. + */ +void +ar5211BeaconInit(struct ath_hal *ah, + uint32_t next_beacon, uint32_t beacon_period) +{ + HAL_BEACON_TIMERS bt; + + bt.bt_nexttbtt = next_beacon; + /* + * TIMER1: in AP/adhoc mode this controls the DMA beacon + * alert timer; otherwise it controls the next wakeup time. + * TIMER2: in AP mode, it controls the SBA beacon alert + * interrupt; otherwise it sets the start of the next CFP. + */ + switch (AH_PRIVATE(ah)->ah_opmode) { + case HAL_M_STA: + case HAL_M_MONITOR: + bt.bt_nextdba = 0xffff; + bt.bt_nextswba = 0x7ffff; + break; + case HAL_M_IBSS: + case HAL_M_HOSTAP: + bt.bt_nextdba = (next_beacon - + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ + bt.bt_nextswba = (next_beacon - + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ + break; + } + /* + * Set the ATIM window + * Our hardware does not support an ATIM window of 0 + * (beacons will not work). If the ATIM windows is 0, + * force it to 1. + */ + bt.bt_nextatim = next_beacon + 1; + bt.bt_intval = beacon_period & + (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN); + ar5211SetBeaconTimers(ah, &bt); +} + +void +ar5211ResetStaBeaconTimers(struct ath_hal *ah) +{ + uint32_t val; + + OS_REG_WRITE(ah, AR_TIMER0, 0); /* no beacons */ + val = OS_REG_READ(ah, AR_STA_ID1); + val |= AR_STA_ID1_PWR_SAV; /* XXX */ + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + val & ~(AR_STA_ID1_DEFAULT_ANTENNA | AR_STA_ID1_PCF)); + OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_PERIOD); +} + +/* + * Set all the beacon related bits on the h/w for stations + * i.e. initializes the corresponding h/w timers; + * also tells the h/w whether to anticipate PCF beacons + */ +void +ar5211SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: setting beacon timers\n", __func__); + + HALASSERT(bs->bs_intval != 0); + /* if the AP will do PCF */ + if (bs->bs_cfpmaxduration != 0) { + /* tell the h/w that the associated AP is PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PCF); + + /* set CFP_PERIOD(1.024ms) register */ + OS_REG_WRITE(ah, AR_CFP_PERIOD, bs->bs_cfpperiod); + + /* set CFP_DUR(1.024ms) register to max cfp duration */ + OS_REG_WRITE(ah, AR_CFP_DUR, bs->bs_cfpmaxduration); + + /* set TIMER2(128us) to anticipated time of next CFP */ + OS_REG_WRITE(ah, AR_TIMER2, bs->bs_cfpnext << 3); + } else { + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + OS_REG_READ(ah, AR_STA_ID1) &~ AR_STA_ID1_PCF); + } + + /* + * Set TIMER0(1.024ms) to the anticipated time of the next beacon. + */ + OS_REG_WRITE(ah, AR_TIMER0, bs->bs_nexttbtt); + + /* + * Start the beacon timers by setting the BEACON register + * to the beacon interval; also write the tim offset which + * we should know by now. The code, in ar5211WriteAssocid, + * also sets the tim offset once the AID is known which can + * be left as such for now. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_PERIOD|AR_BEACON_TIM)) + | SM(bs->bs_intval, AR_BEACON_PERIOD) + | SM(bs->bs_timoffset ? bs->bs_timoffset + 4 : 0, AR_BEACON_TIM) + ); + + /* + * Configure the BMISS interrupt. Note that we + * assume the caller blocks interrupts while enabling + * the threshold. + */ + HALASSERT(bs->bs_bmissthreshold <= MS(0xffffffff, AR_RSSI_THR_BM_THR)); + ahp->ah_rssiThr = (ahp->ah_rssiThr &~ AR_RSSI_THR_BM_THR) + | SM(bs->bs_bmissthreshold, AR_RSSI_THR_BM_THR); + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + + /* + * Set the sleep duration in 1/8 TU's. + */ +#define SLEEP_SLOP 3 + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLDUR, + (bs->bs_sleepduration - SLEEP_SLOP) << 3); +#undef SLEEP_SLOP +} diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211_interrupts.c b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_interrupts.c new file mode 100644 index 0000000..4c20ca1 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_interrupts.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" + +/* + * Checks to see if an interrupt is pending on our NIC + * + * Returns: TRUE if an interrupt is pending + * FALSE if not + */ +HAL_BOOL +ar5211IsInterruptPending(struct ath_hal *ah) +{ + return OS_REG_READ(ah, AR_INTPEND) != 0; +} + +/* + * Reads the Interrupt Status Register value from the NIC, thus deasserting + * the interrupt line, and returns both the masked and unmasked mapped ISR + * values. The value returned is mapped to abstract the hw-specific bit + * locations in the Interrupt Status Register. + * + * Returns: A hardware-abstracted bitmap of all non-masked-out + * interrupts pending, as well as an unmasked value + */ +HAL_BOOL +ar5211GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) +{ + uint32_t isr; + + isr = OS_REG_READ(ah, AR_ISR_RAC); + if (isr == 0xffffffff) { + *masked = 0; + return AH_FALSE; + } + + *masked = isr & HAL_INT_COMMON; + + if (isr & AR_ISR_HIUERR) + *masked |= HAL_INT_FATAL; + if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) + *masked |= HAL_INT_RX; + if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) + *masked |= HAL_INT_TX; + /* + * Receive overrun is usually non-fatal on Oahu/Spirit. + * BUT on some parts rx could fail and the chip must be reset. + * So we force a hardware reset in all cases. + */ + if ((isr & AR_ISR_RXORN) && AH_PRIVATE(ah)->ah_rxornIsFatal) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: receive FIFO overrun interrupt\n", __func__); + *masked |= HAL_INT_FATAL; + } + + /* + * On fatal errors collect ISR state for debugging. + */ + if (*masked & HAL_INT_FATAL) { + AH_PRIVATE(ah)->ah_fatalState[0] = isr; + AH_PRIVATE(ah)->ah_fatalState[1] = OS_REG_READ(ah, AR_ISR_S0_S); + AH_PRIVATE(ah)->ah_fatalState[2] = OS_REG_READ(ah, AR_ISR_S1_S); + AH_PRIVATE(ah)->ah_fatalState[3] = OS_REG_READ(ah, AR_ISR_S2_S); + AH_PRIVATE(ah)->ah_fatalState[4] = OS_REG_READ(ah, AR_ISR_S3_S); + AH_PRIVATE(ah)->ah_fatalState[5] = OS_REG_READ(ah, AR_ISR_S4_S); + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: fatal error, ISR_RAC=0x%x ISR_S2_S=0x%x\n", + __func__, isr, AH_PRIVATE(ah)->ah_fatalState[3]); + } + return AH_TRUE; +} + +HAL_INT +ar5211GetInterrupts(struct ath_hal *ah) +{ + return AH5211(ah)->ah_maskReg; +} + +/* + * Atomically enables NIC interrupts. Interrupts are passed in + * via the enumerated bitmask in ints. + */ +HAL_INT +ar5211SetInterrupts(struct ath_hal *ah, HAL_INT ints) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + uint32_t omask = ahp->ah_maskReg; + uint32_t mask; + + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n", + __func__, omask, ints); + + /* + * Disable interrupts here before reading & modifying + * the mask so that the ISR does not modify the mask + * out from under us. + */ + if (omask & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + /* XXX??? */ + (void) OS_REG_READ(ah, AR_IER); /* flush write to HW */ + } + + mask = ints & HAL_INT_COMMON; + if (ints & HAL_INT_TX) { + if (ahp->ah_txOkInterruptMask) + mask |= AR_IMR_TXOK; + if (ahp->ah_txErrInterruptMask) + mask |= AR_IMR_TXERR; + if (ahp->ah_txDescInterruptMask) + mask |= AR_IMR_TXDESC; + if (ahp->ah_txEolInterruptMask) + mask |= AR_IMR_TXEOL; + } + if (ints & HAL_INT_RX) + mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC; + if (ints & HAL_INT_FATAL) { + /* + * NB: ar5212Reset sets MCABT+SSERR+DPERR in AR_IMR_S2 + * so enabling HIUERR enables delivery. + */ + mask |= AR_IMR_HIUERR; + } + + /* Write the new IMR and store off our SW copy. */ + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); + OS_REG_WRITE(ah, AR_IMR, mask); + ahp->ah_maskReg = ints; + + /* Re-enable interrupts as appropriate. */ + if (ints & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + } + + return omask; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211_keycache.c b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_keycache.c new file mode 100644 index 0000000..3e0f922 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_keycache.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" + +/* + * Chips-specific key cache routines. + */ + +#define AR_KEYTABLE_SIZE 128 +#define KEY_XOR 0xaa + +/* + * Return the size of the hardware key cache. + */ +uint32_t +ar5211GetKeyCacheSize(struct ath_hal *ah) +{ + return AR_KEYTABLE_SIZE; +} + +/* + * Return true if the specific key cache entry is valid. + */ +HAL_BOOL +ar5211IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry) +{ + if (entry < AR_KEYTABLE_SIZE) { + uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry)); + if (val & AR_KEYTABLE_VALID) + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Clear the specified key cache entry + */ +HAL_BOOL +ar5211ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry) +{ + if (entry < AR_KEYTABLE_SIZE) { + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Sets the mac part of the specified key cache entry and mark it valid. + */ +HAL_BOOL +ar5211SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac) +{ + uint32_t macHi, macLo; + + if (entry >= AR_KEYTABLE_SIZE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n", + __func__, entry); + return AH_FALSE; + } + + /* + * Set MAC address -- shifted right by 1. MacLo is + * the 4 MSBs, and MacHi is the 2 LSBs. + */ + if (mac != AH_NULL) { + macHi = (mac[5] << 8) | mac[4]; + macLo = (mac[3] << 24)| (mac[2] << 16) + | (mac[1] << 8) | mac[0]; + macLo >>= 1; + macLo |= (macHi & 1) << 31; /* carry */ + macHi >>= 1; + } else { + macLo = macHi = 0; + } + + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID); + return AH_TRUE; +} + +/* + * Sets the contents of the specified key cache entry. + */ +HAL_BOOL +ar5211SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, + const HAL_KEYVAL *k, const uint8_t *mac, + int xorKey) +{ + uint32_t key0, key1, key2, key3, key4; + uint32_t keyType; + uint32_t xorMask= xorKey ? + (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0; + + if (entry >= AR_KEYTABLE_SIZE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n", + __func__, entry); + return AH_FALSE; + } + switch (k->kv_type) { + case HAL_CIPHER_AES_OCB: + keyType = AR_KEYTABLE_TYPE_AES; + break; + case HAL_CIPHER_WEP: + if (k->kv_len < 40 / NBBY) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: WEP key length %u too small\n", + __func__, k->kv_len); + return AH_FALSE; + } + if (k->kv_len <= 40 / NBBY) + keyType = AR_KEYTABLE_TYPE_40; + else if (k->kv_len <= 104 / NBBY) + keyType = AR_KEYTABLE_TYPE_104; + else + keyType = AR_KEYTABLE_TYPE_128; + break; + case HAL_CIPHER_CLR: + keyType = AR_KEYTABLE_TYPE_CLR; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n", + __func__, k->kv_type); + return AH_FALSE; + } + + key0 = LE_READ_4(k->kv_val+0) ^ xorMask; + key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff; + key2 = LE_READ_4(k->kv_val+6) ^ xorMask; + key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff; + key4 = LE_READ_4(k->kv_val+12) ^ xorMask; + if (k->kv_len <= 104 / NBBY) + key4 &= 0xff; + + + /* + * Note: WEP key cache hardware requires that each double-word + * pair be written in even/odd order (since the destination is + * a 64-bit register). Don't reorder these writes w/o + * understanding this! + */ + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); + return ar5211SetKeyCacheEntryMac(ah, entry, mac); +} diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211_misc.c b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_misc.c new file mode 100644 index 0000000..a1a5967 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_misc.c @@ -0,0 +1,727 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211phy.h" + +#include "ah_eeprom_v3.h" + +#define AR_NUM_GPIO 6 /* 6 GPIO bits */ +#define AR_GPIOD_MASK 0x2f /* 6-bit mask */ + +void +ar5211GetMacAddress(struct ath_hal *ah, uint8_t *mac) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5211SetMacAddress(struct ath_hal *ah, const uint8_t *mac) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); + return AH_TRUE; +} + +void +ar5211GetBssIdMask(struct ath_hal *ah, uint8_t *mask) +{ + static const uint8_t ones[IEEE80211_ADDR_LEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5211SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) +{ + return AH_FALSE; +} + +/* + * Read 16 bits of data from the specified EEPROM offset. + */ +HAL_BOOL +ar5211EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) +{ + OS_REG_WRITE(ah, AR_EEPROM_ADDR, off); + OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_READ); + + if (!ath_hal_wait(ah, AR_EEPROM_STS, + AR_EEPROM_STS_READ_COMPLETE | AR_EEPROM_STS_READ_ERROR, + AR_EEPROM_STS_READ_COMPLETE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: read failed for entry 0x%x\n", __func__, off); + return AH_FALSE; + } + *data = OS_REG_READ(ah, AR_EEPROM_DATA) & 0xffff; + return AH_TRUE; +} + +#ifdef AH_SUPPORT_WRITE_EEPROM +/* + * Write 16 bits of data to the specified EEPROM offset. + */ +HAL_BOOL +ar5211EepromWrite(struct ath_hal *ah, u_int off, uint16_t data) +{ + return AH_FALSE; +} +#endif /* AH_SUPPORT_WRITE_EEPROM */ + +/* + * Attempt to change the cards operating regulatory domain to the given value + */ +HAL_BOOL +ar5211SetRegulatoryDomain(struct ath_hal *ah, + uint16_t regDomain, HAL_STATUS *status) +{ + HAL_STATUS ecode; + + if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { + ecode = HAL_EINVAL; + goto bad; + } + /* + * Check if EEPROM is configured to allow this; must + * be a proper version and the protection bits must + * permit re-writing that segment of the EEPROM. + */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { + ecode = HAL_EEWRITE; + goto bad; + } +#ifdef AH_SUPPORT_WRITE_REGDOMAIN + if (ar5211EepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: set regulatory domain to %u (0x%x)\n", + __func__, regDomain, regDomain); + AH_PRIVATE(ah)->ah_currentRD = regDomain; + return AH_TRUE; + } +#endif + ecode = HAL_EIO; +bad: + if (status) + *status = ecode; + return AH_FALSE; +} + +/* + * Return the wireless modes (a,b,g,t) supported by hardware. + * + * This value is what is actually supported by the hardware + * and is unaffected by regulatory/country code settings. + * + */ +u_int +ar5211GetWirelessModes(struct ath_hal *ah) +{ + u_int mode = 0; + + if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { + mode = HAL_MODE_11A; + if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) + mode |= HAL_MODE_TURBO | HAL_MODE_108A; + } + if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) + mode |= HAL_MODE_11B; + return mode; +} + +#if 0 +HAL_BOOL +ar5211GetTurboDisable(struct ath_hal *ah) +{ + return (AH5211(ah)->ah_turboDisable != 0); +} +#endif + +/* + * Called if RfKill is supported (according to EEPROM). Set the interrupt and + * GPIO values so the ISR and can disable RF on a switch signal + */ +void +ar5211EnableRfKill(struct ath_hal *ah) +{ + uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; + int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); + int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); + + /* + * Configure the desired GPIO port for input + * and enable baseband rf silence. + */ + ar5211GpioCfgInput(ah, select); + OS_REG_SET_BIT(ah, AR_PHY_BASE, 0x00002000); + /* + * If radio disable switch connection to GPIO bit x is enabled + * program GPIO interrupt. + * If rfkill bit on eeprom is 1, setupeeprommap routine has already + * verified that it is a later version of eeprom, it has a place for + * rfkill bit and it is set to 1, indicating that GPIO bit x hardware + * connection is present. + */ + ar5211GpioSetIntr(ah, select, (ar5211GpioGet(ah, select) != polarity)); +} + +/* + * Configure GPIO Output lines + */ +HAL_BOOL +ar5211GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) +{ + uint32_t reg; + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, AR_GPIOCR); + reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT)); + reg |= AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT); + + OS_REG_WRITE(ah, AR_GPIOCR, reg); + return AH_TRUE; +} + +/* + * Configure GPIO Input lines + */ +HAL_BOOL +ar5211GpioCfgInput(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t reg; + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, AR_GPIOCR); + reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT)); + reg |= AR_GPIOCR_0_CR_N << (gpio * AR_GPIOCR_CR_SHIFT); + + OS_REG_WRITE(ah, AR_GPIOCR, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - set output lines + */ +HAL_BOOL +ar5211GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) +{ + uint32_t reg; + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, AR_GPIODO); + reg &= ~(1 << gpio); + reg |= (val&1) << gpio; + + OS_REG_WRITE(ah, AR_GPIODO, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - get input lines + */ +uint32_t +ar5211GpioGet(struct ath_hal *ah, uint32_t gpio) +{ + if (gpio < AR_NUM_GPIO) { + uint32_t val = OS_REG_READ(ah, AR_GPIODI); + val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1; + return val; + } else { + return 0xffffffff; + } +} + +/* + * Set the GPIO 0 Interrupt (gpio is ignored) + */ +void +ar5211GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) +{ + uint32_t val = OS_REG_READ(ah, AR_GPIOCR); + + /* Clear the bits that we will modify. */ + val &= ~(AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA | + AR_GPIOCR_0_CR_A); + + val |= AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_ENA; + if (ilevel) + val |= AR_GPIOCR_INT_SELH; + + /* Don't need to change anything for low level interrupt. */ + OS_REG_WRITE(ah, AR_GPIOCR, val); + + /* Change the interrupt mask. */ + ar5211SetInterrupts(ah, AH5211(ah)->ah_maskReg | HAL_INT_GPIO); +} + +/* + * Change the LED blinking pattern to correspond to the connectivity + */ +void +ar5211SetLedState(struct ath_hal *ah, HAL_LED_STATE state) +{ + static const uint32_t ledbits[8] = { + AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_INIT */ + AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_SCAN */ + AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_AUTH */ + AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_ASSOC*/ + AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_RUN */ + AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, + AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, + AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, + }; + OS_REG_WRITE(ah, AR_PCICFG, + (OS_REG_READ(ah, AR_PCICFG) &~ + (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE)) + | ledbits[state & 0x7] + ); +} + +/* + * Change association related fields programmed into the hardware. + * Writing a valid BSSID to the hardware effectively enables the hardware + * to synchronize its TSF to the correct beacons and receive frames coming + * from that BSSID. It is called by the SME JOIN operation. + */ +void +ar5211WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + /* XXX save bssid for possible re-use on reset */ + OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | + ((assocId & 0x3fff)<> 19) & 0x1ff; + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + return (OS_REG_READ(ah, AR_TSF_U32) ^ + OS_REG_READ(ah, AR_TSF_L32) ^ nf); +} + +/* + * Detect if our card is present + */ +HAL_BOOL +ar5211DetectCardPresent(struct ath_hal *ah) +{ + uint16_t macVersion, macRev; + uint32_t v; + + /* + * Read the Silicon Revision register and compare that + * to what we read at attach time. If the same, we say + * a card/device is present. + */ + v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M; + macVersion = v >> AR_SREV_ID_S; + macRev = v & AR_SREV_REVISION_M; + return (AH_PRIVATE(ah)->ah_macVersion == macVersion && + AH_PRIVATE(ah)->ah_macRev == macRev); +} + +/* + * Update MIB Counters + */ +void +ar5211UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats) +{ + stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); + stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); + stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); + stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); + stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); +} + +HAL_BOOL +ar5211SetSifsTime(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (us > ath_hal_mac_usec(ah, 0xffff)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", + __func__, us); + ahp->ah_sifstime = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us)); + ahp->ah_slottime = us; + return AH_TRUE; + } +} + +u_int +ar5211GetSifsTime(struct ath_hal *ah) +{ + u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff; + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5211SetSlotTime(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", + __func__, us); + ahp->ah_slottime = us; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us)); + ahp->ah_slottime = us; + return AH_TRUE; + } +} + +u_int +ar5211GetSlotTime(struct ath_hal *ah) +{ + u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff; + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5211SetAckTimeout(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", + __func__, us); + ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); + ahp->ah_acktimeout = us; + return AH_TRUE; + } +} + +u_int +ar5211GetAckTimeout(struct ath_hal *ah) +{ + u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +u_int +ar5211GetAckCTSRate(struct ath_hal *ah) +{ + return ((AH5211(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); +} + +HAL_BOOL +ar5211SetAckCTSRate(struct ath_hal *ah, u_int high) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (high) { + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); + ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; + } else { + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); + ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; + } + return AH_TRUE; +} + +HAL_BOOL +ar5211SetCTSTimeout(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", + __func__, us); + ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); + ahp->ah_ctstimeout = us; + return AH_TRUE; + } +} + +u_int +ar5211GetCTSTimeout(struct ath_hal *ah) +{ + u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5211SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) +{ + /* nothing to do */ + return AH_TRUE; +} + +void +ar5211SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) +{ +} + +/* + * Control Adaptive Noise Immunity Parameters + */ +HAL_BOOL +ar5211AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) +{ + return AH_FALSE; +} + +void +ar5211AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +} + +void +ar5211RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats, + const struct ieee80211_channel *chan) +{ +} + +void +ar5211MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats) +{ +} + +/* + * Get the rssi of frame curently being received. + */ +uint32_t +ar5211GetCurRssi(struct ath_hal *ah) +{ + return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff); +} + +u_int +ar5211GetDefAntenna(struct ath_hal *ah) +{ + return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7); +} + +void +ar5211SetDefAntenna(struct ath_hal *ah, u_int antenna) +{ + OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); +} + +HAL_ANT_SETTING +ar5211GetAntennaSwitch(struct ath_hal *ah) +{ + return AH5211(ah)->ah_diversityControl; +} + +HAL_BOOL +ar5211SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) +{ + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + + if (chan == AH_NULL) { + AH5211(ah)->ah_diversityControl = settings; + return AH_TRUE; + } + return ar5211SetAntennaSwitchInternal(ah, settings, chan); +} + +HAL_STATUS +ar5211GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t *result) +{ + + switch (type) { + case HAL_CAP_CIPHER: /* cipher handled in hardware */ + switch (capability) { + case HAL_CIPHER_AES_OCB: + case HAL_CIPHER_WEP: + case HAL_CIPHER_CLR: + return HAL_OK; + default: + return HAL_ENOTSUPP; + } + default: + return ath_hal_getcapability(ah, type, capability, result); + } +} + +HAL_BOOL +ar5211SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t setting, HAL_STATUS *status) +{ + switch (type) { + case HAL_CAP_DIAG: /* hardware diagnostic support */ + /* + * NB: could split this up into virtual capabilities, + * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly + * seems worth the additional complexity. + */ +#ifdef AH_DEBUG + AH_PRIVATE(ah)->ah_diagreg = setting; +#else + AH_PRIVATE(ah)->ah_diagreg = setting & 0x6; /* ACK+CTS */ +#endif + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); + return AH_TRUE; + default: + return ath_hal_setcapability(ah, type, capability, + setting, status); + } +} + +HAL_BOOL +ar5211GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + (void) ahp; + if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) + return AH_TRUE; + switch (request) { + case HAL_DIAG_EEPROM: + return ath_hal_eepromDiag(ah, request, + args, argsize, result, resultsize); + case HAL_DIAG_RFGAIN: + *result = &ahp->ah_gainValues; + *resultsize = sizeof(GAIN_VALUES); + return AH_TRUE; + case HAL_DIAG_RFGAIN_CURSTEP: + *result = __DECONST(void *, ahp->ah_gainValues.currStep); + *resultsize = (*result == AH_NULL) ? + 0 : sizeof(GAIN_OPTIMIZATION_STEP); + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Return what percentage of the extension channel is busy. + * This is always disabled for AR5211 series NICs. + */ +uint32_t +ar5211Get11nExtBusy(struct ath_hal *ah) +{ + return (0); +} + + +/* + * There's no channel survey support for the AR5211. + */ +HAL_BOOL +ar5211GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) +{ + + return (AH_FALSE); +} + +void +ar5211SetChainMasks(struct ath_hal *ah, uint32_t txchainmask, + uint32_t rxchainmask) +{ +} + +void +ar5211EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ +} + +void +ar5211GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ +} diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211_phy.c b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_phy.c new file mode 100644 index 0000000..d224732 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_phy.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5211/ar5211.h" + +/* shorthands to compact tables for readability */ +#define OFDM IEEE80211_T_OFDM +#define CCK IEEE80211_T_CCK +#define TURBO IEEE80211_T_TURBO + +HAL_RATE_TABLE ar5211_11a_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 } + }, +}; + +HAL_RATE_TABLE ar5211_turbo_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, TURBO, 12000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, TURBO, 18000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, TURBO, 24000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, TURBO, 36000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, TURBO, 48000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, TURBO, 72000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, TURBO, 96000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, TURBO, 108000, 0x0c, 0x00, 108, 4 } + }, +}; + +HAL_RATE_TABLE ar5211_11b_table = { + 4, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 1 Mb */ { AH_TRUE, CCK, 1000, 0x0b, 0x00, (0x80| 2), 0 }, +/* 2 Mb */ { AH_TRUE, CCK, 2000, 0x0a, 0x04, (0x80| 4), 1 }, +/* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x09, 0x04, (0x80|11), 1 }, +/* 11 Mb */ { AH_TRUE, CCK, 11000, 0x08, 0x04, (0x80|22), 1 } + }, +}; + +#undef OFDM +#undef CCK +#undef TURBO + + +const HAL_RATE_TABLE * +ar5211GetRateTable(struct ath_hal *ah, u_int mode) +{ + HAL_RATE_TABLE *rt; + switch (mode) { + case HAL_MODE_11A: + rt = &ar5211_11a_table; + break; + case HAL_MODE_11B: + rt = &ar5211_11b_table; + break; + case HAL_MODE_TURBO: + rt = &ar5211_turbo_table; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", + __func__, mode); + return AH_NULL; + } + ath_hal_setupratetable(ah, rt); + return rt; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211_power.c b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_power.c new file mode 100644 index 0000000..e646d90 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_power.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211desc.h" + +/* + * Notify Power Mgt is enabled in self-generated frames. + * If requested, force chip awake. + * + * Returns A_OK if chip is awake or successfully forced awake. + * + * WARNING WARNING WARNING + * There is a problem with the chip where sometimes it will not wake up. + */ +static HAL_BOOL +ar5211SetPowerModeAwake(struct ath_hal *ah, int setChip) +{ +#define POWER_UP_TIME 2000 + uint32_t val; + int i; + + if (setChip) { + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_WAKE); + OS_DELAY(10); /* Give chip the chance to awake */ + + for (i = POWER_UP_TIME / 200; i != 0; i--) { + val = OS_REG_READ(ah, AR_PCICFG); + if ((val & AR_PCICFG_SPWR_DN) == 0) + break; + OS_DELAY(200); + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, + AR_SCR_SLE_WAKE); + } + if (i == 0) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n", + __func__, POWER_UP_TIME/20); +#endif + return AH_FALSE; + } + } + + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + return AH_TRUE; +#undef POWER_UP_TIME +} + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, force chip to sleep. + */ +static void +ar5211SetPowerModeSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_SLP); +} + +/* + * Notify Power Management is enabled in self-generating + * fames. If request, set power mode of chip to + * auto/normal. Duration in units of 128us (1/8 TU). + */ +static void +ar5211SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_NORM); +} + +HAL_BOOL +ar5211SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) +{ +#ifdef AH_DEBUG + static const char* modes[] = { + "AWAKE", + "FULL-SLEEP", + "NETWORK SLEEP", + "UNDEFINED" + }; +#endif + int status = AH_TRUE; + + HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, + modes[ah->ah_powerMode], modes[mode], + setChip ? "set chip " : ""); + switch (mode) { + case HAL_PM_AWAKE: + if (setChip) + ah->ah_powerMode = mode; + status = ar5211SetPowerModeAwake(ah, setChip); + break; + case HAL_PM_FULL_SLEEP: + ar5211SetPowerModeSleep(ah, setChip); + if (setChip) + ah->ah_powerMode = mode; + break; + case HAL_PM_NETWORK_SLEEP: + ar5211SetPowerModeNetworkSleep(ah, setChip); + if (setChip) + ah->ah_powerMode = mode; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n", + __func__, mode); + return AH_FALSE; + } + return status; +} + +HAL_POWER_MODE +ar5211GetPowerMode(struct ath_hal *ah) +{ + /* Just so happens the h/w maps directly to the abstracted value */ + return MS(OS_REG_READ(ah, AR_SCR), AR_SCR_SLE); +} diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211_recv.c b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_recv.c new file mode 100644 index 0000000..27c4835 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_recv.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211desc.h" + +/* + * Get the RXDP. + */ +uint32_t +ar5211GetRxDP(struct ath_hal *ah, HAL_RX_QUEUE qtype) +{ + + HALASSERT(qtype == HAL_RX_QUEUE_HP); + return OS_REG_READ(ah, AR_RXDP); +} + +/* + * Set the RxDP. + */ +void +ar5211SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE qtype) +{ + + HALASSERT(qtype == HAL_RX_QUEUE_HP); + OS_REG_WRITE(ah, AR_RXDP, rxdp); + HALASSERT(OS_REG_READ(ah, AR_RXDP) == rxdp); +} + + +/* + * Set Receive Enable bits. + */ +void +ar5211EnableReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_CR, AR_CR_RXE); +} + +/* + * Stop Receive at the DMA engine + */ +HAL_BOOL +ar5211StopDmaReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */ + if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0)) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s failed to stop in 10ms\n" + "AR_CR=0x%08X\nAR_DIAG_SW=0x%08X\n" + , __func__ + , OS_REG_READ(ah, AR_CR) + , OS_REG_READ(ah, AR_DIAG_SW) + ); +#endif + return AH_FALSE; + } else { + return AH_TRUE; + } +} + +/* + * Start Transmit at the PCU engine (unpause receive) + */ +void +ar5211StartPcuReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_RX)); +} + +/* + * Stop Transmit at the PCU engine (pause receive) + */ +void +ar5211StopPcuReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_SW_DIS_RX); +} + +/* + * Set multicast filter 0 (lower 32-bits) + * filter 1 (upper 32-bits) + */ +void +ar5211SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1) +{ + OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0); + OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1); +} + +/* + * Clear multicast filter by index + */ +HAL_BOOL +ar5211ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix) +{ + uint32_t val; + + if (ix >= 64) + return AH_FALSE; + if (ix >= 32) { + val = OS_REG_READ(ah, AR_MCAST_FIL1); + OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32)))); + } else { + val = OS_REG_READ(ah, AR_MCAST_FIL0); + OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<= 64) + return AH_FALSE; + if (ix >= 32) { + val = OS_REG_READ(ah, AR_MCAST_FIL1); + OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32)))); + } else { + val = OS_REG_READ(ah, AR_MCAST_FIL0); + OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<ds_ctl0 = 0; + ads->ds_ctl1 = size & AR_BufLen; + if (ads->ds_ctl1 != size) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: buffer size %u too large\n", + __func__, size); + return AH_FALSE; + } + if (flags & HAL_RXDESC_INTREQ) + ads->ds_ctl1 |= AR_RxInterReq; + ads->ds_status0 = ads->ds_status1 = 0; + + return AH_TRUE; +} + +/* + * Process an RX descriptor, and return the status to the caller. + * Copy some hardware specific items into the software portion + * of the descriptor. + * + * NB: the caller is responsible for validating the memory contents + * of the descriptor (e.g. flushing any cached copy). + */ +HAL_STATUS +ar5211ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, + uint32_t pa, struct ath_desc *nds, uint64_t tsf, + struct ath_rx_status *rs) +{ + struct ar5211_desc *ads = AR5211DESC(ds); + struct ar5211_desc *ands = AR5211DESC(nds); + + if ((ads->ds_status1 & AR_Done) == 0) + return HAL_EINPROGRESS; + /* + * Given the use of a self-linked tail be very sure that the hw is + * done with this descriptor; the hw may have done this descriptor + * once and picked it up again...make sure the hw has moved on. + */ + if ((ands->ds_status1 & AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa) + return HAL_EINPROGRESS; + + rs->rs_datalen = ads->ds_status0 & AR_DataLen; + rs->rs_tstamp = MS(ads->ds_status1, AR_RcvTimestamp); + rs->rs_status = 0; + if ((ads->ds_status1 & AR_FrmRcvOK) == 0) { + if (ads->ds_status1 & AR_CRCErr) + rs->rs_status |= HAL_RXERR_CRC; + else if (ads->ds_status1 & AR_DecryptCRCErr) + rs->rs_status |= HAL_RXERR_DECRYPT; + else { + rs->rs_status |= HAL_RXERR_PHY; + rs->rs_phyerr = MS(ads->ds_status1, AR_PHYErr); + } + } + /* XXX what about KeyCacheMiss? */ + rs->rs_rssi = MS(ads->ds_status0, AR_RcvSigStrength); + if (ads->ds_status1 & AR_KeyIdxValid) + rs->rs_keyix = MS(ads->ds_status1, AR_KeyIdx); + else + rs->rs_keyix = HAL_RXKEYIX_INVALID; + /* NB: caller expected to do rate table mapping */ + rs->rs_rate = MS(ads->ds_status0, AR_RcvRate); + rs->rs_antenna = MS(ads->ds_status0, AR_RcvAntenna); + rs->rs_more = (ads->ds_status0 & AR_More) ? 1 : 0; + + return HAL_OK; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211_reset.c b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_reset.c new file mode 100644 index 0000000..14c2087 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_reset.c @@ -0,0 +1,2120 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +/* + * Chips specific device attachment and device info collection + * Connects Init Reg Vectors, EEPROM Data, and device Functions. + */ +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211phy.h" + +#include "ah_eeprom_v3.h" + +/* Add static register initialization vectors */ +#include "ar5211/boss.ini" + +/* + * Structure to hold 11b tuning information for Beanie/Sombrero + * 16 MHz mode, divider ratio = 198 = NP+S. N=16, S=4 or 6, P=12 + */ +typedef struct { + uint32_t refClkSel; /* reference clock, 1 for 16 MHz */ + uint32_t channelSelect; /* P[7:4]S[3:0] bits */ + uint16_t channel5111; /* 11a channel for 5111 */ +} CHAN_INFO_2GHZ; + +#define CI_2GHZ_INDEX_CORRECTION 19 +static const CHAN_INFO_2GHZ chan2GHzData[] = { + { 1, 0x46, 96 }, /* 2312 -19 */ + { 1, 0x46, 97 }, /* 2317 -18 */ + { 1, 0x46, 98 }, /* 2322 -17 */ + { 1, 0x46, 99 }, /* 2327 -16 */ + { 1, 0x46, 100 }, /* 2332 -15 */ + { 1, 0x46, 101 }, /* 2337 -14 */ + { 1, 0x46, 102 }, /* 2342 -13 */ + { 1, 0x46, 103 }, /* 2347 -12 */ + { 1, 0x46, 104 }, /* 2352 -11 */ + { 1, 0x46, 105 }, /* 2357 -10 */ + { 1, 0x46, 106 }, /* 2362 -9 */ + { 1, 0x46, 107 }, /* 2367 -8 */ + { 1, 0x46, 108 }, /* 2372 -7 */ + /* index -6 to 0 are pad to make this a nolookup table */ + { 1, 0x46, 116 }, /* -6 */ + { 1, 0x46, 116 }, /* -5 */ + { 1, 0x46, 116 }, /* -4 */ + { 1, 0x46, 116 }, /* -3 */ + { 1, 0x46, 116 }, /* -2 */ + { 1, 0x46, 116 }, /* -1 */ + { 1, 0x46, 116 }, /* 0 */ + { 1, 0x46, 116 }, /* 2412 1 */ + { 1, 0x46, 117 }, /* 2417 2 */ + { 1, 0x46, 118 }, /* 2422 3 */ + { 1, 0x46, 119 }, /* 2427 4 */ + { 1, 0x46, 120 }, /* 2432 5 */ + { 1, 0x46, 121 }, /* 2437 6 */ + { 1, 0x46, 122 }, /* 2442 7 */ + { 1, 0x46, 123 }, /* 2447 8 */ + { 1, 0x46, 124 }, /* 2452 9 */ + { 1, 0x46, 125 }, /* 2457 10 */ + { 1, 0x46, 126 }, /* 2462 11 */ + { 1, 0x46, 127 }, /* 2467 12 */ + { 1, 0x46, 128 }, /* 2472 13 */ + { 1, 0x44, 124 }, /* 2484 14 */ + { 1, 0x46, 136 }, /* 2512 15 */ + { 1, 0x46, 140 }, /* 2532 16 */ + { 1, 0x46, 144 }, /* 2552 17 */ + { 1, 0x46, 148 }, /* 2572 18 */ + { 1, 0x46, 152 }, /* 2592 19 */ + { 1, 0x46, 156 }, /* 2612 20 */ + { 1, 0x46, 160 }, /* 2632 21 */ + { 1, 0x46, 164 }, /* 2652 22 */ + { 1, 0x46, 168 }, /* 2672 23 */ + { 1, 0x46, 172 }, /* 2692 24 */ + { 1, 0x46, 176 }, /* 2712 25 */ + { 1, 0x46, 180 } /* 2732 26 */ +}; + +/* Power timeouts in usec to wait for chip to wake-up. */ +#define POWER_UP_TIME 2000 + +#define DELAY_PLL_SETTLE 300 /* 300 us */ +#define DELAY_BASE_ACTIVATE 100 /* 100 us */ + +#define NUM_RATES 8 + +static HAL_BOOL ar5211SetResetReg(struct ath_hal *ah, uint32_t resetMask); +static HAL_BOOL ar5211SetChannel(struct ath_hal *, + const struct ieee80211_channel *); +static int16_t ar5211RunNoiseFloor(struct ath_hal *, + uint8_t runTime, int16_t startingNF); +static HAL_BOOL ar5211IsNfGood(struct ath_hal *, + struct ieee80211_channel *chan); +static HAL_BOOL ar5211SetRf6and7(struct ath_hal *, + const struct ieee80211_channel *chan); +static HAL_BOOL ar5211SetBoardValues(struct ath_hal *, + const struct ieee80211_channel *chan); +static void ar5211SetPowerTable(struct ath_hal *, + PCDACS_EEPROM *pSrcStruct, uint16_t channel); +static HAL_BOOL ar5211SetTransmitPower(struct ath_hal *, + const struct ieee80211_channel *); +static void ar5211SetRateTable(struct ath_hal *, + RD_EDGES_POWER *pRdEdgesPower, TRGT_POWER_INFO *pPowerInfo, + uint16_t numChannels, const struct ieee80211_channel *chan); +static uint16_t ar5211GetScaledPower(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct); +static HAL_BOOL ar5211FindValueInList(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue); +static uint16_t ar5211GetInterpolatedValue(uint16_t target, + uint16_t srcLeft, uint16_t srcRight, + uint16_t targetLeft, uint16_t targetRight, HAL_BOOL scaleUp); +static void ar5211GetLowerUpperValues(uint16_t value, + const uint16_t *pList, uint16_t listSize, + uint16_t *pLowerValue, uint16_t *pUpperValue); +static void ar5211GetLowerUpperPcdacs(uint16_t pcdac, + uint16_t channel, const PCDACS_EEPROM *pSrcStruct, + uint16_t *pLowerPcdac, uint16_t *pUpperPcdac); + +static void ar5211SetRfgain(struct ath_hal *, const GAIN_VALUES *); +static void ar5211RequestRfgain(struct ath_hal *); +static HAL_BOOL ar5211InvalidGainReadback(struct ath_hal *, GAIN_VALUES *); +static HAL_BOOL ar5211IsGainAdjustNeeded(struct ath_hal *, const GAIN_VALUES *); +static int32_t ar5211AdjustGain(struct ath_hal *, GAIN_VALUES *); +static void ar5211SetOperatingMode(struct ath_hal *, int opmode); + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + * + * bChannelChange is used to preserve DMA/PCU registers across + * a HW Reset during channel change. + */ +HAL_BOOL +ar5211Reset(struct ath_hal *ah, HAL_OPMODE opmode, + struct ieee80211_channel *chan, HAL_BOOL bChannelChange, + HAL_RESET_TYPE resetType, + HAL_STATUS *status) +{ +uint32_t softLedCfg, softLedState; +#define N(a) (sizeof (a) /sizeof (a[0])) +#define FAIL(_code) do { ecode = _code; goto bad; } while (0) + struct ath_hal_5211 *ahp = AH5211(ah); + HAL_CHANNEL_INTERNAL *ichan; + uint32_t i, ledstate; + HAL_STATUS ecode; + int q; + + uint32_t data, synthDelay; + uint32_t macStaId1; + uint16_t modesIndex = 0, freqIndex = 0; + uint32_t saveFrameSeqCount[AR_NUM_DCU]; + uint32_t saveTsfLow = 0, saveTsfHigh = 0; + uint32_t saveDefAntenna; + + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: opmode %u channel %u/0x%x %s channel\n", + __func__, opmode, chan->ic_freq, chan->ic_flags, + bChannelChange ? "change" : "same"); + + OS_MARK(ah, AH_MARK_RESET, bChannelChange); + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) + FAIL(HAL_EINVAL); + switch (opmode) { + case HAL_M_STA: + case HAL_M_IBSS: + case HAL_M_HOSTAP: + case HAL_M_MONITOR: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid operating mode %u\n", __func__, opmode); + FAIL(HAL_EINVAL); + break; + } + HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3); + + /* Preserve certain DMA hardware registers on a channel change */ + if (bChannelChange) { + /* + * Need to save/restore the TSF because of an issue + * that accelerates the TSF during a chip reset. + * + * We could use system timer routines to more + * accurately restore the TSF, but + * 1. Timer routines on certain platforms are + * not accurate enough (e.g. 1 ms resolution). + * 2. It would still not be accurate. + * + * The most important aspect of this workaround, + * is that, after reset, the TSF is behind + * other STAs TSFs. This will allow the STA to + * properly resynchronize its TSF in adhoc mode. + */ + saveTsfLow = OS_REG_READ(ah, AR_TSF_L32); + saveTsfHigh = OS_REG_READ(ah, AR_TSF_U32); + + /* Read frame sequence count */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) { + saveFrameSeqCount[0] = OS_REG_READ(ah, AR_D0_SEQNUM); + } else { + for (i = 0; i < AR_NUM_DCU; i++) + saveFrameSeqCount[i] = OS_REG_READ(ah, AR_DSEQNUM(i)); + } + if (!IEEE80211_IS_CHAN_DFS(chan)) + chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT; + } + + /* + * Preserve the antenna on a channel change + */ + saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA); + if (saveDefAntenna == 0) + saveDefAntenna = 1; + + /* Save hardware flag before chip reset clears the register */ + macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; + + /* Save led state from pci config register */ + ledstate = OS_REG_READ(ah, AR_PCICFG) & + (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK | + AR_PCICFG_LEDSLOW); + softLedCfg = OS_REG_READ(ah, AR_GPIOCR); + softLedState = OS_REG_READ(ah, AR_GPIODO); + + if (!ar5211ChipReset(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + FAIL(HAL_EIO); + } + + /* Setup the indices for the next set of register array writes */ + if (IEEE80211_IS_CHAN_5GHZ(chan)) { + freqIndex = 1; + if (IEEE80211_IS_CHAN_TURBO(chan)) + modesIndex = 2; + else if (IEEE80211_IS_CHAN_A(chan)) + modesIndex = 1; + else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x\n", + __func__, chan->ic_freq, chan->ic_flags); + FAIL(HAL_EINVAL); + } + } else { + freqIndex = 2; + if (IEEE80211_IS_CHAN_B(chan)) + modesIndex = 3; + else if (IEEE80211_IS_CHAN_PUREG(chan)) + modesIndex = 4; + else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x\n", + __func__, chan->ic_freq, chan->ic_flags); + FAIL(HAL_EINVAL); + } + } + + /* Set correct Baseband to analog shift setting to access analog chips. */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) { + OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007); + } else { + OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000047); + } + + /* Write parameters specific to AR5211 */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) { + if (IEEE80211_IS_CHAN_2GHZ(chan) && + AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1) { + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint32_t ob2GHz, db2GHz; + + if (IEEE80211_IS_CHAN_CCK(chan)) { + ob2GHz = ee->ee_ob2GHz[0]; + db2GHz = ee->ee_db2GHz[0]; + } else { + ob2GHz = ee->ee_ob2GHz[1]; + db2GHz = ee->ee_db2GHz[1]; + } + ob2GHz = ath_hal_reverseBits(ob2GHz, 3); + db2GHz = ath_hal_reverseBits(db2GHz, 3); + ar5211Mode2_4[25][freqIndex] = + (ar5211Mode2_4[25][freqIndex] & ~0xC0) | + ((ob2GHz << 6) & 0xC0); + ar5211Mode2_4[26][freqIndex] = + (ar5211Mode2_4[26][freqIndex] & ~0x0F) | + (((ob2GHz >> 2) & 0x1) | + ((db2GHz << 1) & 0x0E)); + } + for (i = 0; i < N(ar5211Mode2_4); i++) + OS_REG_WRITE(ah, ar5211Mode2_4[i][0], + ar5211Mode2_4[i][freqIndex]); + } + + /* Write the analog registers 6 and 7 before other config */ + ar5211SetRf6and7(ah, chan); + + /* Write registers that vary across all modes */ + for (i = 0; i < N(ar5211Modes); i++) + OS_REG_WRITE(ah, ar5211Modes[i][0], ar5211Modes[i][modesIndex]); + + /* Write RFGain Parameters that differ between 2.4 and 5 GHz */ + for (i = 0; i < N(ar5211BB_RfGain); i++) + OS_REG_WRITE(ah, ar5211BB_RfGain[i][0], ar5211BB_RfGain[i][freqIndex]); + + /* Write Common Array Parameters */ + for (i = 0; i < N(ar5211Common); i++) { + uint32_t reg = ar5211Common[i][0]; + /* On channel change, don't reset the PCU registers */ + if (!(bChannelChange && (0x8000 <= reg && reg < 0x9000))) + OS_REG_WRITE(ah, reg, ar5211Common[i][1]); + } + + /* Fix pre-AR5211 register values, this includes AR5311s. */ + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) { + /* + * The TX and RX latency values have changed locations + * within the USEC register in AR5211. Since they're + * set via the .ini, for both AR5211 and AR5311, they + * are written properly here for AR5311. + */ + data = OS_REG_READ(ah, AR_USEC); + /* Must be 0 for proper write in AR5311 */ + HALASSERT((data & 0x00700000) == 0); + OS_REG_WRITE(ah, AR_USEC, + (data & (AR_USEC_M | AR_USEC_32_M | AR5311_USEC_TX_LAT_M)) | + ((29 << AR5311_USEC_RX_LAT_S) & AR5311_USEC_RX_LAT_M)); + /* The following registers exist only on AR5311. */ + OS_REG_WRITE(ah, AR5311_QDCLKGATE, 0); + + /* Set proper ADC & DAC delays for AR5311. */ + OS_REG_WRITE(ah, 0x00009878, 0x00000008); + + /* Enable the PCU FIFO corruption ECO on AR5311. */ + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) | AR5311_DIAG_SW_USE_ECO); + } + + /* Restore certain DMA hardware registers on a channel change */ + if (bChannelChange) { + /* Restore TSF */ + OS_REG_WRITE(ah, AR_TSF_L32, saveTsfLow); + OS_REG_WRITE(ah, AR_TSF_U32, saveTsfHigh); + + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) { + OS_REG_WRITE(ah, AR_D0_SEQNUM, saveFrameSeqCount[0]); + } else { + for (i = 0; i < AR_NUM_DCU; i++) + OS_REG_WRITE(ah, AR_DSEQNUM(i), saveFrameSeqCount[i]); + } + } + + OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); + OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4) + | macStaId1 + ); + ar5211SetOperatingMode(ah, opmode); + + /* Restore previous led state */ + OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate); + OS_REG_WRITE(ah, AR_GPIOCR, softLedCfg); + OS_REG_WRITE(ah, AR_GPIODO, softLedState); + + /* Restore previous antenna */ + OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); + + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4)); + + /* Restore bmiss rssi & count thresholds */ + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + + OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */ + + /* + * for pre-Production Oahu only. + * Disable clock gating in all DMA blocks. Helps when using + * 11B and AES but results in higher power consumption. + */ + if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_OAHU && + AH_PRIVATE(ah)->ah_macRev < AR_SREV_OAHU_PROD) { + OS_REG_WRITE(ah, AR_CFG, + OS_REG_READ(ah, AR_CFG) | AR_CFG_CLK_GATE_DIS); + } + + /* Setup the transmit power values. */ + if (!ar5211SetTransmitPower(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + FAIL(HAL_EIO); + } + + /* + * Configurable OFDM spoofing for 11n compatibility; used + * only when operating in station mode. + */ + if (opmode != HAL_M_HOSTAP && + (AH_PRIVATE(ah)->ah_11nCompat & HAL_DIAG_11N_SERVICES) != 0) { + /* NB: override the .ini setting */ + OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, + AR_PHY_FRAME_CTL_ERR_SERV, + MS(AH_PRIVATE(ah)->ah_11nCompat, HAL_DIAG_11N_SERVICES)&1); + } + + /* Setup board specific options for EEPROM version 3 */ + ar5211SetBoardValues(ah, chan); + + if (!ar5211SetChannel(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set channel\n", + __func__); + FAIL(HAL_EIO); + } + + /* Activate the PHY */ + if (AH_PRIVATE(ah)->ah_devid == AR5211_FPGA11B && + IEEE80211_IS_CHAN_2GHZ(chan)) + OS_REG_WRITE(ah, 0xd808, 0x502); /* required for FPGA */ + OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + + /* + * Wait for the frequency synth to settle (synth goes on + * via AR_PHY_ACTIVE_EN). Read the phy active delay register. + * Value is in 100ns increments. + */ + data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_M; + if (IEEE80211_IS_CHAN_CCK(chan)) { + synthDelay = (4 * data) / 22; + } else { + synthDelay = data / 10; + } + /* + * There is an issue if the AP starts the calibration before + * the baseband timeout completes. This could result in the + * rxclear false triggering. Add an extra delay to ensure this + * this does not happen. + */ + OS_DELAY(synthDelay + DELAY_BASE_ACTIVATE); + + /* Calibrate the AGC and wait for completion. */ + OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, + OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL); + (void) ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0); + + /* Perform noise floor and set status */ + if (!ar5211CalNoiseFloor(ah, chan)) { + if (!IEEE80211_IS_CHAN_CCK(chan)) + chan->ic_state |= IEEE80211_CHANSTATE_CWINT; + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: noise floor calibration failed\n", __func__); + FAIL(HAL_EIO); + } + + /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */ + if (ahp->ah_calibrationTime != 0) { + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_DO_IQCAL | (INIT_IQCAL_LOG_COUNT_MAX << AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S)); + ahp->ah_bIQCalibration = AH_TRUE; + } + + /* set 1:1 QCU to DCU mapping for all queues */ + for (q = 0; q < AR_NUM_DCU; q++) + OS_REG_WRITE(ah, AR_DQCUMASK(q), 1<ah_maskReg = INIT_INTERRUPT_MASK; + + /* Enable bus error interrupts */ + OS_REG_WRITE(ah, AR_IMR_S2, OS_REG_READ(ah, AR_IMR_S2) | + AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR); + + /* Enable interrupts specific to AP */ + if (opmode == HAL_M_HOSTAP) { + OS_REG_WRITE(ah, AR_IMR, OS_REG_READ(ah, AR_IMR) | AR_IMR_MIB); + ahp->ah_maskReg |= AR_IMR_MIB; + } + + if (AH_PRIVATE(ah)->ah_rfkillEnabled) + ar5211EnableRfKill(ah); + + /* + * Writing to AR_BEACON will start timers. Hence it should + * be the last register to be written. Do not reset tsf, do + * not enable beacons at this point, but preserve other values + * like beaconInterval. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF))); + + /* Restore user-specified slot time and timeouts */ + if (ahp->ah_sifstime != (u_int) -1) + ar5211SetSifsTime(ah, ahp->ah_sifstime); + if (ahp->ah_slottime != (u_int) -1) + ar5211SetSlotTime(ah, ahp->ah_slottime); + if (ahp->ah_acktimeout != (u_int) -1) + ar5211SetAckTimeout(ah, ahp->ah_acktimeout); + if (ahp->ah_ctstimeout != (u_int) -1) + ar5211SetCTSTimeout(ah, ahp->ah_ctstimeout); + if (AH_PRIVATE(ah)->ah_diagreg != 0) + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); + + AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); + + return AH_TRUE; +bad: + if (status != AH_NULL) + *status = ecode; + return AH_FALSE; +#undef FAIL +#undef N +} + +/* + * Places the PHY and Radio chips into reset. A full reset + * must be called to leave this state. The PCI/MAC/PCU are + * not placed into reset as we must receive interrupt to + * re-enable the hardware. + */ +HAL_BOOL +ar5211PhyDisable(struct ath_hal *ah) +{ + return ar5211SetResetReg(ah, AR_RC_BB); +} + +/* + * Places all of hardware into reset + */ +HAL_BOOL +ar5211Disable(struct ath_hal *ah) +{ + if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + /* + * Reset the HW - PCI must be reset after the rest of the + * device has been reset. + */ + if (!ar5211SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI)) + return AH_FALSE; + OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */ + + return AH_TRUE; +} + +/* + * Places the hardware into reset and then pulls it out of reset + * + * Only write the PLL if we're changing to or from CCK mode + * + * Attach calls with channelFlags = 0, as the coldreset should have + * us in the correct mode and we cannot check the hwchannel flags. + */ +HAL_BOOL +ar5211ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* NB: called from attach with chan null */ + if (chan != AH_NULL) { + /* Set CCK and Turbo modes correctly */ + OS_REG_WRITE(ah, AR_PHY_TURBO, IEEE80211_IS_CHAN_TURBO(chan) ? + AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT : 0); + if (IEEE80211_IS_CHAN_B(chan)) { + OS_REG_WRITE(ah, AR5211_PHY_MODE, + AR5211_PHY_MODE_CCK | AR5211_PHY_MODE_RF2GHZ); + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_44); + /* Wait for the PLL to settle */ + OS_DELAY(DELAY_PLL_SETTLE); + } else if (AH_PRIVATE(ah)->ah_devid == AR5211_DEVID) { + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_40); + OS_DELAY(DELAY_PLL_SETTLE); + OS_REG_WRITE(ah, AR5211_PHY_MODE, + AR5211_PHY_MODE_OFDM | (IEEE80211_IS_CHAN_2GHZ(chan) ? + AR5211_PHY_MODE_RF2GHZ : + AR5211_PHY_MODE_RF5GHZ)); + } + } + + /* + * Reset the HW - PCI must be reset after the rest of the + * device has been reset + */ + if (!ar5211SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI)) + return AH_FALSE; + OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */ + + /* Bring out of sleep mode (AGAIN) */ + if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* Clear warm reset register */ + return ar5211SetResetReg(ah, 0); +} + +/* + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +HAL_BOOL +ar5211PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + HAL_CHANNEL_INTERNAL *ichan; + int32_t qCoff, qCoffDenom; + uint32_t data; + int32_t iqCorrMeas; + int32_t iCoff, iCoffDenom; + uint32_t powerMeasQ, powerMeasI; + + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->ic_freq, chan->ic_flags); + return AH_FALSE; + } + /* IQ calibration in progress. Check to see if it has finished. */ + if (ahp->ah_bIQCalibration && + !(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_IQCAL)) { + /* IQ Calibration has finished. */ + ahp->ah_bIQCalibration = AH_FALSE; + + /* Read calibration results. */ + powerMeasI = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_I); + powerMeasQ = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_Q); + iqCorrMeas = OS_REG_READ(ah, AR_PHY_IQCAL_RES_IQ_CORR_MEAS); + + /* + * Prescale these values to remove 64-bit operation requirement at the loss + * of a little precision. + */ + iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; + qCoffDenom = powerMeasQ / 64; + + /* Protect against divide-by-0. */ + if (iCoffDenom != 0 && qCoffDenom != 0) { + iCoff = (-iqCorrMeas) / iCoffDenom; + /* IQCORR_Q_I_COFF is a signed 6 bit number */ + iCoff = iCoff & 0x3f; + + qCoff = ((int32_t)powerMeasI / qCoffDenom) - 64; + /* IQCORR_Q_Q_COFF is a signed 5 bit number */ + qCoff = qCoff & 0x1f; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, "powerMeasI = 0x%08x\n", + powerMeasI); + HALDEBUG(ah, HAL_DEBUG_PERCAL, "powerMeasQ = 0x%08x\n", + powerMeasQ); + HALDEBUG(ah, HAL_DEBUG_PERCAL, "iqCorrMeas = 0x%08x\n", + iqCorrMeas); + HALDEBUG(ah, HAL_DEBUG_PERCAL, "iCoff = %d\n", + iCoff); + HALDEBUG(ah, HAL_DEBUG_PERCAL, "qCoff = %d\n", + qCoff); + + /* Write IQ */ + data = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) | + AR_PHY_TIMING_CTRL4_IQCORR_ENABLE | + (((uint32_t)iCoff) << AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S) | + ((uint32_t)qCoff); + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4, data); + } + } + *isCalDone = !ahp->ah_bIQCalibration; + + if (longCal) { + /* Perform noise floor and set status */ + if (!ar5211IsNfGood(ah, chan)) { + /* report up and clear internal state */ + chan->ic_state |= IEEE80211_CHANSTATE_CWINT; + return AH_FALSE; + } + if (!ar5211CalNoiseFloor(ah, chan)) { + /* + * Delay 5ms before retrying the noise floor + * just to make sure, as we are in an error + * condition here. + */ + OS_DELAY(5000); + if (!ar5211CalNoiseFloor(ah, chan)) { + if (!IEEE80211_IS_CHAN_CCK(chan)) + chan->ic_state |= IEEE80211_CHANSTATE_CWINT; + return AH_FALSE; + } + } + ar5211RequestRfgain(ah); + } + return AH_TRUE; +} + +HAL_BOOL +ar5211PerCalibration(struct ath_hal *ah, struct ieee80211_channel *chan, + HAL_BOOL *isIQdone) +{ + return ar5211PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone); +} + +HAL_BOOL +ar5211ResetCalValid(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + /* XXX */ + return AH_TRUE; +} + +/* + * Writes the given reset bit mask into the reset register + */ +static HAL_BOOL +ar5211SetResetReg(struct ath_hal *ah, uint32_t resetMask) +{ + uint32_t mask = resetMask ? resetMask : ~0; + HAL_BOOL rt; + + (void) OS_REG_READ(ah, AR_RXDP);/* flush any pending MMR writes */ + OS_REG_WRITE(ah, AR_RC, resetMask); + + /* need to wait at least 128 clocks when reseting PCI before read */ + OS_DELAY(15); + + resetMask &= AR_RC_MAC | AR_RC_BB; + mask &= AR_RC_MAC | AR_RC_BB; + rt = ath_hal_wait(ah, AR_RC, mask, resetMask); + if ((resetMask & AR_RC_MAC) == 0) { + if (isBigEndian()) { + /* + * Set CFG, little-endian for descriptor accesses. + */ + mask = INIT_CONFIG_STATUS | AR_CFG_SWTD | AR_CFG_SWRD; + OS_REG_WRITE(ah, AR_CFG, mask); + } else + OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS); + } + return rt; +} + +/* + * Takes the MHz channel value and sets the Channel value + * + * ASSUMES: Writes enabled to analog bus before AGC is active + * or by disabling the AGC. + */ +static HAL_BOOL +ar5211SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t refClk, reg32, data2111; + int16_t chan5111, chanIEEE; + + chanIEEE = chan->ic_ieee; + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + const CHAN_INFO_2GHZ* ci = + &chan2GHzData[chanIEEE + CI_2GHZ_INDEX_CORRECTION]; + + data2111 = ((ath_hal_reverseBits(ci->channelSelect, 8) & 0xff) + << 5) + | (ci->refClkSel << 4); + chan5111 = ci->channel5111; + } else { + data2111 = 0; + chan5111 = chanIEEE; + } + + /* Rest of the code is common for 5 GHz and 2.4 GHz. */ + if (chan5111 >= 145 || (chan5111 & 0x1)) { + reg32 = ath_hal_reverseBits(chan5111 - 24, 8) & 0xFF; + refClk = 1; + } else { + reg32 = ath_hal_reverseBits(((chan5111 - 24) / 2), 8) & 0xFF; + refClk = 0; + } + + reg32 = (reg32 << 2) | (refClk << 1) | (1 << 10) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), ((data2111 & 0xff) << 8) | (reg32 & 0xff)); + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x34), (data2111 & 0xff00) | (reg32 & 0xff)); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +static int16_t +ar5211GetNoiseFloor(struct ath_hal *ah) +{ + int16_t nf; + + nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + return nf; +} + +/* + * Peform the noisefloor calibration for the length of time set + * in runTime (valid values 1 to 7) + * + * Returns: The NF value at the end of the given time (or 0 for failure) + */ +int16_t +ar5211RunNoiseFloor(struct ath_hal *ah, uint8_t runTime, int16_t startingNF) +{ + int i, searchTime; + + HALASSERT(runTime <= 7); + + /* Setup noise floor run time and starting value */ + OS_REG_WRITE(ah, AR_PHY(25), + (OS_REG_READ(ah, AR_PHY(25)) & ~0xFFF) | + ((runTime << 9) & 0xE00) | (startingNF & 0x1FF)); + /* Calibrate the noise floor */ + OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, + OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); + + /* Compute the required amount of searchTime needed to finish NF */ + if (runTime == 0) { + /* 8 search windows * 6.4us each */ + searchTime = 8 * 7; + } else { + /* 512 * runtime search windows * 6.4us each */ + searchTime = (runTime * 512) * 7; + } + + /* + * Do not read noise floor until it has been updated + * + * As a guesstimate - we may only get 1/60th the time on + * the air to see search windows in a heavily congested + * network (40 us every 2400 us of time) + */ + for (i = 0; i < 60; i++) { + if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) + break; + OS_DELAY(searchTime); + } + if (i >= 60) { + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF with runTime %d failed to end on channel %d\n", + runTime, AH_PRIVATE(ah)->ah_curchan->ic_freq); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + " PHY NF Reg state: 0x%x\n", + OS_REG_READ(ah, AR_PHY_AGC_CONTROL)); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + " PHY Active Reg state: 0x%x\n", + OS_REG_READ(ah, AR_PHY_ACTIVE)); + return 0; + } + + return ar5211GetNoiseFloor(ah); +} + +static HAL_BOOL +getNoiseFloorThresh(struct ath_hal *ah, const struct ieee80211_channel *chan, + int16_t *nft) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) { + case IEEE80211_CHAN_A: + *nft = ee->ee_noiseFloorThresh[0]; + break; + case IEEE80211_CHAN_B: + *nft = ee->ee_noiseFloorThresh[1]; + break; + case IEEE80211_CHAN_PUREG: + *nft = ee->ee_noiseFloorThresh[2]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->ic_flags); + return AH_FALSE; + } + return AH_TRUE; +} + +/* + * Read the NF and check it against the noise floor threshhold + * + * Returns: TRUE if the NF is good + */ +static HAL_BOOL +ar5211IsNfGood(struct ath_hal *ah, struct ieee80211_channel *chan) +{ + HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); + int16_t nf, nfThresh; + + if (!getNoiseFloorThresh(ah, chan, &nfThresh)) + return AH_FALSE; + if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: NF did not complete in calibration window\n", __func__); + } + nf = ar5211GetNoiseFloor(ah); + if (nf > nfThresh) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: noise floor failed; detected %u, threshold %u\n", + __func__, nf, nfThresh); + /* + * NB: Don't discriminate 2.4 vs 5Ghz, if this + * happens it indicates a problem regardless + * of the band. + */ + chan->ic_state |= IEEE80211_CHANSTATE_CWINT; + } + ichan->rawNoiseFloor = nf; + return (nf <= nfThresh); +} + +/* + * Peform the noisefloor calibration and check for any constant channel + * interference. + * + * NOTE: preAR5211 have a lengthy carrier wave detection process - hence + * it is if'ed for MKK regulatory domain only. + * + * Returns: TRUE for a successful noise floor calibration; else FALSE + */ +HAL_BOOL +ar5211CalNoiseFloor(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) + /* Check for Carrier Wave interference in MKK regulatory zone */ + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU && + (chan->ic_flags & CHANNEL_NFCREQUIRED)) { + static const uint8_t runtime[3] = { 0, 2, 7 }; + HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); + int16_t nf, nfThresh; + int i; + + if (!getNoiseFloorThresh(ah, chan, &nfThresh)) + return AH_FALSE; + /* + * Run a quick noise floor that will hopefully + * complete (decrease delay time). + */ + for (i = 0; i < N(runtime); i++) { + nf = ar5211RunNoiseFloor(ah, runtime[i], 0); + if (nf > nfThresh) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: run failed with %u > threshold %u " + "(runtime %u)\n", __func__, + nf, nfThresh, runtime[i]); + ichan->rawNoiseFloor = 0; + } else + ichan->rawNoiseFloor = nf; + } + return (i <= N(runtime)); + } else { + /* Calibrate the noise floor */ + OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, + OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | + AR_PHY_AGC_CONTROL_NF); + } + return AH_TRUE; +#undef N +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + */ +int16_t +ar5211GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + static const struct { + uint16_t freqLow; + int16_t adjust; + } adjust5111[] = { + { 5790, 11 }, /* NB: ordered high -> low */ + { 5730, 10 }, + { 5690, 9 }, + { 5660, 8 }, + { 5610, 7 }, + { 5530, 5 }, + { 5450, 4 }, + { 5379, 2 }, + { 5209, 0 }, /* XXX? bogus but doesn't matter */ + { 0, 1 }, + }; + int i; + + for (i = 0; c->channel <= adjust5111[i].freqLow; i++) + ; + /* NB: placeholder for 5111's less severe requirement */ + return adjust5111[i].adjust / 3; +} + +/* + * Reads EEPROM header info from device structure and programs + * analog registers 6 and 7 + * + * REQUIRES: Access to the analog device + */ +static HAL_BOOL +ar5211SetRf6and7(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) + uint16_t freq = ath_hal_gethwchannel(ah, chan); + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ath_hal_5211 *ahp = AH5211(ah); + uint16_t rfXpdGain, rfPloSel, rfPwdXpd; + uint16_t tempOB, tempDB; + uint16_t freqIndex; + int i; + + freqIndex = IEEE80211_IS_CHAN_2GHZ(chan) ? 2 : 1; + + /* + * TODO: This array mode correspondes with the index used + * during the read. + * For readability, this should be changed to an enum or #define + */ + switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) { + case IEEE80211_CHAN_A: + if (freq > 4000 && freq < 5260) { + tempOB = ee->ee_ob1; + tempDB = ee->ee_db1; + } else if (freq >= 5260 && freq < 5500) { + tempOB = ee->ee_ob2; + tempDB = ee->ee_db2; + } else if (freq >= 5500 && freq < 5725) { + tempOB = ee->ee_ob3; + tempDB = ee->ee_db3; + } else if (freq >= 5725) { + tempOB = ee->ee_ob4; + tempDB = ee->ee_db4; + } else { + /* XXX panic?? */ + tempOB = tempDB = 0; + } + + rfXpdGain = ee->ee_xgain[0]; + rfPloSel = ee->ee_xpd[0]; + rfPwdXpd = !ee->ee_xpd[0]; + + ar5211Rf6n7[5][freqIndex] = + (ar5211Rf6n7[5][freqIndex] & ~0x10000000) | + (ee->ee_cornerCal.pd84<< 28); + ar5211Rf6n7[6][freqIndex] = + (ar5211Rf6n7[6][freqIndex] & ~0x04000000) | + (ee->ee_cornerCal.pd90 << 26); + ar5211Rf6n7[21][freqIndex] = + (ar5211Rf6n7[21][freqIndex] & ~0x08) | + (ee->ee_cornerCal.gSel << 3); + break; + case IEEE80211_CHAN_B: + tempOB = ee->ee_obFor24; + tempDB = ee->ee_dbFor24; + rfXpdGain = ee->ee_xgain[1]; + rfPloSel = ee->ee_xpd[1]; + rfPwdXpd = !ee->ee_xpd[1]; + break; + case IEEE80211_CHAN_PUREG: + tempOB = ee->ee_obFor24g; + tempDB = ee->ee_dbFor24g; + rfXpdGain = ee->ee_xgain[2]; + rfPloSel = ee->ee_xpd[2]; + rfPwdXpd = !ee->ee_xpd[2]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->ic_flags); + return AH_FALSE; + } + + HALASSERT(1 <= tempOB && tempOB <= 5); + HALASSERT(1 <= tempDB && tempDB <= 5); + + /* Set rfXpdGain and rfPwdXpd */ + ar5211Rf6n7[11][freqIndex] = (ar5211Rf6n7[11][freqIndex] & ~0xC0) | + (((ath_hal_reverseBits(rfXpdGain, 4) << 7) | (rfPwdXpd << 6)) & 0xC0); + ar5211Rf6n7[12][freqIndex] = (ar5211Rf6n7[12][freqIndex] & ~0x07) | + ((ath_hal_reverseBits(rfXpdGain, 4) >> 1) & 0x07); + + /* Set OB */ + ar5211Rf6n7[12][freqIndex] = (ar5211Rf6n7[12][freqIndex] & ~0x80) | + ((ath_hal_reverseBits(tempOB, 3) << 7) & 0x80); + ar5211Rf6n7[13][freqIndex] = (ar5211Rf6n7[13][freqIndex] & ~0x03) | + ((ath_hal_reverseBits(tempOB, 3) >> 1) & 0x03); + + /* Set DB */ + ar5211Rf6n7[13][freqIndex] = (ar5211Rf6n7[13][freqIndex] & ~0x1C) | + ((ath_hal_reverseBits(tempDB, 3) << 2) & 0x1C); + + /* Set rfPloSel */ + ar5211Rf6n7[17][freqIndex] = (ar5211Rf6n7[17][freqIndex] & ~0x08) | + ((rfPloSel << 3) & 0x08); + + /* Write the Rf registers 6 & 7 */ + for (i = 0; i < N(ar5211Rf6n7); i++) + OS_REG_WRITE(ah, ar5211Rf6n7[i][0], ar5211Rf6n7[i][freqIndex]); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = RFGAIN_INACTIVE; + + return AH_TRUE; +#undef N +} + +HAL_BOOL +ar5211SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings, + const struct ieee80211_channel *chan) +{ +#define ANT_SWITCH_TABLE1 0x9960 +#define ANT_SWITCH_TABLE2 0x9964 + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ath_hal_5211 *ahp = AH5211(ah); + uint32_t antSwitchA, antSwitchB; + int ix; + + switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) { + case IEEE80211_CHAN_A: ix = 0; break; + case IEEE80211_CHAN_B: ix = 1; break; + case IEEE80211_CHAN_PUREG: ix = 2; break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->ic_flags); + return AH_FALSE; + } + + antSwitchA = ee->ee_antennaControl[1][ix] + | (ee->ee_antennaControl[2][ix] << 6) + | (ee->ee_antennaControl[3][ix] << 12) + | (ee->ee_antennaControl[4][ix] << 18) + | (ee->ee_antennaControl[5][ix] << 24) + ; + antSwitchB = ee->ee_antennaControl[6][ix] + | (ee->ee_antennaControl[7][ix] << 6) + | (ee->ee_antennaControl[8][ix] << 12) + | (ee->ee_antennaControl[9][ix] << 18) + | (ee->ee_antennaControl[10][ix] << 24) + ; + /* + * For fixed antenna, give the same setting for both switch banks + */ + switch (settings) { + case HAL_ANT_FIXED_A: + antSwitchB = antSwitchA; + break; + case HAL_ANT_FIXED_B: + antSwitchA = antSwitchB; + break; + case HAL_ANT_VARIABLE: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad antenna setting %u\n", + __func__, settings); + return AH_FALSE; + } + ahp->ah_diversityControl = settings; + + OS_REG_WRITE(ah, ANT_SWITCH_TABLE1, antSwitchA); + OS_REG_WRITE(ah, ANT_SWITCH_TABLE2, antSwitchB); + + return AH_TRUE; +#undef ANT_SWITCH_TABLE1 +#undef ANT_SWITCH_TABLE2 +} + +/* + * Reads EEPROM header info and programs the device for correct operation + * given the channel value + */ +static HAL_BOOL +ar5211SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ath_hal_5211 *ahp = AH5211(ah); + int arrayMode, falseDectectBackoff; + + switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) { + case IEEE80211_CHAN_A: + arrayMode = 0; + OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, + AR_PHY_FRAME_CTL_TX_CLIP, ee->ee_cornerCal.clip); + break; + case IEEE80211_CHAN_B: + arrayMode = 1; + break; + case IEEE80211_CHAN_PUREG: + arrayMode = 2; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->ic_flags); + return AH_FALSE; + } + + /* Set the antenna register(s) correctly for the chip revision */ + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) { + OS_REG_WRITE(ah, AR_PHY(68), + (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFFFC) | 0x3); + } else { + OS_REG_WRITE(ah, AR_PHY(68), + (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFC06) | + (ee->ee_antennaControl[0][arrayMode] << 4) | 0x1); + + ar5211SetAntennaSwitchInternal(ah, + ahp->ah_diversityControl, chan); + + /* Set the Noise Floor Thresh on ar5211 devices */ + OS_REG_WRITE(ah, AR_PHY_BASE + (90 << 2), + (ee->ee_noiseFloorThresh[arrayMode] & 0x1FF) | (1<<9)); + } + OS_REG_WRITE(ah, AR_PHY_BASE + (17 << 2), + (OS_REG_READ(ah, AR_PHY_BASE + (17 << 2)) & 0xFFFFC07F) | + ((ee->ee_switchSettling[arrayMode] << 7) & 0x3F80)); + OS_REG_WRITE(ah, AR_PHY_BASE + (18 << 2), + (OS_REG_READ(ah, AR_PHY_BASE + (18 << 2)) & 0xFFFC0FFF) | + ((ee->ee_txrxAtten[arrayMode] << 12) & 0x3F000)); + OS_REG_WRITE(ah, AR_PHY_BASE + (20 << 2), + (OS_REG_READ(ah, AR_PHY_BASE + (20 << 2)) & 0xFFFF0000) | + ((ee->ee_pgaDesiredSize[arrayMode] << 8) & 0xFF00) | + (ee->ee_adcDesiredSize[arrayMode] & 0x00FF)); + OS_REG_WRITE(ah, AR_PHY_BASE + (13 << 2), + (ee->ee_txEndToXPAOff[arrayMode] << 24) | + (ee->ee_txEndToXPAOff[arrayMode] << 16) | + (ee->ee_txFrameToXPAOn[arrayMode] << 8) | + ee->ee_txFrameToXPAOn[arrayMode]); + OS_REG_WRITE(ah, AR_PHY_BASE + (10 << 2), + (OS_REG_READ(ah, AR_PHY_BASE + (10 << 2)) & 0xFFFF00FF) | + (ee->ee_txEndToXLNAOn[arrayMode] << 8)); + OS_REG_WRITE(ah, AR_PHY_BASE + (25 << 2), + (OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) & 0xFFF80FFF) | + ((ee->ee_thresh62[arrayMode] << 12) & 0x7F000)); + +#define NO_FALSE_DETECT_BACKOFF 2 +#define CB22_FALSE_DETECT_BACKOFF 6 + /* + * False detect backoff - suspected 32 MHz spur causes + * false detects in OFDM, causing Tx Hangs. Decrease + * weak signal sensitivity for this card. + */ + falseDectectBackoff = NO_FALSE_DETECT_BACKOFF; + if (AH_PRIVATE(ah)->ah_eeversion < AR_EEPROM_VER3_3) { + if (AH_PRIVATE(ah)->ah_subvendorid == 0x1022 && + IEEE80211_IS_CHAN_OFDM(chan)) + falseDectectBackoff += CB22_FALSE_DETECT_BACKOFF; + } else { + uint16_t freq = ath_hal_gethwchannel(ah, chan); + uint32_t remainder = freq % 32; + + if (remainder && (remainder < 10 || remainder > 22)) + falseDectectBackoff += ee->ee_falseDetectBackoff[arrayMode]; + } + OS_REG_WRITE(ah, 0x9924, + (OS_REG_READ(ah, 0x9924) & 0xFFFFFF01) + | ((falseDectectBackoff << 1) & 0xF7)); + + return AH_TRUE; +#undef NO_FALSE_DETECT_BACKOFF +#undef CB22_FALSE_DETECT_BACKOFF +} + +/* + * Set the limit on the overall output power. Used for dynamic + * transmit power control and the like. + * + * NOTE: The power is passed in is in units of 0.5 dBm. + */ +HAL_BOOL +ar5211SetTxPowerLimit(struct ath_hal *ah, uint32_t limit) +{ + + AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, limit); + return AH_TRUE; +} + +/* + * Sets the transmit power in the baseband for the given + * operating channel and mode. + */ +static HAL_BOOL +ar5211SetTransmitPower(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + TRGT_POWER_INFO *pi; + RD_EDGES_POWER *rep; + PCDACS_EEPROM eepromPcdacs; + u_int nchan, cfgCtl; + int i; + + /* setup the pcdac struct to point to the correct info, based on mode */ + switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) { + case IEEE80211_CHAN_A: + eepromPcdacs.numChannels = ee->ee_numChannels11a; + eepromPcdacs.pChannelList= ee->ee_channels11a; + eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11a; + nchan = ee->ee_numTargetPwr_11a; + pi = ee->ee_trgtPwr_11a; + break; + case IEEE80211_CHAN_PUREG: + eepromPcdacs.numChannels = ee->ee_numChannels2_4; + eepromPcdacs.pChannelList= ee->ee_channels11g; + eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11g; + nchan = ee->ee_numTargetPwr_11g; + pi = ee->ee_trgtPwr_11g; + break; + case IEEE80211_CHAN_B: + eepromPcdacs.numChannels = ee->ee_numChannels2_4; + eepromPcdacs.pChannelList= ee->ee_channels11b; + eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11b; + nchan = ee->ee_numTargetPwr_11b; + pi = ee->ee_trgtPwr_11b; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->ic_flags); + return AH_FALSE; + } + + ar5211SetPowerTable(ah, &eepromPcdacs, freq); + + rep = AH_NULL; + /* Match CTL to EEPROM value */ + cfgCtl = ath_hal_getctl(ah, chan); + for (i = 0; i < ee->ee_numCtls; i++) + if (ee->ee_ctl[i] != 0 && ee->ee_ctl[i] == cfgCtl) { + rep = &ee->ee_rdEdgesPower[i * NUM_EDGES]; + break; + } + ar5211SetRateTable(ah, rep, pi, nchan, chan); + + return AH_TRUE; +} + +/* + * Read the transmit power levels from the structures taken + * from EEPROM. Interpolate read transmit power values for + * this channel. Organize the transmit power values into a + * table for writing into the hardware. + */ +void +ar5211SetPowerTable(struct ath_hal *ah, PCDACS_EEPROM *pSrcStruct, + uint16_t channel) +{ + static FULL_PCDAC_STRUCT pcdacStruct; + static uint16_t pcdacTable[PWR_TABLE_SIZE]; + + uint16_t i, j; + uint16_t *pPcdacValues; + int16_t *pScaledUpDbm; + int16_t minScaledPwr; + int16_t maxScaledPwr; + int16_t pwr; + uint16_t pcdacMin = 0; + uint16_t pcdacMax = 63; + uint16_t pcdacTableIndex; + uint16_t scaledPcdac; + uint32_t addr; + uint32_t temp32; + + OS_MEMZERO(&pcdacStruct, sizeof(FULL_PCDAC_STRUCT)); + OS_MEMZERO(pcdacTable, sizeof(uint16_t) * PWR_TABLE_SIZE); + pPcdacValues = pcdacStruct.PcdacValues; + pScaledUpDbm = pcdacStruct.PwrValues; + + /* Initialize the pcdacs to dBM structs pcdacs to be 1 to 63 */ + for (i = PCDAC_START, j = 0; i <= PCDAC_STOP; i+= PCDAC_STEP, j++) + pPcdacValues[j] = i; + + pcdacStruct.numPcdacValues = j; + pcdacStruct.pcdacMin = PCDAC_START; + pcdacStruct.pcdacMax = PCDAC_STOP; + + /* Fill out the power values for this channel */ + for (j = 0; j < pcdacStruct.numPcdacValues; j++ ) + pScaledUpDbm[j] = ar5211GetScaledPower(channel, pPcdacValues[j], pSrcStruct); + + /* Now scale the pcdac values to fit in the 64 entry power table */ + minScaledPwr = pScaledUpDbm[0]; + maxScaledPwr = pScaledUpDbm[pcdacStruct.numPcdacValues - 1]; + + /* find minimum and make monotonic */ + for (j = 0; j < pcdacStruct.numPcdacValues; j++) { + if (minScaledPwr >= pScaledUpDbm[j]) { + minScaledPwr = pScaledUpDbm[j]; + pcdacMin = j; + } + /* + * Make the full_hsh monotonically increasing otherwise + * interpolation algorithm will get fooled gotta start + * working from the top, hence i = 63 - j. + */ + i = (uint16_t)(pcdacStruct.numPcdacValues - 1 - j); + if (i == 0) + break; + if (pScaledUpDbm[i-1] > pScaledUpDbm[i]) { + /* + * It could be a glitch, so make the power for + * this pcdac the same as the power from the + * next highest pcdac. + */ + pScaledUpDbm[i - 1] = pScaledUpDbm[i]; + } + } + + for (j = 0; j < pcdacStruct.numPcdacValues; j++) + if (maxScaledPwr < pScaledUpDbm[j]) { + maxScaledPwr = pScaledUpDbm[j]; + pcdacMax = j; + } + + /* Find the first power level with a pcdac */ + pwr = (uint16_t)(PWR_STEP * ((minScaledPwr - PWR_MIN + PWR_STEP / 2) / PWR_STEP) + PWR_MIN); + + /* Write all the first pcdac entries based off the pcdacMin */ + pcdacTableIndex = 0; + for (i = 0; i < (2 * (pwr - PWR_MIN) / EEP_SCALE + 1); i++) + pcdacTable[pcdacTableIndex++] = pcdacMin; + + i = 0; + while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1]) { + pwr += PWR_STEP; + /* stop if dbM > max_power_possible */ + while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] && + (pwr - pScaledUpDbm[i])*(pwr - pScaledUpDbm[i+1]) > 0) + i++; + /* scale by 2 and add 1 to enable round up or down as needed */ + scaledPcdac = (uint16_t)(ar5211GetInterpolatedValue(pwr, + pScaledUpDbm[i], pScaledUpDbm[i+1], + (uint16_t)(pPcdacValues[i] * 2), + (uint16_t)(pPcdacValues[i+1] * 2), 0) + 1); + + pcdacTable[pcdacTableIndex] = scaledPcdac / 2; + if (pcdacTable[pcdacTableIndex] > pcdacMax) + pcdacTable[pcdacTableIndex] = pcdacMax; + pcdacTableIndex++; + } + + /* Write all the last pcdac entries based off the last valid pcdac */ + while (pcdacTableIndex < PWR_TABLE_SIZE) { + pcdacTable[pcdacTableIndex] = pcdacTable[pcdacTableIndex - 1]; + pcdacTableIndex++; + } + + /* Finally, write the power values into the baseband power table */ + addr = AR_PHY_BASE + (608 << 2); + for (i = 0; i < 32; i++) { + temp32 = 0xffff & ((pcdacTable[2 * i + 1] << 8) | 0xff); + temp32 = (temp32 << 16) | (0xffff & ((pcdacTable[2 * i] << 8) | 0xff)); + OS_REG_WRITE(ah, addr, temp32); + addr += 4; + } + +} + +/* + * Set the transmit power in the baseband for the given + * operating channel and mode. + */ +static void +ar5211SetRateTable(struct ath_hal *ah, RD_EDGES_POWER *pRdEdgesPower, + TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels, + const struct ieee80211_channel *chan) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ath_hal_5211 *ahp = AH5211(ah); + static uint16_t ratesArray[NUM_RATES]; + static const uint16_t tpcScaleReductionTable[5] = + { 0, 3, 6, 9, MAX_RATE_POWER }; + + uint16_t *pRatesPower; + uint16_t lowerChannel, lowerIndex=0, lowerPower=0; + uint16_t upperChannel, upperIndex=0, upperPower=0; + uint16_t twiceMaxEdgePower=63; + uint16_t twicePower = 0; + uint16_t i, numEdges; + uint16_t tempChannelList[NUM_EDGES]; /* temp array for holding edge channels */ + uint16_t twiceMaxRDPower; + int16_t scaledPower = 0; /* for gcc -O2 */ + uint16_t mask = 0x3f; + HAL_BOOL paPreDEnable = 0; + int8_t twiceAntennaGain, twiceAntennaReduction = 0; + + pRatesPower = ratesArray; + twiceMaxRDPower = chan->ic_maxregpower * 2; + + if (IEEE80211_IS_CHAN_5GHZ(chan)) { + twiceAntennaGain = ee->ee_antennaGainMax[0]; + } else { + twiceAntennaGain = ee->ee_antennaGainMax[1]; + } + + twiceAntennaReduction = ath_hal_getantennareduction(ah, chan, twiceAntennaGain); + + if (pRdEdgesPower) { + /* Get the edge power */ + for (i = 0; i < NUM_EDGES; i++) { + if (pRdEdgesPower[i].rdEdge == 0) + break; + tempChannelList[i] = pRdEdgesPower[i].rdEdge; + } + numEdges = i; + + ar5211GetLowerUpperValues(freq, tempChannelList, + numEdges, &lowerChannel, &upperChannel); + /* Get the index for this channel */ + for (i = 0; i < numEdges; i++) + if (lowerChannel == tempChannelList[i]) + break; + HALASSERT(i != numEdges); + + if ((lowerChannel == upperChannel && + lowerChannel == freq) || + pRdEdgesPower[i].flag) { + twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower; + HALASSERT(twiceMaxEdgePower > 0); + } + } + + /* extrapolate the power values for the test Groups */ + for (i = 0; i < numChannels; i++) + tempChannelList[i] = pPowerInfo[i].testChannel; + + ar5211GetLowerUpperValues(freq, tempChannelList, + numChannels, &lowerChannel, &upperChannel); + + /* get the index for the channel */ + for (i = 0; i < numChannels; i++) { + if (lowerChannel == tempChannelList[i]) + lowerIndex = i; + if (upperChannel == tempChannelList[i]) { + upperIndex = i; + break; + } + } + + for (i = 0; i < NUM_RATES; i++) { + if (IEEE80211_IS_CHAN_OFDM(chan)) { + /* power for rates 6,9,12,18,24 is all the same */ + if (i < 5) { + lowerPower = pPowerInfo[lowerIndex].twicePwr6_24; + upperPower = pPowerInfo[upperIndex].twicePwr6_24; + } else if (i == 5) { + lowerPower = pPowerInfo[lowerIndex].twicePwr36; + upperPower = pPowerInfo[upperIndex].twicePwr36; + } else if (i == 6) { + lowerPower = pPowerInfo[lowerIndex].twicePwr48; + upperPower = pPowerInfo[upperIndex].twicePwr48; + } else if (i == 7) { + lowerPower = pPowerInfo[lowerIndex].twicePwr54; + upperPower = pPowerInfo[upperIndex].twicePwr54; + } + } else { + switch (i) { + case 0: + case 1: + lowerPower = pPowerInfo[lowerIndex].twicePwr6_24; + upperPower = pPowerInfo[upperIndex].twicePwr6_24; + break; + case 2: + case 3: + lowerPower = pPowerInfo[lowerIndex].twicePwr36; + upperPower = pPowerInfo[upperIndex].twicePwr36; + break; + case 4: + case 5: + lowerPower = pPowerInfo[lowerIndex].twicePwr48; + upperPower = pPowerInfo[upperIndex].twicePwr48; + break; + case 6: + case 7: + lowerPower = pPowerInfo[lowerIndex].twicePwr54; + upperPower = pPowerInfo[upperIndex].twicePwr54; + break; + } + } + + twicePower = ar5211GetInterpolatedValue(freq, + lowerChannel, upperChannel, lowerPower, upperPower, 0); + + /* Reduce power by band edge restrictions */ + twicePower = AH_MIN(twicePower, twiceMaxEdgePower); + + /* + * If turbo is set, reduce power to keep power + * consumption under 2 Watts. Note that we always do + * this unless specially configured. Then we limit + * power only for non-AP operation. + */ + if (IEEE80211_IS_CHAN_TURBO(chan) && + AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1 +#ifdef AH_ENABLE_AP_SUPPORT + && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP +#endif + ) { + twicePower = AH_MIN(twicePower, ee->ee_turbo2WMaxPower5); + } + + /* Reduce power by max regulatory domain allowed restrictions */ + pRatesPower[i] = AH_MIN(twicePower, twiceMaxRDPower - twiceAntennaReduction); + + /* Use 6 Mb power level for transmit power scaling reduction */ + /* We don't want to reduce higher rates if its not needed */ + if (i == 0) { + scaledPower = pRatesPower[0] - + (tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale] * 2); + if (scaledPower < 1) + scaledPower = 1; + } + + pRatesPower[i] = AH_MIN(pRatesPower[i], scaledPower); + } + + /* Record txPower at Rate 6 for info gathering */ + ahp->ah_tx6PowerInHalfDbm = pRatesPower[0]; + +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: final output power setting %d MHz:\n", + __func__, chan->ic_freq); + HALDEBUG(ah, HAL_DEBUG_RESET, + "6 Mb %d dBm, MaxRD: %d dBm, MaxEdge %d dBm\n", + scaledPower / 2, twiceMaxRDPower / 2, twiceMaxEdgePower / 2); + HALDEBUG(ah, HAL_DEBUG_RESET, "TPC Scale %d dBm - Ant Red %d dBm\n", + tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale] * 2, + twiceAntennaReduction / 2); + if (IEEE80211_IS_CHAN_TURBO(chan) && + AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1) + HALDEBUG(ah, HAL_DEBUG_RESET, "Max Turbo %d dBm\n", + ee->ee_turbo2WMaxPower5); + HALDEBUG(ah, HAL_DEBUG_RESET, + " %2d | %2d | %2d | %2d | %2d | %2d | %2d | %2d dBm\n", + pRatesPower[0] / 2, pRatesPower[1] / 2, pRatesPower[2] / 2, + pRatesPower[3] / 2, pRatesPower[4] / 2, pRatesPower[5] / 2, + pRatesPower[6] / 2, pRatesPower[7] / 2); +#endif /* AH_DEBUG */ + + /* Write the power table into the hardware */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, + ((paPreDEnable & 1)<< 30) | ((pRatesPower[3] & mask) << 24) | + ((paPreDEnable & 1)<< 22) | ((pRatesPower[2] & mask) << 16) | + ((paPreDEnable & 1)<< 14) | ((pRatesPower[1] & mask) << 8) | + ((paPreDEnable & 1)<< 6 ) | (pRatesPower[0] & mask)); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, + ((paPreDEnable & 1)<< 30) | ((pRatesPower[7] & mask) << 24) | + ((paPreDEnable & 1)<< 22) | ((pRatesPower[6] & mask) << 16) | + ((paPreDEnable & 1)<< 14) | ((pRatesPower[5] & mask) << 8) | + ((paPreDEnable & 1)<< 6 ) | (pRatesPower[4] & mask)); + + /* set max power to the power value at rate 6 */ + ar5211SetTxPowerLimit(ah, pRatesPower[0]); + + AH_PRIVATE(ah)->ah_maxPowerLevel = pRatesPower[0]; +} + +/* + * Get or interpolate the pcdac value from the calibrated data + */ +uint16_t +ar5211GetScaledPower(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct) +{ + uint16_t powerValue; + uint16_t lFreq, rFreq; /* left and right frequency values */ + uint16_t llPcdac, ulPcdac; /* lower and upper left pcdac values */ + uint16_t lrPcdac, urPcdac; /* lower and upper right pcdac values */ + uint16_t lPwr, uPwr; /* lower and upper temp pwr values */ + uint16_t lScaledPwr, rScaledPwr; /* left and right scaled power */ + + if (ar5211FindValueInList(channel, pcdacValue, pSrcStruct, &powerValue)) + /* value was copied from srcStruct */ + return powerValue; + + ar5211GetLowerUpperValues(channel, pSrcStruct->pChannelList, + pSrcStruct->numChannels, &lFreq, &rFreq); + ar5211GetLowerUpperPcdacs(pcdacValue, lFreq, pSrcStruct, + &llPcdac, &ulPcdac); + ar5211GetLowerUpperPcdacs(pcdacValue, rFreq, pSrcStruct, + &lrPcdac, &urPcdac); + + /* get the power index for the pcdac value */ + ar5211FindValueInList(lFreq, llPcdac, pSrcStruct, &lPwr); + ar5211FindValueInList(lFreq, ulPcdac, pSrcStruct, &uPwr); + lScaledPwr = ar5211GetInterpolatedValue(pcdacValue, + llPcdac, ulPcdac, lPwr, uPwr, 0); + + ar5211FindValueInList(rFreq, lrPcdac, pSrcStruct, &lPwr); + ar5211FindValueInList(rFreq, urPcdac, pSrcStruct, &uPwr); + rScaledPwr = ar5211GetInterpolatedValue(pcdacValue, + lrPcdac, urPcdac, lPwr, uPwr, 0); + + return ar5211GetInterpolatedValue(channel, lFreq, rFreq, + lScaledPwr, rScaledPwr, 0); +} + +/* + * Find the value from the calibrated source data struct + */ +HAL_BOOL +ar5211FindValueInList(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue) +{ + const DATA_PER_CHANNEL *pChannelData; + const uint16_t *pPcdac; + uint16_t i, j; + + pChannelData = pSrcStruct->pDataPerChannel; + for (i = 0; i < pSrcStruct->numChannels; i++ ) { + if (pChannelData->channelValue == channel) { + pPcdac = pChannelData->PcdacValues; + for (j = 0; j < pChannelData->numPcdacValues; j++ ) { + if (*pPcdac == pcdacValue) { + *powerValue = pChannelData->PwrValues[j]; + return AH_TRUE; + } + pPcdac++; + } + } + pChannelData++; + } + return AH_FALSE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +uint16_t +ar5211GetInterpolatedValue(uint16_t target, + uint16_t srcLeft, uint16_t srcRight, + uint16_t targetLeft, uint16_t targetRight, + HAL_BOOL scaleUp) +{ + uint16_t rv; + int16_t lRatio; + uint16_t scaleValue = EEP_SCALE; + + /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */ + if ((targetLeft * targetRight) == 0) + return 0; + if (scaleUp) + scaleValue = 1; + + if (srcRight != srcLeft) { + /* + * Note the ratio always need to be scaled, + * since it will be a fraction. + */ + lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft); + if (lRatio < 0) { + /* Return as Left target if value would be negative */ + rv = targetLeft * (scaleUp ? EEP_SCALE : 1); + } else if (lRatio > EEP_SCALE) { + /* Return as Right target if Ratio is greater than 100% (SCALE) */ + rv = targetRight * (scaleUp ? EEP_SCALE : 1); + } else { + rv = (lRatio * targetRight + (EEP_SCALE - lRatio) * + targetLeft) / scaleValue; + } + } else { + rv = targetLeft; + if (scaleUp) + rv *= EEP_SCALE; + } + return rv; +} + +/* + * Look for value being within 0.1 of the search values + * however, NDIS can't do float calculations, so multiply everything + * up by EEP_SCALE so can do integer arithmatic + * + * INPUT value -value to search for + * INPUT pList -ptr to the list to search + * INPUT listSize -number of entries in list + * OUTPUT pLowerValue -return the lower value + * OUTPUT pUpperValue -return the upper value + */ +void +ar5211GetLowerUpperValues(uint16_t value, + const uint16_t *pList, uint16_t listSize, + uint16_t *pLowerValue, uint16_t *pUpperValue) +{ + const uint16_t listEndValue = *(pList + listSize - 1); + uint32_t target = value * EEP_SCALE; + int i; + + /* + * See if value is lower than the first value in the list + * if so return first value + */ + if (target < (uint32_t)(*pList * EEP_SCALE - EEP_DELTA)) { + *pLowerValue = *pList; + *pUpperValue = *pList; + return; + } + + /* + * See if value is greater than last value in list + * if so return last value + */ + if (target > (uint32_t)(listEndValue * EEP_SCALE + EEP_DELTA)) { + *pLowerValue = listEndValue; + *pUpperValue = listEndValue; + return; + } + + /* look for value being near or between 2 values in list */ + for (i = 0; i < listSize; i++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (abs(pList[i] * EEP_SCALE - (int32_t) target) < EEP_DELTA) { + *pLowerValue = pList[i]; + *pUpperValue = pList[i]; + return; + } + + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < (uint32_t)(pList[i + 1] * EEP_SCALE - EEP_DELTA)) { + *pLowerValue = pList[i]; + *pUpperValue = pList[i + 1]; + return; + } + } +} + +/* + * Get the upper and lower pcdac given the channel and the pcdac + * used in the search + */ +void +ar5211GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel, + const PCDACS_EEPROM *pSrcStruct, + uint16_t *pLowerPcdac, uint16_t *pUpperPcdac) +{ + const DATA_PER_CHANNEL *pChannelData; + int i; + + /* Find the channel information */ + pChannelData = pSrcStruct->pDataPerChannel; + for (i = 0; i < pSrcStruct->numChannels; i++) { + if (pChannelData->channelValue == channel) + break; + pChannelData++; + } + ar5211GetLowerUpperValues(pcdac, pChannelData->PcdacValues, + pChannelData->numPcdacValues, pLowerPcdac, pUpperPcdac); +} + +#define DYN_ADJ_UP_MARGIN 15 +#define DYN_ADJ_LO_MARGIN 20 + +static const GAIN_OPTIMIZATION_LADDER gainLadder = { + 9, /* numStepsInLadder */ + 4, /* defaultStepNum */ + { { {4, 1, 1, 1}, 6, "FG8"}, + { {4, 0, 1, 1}, 4, "FG7"}, + { {3, 1, 1, 1}, 3, "FG6"}, + { {4, 0, 0, 1}, 1, "FG5"}, + { {4, 1, 1, 0}, 0, "FG4"}, /* noJack */ + { {4, 0, 1, 0}, -2, "FG3"}, /* halfJack */ + { {3, 1, 1, 0}, -3, "FG2"}, /* clip3 */ + { {4, 0, 0, 0}, -4, "FG1"}, /* noJack */ + { {2, 1, 1, 0}, -6, "FG0"} /* clip2 */ + } +}; + +/* + * Initialize the gain structure to good values + */ +void +ar5211InitializeGainValues(struct ath_hal *ah) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + + /* initialize gain optimization values */ + gv->currStepNum = gainLadder.defaultStepNum; + gv->currStep = &gainLadder.optStep[gainLadder.defaultStepNum]; + gv->active = AH_TRUE; + gv->loTrig = 20; + gv->hiTrig = 35; +} + +static HAL_BOOL +ar5211InvalidGainReadback(struct ath_hal *ah, GAIN_VALUES *gv) +{ + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + uint32_t gStep, g; + uint32_t L1, L2, L3, L4; + + if (IEEE80211_IS_CHAN_CCK(chan)) { + gStep = 0x18; + L1 = 0; + L2 = gStep + 4; + L3 = 0x40; + L4 = L3 + 50; + + gv->loTrig = L1; + gv->hiTrig = L4+5; + } else { + gStep = 0x3f; + L1 = 0; + L2 = 50; + L3 = L1; + L4 = L3 + 50; + + gv->loTrig = L1 + DYN_ADJ_LO_MARGIN; + gv->hiTrig = L4 - DYN_ADJ_UP_MARGIN; + } + g = gv->currGain; + + return !((g >= L1 && g<= L2) || (g >= L3 && g <= L4)); +} + +/* + * Enable the probe gain check on the next packet + */ +static void +ar5211RequestRfgain(struct ath_hal *ah) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + /* Enable the gain readback probe */ + OS_REG_WRITE(ah, AR_PHY_PAPD_PROBE, + SM(ahp->ah_tx6PowerInHalfDbm, AR_PHY_PAPD_PROBE_POWERTX) + | AR_PHY_PAPD_PROBE_NEXT_TX); + + ahp->ah_rfgainState = HAL_RFGAIN_READ_REQUESTED; +} + +/* + * Exported call to check for a recent gain reading and return + * the current state of the thermal calibration gain engine. + */ +HAL_RFGAIN +ar5211GetRfgain(struct ath_hal *ah) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + uint32_t rddata; + + if (!gv->active) + return HAL_RFGAIN_INACTIVE; + + if (ahp->ah_rfgainState == HAL_RFGAIN_READ_REQUESTED) { + /* Caller had asked to setup a new reading. Check it. */ + rddata = OS_REG_READ(ah, AR_PHY_PAPD_PROBE); + + if ((rddata & AR_PHY_PAPD_PROBE_NEXT_TX) == 0) { + /* bit got cleared, we have a new reading. */ + gv->currGain = rddata >> AR_PHY_PAPD_PROBE_GAINF_S; + /* inactive by default */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + if (!ar5211InvalidGainReadback(ah, gv) && + ar5211IsGainAdjustNeeded(ah, gv) && + ar5211AdjustGain(ah, gv) > 0) { + /* + * Change needed. Copy ladder info + * into eeprom info. + */ + ar5211SetRfgain(ah, gv); + ahp->ah_rfgainState = HAL_RFGAIN_NEED_CHANGE; + } + } + } + return ahp->ah_rfgainState; +} + +/* + * Check to see if our readback gain level sits within the linear + * region of our current variable attenuation window + */ +static HAL_BOOL +ar5211IsGainAdjustNeeded(struct ath_hal *ah, const GAIN_VALUES *gv) +{ + return (gv->currGain <= gv->loTrig || gv->currGain >= gv->hiTrig); +} + +/* + * Move the rabbit ears in the correct direction. + */ +static int32_t +ar5211AdjustGain(struct ath_hal *ah, GAIN_VALUES *gv) +{ + /* return > 0 for valid adjustments. */ + if (!gv->active) + return -1; + + gv->currStep = &gainLadder.optStep[gv->currStepNum]; + if (gv->currGain >= gv->hiTrig) { + if (gv->currStepNum == 0) { + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Max gain limit.\n", __func__); + return -1; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Adding gain: currG=%d [%s] --> ", + __func__, gv->currGain, gv->currStep->stepName); + gv->targetGain = gv->currGain; + while (gv->targetGain >= gv->hiTrig && gv->currStepNum > 0) { + gv->targetGain -= 2 * (gainLadder.optStep[--(gv->currStepNum)].stepGain - + gv->currStep->stepGain); + gv->currStep = &gainLadder.optStep[gv->currStepNum]; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n", + gv->targetGain, gv->currStep->stepName); + return 1; + } + if (gv->currGain <= gv->loTrig) { + if (gv->currStepNum == gainLadder.numStepsInLadder-1) { + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Min gain limit.\n", __func__); + return -2; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Deducting gain: currG=%d [%s] --> ", + __func__, gv->currGain, gv->currStep->stepName); + gv->targetGain = gv->currGain; + while (gv->targetGain <= gv->loTrig && + gv->currStepNum < (gainLadder.numStepsInLadder - 1)) { + gv->targetGain -= 2 * + (gainLadder.optStep[++(gv->currStepNum)].stepGain - gv->currStep->stepGain); + gv->currStep = &gainLadder.optStep[gv->currStepNum]; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n", + gv->targetGain, gv->currStep->stepName); + return 2; + } + return 0; /* caller didn't call needAdjGain first */ +} + +/* + * Adjust the 5GHz EEPROM information with the desired calibration values. + */ +static void +ar5211SetRfgain(struct ath_hal *ah, const GAIN_VALUES *gv) +{ + HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + if (!gv->active) + return; + ee->ee_cornerCal.clip = gv->currStep->paramVal[0]; /* bb_tx_clip */ + ee->ee_cornerCal.pd90 = gv->currStep->paramVal[1]; /* rf_pwd_90 */ + ee->ee_cornerCal.pd84 = gv->currStep->paramVal[2]; /* rf_pwd_84 */ + ee->ee_cornerCal.gSel = gv->currStep->paramVal[3]; /* rf_rfgainsel */ +} + +static void +ar5211SetOperatingMode(struct ath_hal *ah, int opmode) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + uint32_t val; + + val = OS_REG_READ(ah, AR_STA_ID1) & 0xffff; + switch (opmode) { + case HAL_M_HOSTAP: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_STA_AP + | AR_STA_ID1_RTS_USE_DEF + | ahp->ah_staId1Defaults); + break; + case HAL_M_IBSS: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_ADHOC + | AR_STA_ID1_DESC_ANTENNA + | ahp->ah_staId1Defaults); + break; + case HAL_M_STA: + case HAL_M_MONITOR: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_DEFAULT_ANTENNA + | ahp->ah_staId1Defaults); + break; + } +} + +void +ar5211SetPCUConfig(struct ath_hal *ah) +{ + ar5211SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode); +} diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211_xmit.c b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_xmit.c new file mode 100644 index 0000000..dc0ad3f --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211_xmit.c @@ -0,0 +1,701 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5211/ar5211.h" +#include "ar5211/ar5211reg.h" +#include "ar5211/ar5211desc.h" + +/* + * Update Tx FIFO trigger level. + * + * Set bIncTrigLevel to TRUE to increase the trigger level. + * Set bIncTrigLevel to FALSE to decrease the trigger level. + * + * Returns TRUE if the trigger level was updated + */ +HAL_BOOL +ar5211UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel) +{ + uint32_t curTrigLevel, txcfg; + HAL_INT ints = ar5211GetInterrupts(ah); + + /* + * Disable chip interrupts. This is because halUpdateTxTrigLevel + * is called from both ISR and non-ISR contexts. + */ + ar5211SetInterrupts(ah, ints &~ HAL_INT_GLOBAL); + txcfg = OS_REG_READ(ah, AR_TXCFG); + curTrigLevel = (txcfg & AR_TXCFG_FTRIG_M) >> AR_TXCFG_FTRIG_S; + if (bIncTrigLevel){ + /* increase the trigger level */ + curTrigLevel = curTrigLevel + + ((MAX_TX_FIFO_THRESHOLD - curTrigLevel) / 2); + } else { + /* decrease the trigger level if not already at the minimum */ + if (curTrigLevel > MIN_TX_FIFO_THRESHOLD) { + /* decrease the trigger level */ + curTrigLevel--; + } else { + /* no update to the trigger level */ + /* re-enable chip interrupts */ + ar5211SetInterrupts(ah, ints); + return AH_FALSE; + } + } + /* Update the trigger level */ + OS_REG_WRITE(ah, AR_TXCFG, (txcfg &~ AR_TXCFG_FTRIG_M) | + ((curTrigLevel << AR_TXCFG_FTRIG_S) & AR_TXCFG_FTRIG_M)); + /* re-enable chip interrupts */ + ar5211SetInterrupts(ah, ints); + return AH_TRUE; +} + +/* + * Set the properties of the tx queue with the parameters + * from qInfo. The queue must previously have been setup + * with a call to ar5211SetupTxQueue. + */ +HAL_BOOL +ar5211SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo); +} + +/* + * Return the properties for the specified tx queue. + */ +HAL_BOOL +ar5211GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]); +} + +/* + * Allocate and initialize a tx DCU/QCU combination. + */ +int +ar5211SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + HAL_TX_QUEUE_INFO *qi; + int q; + + switch (type) { + case HAL_TX_QUEUE_BEACON: + q = 9; + break; + case HAL_TX_QUEUE_CAB: + q = 8; + break; + case HAL_TX_QUEUE_DATA: + q = 0; + if (ahp->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE) + return q; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad tx queue type %u\n", + __func__, type); + return -1; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + + qi = &ahp->ah_txq[q]; + if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n", + __func__, q); + return -1; + } + OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); + qi->tqi_type = type; + if (qInfo == AH_NULL) { + /* by default enable OK+ERR+DESC+URN interrupts */ + qi->tqi_qflags = + HAL_TXQ_TXOKINT_ENABLE + | HAL_TXQ_TXERRINT_ENABLE + | HAL_TXQ_TXDESCINT_ENABLE + | HAL_TXQ_TXURNINT_ENABLE + ; + qi->tqi_aifs = INIT_AIFS; + qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ + qi->tqi_cwmax = INIT_CWMAX; + qi->tqi_shretry = INIT_SH_RETRY; + qi->tqi_lgretry = INIT_LG_RETRY; + } else + (void) ar5211SetTxQueueProps(ah, q, qInfo); + return q; +} + +/* + * Update the h/w interrupt registers to reflect a tx q's configuration. + */ +static void +setTxQInterrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", __func__ + , ahp->ah_txOkInterruptMask + , ahp->ah_txErrInterruptMask + , ahp->ah_txDescInterruptMask + , ahp->ah_txEolInterruptMask + , ahp->ah_txUrnInterruptMask + ); + + OS_REG_WRITE(ah, AR_IMR_S0, + SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK) + | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC) + ); + OS_REG_WRITE(ah, AR_IMR_S1, + SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR) + | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL) + ); + OS_REG_RMW_FIELD(ah, AR_IMR_S2, + AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask); +} + + +/* + * Free a tx DCU/QCU combination. + */ +HAL_BOOL +ar5211ReleaseTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + HAL_TX_QUEUE_INFO *qi; + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_FALSE; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q); + + qi->tqi_type = HAL_TX_QUEUE_INACTIVE; + ahp->ah_txOkInterruptMask &= ~(1 << q); + ahp->ah_txErrInterruptMask &= ~(1 << q); + ahp->ah_txDescInterruptMask &= ~(1 << q); + ahp->ah_txEolInterruptMask &= ~(1 << q); + ahp->ah_txUrnInterruptMask &= ~(1 << q); + setTxQInterrupts(ah, qi); + + return AH_TRUE; +} + +/* + * Set the retry, aifs, cwmin/max, readyTime regs for specified queue + */ +HAL_BOOL +ar5211ResetTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5211 *ahp = AH5211(ah); + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + HAL_TX_QUEUE_INFO *qi; + uint32_t cwMin, chanCwMin, value; + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_TRUE; /* XXX??? */ + } + + if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) { + /* + * Select cwmin according to channel type. + * NB: chan can be NULL during attach + */ + if (chan && IEEE80211_IS_CHAN_B(chan)) + chanCwMin = INIT_CWMIN_11B; + else + chanCwMin = INIT_CWMIN; + /* make sure that the CWmin is of the form (2^n - 1) */ + for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1) + ; + } else + cwMin = qi->tqi_cwmin; + + /* set cwMin/Max and AIFS values */ + OS_REG_WRITE(ah, AR_DLCL_IFS(q), + SM(cwMin, AR_D_LCL_IFS_CWMIN) + | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) + | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); + + /* Set retry limit values */ + OS_REG_WRITE(ah, AR_DRETRY_LIMIT(q), + SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) + | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) + | SM(qi->tqi_lgretry, AR_D_RETRY_LIMIT_FR_LG) + | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH) + ); + + /* enable early termination on the QCU */ + OS_REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); + + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) { + /* Configure DCU to use the global sequence count */ + OS_REG_WRITE(ah, AR_DMISC(q), AR5311_D_MISC_SEQ_NUM_CONTROL); + } + /* multiqueue support */ + if (qi->tqi_cbrPeriod) { + OS_REG_WRITE(ah, AR_QCBRCFG(q), + SM(qi->tqi_cbrPeriod,AR_Q_CBRCFG_CBR_INTERVAL) + | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_CBR_OVF_THRESH)); + OS_REG_WRITE(ah, AR_QMISC(q), + OS_REG_READ(ah, AR_QMISC(q)) | + AR_Q_MISC_FSP_CBR | + (qi->tqi_cbrOverflowLimit ? + AR_Q_MISC_CBR_EXP_CNTR_LIMIT : 0)); + } + if (qi->tqi_readyTime) { + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), + SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT) | + AR_Q_RDYTIMECFG_EN); + } + if (qi->tqi_burstTime) { + OS_REG_WRITE(ah, AR_DCHNTIME(q), + SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | + AR_D_CHNTIME_EN); + if (qi->tqi_qflags & HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE) { + OS_REG_WRITE(ah, AR_QMISC(q), + OS_REG_READ(ah, AR_QMISC(q)) | + AR_Q_MISC_RDYTIME_EXP_POLICY); + } + } + + if (qi->tqi_qflags & HAL_TXQ_BACKOFF_DISABLE) { + OS_REG_WRITE(ah, AR_DMISC(q), + OS_REG_READ(ah, AR_DMISC(q)) | + AR_D_MISC_POST_FR_BKOFF_DIS); + } + if (qi->tqi_qflags & HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE) { + OS_REG_WRITE(ah, AR_DMISC(q), + OS_REG_READ(ah, AR_DMISC(q)) | + AR_D_MISC_FRAG_BKOFF_EN); + } + switch (qi->tqi_type) { + case HAL_TX_QUEUE_BEACON: + /* Configure QCU for beacons */ + OS_REG_WRITE(ah, AR_QMISC(q), + OS_REG_READ(ah, AR_QMISC(q)) + | AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_BEACON_USE + | AR_Q_MISC_CBR_INCR_DIS1); + /* Configure DCU for beacons */ + value = (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S) + | AR_D_MISC_BEACON_USE | AR_D_MISC_POST_FR_BKOFF_DIS; + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) + value |= AR5311_D_MISC_SEQ_NUM_CONTROL; + OS_REG_WRITE(ah, AR_DMISC(q), value); + break; + case HAL_TX_QUEUE_CAB: + /* Configure QCU for CAB (Crap After Beacon) frames */ + OS_REG_WRITE(ah, AR_QMISC(q), + OS_REG_READ(ah, AR_QMISC(q)) + | AR_Q_MISC_FSP_DBA_GATED | AR_Q_MISC_CBR_INCR_DIS1 + | AR_Q_MISC_CBR_INCR_DIS0 | AR_Q_MISC_RDYTIME_EXP_POLICY); + + value = (ahp->ah_beaconInterval + - (ah->ah_config.ah_sw_beacon_response_time + - ah->ah_config.ah_dma_beacon_response_time) + - ah->ah_config.ah_additional_swba_backoff) * 1024; + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_EN); + + /* Configure DCU for CAB */ + value = (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S); + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) + value |= AR5311_D_MISC_SEQ_NUM_CONTROL; + OS_REG_WRITE(ah, AR_QMISC(q), value); + break; + default: + /* NB: silence compiler */ + break; + } + + /* + * Always update the secondary interrupt mask registers - this + * could be a new queue getting enabled in a running system or + * hw getting re-initialized during a reset! + * + * Since we don't differentiate between tx interrupts corresponding + * to individual queues - secondary tx mask regs are always unmasked; + * tx interrupts are enabled/disabled for all queues collectively + * using the primary mask reg + */ + if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) + ahp->ah_txOkInterruptMask |= 1 << q; + else + ahp->ah_txOkInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) + ahp->ah_txErrInterruptMask |= 1 << q; + else + ahp->ah_txErrInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE) + ahp->ah_txDescInterruptMask |= 1 << q; + else + ahp->ah_txDescInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) + ahp->ah_txEolInterruptMask |= 1 << q; + else + ahp->ah_txEolInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) + ahp->ah_txUrnInterruptMask |= 1 << q; + else + ahp->ah_txUrnInterruptMask &= ~(1 << q); + setTxQInterrupts(ah, qi); + + return AH_TRUE; +} + +/* + * Get the TXDP for the specified data queue. + */ +uint32_t +ar5211GetTxDP(struct ath_hal *ah, u_int q) +{ + HALASSERT(q < HAL_NUM_TX_QUEUES); + return OS_REG_READ(ah, AR_QTXDP(q)); +} + +/* + * Set the TxDP for the specified tx queue. + */ +HAL_BOOL +ar5211SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp) +{ + HALASSERT(q < HAL_NUM_TX_QUEUES); + HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + /* + * Make sure that TXE is deasserted before setting the TXDP. If TXE + * is still asserted, setting TXDP will have no effect. + */ + HALASSERT((OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) == 0); + + OS_REG_WRITE(ah, AR_QTXDP(q), txdp); + + return AH_TRUE; +} + +/* + * Set Transmit Enable bits for the specified queues. + */ +HAL_BOOL +ar5211StartTxDma(struct ath_hal *ah, u_int q) +{ + HALASSERT(q < HAL_NUM_TX_QUEUES); + HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + /* Check that queue is not already active */ + HALASSERT((OS_REG_READ(ah, AR_Q_TXD) & (1<ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + n = OS_REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT_M; + /* + * Pending frame count (PFC) can momentarily go to zero + * while TXE remains asserted. In other words a PFC of + * zero is not sufficient to say that the queue has stopped. + */ + if (n == 0 && (OS_REG_READ(ah, AR_Q_TXE) & (1<ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + OS_REG_WRITE(ah, AR_Q_TXD, 1<ds_ctl0 = (pktLen & AR_FrameLen) + | (txRate0 << AR_XmitRate_S) + | (antMode << AR_AntModeXmit_S) + | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0) + | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0) + | (flags & HAL_TXDESC_RTSENA ? AR_RTSCTSEnable : 0) + | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0) + ; + ads->ds_ctl1 = (type << 26) + | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0) + ; + + if (keyIx != HAL_TXKEYIX_INVALID) { + ads->ds_ctl1 |= + (keyIx << AR_EncryptKeyIdx_S) & AR_EncryptKeyIdx; + ads->ds_ctl0 |= AR_EncryptKeyValid; + } + return AH_TRUE; +#undef RATE +} + +HAL_BOOL +ar5211SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int txRate1, u_int txTries1, + u_int txRate2, u_int txTries2, + u_int txRate3, u_int txTries3) +{ + (void) ah; (void) ds; + (void) txRate1; (void) txTries1; + (void) txRate2; (void) txTries2; + (void) txRate3; (void) txTries3; + return AH_FALSE; +} + +void +ar5211IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds) +{ + struct ar5211_desc *ads = AR5211DESC(ds); + + ads->ds_ctl0 |= AR_TxInterReq; +} + +HAL_BOOL +ar5211FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, + HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, u_int qcuId, + u_int descId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0) +{ + struct ar5211_desc *ads = AR5211DESC(ds); + uint32_t segLen = segLenList[0]; + + ds->ds_data = bufAddrList[0]; + + HALASSERT((segLen &~ AR_BufLen) == 0); + + if (firstSeg) { + /* + * First descriptor, don't clobber xmit control data + * setup by ar5211SetupTxDesc. + */ + ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More); + } else if (lastSeg) { /* !firstSeg && lastSeg */ + /* + * Last descriptor in a multi-descriptor frame, + * copy the transmit parameters from the first + * frame for processing on completion. + */ + ads->ds_ctl0 = AR5211DESC_CONST(ds0)->ds_ctl0; + ads->ds_ctl1 = segLen; + } else { /* !firstSeg && !lastSeg */ + /* + * Intermediate descriptor in a multi-descriptor frame. + */ + ads->ds_ctl0 = 0; + ads->ds_ctl1 = segLen | AR_More; + } + ads->ds_status0 = ads->ds_status1 = 0; + return AH_TRUE; +} + +/* + * Processing of HW TX descriptor. + */ +HAL_STATUS +ar5211ProcTxDesc(struct ath_hal *ah, + struct ath_desc *ds, struct ath_tx_status *ts) +{ + struct ar5211_desc *ads = AR5211DESC(ds); + + if ((ads->ds_status1 & AR_Done) == 0) + return HAL_EINPROGRESS; + + /* Update software copies of the HW status */ + ts->ts_seqnum = MS(ads->ds_status1, AR_SeqNum); + ts->ts_tstamp = MS(ads->ds_status0, AR_SendTimestamp); + ts->ts_status = 0; + if ((ads->ds_status0 & AR_FrmXmitOK) == 0) { + if (ads->ds_status0 & AR_ExcessiveRetries) + ts->ts_status |= HAL_TXERR_XRETRY; + if (ads->ds_status0 & AR_Filtered) + ts->ts_status |= HAL_TXERR_FILT; + if (ads->ds_status0 & AR_FIFOUnderrun) + ts->ts_status |= HAL_TXERR_FIFO; + } + ts->ts_rate = MS(ads->ds_ctl0, AR_XmitRate); + ts->ts_rssi = MS(ads->ds_status1, AR_AckSigStrength); + ts->ts_shortretry = MS(ads->ds_status0, AR_ShortRetryCnt); + ts->ts_longretry = MS(ads->ds_status0, AR_LongRetryCnt); + ts->ts_virtcol = MS(ads->ds_status0, AR_VirtCollCnt); + ts->ts_antenna = 0; /* NB: don't know */ + ts->ts_finaltsi = 0; + /* + * NB: the number of retries is one less than it should be. + * Also, 0 retries and 1 retry are both reported as 0 retries. + */ + if (ts->ts_shortretry > 0) + ts->ts_shortretry++; + if (ts->ts_longretry > 0) + ts->ts_longretry++; + + return HAL_OK; +} + +/* + * Determine which tx queues need interrupt servicing. + * STUB. + */ +void +ar5211GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs) +{ + return; +} + +/* + * Retrieve the rate table from the given TX completion descriptor + */ +HAL_BOOL +ar5211GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries) +{ + return AH_FALSE; +} + + +void +ar5211SetTxDescLink(struct ath_hal *ah, void *ds, uint32_t link) +{ + struct ar5211_desc *ads = AR5211DESC(ds); + + ads->ds_link = link; +} + +void +ar5211GetTxDescLink(struct ath_hal *ah, void *ds, uint32_t *link) +{ + struct ar5211_desc *ads = AR5211DESC(ds); + + *link = ads->ds_link; +} + +void +ar5211GetTxDescLinkPtr(struct ath_hal *ah, void *ds, uint32_t **linkptr) +{ + struct ar5211_desc *ads = AR5211DESC(ds); + + *linkptr = &ads->ds_link; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211desc.h b/sys/external/isc/atheros_hal/dist/ar5211/ar5211desc.h new file mode 100644 index 0000000..8702e91 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211desc.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _DEV_ATH_AR5211DESC_H +#define _DEV_ATH_AR5211DESC_H + +/* + * Defintions for the DMA descriptors used by the Atheros + * AR5211 and AR5110 Wireless Lan controller parts. + */ + +/* DMA descriptors */ +struct ar5211_desc { + uint32_t ds_link; /* link pointer */ + uint32_t ds_data; /* data buffer pointer */ + uint32_t ds_ctl0; /* DMA control 0 */ + uint32_t ds_ctl1; /* DMA control 1 */ + uint32_t ds_status0; /* DMA status 0 */ + uint32_t ds_status1; /* DMA status 1 */ +} __packed; +#define AR5211DESC(_ds) ((struct ar5211_desc *)(_ds)) +#define AR5211DESC_CONST(_ds) ((const struct ar5211_desc *)(_ds)) + +/* TX ds_ctl0 */ +#define AR_FrameLen 0x00000fff /* frame length */ +/* bits 12-17 are reserved */ +#define AR_XmitRate 0x003c0000 /* txrate */ +#define AR_XmitRate_S 18 +#define AR_RTSCTSEnable 0x00400000 /* RTS/CTS enable */ +#define AR_VEOL 0x00800000 /* virtual end-of-list */ +#define AR_ClearDestMask 0x01000000 /* Clear destination mask bit */ +#define AR_AntModeXmit 0x1e000000 /* TX antenna seslection */ +#define AR_AntModeXmit_S 25 +#define AR_TxInterReq 0x20000000 /* TX interrupt request */ +#define AR_EncryptKeyValid 0x40000000 /* EncryptKeyIdx is valid */ +/* bit 31 is reserved */ + +/* TX ds_ctl1 */ +#define AR_BufLen 0x00000fff /* data buffer length */ +#define AR_More 0x00001000 /* more desc in this frame */ +#define AR_EncryptKeyIdx 0x000fe000 /* ecnrypt key table index */ +#define AR_EncryptKeyIdx_S 13 +#define AR_FrmType 0x00700000 /* frame type indication */ +#define AR_FrmType_S 20 +#define AR_Frm_Normal 0x00000000 /* normal frame */ +#define AR_Frm_ATIM 0x00100000 /* ATIM frame */ +#define AR_Frm_PSPOLL 0x00200000 /* PS poll frame */ +#define AR_Frm_Beacon 0x00300000 /* Beacon frame */ +#define AR_Frm_ProbeResp 0x00400000 /* no delay data */ +#define AR_NoAck 0x00800000 /* No ACK flag */ +/* bits 24-31 are reserved */ + +/* RX ds_ctl1 */ +/* AR_BufLen 0x00000fff data buffer length */ +/* bit 12 is reserved */ +#define AR_RxInterReq 0x00002000 /* RX interrupt request */ +/* bits 14-31 are reserved */ + +/* TX ds_status0 */ +#define AR_FrmXmitOK 0x00000001 /* TX success */ +#define AR_ExcessiveRetries 0x00000002 /* excessive retries */ +#define AR_FIFOUnderrun 0x00000004 /* TX FIFO underrun */ +#define AR_Filtered 0x00000008 /* TX filter indication */ +/* NB: the spec has the Short+Long retry counts reversed */ +#define AR_LongRetryCnt 0x000000f0 /* long retry count */ +#define AR_LongRetryCnt_S 4 +#define AR_ShortRetryCnt 0x00000f00 /* short retry count */ +#define AR_ShortRetryCnt_S 8 +#define AR_VirtCollCnt 0x0000f000 /* virtual collision count */ +#define AR_VirtCollCnt_S 12 +#define AR_SendTimestamp 0xffff0000 /* TX timestamp */ +#define AR_SendTimestamp_S 16 + +/* RX ds_status0 */ +#define AR_DataLen 0x00000fff /* RX data length */ +/* AR_More 0x00001000 more desc in this frame */ +/* bits 13-14 are reserved */ +#define AR_RcvRate 0x00078000 /* reception rate */ +#define AR_RcvRate_S 15 +#define AR_RcvSigStrength 0x07f80000 /* receive signal strength */ +#define AR_RcvSigStrength_S 19 +#define AR_RcvAntenna 0x38000000 /* receive antenaa */ +#define AR_RcvAntenna_S 27 +/* bits 30-31 are reserved */ + +/* TX ds_status1 */ +#define AR_Done 0x00000001 /* descripter complete */ +#define AR_SeqNum 0x00001ffe /* TX sequence number */ +#define AR_SeqNum_S 1 +#define AR_AckSigStrength 0x001fe000 /* strength of ACK */ +#define AR_AckSigStrength_S 13 +/* bits 21-31 are reserved */ + +/* RX ds_status1 */ +/* AR_Done 0x00000001 descripter complete */ +#define AR_FrmRcvOK 0x00000002 /* frame reception success */ +#define AR_CRCErr 0x00000004 /* CRC error */ +/* bit 3 reserved */ +#define AR_DecryptCRCErr 0x00000010 /* Decryption CRC fiailure */ +#define AR_PHYErr 0x000000e0 /* PHY error */ +#define AR_PHYErr_S 5 +#define AR_PHYErr_Underrun 0x00000000 /* Transmit underrun */ +#define AR_PHYErr_Tim 0x00000020 /* Timing error */ +#define AR_PHYErr_Par 0x00000040 /* Parity error */ +#define AR_PHYErr_Rate 0x00000060 /* Illegal rate */ +#define AR_PHYErr_Len 0x00000080 /* Illegal length */ +#define AR_PHYErr_Radar 0x000000a0 /* Radar detect */ +#define AR_PHYErr_Srv 0x000000c0 /* Illegal service */ +#define AR_PHYErr_TOR 0x000000e0 /* Transmit override receive */ +#define AR_KeyIdxValid 0x00000100 /* decryption key index valid */ +#define AR_KeyIdx 0x00007e00 /* Decryption key index */ +#define AR_KeyIdx_S 9 +#define AR_RcvTimestamp 0x0fff8000 /* timestamp */ +#define AR_RcvTimestamp_S 15 +#define AR_KeyCacheMiss 0x10000000 /* key cache miss indication */ + +#endif /* _DEV_ATH_AR5211DESC_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211phy.h b/sys/external/isc/atheros_hal/dist/ar5211/ar5211phy.h new file mode 100644 index 0000000..bf5b67e --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211phy.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _DEV_ATH_AR5211PHY_H +#define _DEV_ATH_AR5211PHY_H + +/* + * Definitions for the PHY on the Atheros AR5211/5311 chipset. + */ + +/* PHY registers */ +#define AR_PHY_BASE 0x9800 /* PHY registers base address */ +#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) + +#define AR_PHY_TURBO 0x9804 /* PHY frame control register */ +#define AR_PHY_FC_TURBO_MODE 0x00000001 /* Set turbo mode bits */ +#define AR_PHY_FC_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode setting */ + +#define AR_PHY_CHIP_ID 0x9818 /* PHY chip revision ID */ + +#define AR_PHY_ACTIVE 0x981C /* PHY activation register */ +#define AR_PHY_ACTIVE_EN 0x00000001 /* Activate PHY chips */ +#define AR_PHY_ACTIVE_DIS 0x00000000 /* Deactivate PHY chips */ + +#define AR_PHY_AGC_CONTROL 0x9860 /* PHY chip calibration and noise floor setting */ +#define AR_PHY_AGC_CONTROL_CAL 0x00000001 /* Perform PHY chip internal calibration */ +#define AR_PHY_AGC_CONTROL_NF 0x00000002 /* Perform PHY chip noise-floor calculation */ + +#define AR_PHY_PLL_CTL 0x987c /* PLL control register */ +#define AR_PHY_PLL_CTL_44 0x19 /* 44 MHz for 11b channels and FPGA */ +#define AR_PHY_PLL_CTL_40 0x18 /* 40 MHz */ +#define AR_PHY_PLL_CTL_20 0x13 /* 20 MHz half rate 11a for emulation */ + + +#define AR_PHY_RX_DELAY 0x9914 /* PHY analog_power_on_time, in 100ns increments */ +#define AR_PHY_RX_DELAY_M 0x00003FFF /* Mask for delay from active assertion (wake up) */ + /* to enable_receiver */ + +#define AR_PHY_TIMING_CTRL4 0x9920 /* PHY */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_M 0x0000001F /* Mask for kcos_theta-1 for q correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_M 0x000007E0 /* Mask for sin_theta for i correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 /* Shift for sin_theta for i correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x00000800 /* enable IQ correction */ +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_M 0x0000F000 /* Mask for max number of samples (logarithmic) */ +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 /* Shift for max number of samples */ +#define AR_PHY_TIMING_CTRL4_DO_IQCAL 0x00010000 /* perform IQ calibration */ + +#define AR_PHY_PAPD_PROBE 0x9930 +#define AR_PHY_PAPD_PROBE_POWERTX 0x00007E00 +#define AR_PHY_PAPD_PROBE_POWERTX_S 9 +#define AR_PHY_PAPD_PROBE_NEXT_TX 0x00008000 /* command to take next reading */ +#define AR_PHY_PAPD_PROBE_GAINF 0xFE000000 +#define AR_PHY_PAPD_PROBE_GAINF_S 25 + +#define AR_PHY_POWER_TX_RATE1 0x9934 +#define AR_PHY_POWER_TX_RATE2 0x9938 +#define AR_PHY_POWER_TX_RATE_MAX 0x993c + +#define AR_PHY_FRAME_CTL 0x9944 +#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038 +#define AR_PHY_FRAME_CTL_TX_CLIP_S 3 +#define AR_PHY_FRAME_CTL_ERR_SERV 0x20000000 +#define AR_PHY_FRAME_CTL_ERR_SERV_S 29 + +#define AR_PHY_RADAR_0 0x9954 /* PHY radar detection settings */ +#define AR_PHY_RADAR_0_ENA 0x00000001 /* Enable radar detection */ + +#define AR_PHY_IQCAL_RES_PWR_MEAS_I 0x9c10 /*PHY IQ calibration results - power measurement for I */ +#define AR_PHY_IQCAL_RES_PWR_MEAS_Q 0x9c14 /*PHY IQ calibration results - power measurement for Q */ +#define AR_PHY_IQCAL_RES_IQ_CORR_MEAS 0x9c18 /*PHY IQ calibration results - IQ correlation measurement */ +#define AR_PHY_CURRENT_RSSI 0x9c1c /* rssi of current frame being received */ + +#define AR5211_PHY_MODE 0xA200 /* Mode register */ +#define AR5211_PHY_MODE_OFDM 0x0 /* bit 0 = 0 for OFDM */ +#define AR5211_PHY_MODE_CCK 0x1 /* bit 0 = 1 for CCK */ +#define AR5211_PHY_MODE_RF5GHZ 0x0 /* bit 1 = 0 for 5 GHz */ +#define AR5211_PHY_MODE_RF2GHZ 0x2 /* bit 1 = 1 for 2.4 GHz */ + +#endif /* _DEV_ATH_AR5211PHY_H */ diff --git a/sys/external/isc/atheros_hal/dist/ar5211/ar5211reg.h b/sys/external/isc/atheros_hal/dist/ar5211/ar5211reg.h new file mode 100644 index 0000000..93d4fc5 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/ar5211reg.h @@ -0,0 +1,864 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _DEV_ATH_AR5211REG_H +#define _DEV_ATH_AR5211REG_H + +/* + * Definitions for the Atheros AR5211/5311 chipset. + */ + +/* + * Maui2/Spirit specific registers/fields are indicated by AR5311. + * Oahu specific registers/fields are indicated by AR5211. + */ + +/* DMA Control and Interrupt Registers */ +#define AR_CR 0x0008 /* control register */ +#define AR_RXDP 0x000C /* receive queue descriptor pointer */ +#define AR_CFG 0x0014 /* configuration and status register */ +#define AR_IER 0x0024 /* Interrupt enable register */ +#define AR_RTSD0 0x0028 /* RTS Duration Parameters 0 */ +#define AR_RTSD1 0x002c /* RTS Duration Parameters 1 */ +#define AR_TXCFG 0x0030 /* tx DMA size config register */ +#define AR_RXCFG 0x0034 /* rx DMA size config register */ +#define AR5211_JUMBO_LAST 0x0038 /* Jumbo descriptor last address */ +#define AR_MIBC 0x0040 /* MIB control register */ +#define AR_TOPS 0x0044 /* timeout prescale count */ +#define AR_RXNPTO 0x0048 /* no frame received timeout */ +#define AR_TXNPTO 0x004C /* no frame trasmitted timeout */ +#define AR_RFGTO 0x0050 /* receive frame gap timeout */ +#define AR_RFCNT 0x0054 /* receive frame count limit */ +#define AR_MACMISC 0x0058 /* miscellaneous control/status */ +#define AR5311_QDCLKGATE 0x005c /* QCU/DCU clock gating control */ +#define AR_ISR 0x0080 /* Primary interrupt status register */ +#define AR_ISR_S0 0x0084 /* Secondary interrupt status reg 0 */ +#define AR_ISR_S1 0x0088 /* Secondary interrupt status reg 1 */ +#define AR_ISR_S2 0x008c /* Secondary interrupt status reg 2 */ +#define AR_ISR_S3 0x0090 /* Secondary interrupt status reg 3 */ +#define AR_ISR_S4 0x0094 /* Secondary interrupt status reg 4 */ +#define AR_IMR 0x00a0 /* Primary interrupt mask register */ +#define AR_IMR_S0 0x00a4 /* Secondary interrupt mask reg 0 */ +#define AR_IMR_S1 0x00a8 /* Secondary interrupt mask reg 1 */ +#define AR_IMR_S2 0x00ac /* Secondary interrupt mask reg 2 */ +#define AR_IMR_S3 0x00b0 /* Secondary interrupt mask reg 3 */ +#define AR_IMR_S4 0x00b4 /* Secondary interrupt mask reg 4 */ +#define AR_ISR_RAC 0x00c0 /* Primary interrupt status reg, */ +/* Shadow copies with read-and-clear access */ +#define AR_ISR_S0_S 0x00c4 /* Secondary interrupt status reg 0 */ +#define AR_ISR_S1_S 0x00c8 /* Secondary interrupt status reg 1 */ +#define AR_ISR_S2_S 0x00cc /* Secondary interrupt status reg 2 */ +#define AR_ISR_S3_S 0x00d0 /* Secondary interrupt status reg 3 */ +#define AR_ISR_S4_S 0x00d4 /* Secondary interrupt status reg 4 */ + +#define AR_Q0_TXDP 0x0800 /* Transmit Queue descriptor pointer */ +#define AR_Q1_TXDP 0x0804 /* Transmit Queue descriptor pointer */ +#define AR_Q2_TXDP 0x0808 /* Transmit Queue descriptor pointer */ +#define AR_Q3_TXDP 0x080c /* Transmit Queue descriptor pointer */ +#define AR_Q4_TXDP 0x0810 /* Transmit Queue descriptor pointer */ +#define AR_Q5_TXDP 0x0814 /* Transmit Queue descriptor pointer */ +#define AR_Q6_TXDP 0x0818 /* Transmit Queue descriptor pointer */ +#define AR_Q7_TXDP 0x081c /* Transmit Queue descriptor pointer */ +#define AR_Q8_TXDP 0x0820 /* Transmit Queue descriptor pointer */ +#define AR_Q9_TXDP 0x0824 /* Transmit Queue descriptor pointer */ +#define AR_QTXDP(i) (AR_Q0_TXDP + ((i)<<2)) + +#define AR_Q_TXE 0x0840 /* Transmit Queue enable */ +#define AR_Q_TXD 0x0880 /* Transmit Queue disable */ + +#define AR_Q0_CBRCFG 0x08c0 /* CBR configuration */ +#define AR_Q1_CBRCFG 0x08c4 /* CBR configuration */ +#define AR_Q2_CBRCFG 0x08c8 /* CBR configuration */ +#define AR_Q3_CBRCFG 0x08cc /* CBR configuration */ +#define AR_Q4_CBRCFG 0x08d0 /* CBR configuration */ +#define AR_Q5_CBRCFG 0x08d4 /* CBR configuration */ +#define AR_Q6_CBRCFG 0x08d8 /* CBR configuration */ +#define AR_Q7_CBRCFG 0x08dc /* CBR configuration */ +#define AR_Q8_CBRCFG 0x08e0 /* CBR configuration */ +#define AR_Q9_CBRCFG 0x08e4 /* CBR configuration */ +#define AR_QCBRCFG(i) (AR_Q0_CBRCFG + ((i)<<2)) + +#define AR_Q0_RDYTIMECFG 0x0900 /* ReadyTime configuration */ +#define AR_Q1_RDYTIMECFG 0x0904 /* ReadyTime configuration */ +#define AR_Q2_RDYTIMECFG 0x0908 /* ReadyTime configuration */ +#define AR_Q3_RDYTIMECFG 0x090c /* ReadyTime configuration */ +#define AR_Q4_RDYTIMECFG 0x0910 /* ReadyTime configuration */ +#define AR_Q5_RDYTIMECFG 0x0914 /* ReadyTime configuration */ +#define AR_Q6_RDYTIMECFG 0x0918 /* ReadyTime configuration */ +#define AR_Q7_RDYTIMECFG 0x091c /* ReadyTime configuration */ +#define AR_Q8_RDYTIMECFG 0x0920 /* ReadyTime configuration */ +#define AR_Q9_RDYTIMECFG 0x0924 /* ReadyTime configuration */ +#define AR_QRDYTIMECFG(i) (AR_Q0_RDYTIMECFG + ((i)<<2)) + +#define AR_Q_ONESHOTARM_SC 0x0940 /* OneShotArm set control */ +#define AR_Q_ONESHOTARM_CC 0x0980 /* OneShotArm clear control */ + +#define AR_Q0_MISC 0x09c0 /* Miscellaneous QCU settings */ +#define AR_Q1_MISC 0x09c4 /* Miscellaneous QCU settings */ +#define AR_Q2_MISC 0x09c8 /* Miscellaneous QCU settings */ +#define AR_Q3_MISC 0x09cc /* Miscellaneous QCU settings */ +#define AR_Q4_MISC 0x09d0 /* Miscellaneous QCU settings */ +#define AR_Q5_MISC 0x09d4 /* Miscellaneous QCU settings */ +#define AR_Q6_MISC 0x09d8 /* Miscellaneous QCU settings */ +#define AR_Q7_MISC 0x09dc /* Miscellaneous QCU settings */ +#define AR_Q8_MISC 0x09e0 /* Miscellaneous QCU settings */ +#define AR_Q9_MISC 0x09e4 /* Miscellaneous QCU settings */ +#define AR_QMISC(i) (AR_Q0_MISC + ((i)<<2)) + +#define AR_Q0_STS 0x0a00 /* Miscellaneous QCU status */ +#define AR_Q1_STS 0x0a04 /* Miscellaneous QCU status */ +#define AR_Q2_STS 0x0a08 /* Miscellaneous QCU status */ +#define AR_Q3_STS 0x0a0c /* Miscellaneous QCU status */ +#define AR_Q4_STS 0x0a10 /* Miscellaneous QCU status */ +#define AR_Q5_STS 0x0a14 /* Miscellaneous QCU status */ +#define AR_Q6_STS 0x0a18 /* Miscellaneous QCU status */ +#define AR_Q7_STS 0x0a1c /* Miscellaneous QCU status */ +#define AR_Q8_STS 0x0a20 /* Miscellaneous QCU status */ +#define AR_Q9_STS 0x0a24 /* Miscellaneous QCU status */ +#define AR_QSTS(i) (AR_Q0_STS + ((i)<<2)) + +#define AR_Q_RDYTIMESHDN 0x0a40 /* ReadyTimeShutdown status */ +#define AR_D0_QCUMASK 0x1000 /* QCU Mask */ +#define AR_D1_QCUMASK 0x1004 /* QCU Mask */ +#define AR_D2_QCUMASK 0x1008 /* QCU Mask */ +#define AR_D3_QCUMASK 0x100c /* QCU Mask */ +#define AR_D4_QCUMASK 0x1010 /* QCU Mask */ +#define AR_D5_QCUMASK 0x1014 /* QCU Mask */ +#define AR_D6_QCUMASK 0x1018 /* QCU Mask */ +#define AR_D7_QCUMASK 0x101c /* QCU Mask */ +#define AR_D8_QCUMASK 0x1020 /* QCU Mask */ +#define AR_D9_QCUMASK 0x1024 /* QCU Mask */ +#define AR_DQCUMASK(i) (AR_D0_QCUMASK + ((i)<<2)) + +#define AR_D0_LCL_IFS 0x1040 /* DCU-specific IFS settings */ +#define AR_D1_LCL_IFS 0x1044 /* DCU-specific IFS settings */ +#define AR_D2_LCL_IFS 0x1048 /* DCU-specific IFS settings */ +#define AR_D3_LCL_IFS 0x104c /* DCU-specific IFS settings */ +#define AR_D4_LCL_IFS 0x1050 /* DCU-specific IFS settings */ +#define AR_D5_LCL_IFS 0x1054 /* DCU-specific IFS settings */ +#define AR_D6_LCL_IFS 0x1058 /* DCU-specific IFS settings */ +#define AR_D7_LCL_IFS 0x105c /* DCU-specific IFS settings */ +#define AR_D8_LCL_IFS 0x1060 /* DCU-specific IFS settings */ +#define AR_D9_LCL_IFS 0x1064 /* DCU-specific IFS settings */ +#define AR_DLCL_IFS(i) (AR_D0_LCL_IFS + ((i)<<2)) + +#define AR_D0_RETRY_LIMIT 0x1080 /* Retry limits */ +#define AR_D1_RETRY_LIMIT 0x1084 /* Retry limits */ +#define AR_D2_RETRY_LIMIT 0x1088 /* Retry limits */ +#define AR_D3_RETRY_LIMIT 0x108c /* Retry limits */ +#define AR_D4_RETRY_LIMIT 0x1090 /* Retry limits */ +#define AR_D5_RETRY_LIMIT 0x1094 /* Retry limits */ +#define AR_D6_RETRY_LIMIT 0x1098 /* Retry limits */ +#define AR_D7_RETRY_LIMIT 0x109c /* Retry limits */ +#define AR_D8_RETRY_LIMIT 0x10a0 /* Retry limits */ +#define AR_D9_RETRY_LIMIT 0x10a4 /* Retry limits */ +#define AR_DRETRY_LIMIT(i) (AR_D0_RETRY_LIMIT + ((i)<<2)) + +#define AR_D0_CHNTIME 0x10c0 /* ChannelTime settings */ +#define AR_D1_CHNTIME 0x10c4 /* ChannelTime settings */ +#define AR_D2_CHNTIME 0x10c8 /* ChannelTime settings */ +#define AR_D3_CHNTIME 0x10cc /* ChannelTime settings */ +#define AR_D4_CHNTIME 0x10d0 /* ChannelTime settings */ +#define AR_D5_CHNTIME 0x10d4 /* ChannelTime settings */ +#define AR_D6_CHNTIME 0x10d8 /* ChannelTime settings */ +#define AR_D7_CHNTIME 0x10dc /* ChannelTime settings */ +#define AR_D8_CHNTIME 0x10e0 /* ChannelTime settings */ +#define AR_D9_CHNTIME 0x10e4 /* ChannelTime settings */ +#define AR_DCHNTIME(i) (AR_D0_CHNTIME + ((i)<<2)) + +#define AR_D0_MISC 0x1100 /* Misc DCU-specific settings */ +#define AR_D1_MISC 0x1104 /* Misc DCU-specific settings */ +#define AR_D2_MISC 0x1108 /* Misc DCU-specific settings */ +#define AR_D3_MISC 0x110c /* Misc DCU-specific settings */ +#define AR_D4_MISC 0x1110 /* Misc DCU-specific settings */ +#define AR_D5_MISC 0x1114 /* Misc DCU-specific settings */ +#define AR_D6_MISC 0x1118 /* Misc DCU-specific settings */ +#define AR_D7_MISC 0x111c /* Misc DCU-specific settings */ +#define AR_D8_MISC 0x1120 /* Misc DCU-specific settings */ +#define AR_D9_MISC 0x1124 /* Misc DCU-specific settings */ +#define AR_DMISC(i) (AR_D0_MISC + ((i)<<2)) + +#define AR_D0_SEQNUM 0x1140 /* Frame seqnum control/status */ +#define AR_D1_SEQNUM 0x1144 /* Frame seqnum control/status */ +#define AR_D2_SEQNUM 0x1148 /* Frame seqnum control/status */ +#define AR_D3_SEQNUM 0x114c /* Frame seqnum control/status */ +#define AR_D4_SEQNUM 0x1150 /* Frame seqnum control/status */ +#define AR_D5_SEQNUM 0x1154 /* Frame seqnum control/status */ +#define AR_D6_SEQNUM 0x1158 /* Frame seqnum control/status */ +#define AR_D7_SEQNUM 0x115c /* Frame seqnum control/status */ +#define AR_D8_SEQNUM 0x1160 /* Frame seqnum control/status */ +#define AR_D9_SEQNUM 0x1164 /* Frame seqnum control/status */ +#define AR_DSEQNUM(i) (AR_D0_SEQNUM + ((i<<2))) + +/* MAC DCU-global IFS settings */ +#define AR_D_GBL_IFS_SIFS 0x1030 /* DCU global SIFS settings */ +#define AR_D_GBL_IFS_SLOT 0x1070 /* DC global slot interval */ +#define AR_D_GBL_IFS_EIFS 0x10b0 /* DCU global EIFS setting */ +#define AR_D_GBL_IFS_MISC 0x10f0 /* DCU global misc. IFS settings */ +#define AR_D_FPCTL 0x1230 /* DCU frame prefetch settings */ +#define AR_D_TXPSE 0x1270 /* DCU transmit pause control/status */ +#define AR_D_TXBLK_CMD 0x1038 /* DCU transmit filter cmd (w/only) */ +#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i)) /* DCU transmit filter data */ +#define AR_D_TXBLK_CLR 0x143c /* DCU clear tx filter (w/only) */ +#define AR_D_TXBLK_SET 0x147c /* DCU set tx filter (w/only) */ + +#define AR_D_TXPSE 0x1270 /* DCU transmit pause control/status */ + +#define AR_RC 0x4000 /* Warm reset control register */ +#define AR_SCR 0x4004 /* Sleep control register */ +#define AR_INTPEND 0x4008 /* Interrupt Pending register */ +#define AR_SFR 0x400C /* Sleep force register */ +#define AR_PCICFG 0x4010 /* PCI configuration register */ +#define AR_GPIOCR 0x4014 /* GPIO control register */ +#define AR_GPIODO 0x4018 /* GPIO data output access register */ +#define AR_GPIODI 0x401C /* GPIO data input access register */ +#define AR_SREV 0x4020 /* Silicon Revision register */ + +#define AR_EEPROM_ADDR 0x6000 /* EEPROM address register (10 bit) */ +#define AR_EEPROM_DATA 0x6004 /* EEPROM data register (16 bit) */ +#define AR_EEPROM_CMD 0x6008 /* EEPROM command register */ +#define AR_EEPROM_STS 0x600c /* EEPROM status register */ +#define AR_EEPROM_CFG 0x6010 /* EEPROM configuration register */ + +#define AR_STA_ID0 0x8000 /* station ID0 - low 32 bits */ +#define AR_STA_ID1 0x8004 /* station ID1 - upper 16 bits */ +#define AR_BSS_ID0 0x8008 /* BSSID low 32 bits */ +#define AR_BSS_ID1 0x800C /* BSSID upper 16 bits / AID */ +#define AR_SLOT_TIME 0x8010 /* Time-out after a collision */ +#define AR_TIME_OUT 0x8014 /* ACK & CTS time-out */ +#define AR_RSSI_THR 0x8018 /* RSSI warning & missed beacon threshold */ +#define AR_USEC 0x801c /* transmit latency register */ +#define AR_BEACON 0x8020 /* beacon control value/mode bits */ +#define AR_CFP_PERIOD 0x8024 /* CFP Interval (TU/msec) */ +#define AR_TIMER0 0x8028 /* Next beacon time (TU/msec) */ +#define AR_TIMER1 0x802c /* DMA beacon alert time (1/8 TU) */ +#define AR_TIMER2 0x8030 /* Software beacon alert (1/8 TU) */ +#define AR_TIMER3 0x8034 /* ATIM window time */ +#define AR_CFP_DUR 0x8038 /* maximum CFP duration in TU */ +#define AR_RX_FILTER 0x803C /* receive filter register */ +#define AR_MCAST_FIL0 0x8040 /* multicast filter lower 32 bits */ +#define AR_MCAST_FIL1 0x8044 /* multicast filter upper 32 bits */ +#define AR_DIAG_SW 0x8048 /* PCU control register */ +#define AR_TSF_L32 0x804c /* local clock lower 32 bits */ +#define AR_TSF_U32 0x8050 /* local clock upper 32 bits */ +#define AR_TST_ADDAC 0x8054 /* ADDAC test register */ +#define AR_DEF_ANTENNA 0x8058 /* default antenna register */ + +#define AR_LAST_TSTP 0x8080 /* Time stamp of the last beacon rcvd */ +#define AR_NAV 0x8084 /* current NAV value */ +#define AR_RTS_OK 0x8088 /* RTS exchange success counter */ +#define AR_RTS_FAIL 0x808c /* RTS exchange failure counter */ +#define AR_ACK_FAIL 0x8090 /* ACK failure counter */ +#define AR_FCS_FAIL 0x8094 /* FCS check failure counter */ +#define AR_BEACON_CNT 0x8098 /* Valid beacon counter */ + +#define AR_KEYTABLE_0 0x8800 /* Encryption key table */ +#define AR_KEYTABLE(n) (AR_KEYTABLE_0 + ((n)*32)) + +#define AR_CR_RXE 0x00000004 /* Receive enable */ +#define AR_CR_RXD 0x00000020 /* Receive disable */ +#define AR_CR_SWI 0x00000040 /* One-shot software interrupt */ +#define AR_CR_BITS "\20\3RXE\6RXD\7SWI" + +#define AR_CFG_SWTD 0x00000001 /* byteswap tx descriptor words */ +#define AR_CFG_SWTB 0x00000002 /* byteswap tx data buffer words */ +#define AR_CFG_SWRD 0x00000004 /* byteswap rx descriptor words */ +#define AR_CFG_SWRB 0x00000008 /* byteswap rx data buffer words */ +#define AR_CFG_SWRG 0x00000010 /* byteswap register access data words */ +#define AR_CFG_AP_ADHOC_INDICATION 0x00000020 /* AP/adhoc indication (0-AP, 1-Adhoc) */ +#define AR_CFG_PHOK 0x00000100 /* PHY OK status */ +#define AR_CFG_EEBS 0x00000200 /* EEPROM busy */ +#define AR_CFG_CLK_GATE_DIS 0x00000400 /* Clock gating disable (Oahu only) */ +#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_M 0x00060000 /* Mask of PCI core master request queue full threshold */ +#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 /* Shift for PCI core master request queue full threshold */ +#define AR_CFG_BITS \ + "\20\1SWTD\2SWTB\3SWRD\4SWRB\5SWRG\10PHYOK11EEBS" + +#define AR_IER_ENABLE 0x00000001 /* Global interrupt enable */ +#define AR_IER_DISABLE 0x00000000 /* Global interrupt disable */ +#define AR_IER_BITS "\20\1ENABLE" + +#define AR_RTSD0_RTS_DURATION_6_M 0x000000FF +#define AR_RTSD0_RTS_DURATION_6_S 0 +#define AR_RTSD0_RTS_DURATION_9_M 0x0000FF00 +#define AR_RTSD0_RTS_DURATION_9_S 8 +#define AR_RTSD0_RTS_DURATION_12_M 0x00FF0000 +#define AR_RTSD0_RTS_DURATION_12_S 16 +#define AR_RTSD0_RTS_DURATION_18_M 0xFF000000 +#define AR_RTSD0_RTS_DURATION_18_S 24 + +#define AR_RTSD0_RTS_DURATION_24_M 0x000000FF +#define AR_RTSD0_RTS_DURATION_24_S 0 +#define AR_RTSD0_RTS_DURATION_36_M 0x0000FF00 +#define AR_RTSD0_RTS_DURATION_36_S 8 +#define AR_RTSD0_RTS_DURATION_48_M 0x00FF0000 +#define AR_RTSD0_RTS_DURATION_48_S 16 +#define AR_RTSD0_RTS_DURATION_54_M 0xFF000000 +#define AR_RTSD0_RTS_DURATION_54_S 24 + +#define AR_DMASIZE_4B 0x00000000 /* DMA size 4 bytes (TXCFG + RXCFG) */ +#define AR_DMASIZE_8B 0x00000001 /* DMA size 8 bytes */ +#define AR_DMASIZE_16B 0x00000002 /* DMA size 16 bytes */ +#define AR_DMASIZE_32B 0x00000003 /* DMA size 32 bytes */ +#define AR_DMASIZE_64B 0x00000004 /* DMA size 64 bytes */ +#define AR_DMASIZE_128B 0x00000005 /* DMA size 128 bytes */ +#define AR_DMASIZE_256B 0x00000006 /* DMA size 256 bytes */ +#define AR_DMASIZE_512B 0x00000007 /* DMA size 512 bytes */ + +#define AR_TXCFG_FTRIG_M 0x000003F0 /* Mask for Frame trigger level */ +#define AR_TXCFG_FTRIG_S 4 /* Shift for Frame trigger level */ +#define AR_TXCFG_FTRIG_IMMED 0x00000000 /* bytes in PCU TX FIFO before air */ +#define AR_TXCFG_FTRIG_64B 0x00000010 /* default */ +#define AR_TXCFG_FTRIG_128B 0x00000020 +#define AR_TXCFG_FTRIG_192B 0x00000030 +#define AR_TXCFG_FTRIG_256B 0x00000040 /* 5 bits total */ +#define AR_TXCFG_BITS "\20" + +#define AR5311_RXCFG_DEF_RX_ANTENNA 0x00000008 /* Default Receive Antenna */ + /* Maui2/Spirit only - reserved on Oahu */ +#define AR_RXCFG_ZLFDMA 0x00000010 /* Enable DMA of zero-length frame */ +#define AR_RXCFG_EN_JUM 0x00000020 /* Enable jumbo rx descriptors */ +#define AR_RXCFG_WR_JUM 0x00000040 /* Wrap jumbo rx descriptors */ + +#define AR_MIBC_COW 0x00000001 /* counter overflow warning */ +#define AR_MIBC_FMC 0x00000002 /* freeze MIB counters */ +#define AR_MIBC_CMC 0x00000004 /* clear MIB counters */ +#define AR_MIBC_MCS 0x00000008 /* MIB counter strobe, increment all */ + +#define AR_TOPS_MASK 0x0000FFFF /* Mask for timeout prescale */ + +#define AR_RXNPTO_MASK 0x000003FF /* Mask for no frame received timeout */ + +#define AR_TXNPTO_MASK 0x000003FF /* Mask for no frame transmitted timeout */ +#define AR_TXNPTO_QCU_MASK 0x03FFFC00 /* Mask indicating the set of QCUs */ + /* for which frame completions will cause */ + /* a reset of the no frame transmitted timeout */ + +#define AR_RPGTO_MASK 0x000003FF /* Mask for receive frame gap timeout */ + +#define AR_RPCNT_MASK 0x0000001F /* Mask for receive frame count limit */ + +#define AR_MACMISC_DMA_OBS_M 0x000001E0 /* Mask for DMA observation bus mux select */ +#define AR_MACMISC_DMA_OBS_S 5 /* Shift for DMA observation bus mux select */ +#define AR_MACMISC_MISC_OBS_M 0x00000E00 /* Mask for MISC observation bus mux select */ +#define AR_MACMISC_MISC_OBS_S 9 /* Shift for MISC observation bus mux select */ +#define AR_MACMISC_MAC_OBS_BUS_LSB_M 0x00007000 /* Mask for MAC observation bus mux select (lsb) */ +#define AR_MACMISC_MAC_OBS_BUS_LSB_S 12 /* Shift for MAC observation bus mux select (lsb) */ +#define AR_MACMISC_MAC_OBS_BUS_MSB_M 0x00038000 /* Mask for MAC observation bus mux select (msb) */ +#define AR_MACMISC_MAC_OBS_BUS_MSB_S 15 /* Shift for MAC observation bus mux select (msb) */ + + /* Maui2/Spirit only. */ +#define AR5311_QDCLKGATE_QCU_M 0x0000FFFF /* Mask for QCU clock disable */ +#define AR5311_QDCLKGATE_DCU_M 0x07FF0000 /* Mask for DCU clock disable */ + + /* Interrupt Status Registers */ +#define AR_ISR_RXOK 0x00000001 /* At least one frame received sans errors */ +#define AR_ISR_RXDESC 0x00000002 /* Receive interrupt request */ +#define AR_ISR_RXERR 0x00000004 /* Receive error interrupt */ +#define AR_ISR_RXNOPKT 0x00000008 /* No frame received within timeout clock */ +#define AR_ISR_RXEOL 0x00000010 /* Received descriptor empty interrupt */ +#define AR_ISR_RXORN 0x00000020 /* Receive FIFO overrun interrupt */ +#define AR_ISR_TXOK 0x00000040 /* Transmit okay interrupt */ +#define AR_ISR_TXDESC 0x00000080 /* Transmit interrupt request */ +#define AR_ISR_TXERR 0x00000100 /* Transmit error interrupt */ +#define AR_ISR_TXNOPKT 0x00000200 /* No frame transmitted interrupt */ +#define AR_ISR_TXEOL 0x00000400 /* Transmit descriptor empty interrupt */ +#define AR_ISR_TXURN 0x00000800 /* Transmit FIFO underrun interrupt */ +#define AR_ISR_MIB 0x00001000 /* MIB interrupt - see MIBC */ +#define AR_ISR_SWI 0x00002000 /* Software interrupt */ +#define AR_ISR_RXPHY 0x00004000 /* PHY receive error interrupt */ +#define AR_ISR_RXKCM 0x00008000 /* Key-cache miss interrupt */ +#define AR_ISR_SWBA 0x00010000 /* Software beacon alert interrupt */ +#define AR_ISR_BRSSI 0x00020000 /* Beacon threshold interrupt */ +#define AR_ISR_BMISS 0x00040000 /* Beacon missed interrupt */ +#define AR_ISR_HIUERR 0x00080000 /* An unexpected bus error has occurred */ +#define AR_ISR_BNR 0x00100000 /* Beacon not ready interrupt */ +#define AR_ISR_TIM 0x00800000 /* TIM interrupt */ +#define AR_ISR_GPIO 0x01000000 /* GPIO Interrupt */ +#define AR_ISR_QCBROVF 0x02000000 /* QCU CBR overflow interrupt */ +#define AR_ISR_QCBRURN 0x04000000 /* QCU CBR underrun interrupt */ +#define AR_ISR_QTRIG 0x08000000 /* QCU scheduling trigger interrupt */ +#define AR_ISR_RESV0 0xF0000000 /* Reserved */ + +#define AR_ISR_S0_QCU_TXOK_M 0x000003FF /* Mask for TXOK (QCU 0-9) */ +#define AR_ISR_S0_QCU_TXDESC_M 0x03FF0000 /* Mask for TXDESC (QCU 0-9) */ + +#define AR_ISR_S1_QCU_TXERR_M 0x000003FF /* Mask for TXERR (QCU 0-9) */ +#define AR_ISR_S1_QCU_TXEOL_M 0x03FF0000 /* Mask for TXEOL (QCU 0-9) */ + +#define AR_ISR_S2_QCU_TXURN_M 0x000003FF /* Mask for TXURN (QCU 0-9) */ +#define AR_ISR_S2_MCABT 0x00010000 /* Master cycle abort interrupt */ +#define AR_ISR_S2_SSERR 0x00020000 /* SERR interrupt */ +#define AR_ISR_S2_DPERR 0x00040000 /* PCI bus parity error */ +#define AR_ISR_S2_RESV0 0xFFF80000 /* Reserved */ + +#define AR_ISR_S3_QCU_QCBROVF_M 0x000003FF /* Mask for QCBROVF (QCU 0-9) */ +#define AR_ISR_S3_QCU_QCBRURN_M 0x03FF0000 /* Mask for QCBRURN (QCU 0-9) */ + +#define AR_ISR_S4_QCU_QTRIG_M 0x000003FF /* Mask for QTRIG (QCU 0-9) */ +#define AR_ISR_S4_RESV0 0xFFFFFC00 /* Reserved */ + + /* Interrupt Mask Registers */ +#define AR_IMR_RXOK 0x00000001 /* At least one frame received sans errors */ +#define AR_IMR_RXDESC 0x00000002 /* Receive interrupt request */ +#define AR_IMR_RXERR 0x00000004 /* Receive error interrupt */ +#define AR_IMR_RXNOPKT 0x00000008 /* No frame received within timeout clock */ +#define AR_IMR_RXEOL 0x00000010 /* Received descriptor empty interrupt */ +#define AR_IMR_RXORN 0x00000020 /* Receive FIFO overrun interrupt */ +#define AR_IMR_TXOK 0x00000040 /* Transmit okay interrupt */ +#define AR_IMR_TXDESC 0x00000080 /* Transmit interrupt request */ +#define AR_IMR_TXERR 0x00000100 /* Transmit error interrupt */ +#define AR_IMR_TXNOPKT 0x00000200 /* No frame transmitted interrupt */ +#define AR_IMR_TXEOL 0x00000400 /* Transmit descriptor empty interrupt */ +#define AR_IMR_TXURN 0x00000800 /* Transmit FIFO underrun interrupt */ +#define AR_IMR_MIB 0x00001000 /* MIB interrupt - see MIBC */ +#define AR_IMR_SWI 0x00002000 /* Software interrupt */ +#define AR_IMR_RXPHY 0x00004000 /* PHY receive error interrupt */ +#define AR_IMR_RXKCM 0x00008000 /* Key-cache miss interrupt */ +#define AR_IMR_SWBA 0x00010000 /* Software beacon alert interrupt */ +#define AR_IMR_BRSSI 0x00020000 /* Beacon threshold interrupt */ +#define AR_IMR_BMISS 0x00040000 /* Beacon missed interrupt */ +#define AR_IMR_HIUERR 0x00080000 /* An unexpected bus error has occurred */ +#define AR_IMR_BNR 0x00100000 /* BNR interrupt */ +#define AR_IMR_TIM 0x00800000 /* TIM interrupt */ +#define AR_IMR_GPIO 0x01000000 /* GPIO Interrupt */ +#define AR_IMR_QCBROVF 0x02000000 /* QCU CBR overflow interrupt */ +#define AR_IMR_QCBRURN 0x04000000 /* QCU CBR underrun interrupt */ +#define AR_IMR_QTRIG 0x08000000 /* QCU scheduling trigger interrupt */ +#define AR_IMR_RESV0 0xF0000000 /* Reserved */ + +#define AR_IMR_S0_QCU_TXOK 0x000003FF /* Mask for TXOK (QCU 0-9) */ +#define AR_IMR_S0_QCU_TXOK_S 0 +#define AR_IMR_S0_QCU_TXDESC 0x03FF0000 /* Mask for TXDESC (QCU 0-9) */ +#define AR_IMR_S0_QCU_TXDESC_S 16 /* Shift for TXDESC (QCU 0-9) */ + +#define AR_IMR_S1_QCU_TXERR 0x000003FF /* Mask for TXERR (QCU 0-9) */ +#define AR_IMR_S1_QCU_TXERR_S 0 +#define AR_IMR_S1_QCU_TXEOL 0x03FF0000 /* Mask for TXEOL (QCU 0-9) */ +#define AR_IMR_S1_QCU_TXEOL_S 16 /* Shift for TXEOL (QCU 0-9) */ + +#define AR_IMR_S2_QCU_TXURN 0x000003FF /* Mask for TXURN (QCU 0-9) */ +#define AR_IMR_S2_QCU_TXURN_S 0 +#define AR_IMR_S2_MCABT 0x00010000 /* Master cycle abort interrupt */ +#define AR_IMR_S2_SSERR 0x00020000 /* SERR interrupt */ +#define AR_IMR_S2_DPERR 0x00040000 /* PCI bus parity error */ +#define AR_IMR_S2_RESV0 0xFFF80000 /* Reserved */ + +#define AR_IMR_S3_QCU_QCBROVF_M 0x000003FF /* Mask for QCBROVF (QCU 0-9) */ +#define AR_IMR_S3_QCU_QCBRURN_M 0x03FF0000 /* Mask for QCBRURN (QCU 0-9) */ +#define AR_IMR_S3_QCU_QCBRURN_S 16 /* Shift for QCBRURN (QCU 0-9) */ + +#define AR_IMR_S4_QCU_QTRIG_M 0x000003FF /* Mask for QTRIG (QCU 0-9) */ +#define AR_IMR_S4_RESV0 0xFFFFFC00 /* Reserved */ + + /* Interrupt status registers (read-and-clear access, secondary shadow copies) */ + + /* QCU registers */ +#define AR_NUM_QCU 10 /* Only use QCU 0-9 for forward QCU compatibility */ +#define AR_QCU_0 0x0001 +#define AR_QCU_1 0x0002 +#define AR_QCU_2 0x0004 +#define AR_QCU_3 0x0008 +#define AR_QCU_4 0x0010 +#define AR_QCU_5 0x0020 +#define AR_QCU_6 0x0040 +#define AR_QCU_7 0x0080 +#define AR_QCU_8 0x0100 +#define AR_QCU_9 0x0200 + +#define AR_Q_TXE_M 0x000003FF /* Mask for TXE (QCU 0-9) */ + +#define AR_Q_TXD_M 0x000003FF /* Mask for TXD (QCU 0-9) */ + +#define AR_Q_CBRCFG_CBR_INTERVAL 0x00FFFFFF /* Mask for CBR interval (us) */ +#define AR_Q_CBRCFG_CBR_INTERVAL_S 0 /* Shift for CBR interval */ +#define AR_Q_CBRCFG_CBR_OVF_THRESH 0xFF000000 /* Mask for CBR overflow threshold */ +#define AR_Q_CBRCFG_CBR_OVF_THRESH_S 24 /* Shift for " " " */ + +#define AR_Q_RDYTIMECFG_INT 0x00FFFFFF /* CBR interval (us) */ +#define AR_Q_RDYTIMECFG_INT_S 0 /* Shift for ReadyTime Interval (us) */ +#define AR_Q_RDYTIMECFG_DURATION_M 0x00FFFFFF /* Mask for CBR interval (us) */ +#define AR_Q_RDYTIMECFG_EN 0x01000000 /* ReadyTime enable */ +#define AR_Q_RDYTIMECFG_RESV0 0xFE000000 /* Reserved */ + +#define AR_Q_ONESHOTARM_SC_M 0x0000FFFF /* Mask for MAC_Q_ONESHOTARM_SC (QCU 0-15) */ +#define AR_Q_ONESHOTARM_SC_RESV0 0xFFFF0000 /* Reserved */ + +#define AR_Q_ONESHOTARM_CC_M 0x0000FFFF /* Mask for MAC_Q_ONESHOTARM_CC (QCU 0-15) */ +#define AR_Q_ONESHOTARM_CC_RESV0 0xFFFF0000 /* Reserved */ + +#define AR_Q_MISC_FSP_M 0x0000000F /* Mask for Frame Scheduling Policy */ +#define AR_Q_MISC_FSP_ASAP 0 /* ASAP */ +#define AR_Q_MISC_FSP_CBR 1 /* CBR */ +#define AR_Q_MISC_FSP_DBA_GATED 2 /* DMA Beacon Alert gated */ +#define AR_Q_MISC_FSP_TIM_GATED 3 /* TIM gated */ +#define AR_Q_MISC_FSP_BEACON_SENT_GATED 4 /* Beacon-sent-gated */ +#define AR_Q_MISC_ONE_SHOT_EN 0x00000010 /* OneShot enable */ +#define AR_Q_MISC_CBR_INCR_DIS1 0x00000020 /* Disable CBR expired counter + incr (empty q) */ +#define AR_Q_MISC_CBR_INCR_DIS0 0x00000040 /* Disable CBR expired counter + incr (empty beacon q) */ +#define AR_Q_MISC_BEACON_USE 0x00000080 /* Beacon use indication */ +#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT 0x00000100 /* CBR expired counter limit enable */ +#define AR_Q_MISC_RDYTIME_EXP_POLICY 0x00000200 /* Enable TXE cleared on ReadyTime expired or VEOL */ +#define AR_Q_MISC_RESET_CBR_EXP_CTR 0x00000400 /* Reset CBR expired counter */ +#define AR_Q_MISC_DCU_EARLY_TERM_REQ 0x00000800 /* DCU frame early termination request control */ +#define AR_Q_MISC_RESV0 0xFFFFF000 /* Reserved */ + +#define AR_Q_STS_PEND_FR_CNT_M 0x00000003 /* Mask for Pending Frame Count */ +#define AR_Q_STS_RESV0 0x000000FC /* Reserved */ +#define AR_Q_STS_CBR_EXP_CNT_M 0x0000FF00 /* Mask for CBR expired counter */ +#define AR_Q_STS_RESV1 0xFFFF0000 /* Reserved */ + +#define AR_Q_RDYTIMESHDN_M 0x000003FF /* Mask for ReadyTimeShutdown status (QCU 0-9) */ + + /* DCU registers */ +#define AR_NUM_DCU 10 /* Only use 10 DCU's for forward QCU/DCU compatibility */ +#define AR_DCU_0 0x0001 +#define AR_DCU_1 0x0002 +#define AR_DCU_2 0x0004 +#define AR_DCU_3 0x0008 +#define AR_DCU_4 0x0010 +#define AR_DCU_5 0x0020 +#define AR_DCU_6 0x0040 +#define AR_DCU_7 0x0080 +#define AR_DCU_8 0x0100 +#define AR_DCU_9 0x0200 + +#define AR_D_QCUMASK_M 0x000003FF /* Mask for QCU Mask (QCU 0-9) */ +#define AR_D_QCUMASK_RESV0 0xFFFFFC00 /* Reserved */ + +#define AR_D_LCL_IFS_CWMIN 0x000003FF /* Mask for CW_MIN */ +#define AR_D_LCL_IFS_CWMIN_S 0 /* Shift for CW_MIN */ +#define AR_D_LCL_IFS_CWMAX 0x000FFC00 /* Mask for CW_MAX */ +#define AR_D_LCL_IFS_CWMAX_S 10 /* Shift for CW_MAX */ +#define AR_D_LCL_IFS_AIFS 0x0FF00000 /* Mask for AIFS */ +#define AR_D_LCL_IFS_AIFS_S 20 /* Shift for AIFS */ +#define AR_D_LCL_IFS_RESV0 0xF0000000 /* Reserved */ + +#define AR_D_RETRY_LIMIT_FR_SH 0x0000000F /* Mask for frame short retry limit */ +#define AR_D_RETRY_LIMIT_FR_SH_S 0 /* Shift for frame short retry limit */ +#define AR_D_RETRY_LIMIT_FR_LG 0x000000F0 /* Mask for frame long retry limit */ +#define AR_D_RETRY_LIMIT_FR_LG_S 4 /* Shift for frame long retry limit */ +#define AR_D_RETRY_LIMIT_STA_SH 0x00003F00 /* Mask for station short retry limit */ +#define AR_D_RETRY_LIMIT_STA_SH_S 8 /* Shift for station short retry limit */ +#define AR_D_RETRY_LIMIT_STA_LG 0x000FC000 /* Mask for station short retry limit */ +#define AR_D_RETRY_LIMIT_STA_LG_S 14 /* Shift for station short retry limit */ +#define AR_D_RETRY_LIMIT_RESV0 0xFFF00000 /* Reserved */ + +#define AR_D_CHNTIME_EN 0x00100000 /* ChannelTime enable */ +#define AR_D_CHNTIME_RESV0 0xFFE00000 /* Reserved */ +#define AR_D_CHNTIME_DUR 0x000FFFFF /* Mask for ChannelTime duration (us) */ +#define AR_D_CHNTIME_DUR_S 0 /* Shift for ChannelTime duration */ + +#define AR_D_MISC_BKOFF_THRESH_M 0x000007FF /* Mask for Backoff threshold setting */ +#define AR_D_MISC_FRAG_BKOFF_EN 0x00000200 /* Backoff during a frag burst */ +#define AR_D_MISC_HCF_POLL_EN 0x00000800 /* HFC poll enable */ +#define AR_D_MISC_BKOFF_PERSISTENCE 0x00001000 /* Backoff persistence factor setting */ +#define AR_D_MISC_FR_PREFETCH_EN 0x00002000 /* Frame prefetch enable */ +#define AR_D_MISC_VIR_COL_HANDLING_M 0x0000C000 /* Mask for Virtual collision handling policy */ +#define AR_D_MISC_VIR_COL_HANDLING_NORMAL 0 /* Normal */ +#define AR_D_MISC_VIR_COL_HANDLING_MODIFIED 1 /* Modified */ +#define AR_D_MISC_VIR_COL_HANDLING_IGNORE 2 /* Ignore */ +#define AR_D_MISC_BEACON_USE 0x00010000 /* Beacon use indication */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL 0x00060000 /* Mask for DCU arbiter lockout control */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17 /* Shift for DCU arbiter lockout control */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE 0 /* No lockout */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1 /* Intra-frame */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL 2 /* Global */ +#define AR_D_MISC_ARB_LOCKOUT_IGNORE 0x00080000 /* DCU arbiter lockout ignore control */ +#define AR_D_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Sequence number increment disable */ +#define AR_D_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Post-frame backoff disable */ +#define AR_D_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual coll. handling policy */ +#define AR_D_MISC_BLOWN_IFS_POLICY 0x00800000 /* Blown IFS handling policy */ +#define AR5311_D_MISC_SEQ_NUM_CONTROL 0x01000000 /* Sequence Number local or global */ + /* Maui2/Spirit only, reserved on Oahu */ +#define AR_D_MISC_RESV0 0xFE000000 /* Reserved */ + +#define AR_D_SEQNUM_M 0x00000FFF /* Mask for value of sequence number */ +#define AR_D_SEQNUM_RESV0 0xFFFFF000 /* Reserved */ + +#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 /* Mask forLFSR slice select */ +#define AR_D_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode indication */ +#define AR_D_GBL_IFS_MISC_SIFS_DURATION_USEC 0x000003F0 /* Mask for SIFS duration (us) */ +#define AR_D_GBL_IFS_MISC_USEC_DURATION 0x000FFC00 /* Mask for microsecond duration */ +#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY 0x00300000 /* Mask for DCU arbiter delay */ +#define AR_D_GBL_IFS_MISC_RESV0 0xFFC00000 /* Reserved */ + +/* Oahu only */ +#define AR_D_TXPSE_CTRL_M 0x000003FF /* Mask of DCUs to pause (DCUs 0-9) */ +#define AR_D_TXPSE_RESV0 0x0000FC00 /* Reserved */ +#define AR_D_TXPSE_STATUS 0x00010000 /* Transmit pause status */ +#define AR_D_TXPSE_RESV1 0xFFFE0000 /* Reserved */ + + /* DMA & PCI Registers in PCI space (usable during sleep) */ +#define AR_RC_MAC 0x00000001 /* MAC reset */ +#define AR_RC_BB 0x00000002 /* Baseband reset */ +#define AR_RC_RESV0 0x00000004 /* Reserved */ +#define AR_RC_RESV1 0x00000008 /* Reserved */ +#define AR_RC_PCI 0x00000010 /* PCI-core reset */ +#define AR_RC_BITS "\20\1MAC\2BB\3RESV0\4RESV1\5RPCI" + +#define AR_SCR_SLDUR 0x0000ffff /* sleep duration mask, units of 128us */ +#define AR_SCR_SLDUR_S 0 +#define AR_SCR_SLE 0x00030000 /* sleep enable mask */ +#define AR_SCR_SLE_S 16 /* sleep enable bits shift */ +/* + * The previous values for the following three defines were: + * + * AR_SCR_SLE_WAKE 0x00000000 + * AR_SCR_SLE_SLP 0x00010000 + * AR_SCR_SLE_NORM 0x00020000 + * + * However, these have been pre-shifted with AR_SCR_SLE_S. The + * OS_REG_READ() macro would attempt to shift them again, effectively + * shifting out any of the set bits completely. + */ +#define AR_SCR_SLE_WAKE 0 /* force wake */ +#define AR_SCR_SLE_SLP 1 /* force sleep */ +#define AR_SCR_SLE_NORM 2 /* sleep logic normal operation */ +#define AR_SCR_SLE_UNITS 0x00000008 /* SCR units/TU */ +#define AR_SCR_BITS "\20\20SLE_SLP\21SLE" + +#define AR_INTPEND_TRUE 0x00000001 /* interrupt pending */ +#define AR_INTPEND_BITS "\20\1IP" + +#define AR_SFR_SLEEP 0x00000001 /* force sleep */ + +#define AR_PCICFG_CLKRUNEN 0x00000004 /* enable PCI CLKRUN function */ +#define AR_PCICFG_EEPROM_SIZE_M 0x00000018 /* Mask for EEPROM size */ +#define AR_PCICFG_EEPROM_SIZE_S 3 /* Mask for EEPROM size */ +#define AR_PCICFG_EEPROM_SIZE_4K 0 /* EEPROM size 4 Kbit */ +#define AR_PCICFG_EEPROM_SIZE_8K 1 /* EEPROM size 8 Kbit */ +#define AR_PCICFG_EEPROM_SIZE_16K 2 /* EEPROM size 16 Kbit */ +#define AR_PCICFG_EEPROM_SIZE_FAILED 3 /* Failure */ +#define AR_PCICFG_LEDCTL 0x00000060 /* LED control Status */ +#define AR_PCICFG_LEDCTL_NONE 0x00000000 /* STA is not associated or trying */ +#define AR_PCICFG_LEDCTL_PEND 0x00000020 /* STA is trying to associate */ +#define AR_PCICFG_LEDCTL_ASSOC 0x00000040 /* STA is associated */ +#define AR_PCICFG_PCI_BUS_SEL_M 0x00000380 /* Mask for PCI observation bus mux select */ +#define AR_PCICFG_DIS_CBE_FIX 0x00000400 /* Disable fix for bad PCI CBE# generation */ +#define AR_PCICFG_SL_INTEN 0x00000800 /* enable interrupt line assertion when asleep */ +#define AR_PCICFG_RESV0 0x00001000 /* Reserved */ +#define AR_PCICFG_SL_INPEN 0x00002000 /* Force asleep when an interrupt is pending */ +#define AR_PCICFG_RESV1 0x0000C000 /* Reserved */ +#define AR_PCICFG_SPWR_DN 0x00010000 /* mask for sleep/awake indication */ +#define AR_PCICFG_LEDMODE 0x000E0000 /* LED mode */ +#define AR_PCICFG_LEDMODE_PROP 0x00000000 /* Blink prop to filtered tx/rx */ +#define AR_PCICFG_LEDMODE_RPROP 0x00020000 /* Blink prop to unfiltered tx/rx */ +#define AR_PCICFG_LEDMODE_SPLIT 0x00040000 /* Blink power for tx/net for rx */ +#define AR_PCICFG_LEDMODE_RAND 0x00060000 /* Blink randomly */ +#define AR_PCICFG_LEDBLINK 0x00700000 /* LED blink threshold select */ +#define AR_PCICFG_LEDBLINK_S 20 +#define AR_PCICFG_LEDSLOW 0x00800000 /* LED slowest blink rate mode */ +#define AR_PCICFG_RESV2 0xFF000000 /* Reserved */ +#define AR_PCICFG_BITS "\20\3CLKRUNEN\13SL_INTEN" + +#define AR_GPIOCR_CR_SHIFT 2 /* Each CR is 2 bits */ +#define AR_GPIOCR_0_CR_N 0x00000000 /* Input only mode for GPIODO[0] */ +#define AR_GPIOCR_0_CR_0 0x00000001 /* Output only if GPIODO[0] = 0 */ +#define AR_GPIOCR_0_CR_1 0x00000002 /* Output only if GPIODO[0] = 1 */ +#define AR_GPIOCR_0_CR_A 0x00000003 /* Always output */ +#define AR_GPIOCR_1_CR_N 0x00000000 /* Input only mode for GPIODO[1] */ +#define AR_GPIOCR_1_CR_0 0x00000004 /* Output only if GPIODO[1] = 0 */ +#define AR_GPIOCR_1_CR_1 0x00000008 /* Output only if GPIODO[1] = 1 */ +#define AR_GPIOCR_1_CR_A 0x0000000C /* Always output */ +#define AR_GPIOCR_2_CR_N 0x00000000 /* Input only mode for GPIODO[2] */ +#define AR_GPIOCR_2_CR_0 0x00000010 /* Output only if GPIODO[2] = 0 */ +#define AR_GPIOCR_2_CR_1 0x00000020 /* Output only if GPIODO[2] = 1 */ +#define AR_GPIOCR_2_CR_A 0x00000030 /* Always output */ +#define AR_GPIOCR_3_CR_N 0x00000000 /* Input only mode for GPIODO[3] */ +#define AR_GPIOCR_3_CR_0 0x00000040 /* Output only if GPIODO[3] = 0 */ +#define AR_GPIOCR_3_CR_1 0x00000080 /* Output only if GPIODO[3] = 1 */ +#define AR_GPIOCR_3_CR_A 0x000000C0 /* Always output */ +#define AR_GPIOCR_4_CR_N 0x00000000 /* Input only mode for GPIODO[4] */ +#define AR_GPIOCR_4_CR_0 0x00000100 /* Output only if GPIODO[4] = 0 */ +#define AR_GPIOCR_4_CR_1 0x00000200 /* Output only if GPIODO[4] = 1 */ +#define AR_GPIOCR_4_CR_A 0x00000300 /* Always output */ +#define AR_GPIOCR_5_CR_N 0x00000000 /* Input only mode for GPIODO[5] */ +#define AR_GPIOCR_5_CR_0 0x00000400 /* Output only if GPIODO[5] = 0 */ +#define AR_GPIOCR_5_CR_1 0x00000800 /* Output only if GPIODO[5] = 1 */ +#define AR_GPIOCR_5_CR_A 0x00000C00 /* Always output */ +#define AR_GPIOCR_INT_SHIFT 12 /* Interrupt select field shifter */ +#define AR_GPIOCR_INT_MASK 0x00007000 /* Interrupt select field mask */ +#define AR_GPIOCR_INT_SEL0 0x00000000 /* Select Interrupt Pin GPIO_0 */ +#define AR_GPIOCR_INT_SEL1 0x00001000 /* Select Interrupt Pin GPIO_1 */ +#define AR_GPIOCR_INT_SEL2 0x00002000 /* Select Interrupt Pin GPIO_2 */ +#define AR_GPIOCR_INT_SEL3 0x00003000 /* Select Interrupt Pin GPIO_3 */ +#define AR_GPIOCR_INT_SEL4 0x00004000 /* Select Interrupt Pin GPIO_4 */ +#define AR_GPIOCR_INT_SEL5 0x00005000 /* Select Interrupt Pin GPIO_5 */ +#define AR_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO Interrupt */ +#define AR_GPIOCR_INT_SELL 0x00000000 /* Generate Interrupt if selected pin is low */ +#define AR_GPIOCR_INT_SELH 0x00010000 /* Generate Interrupt if selected pin is high */ + +#define AR_SREV_ID_M 0x000000FF /* Mask to read SREV info */ +#define AR_PCICFG_EEPROM_SIZE_16K 2 /* EEPROM size 16 Kbit */ +#define AR_SREV_ID_S 4 /* Major Rev Info */ +#define AR_SREV_REVISION_M 0x0000000F /* Chip revision level */ +#define AR_SREV_FPGA 1 +#define AR_SREV_D2PLUS 2 +#define AR_SREV_D2PLUS_MS 3 /* metal spin */ +#define AR_SREV_CRETE 4 +#define AR_SREV_CRETE_MS 5 /* FCS metal spin */ +#define AR_SREV_CRETE_MS23 7 /* 2.3 metal spin (6 skipped) */ +#define AR_SREV_CRETE_23 8 /* 2.3 full tape out */ +#define AR_SREV_VERSION_M 0x000000F0 /* Chip version indication */ +#define AR_SREV_VERSION_CRETE 0 +#define AR_SREV_VERSION_MAUI_1 1 +#define AR_SREV_VERSION_MAUI_2 2 +#define AR_SREV_VERSION_SPIRIT 3 +#define AR_SREV_VERSION_OAHU 4 +#define AR_SREV_OAHU_ES 0 /* Engineering Sample */ +#define AR_SREV_OAHU_PROD 2 /* Production */ + +#define RAD5_SREV_MAJOR 0x10 /* All current supported ar5211 5 GHz radios are rev 0x10 */ +#define RAD5_SREV_PROD 0x15 /* Current production level radios */ +#define RAD2_SREV_MAJOR 0x20 /* All current supported ar5211 2 GHz radios are rev 0x10 */ + + /* EEPROM Registers in the MAC */ +#define AR_EEPROM_CMD_READ 0x00000001 +#define AR_EEPROM_CMD_WRITE 0x00000002 +#define AR_EEPROM_CMD_RESET 0x00000004 + +#define AR_EEPROM_STS_READ_ERROR 0x00000001 +#define AR_EEPROM_STS_READ_COMPLETE 0x00000002 +#define AR_EEPROM_STS_WRITE_ERROR 0x00000004 +#define AR_EEPROM_STS_WRITE_COMPLETE 0x00000008 + +#define AR_EEPROM_CFG_SIZE_M 0x00000003 /* Mask for EEPROM size determination override */ +#define AR_EEPROM_CFG_SIZE_AUTO 0 +#define AR_EEPROM_CFG_SIZE_4KBIT 1 +#define AR_EEPROM_CFG_SIZE_8KBIT 2 +#define AR_EEPROM_CFG_SIZE_16KBIT 3 +#define AR_EEPROM_CFG_DIS_WAIT_WRITE_COMPL 0x00000004 /* Disable wait for write completion */ +#define AR_EEPROM_CFG_CLOCK_M 0x00000018 /* Mask for EEPROM clock rate control */ +#define AR_EEPROM_CFG_CLOCK_S 3 /* Shift for EEPROM clock rate control */ +#define AR_EEPROM_CFG_CLOCK_156KHZ 0 +#define AR_EEPROM_CFG_CLOCK_312KHZ 1 +#define AR_EEPROM_CFG_CLOCK_625KHZ 2 +#define AR_EEPROM_CFG_RESV0 0x000000E0 /* Reserved */ +#define AR_EEPROM_CFG_PROT_KEY_M 0x00FFFF00 /* Mask for EEPROM protection key */ +#define AR_EEPROM_CFG_PROT_KEY_S 8 /* Shift for EEPROM protection key */ +#define AR_EEPROM_CFG_EN_L 0x01000000 /* EPRM_EN_L setting */ + + /* MAC PCU Registers */ +#define AR_STA_ID1_SADH_MASK 0x0000FFFF /* Mask for upper 16 bits of MAC addr */ +#define AR_STA_ID1_STA_AP 0x00010000 /* Device is AP */ +#define AR_STA_ID1_ADHOC 0x00020000 /* Device is ad-hoc */ +#define AR_STA_ID1_PWR_SAV 0x00040000 /* Power save reporting in self-generated frames */ +#define AR_STA_ID1_KSRCHDIS 0x00080000 /* Key search disable */ +#define AR_STA_ID1_PCF 0x00100000 /* Observe PCF */ +#define AR_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */ +#define AR_STA_ID1_DESC_ANTENNA 0x00400000 /* Update default antenna w/ TX antenna */ +#define AR_STA_ID1_RTS_USE_DEF 0x00800000 /* Use default antenna to send RTS */ +#define AR_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mb/s rate for ACK & CTS */ +#define AR_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate for ACK & CTS */ +#define AR_STA_ID1_BITS \ + "\20\20AP\21ADHOC\22PWR_SAV\23KSRCHDIS\25PCF" + +#define AR_BSS_ID1_U16_M 0x0000FFFF /* Mask for upper 16 bits of BSSID */ +#define AR_BSS_ID1_AID_M 0xFFFF0000 /* Mask for association ID */ +#define AR_BSS_ID1_AID_S 16 /* Shift for association ID */ + +#define AR_SLOT_TIME_MASK 0x000007FF /* Slot time mask */ + +#define AR_TIME_OUT_ACK 0x00001FFF /* Mask for ACK time-out */ +#define AR_TIME_OUT_ACK_S 0 /* Shift for ACK time-out */ +#define AR_TIME_OUT_CTS 0x1FFF0000 /* Mask for CTS time-out */ +#define AR_TIME_OUT_CTS_S 16 /* Shift for CTS time-out */ + +#define AR_RSSI_THR_MASK 0x000000FF /* Mask for Beacon RSSI warning threshold */ +#define AR_RSSI_THR_BM_THR 0x0000FF00 /* Mask for Missed beacon threshold */ +#define AR_RSSI_THR_BM_THR_S 8 /* Shift for Missed beacon threshold */ + +#define AR_USEC_M 0x0000007F /* Mask for clock cycles in 1 usec */ +#define AR_USEC_32_M 0x00003F80 /* Mask for number of 32MHz clock cycles in 1 usec */ +#define AR_USEC_32_S 7 /* Shift for number of 32MHz clock cycles in 1 usec */ +/* + * Tx/Rx latencies are to signal start and are in usecs. + * + * NOTE: AR5211/AR5311 difference: on Oahu, the TX latency field + * has increased from 6 bits to 9 bits. The RX latency field + * is unchanged, but is shifted over 3 bits. + */ +#define AR5311_USEC_TX_LAT_M 0x000FC000 /* Tx latency */ +#define AR5311_USEC_TX_LAT_S 14 +#define AR5311_USEC_RX_LAT_M 0x03F00000 /* Rx latency */ +#define AR5311_USEC_RX_LAT_S 20 + +#define AR5211_USEC_TX_LAT_M 0x007FC000 /* Tx latency */ +#define AR5211_USEC_TX_LAT_S 14 +#define AR5211_USEC_RX_LAT_M 0x1F800000 /* Rx latency */ +#define AR5211_USEC_RX_LAT_S 23 + + +#define AR_BEACON_PERIOD 0x0000FFFF /* Beacon period in TU/msec */ +#define AR_BEACON_PERIOD_S 0 /* Byte offset of PERIOD start*/ +#define AR_BEACON_TIM 0x007F0000 /* Byte offset of TIM start */ +#define AR_BEACON_TIM_S 16 /* Byte offset of TIM start */ +#define AR_BEACON_EN 0x00800000 /* beacon enable */ +#define AR_BEACON_RESET_TSF 0x01000000 /* Clears TSF to 0 */ +#define AR_BEACON_BITS "\20\27ENABLE\30RESET_TSF" + +#define AR_RX_FILTER_ALL 0x00000000 /* Disallow all frames */ +#define AR_RX_UCAST 0x00000001 /* Allow unicast frames */ +#define AR_RX_MCAST 0x00000002 /* Allow multicast frames */ +#define AR_RX_BCAST 0x00000004 /* Allow broadcast frames */ +#define AR_RX_CONTROL 0x00000008 /* Allow control frames */ +#define AR_RX_BEACON 0x00000010 /* Allow beacon frames */ +#define AR_RX_PROM 0x00000020 /* Promiscuous mode */ +#define AR_RX_PHY_ERR 0x00000040 /* Allow all phy errors */ +#define AR_RX_PHY_RADAR 0x00000080 /* Allow radar phy errors */ +#define AR_RX_FILTER_BITS \ + "\20\1UCAST\2MCAST\3BCAST\4CONTROL\5BEACON\6PROMISC\7PHY_ERR\10PHY_RADAR" + +#define AR_DIAG_SW_CACHE_ACK 0x00000001 /* disable ACK if no valid key*/ +#define AR_DIAG_SW_DIS_ACK 0x00000002 /* disable ACK generation */ +#define AR_DIAG_SW_DIS_CTS 0x00000004 /* disable CTS generation */ +#define AR_DIAG_SW_DIS_ENCRYPT 0x00000008 /* disable encryption */ +#define AR_DIAG_SW_DIS_DECRYPT 0x00000010 /* disable decryption */ +#define AR_DIAG_SW_DIS_RX 0x00000020 /* disable receive */ +#define AR_DIAG_SW_CORR_FCS 0x00000080 /* corrupt FCS */ +#define AR_DIAG_SW_CHAN_INFO 0x00000100 /* dump channel info */ +#define AR_DIAG_SW_EN_SCRAMSD 0x00000200 /* enable fixed scrambler seed*/ +#define AR5311_DIAG_SW_USE_ECO 0x00000400 /* "super secret" use ECO enable bit */ +#define AR_DIAG_SW_SCRAM_SEED_M 0x0001FC00 /* Fixed scrambler seed mask */ +#define AR_DIAG_SW_SCRAM_SEED_S 10 /* Fixed scrambler seed shfit */ +#define AR_DIAG_SW_FRAME_NV0 0x00020000 /* accept frames of non-zero protocol version */ +#define AR_DIAG_SW_OBS_PT_SEL_M 0x000C0000 /* Observation point select */ +#define AR_DIAG_SW_OBS_PT_SEL_S 18 /* Observation point select */ +#define AR_DIAG_SW_BITS \ + "\20\1DIS_CACHE_ACK\2DIS_ACK\3DIS_CTS\4DIS_ENC\5DIS_DEC\6DIS_RX"\ + "\11CORR_FCS\12CHAN_INFO\13EN_SCRAM_SEED\14USE_ECO\24FRAME_NV0" + +#define AR_KEYTABLE_KEY0(n) (AR_KEYTABLE(n) + 0) /* key bit 0-31 */ +#define AR_KEYTABLE_KEY1(n) (AR_KEYTABLE(n) + 4) /* key bit 32-47 */ +#define AR_KEYTABLE_KEY2(n) (AR_KEYTABLE(n) + 8) /* key bit 48-79 */ +#define AR_KEYTABLE_KEY3(n) (AR_KEYTABLE(n) + 12) /* key bit 80-95 */ +#define AR_KEYTABLE_KEY4(n) (AR_KEYTABLE(n) + 16) /* key bit 96-127 */ +#define AR_KEYTABLE_TYPE(n) (AR_KEYTABLE(n) + 20) /* key type */ +#define AR_KEYTABLE_TYPE_40 0x00000000 /* WEP 40 bit key */ +#define AR_KEYTABLE_TYPE_104 0x00000001 /* WEP 104 bit key */ +#define AR_KEYTABLE_TYPE_128 0x00000003 /* WEP 128 bit key */ +#define AR_KEYTABLE_TYPE_AES 0x00000005 /* AES 128 bit key */ +#define AR_KEYTABLE_TYPE_CLR 0x00000007 /* no encryption */ +#define AR_KEYTABLE_MAC0(n) (AR_KEYTABLE(n) + 24) /* MAC address 1-32 */ +#define AR_KEYTABLE_MAC1(n) (AR_KEYTABLE(n) + 28) /* MAC address 33-47 */ +#define AR_KEYTABLE_VALID 0x00008000 /* key and MAC address valid */ + +#endif /* _DEV_ATH_AR5211REG_H */ diff --git a/sys/external/isc/atheros_hal/dist/ar5211/boss.ini b/sys/external/isc/atheros_hal/dist/ar5211/boss.ini new file mode 100644 index 0000000..e054436 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5211/boss.ini @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2006 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +/* Auto Generated PCI Register Writes. Created: 09/12/02 */ + +static const uint32_t ar5211Modes[][5] = { + { 0x00000030, 0x00000015, 0x00000015, 0x0000001d, 0x00000015 }, + { 0x00001040, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f }, + { 0x00001070, 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 }, + { 0x00001030, 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 }, + { 0x000010b0, 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 }, + { 0x000010f0, 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 }, + { 0x00008014, 0x04000400, 0x08000800, 0x20003000, 0x04000400 }, + { 0x0000801c, 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 }, + { 0x00009804, 0x00000000, 0x00000003, 0x00000000, 0x00000000 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02010200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b }, + { 0x00009844, 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c }, + { 0x00009848, 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 }, + { 0x00009850, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 }, + { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e }, + { 0x0000985c, 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e }, + { 0x00009860, 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 }, + { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009914, 0x00002710, 0x00002710, 0x0000157c, 0x00002710 }, + { 0x00009918, 0x00000190, 0x00000190, 0x00000084, 0x00000190 }, + { 0x00009944, 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 }, + { 0x0000a180, 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff }, + { 0x000098d4, 0x00000010, 0x00000014, 0x00000010, 0x00000010 }, +}; + +static const uint32_t ar5211Common[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000028, 0x84849c9c }, + { 0x0000002c, 0x7c7c7c7c }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001230, 0x00000000 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000000 }, + { 0x00008024, 0x00000000 }, + { 0x00008028, 0x00000030 }, + { 0x0000802c, 0x0007ffff }, + { 0x00008030, 0x01ffffff }, + { 0x00008034, 0x00000031 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008040, 0x00000000 }, + { 0x00008044, 0x00000002 }, + { 0x00008048, 0x00000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0x2d849093 }, + { 0x00009810, 0x7d32e000 }, + { 0x00009814, 0x00000f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x00026ffe }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00020100 }, + { 0x00009840, 0x206a017a }, + { 0x0000984c, 0x1284613c }, + { 0x00009854, 0x00000859 }, + { 0x00009868, 0x409a4190 }, + { 0x0000986c, 0x050cb081 }, + { 0x00009870, 0x0000000f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x0000000c }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00800000 }, + { 0x00009910, 0x00000001 }, + { 0x0000991c, 0x0000092a }, + { 0x00009920, 0x00000000 }, + { 0x00009924, 0x00058a05 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000000 }, + { 0x00009930, 0x00000000 }, + { 0x00009934, 0x00000000 }, + { 0x00009938, 0x00000000 }, + { 0x0000993c, 0x0000003f }, + { 0x00009940, 0x00000004 }, + { 0x00009948, 0x00000000 }, + { 0x0000994c, 0x00000000 }, + { 0x00009950, 0x00000000 }, + { 0x00009954, 0x5d50f14c }, + { 0x00009958, 0x00000018 }, + { 0x0000995c, 0x004b6a8e }, + { 0x0000a184, 0x06ff05ff }, + { 0x0000a188, 0x07ff07ff }, + { 0x0000a18c, 0x08ff08ff }, + { 0x0000a190, 0x09ff09ff }, + { 0x0000a194, 0x0aff0aff }, + { 0x0000a198, 0x0bff0bff }, + { 0x0000a19c, 0x0cff0cff }, + { 0x0000a1a0, 0x0dff0dff }, + { 0x0000a1a4, 0x0fff0eff }, + { 0x0000a1a8, 0x12ff12ff }, + { 0x0000a1ac, 0x14ff13ff }, + { 0x0000a1b0, 0x16ff15ff }, + { 0x0000a1b4, 0x19ff17ff }, + { 0x0000a1b8, 0x1bff1aff }, + { 0x0000a1bc, 0x1eff1dff }, + { 0x0000a1c0, 0x23ff20ff }, + { 0x0000a1c4, 0x27ff25ff }, + { 0x0000a1c8, 0x2cff29ff }, + { 0x0000a1cc, 0x31ff2fff }, + { 0x0000a1d0, 0x37ff34ff }, + { 0x0000a1d4, 0x3aff3aff }, + { 0x0000a1d8, 0x3aff3aff }, + { 0x0000a1dc, 0x3aff3aff }, + { 0x0000a1e0, 0x3aff3aff }, + { 0x0000a1e4, 0x3aff3aff }, + { 0x0000a1e8, 0x3aff3aff }, + { 0x0000a1ec, 0x3aff3aff }, + { 0x0000a1f0, 0x3aff3aff }, + { 0x0000a1f4, 0x3aff3aff }, + { 0x0000a1f8, 0x3aff3aff }, + { 0x0000a1fc, 0x3aff3aff }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000020 }, + { 0x00009b08, 0x00000010 }, + { 0x00009b0c, 0x00000030 }, + { 0x00009b10, 0x00000008 }, + { 0x00009b14, 0x00000028 }, + { 0x00009b18, 0x00000004 }, + { 0x00009b1c, 0x00000024 }, + { 0x00009b20, 0x00000014 }, + { 0x00009b24, 0x00000034 }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000002c }, + { 0x00009b30, 0x00000002 }, + { 0x00009b34, 0x00000022 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000032 }, + { 0x00009b40, 0x0000000a }, + { 0x00009b44, 0x0000002a }, + { 0x00009b48, 0x00000006 }, + { 0x00009b4c, 0x00000026 }, + { 0x00009b50, 0x00000016 }, + { 0x00009b54, 0x00000036 }, + { 0x00009b58, 0x0000000e }, + { 0x00009b5c, 0x0000002e }, + { 0x00009b60, 0x00000001 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000011 }, + { 0x00009b6c, 0x00000031 }, + { 0x00009b70, 0x00000009 }, + { 0x00009b74, 0x00000029 }, + { 0x00009b78, 0x00000005 }, + { 0x00009b7c, 0x00000025 }, + { 0x00009b80, 0x00000015 }, + { 0x00009b84, 0x00000035 }, + { 0x00009b88, 0x0000000d }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000003 }, + { 0x00009b94, 0x00000023 }, + { 0x00009b98, 0x00000013 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x0000000b }, + { 0x00009ba4, 0x0000002b }, + { 0x00009ba8, 0x0000002b }, + { 0x00009bac, 0x0000002b }, + { 0x00009bb0, 0x0000002b }, + { 0x00009bb4, 0x0000002b }, + { 0x00009bb8, 0x0000002b }, + { 0x00009bbc, 0x0000002b }, + { 0x00009bc0, 0x0000002b }, + { 0x00009bc4, 0x0000002b }, + { 0x00009bc8, 0x0000002b }, + { 0x00009bcc, 0x0000002b }, + { 0x00009bd0, 0x0000002b }, + { 0x00009bd4, 0x0000002b }, + { 0x00009bd8, 0x0000002b }, + { 0x00009bdc, 0x0000002b }, + { 0x00009be0, 0x0000002b }, + { 0x00009be4, 0x0000002b }, + { 0x00009be8, 0x0000002b }, + { 0x00009bec, 0x0000002b }, + { 0x00009bf0, 0x0000002b }, + { 0x00009bf4, 0x0000002b }, + { 0x00009bf8, 0x00000002 }, + { 0x00009bfc, 0x00000016 }, + { 0x000098d4, 0x00000020 }, + { 0x000098d8, 0x00601068 }, +}; + +static uint32_t ar5211Mode2_4[][3] = { + { 0x0000a204, 0x00000000, 0x00000000 }, + { 0x0000a208, 0x503e4646, 0x503e4646 }, + { 0x0000a20c, 0x6480416c, 0x6480416c }, + { 0x0000a210, 0x0199a003, 0x0199a003 }, + { 0x0000a214, 0x044cd610, 0x044cd610 }, + { 0x0000a218, 0x13800040, 0x13800040 }, + { 0x0000a21c, 0x1be00060, 0x1be00060 }, + { 0x0000a220, 0x0c53800a, 0x0c53800a }, + { 0x0000a224, 0x0014df3b, 0x0014df3b }, + { 0x0000a228, 0x000001b5, 0x000001b5 }, + { 0x0000a22c, 0x00000020, 0x00000020 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00380000, 0x00380000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x000400f9, 0x000400f9 }, + { 0x000098d4, 0x00000000, 0x00000004 }, +}; + +static const uint32_t ar5211BB_RfGain[][3] = { + { 0x00009a00, 0x000001a9, 0x00000000 }, + { 0x00009a04, 0x000001e9, 0x00000040 }, + { 0x00009a08, 0x00000029, 0x00000080 }, + { 0x00009a0c, 0x00000069, 0x00000150 }, + { 0x00009a10, 0x00000199, 0x00000190 }, + { 0x00009a14, 0x000001d9, 0x000001d0 }, + { 0x00009a18, 0x00000019, 0x00000010 }, + { 0x00009a1c, 0x00000059, 0x00000044 }, + { 0x00009a20, 0x00000099, 0x00000084 }, + { 0x00009a24, 0x000001a5, 0x00000148 }, + { 0x00009a28, 0x000001e5, 0x00000188 }, + { 0x00009a2c, 0x00000025, 0x000001c8 }, + { 0x00009a30, 0x000001c8, 0x00000014 }, + { 0x00009a34, 0x00000008, 0x00000042 }, + { 0x00009a38, 0x00000048, 0x00000082 }, + { 0x00009a3c, 0x00000088, 0x00000178 }, + { 0x00009a40, 0x00000198, 0x000001b8 }, + { 0x00009a44, 0x000001d8, 0x000001f8 }, + { 0x00009a48, 0x00000018, 0x00000012 }, + { 0x00009a4c, 0x00000058, 0x00000052 }, + { 0x00009a50, 0x00000098, 0x00000092 }, + { 0x00009a54, 0x000001a4, 0x0000017c }, + { 0x00009a58, 0x000001e4, 0x000001bc }, + { 0x00009a5c, 0x00000024, 0x000001fc }, + { 0x00009a60, 0x00000064, 0x0000000a }, + { 0x00009a64, 0x000000a4, 0x0000004a }, + { 0x00009a68, 0x000000e4, 0x0000008a }, + { 0x00009a6c, 0x0000010a, 0x0000015a }, + { 0x00009a70, 0x0000014a, 0x0000019a }, + { 0x00009a74, 0x0000018a, 0x000001da }, + { 0x00009a78, 0x000001ca, 0x0000000e }, + { 0x00009a7c, 0x0000000a, 0x0000004e }, + { 0x00009a80, 0x0000004a, 0x0000008e }, + { 0x00009a84, 0x0000008a, 0x0000015e }, + { 0x00009a88, 0x000001ba, 0x0000019e }, + { 0x00009a8c, 0x000001fa, 0x000001de }, + { 0x00009a90, 0x0000003a, 0x00000009 }, + { 0x00009a94, 0x0000007a, 0x00000049 }, + { 0x00009a98, 0x00000186, 0x00000089 }, + { 0x00009a9c, 0x000001c6, 0x00000179 }, + { 0x00009aa0, 0x00000006, 0x000001b9 }, + { 0x00009aa4, 0x00000046, 0x000001f9 }, + { 0x00009aa8, 0x00000086, 0x00000039 }, + { 0x00009aac, 0x000000c6, 0x00000079 }, + { 0x00009ab0, 0x000000c6, 0x000000b9 }, + { 0x00009ab4, 0x000000c6, 0x000001bd }, + { 0x00009ab8, 0x000000c6, 0x000001fd }, + { 0x00009abc, 0x000000c6, 0x0000003d }, + { 0x00009ac0, 0x000000c6, 0x0000007d }, + { 0x00009ac4, 0x000000c6, 0x000000bd }, + { 0x00009ac8, 0x000000c6, 0x000000fd }, + { 0x00009acc, 0x000000c6, 0x000000fd }, + { 0x00009ad0, 0x000000c6, 0x000000fd }, + { 0x00009ad4, 0x000000c6, 0x000000fd }, + { 0x00009ad8, 0x000000c6, 0x000000fd }, + { 0x00009adc, 0x000000c6, 0x000000fd }, + { 0x00009ae0, 0x000000c6, 0x000000fd }, + { 0x00009ae4, 0x000000c6, 0x000000fd }, + { 0x00009ae8, 0x000000c6, 0x000000fd }, + { 0x00009aec, 0x000000c6, 0x000000fd }, + { 0x00009af0, 0x000000c6, 0x000000fd }, + { 0x00009af4, 0x000000c6, 0x000000fd }, + { 0x00009af8, 0x000000c6, 0x000000fd }, + { 0x00009afc, 0x000000c6, 0x000000fd }, +}; + +static uint32_t ar5211Rf6n7[][3] = { + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x10000000, 0x10000000 }, + { 0x0000989c, 0x04000000, 0x04000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x0a000000 }, + { 0x0000989c, 0x00380080, 0x02380080 }, + { 0x0000989c, 0x00020006, 0x00000006 }, + { 0x0000989c, 0x00000092, 0x00000092 }, + { 0x0000989c, 0x000000a0, 0x000000a0 }, + { 0x0000989c, 0x00040007, 0x00040007 }, + { 0x000098d4, 0x0000001a, 0x0000001a }, + { 0x0000989c, 0x00000048, 0x00000048 }, + { 0x0000989c, 0x00000010, 0x00000010 }, + { 0x0000989c, 0x00000008, 0x00000008 }, + { 0x0000989c, 0x0000000f, 0x0000000f }, + { 0x0000989c, 0x000000f2, 0x00000062 }, + { 0x0000989c, 0x0000904f, 0x0000904c }, + { 0x0000989c, 0x0000125a, 0x0000129a }, + { 0x000098cc, 0x0000000e, 0x0000000f }, +}; + diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar2316.c b/sys/external/isc/atheros_hal/dist/ar5212/ar2316.c new file mode 100644 index 0000000..9bfc482 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar2316.c @@ -0,0 +1,763 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +#define AH_5212_2316 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +typedef RAW_DATA_STRUCT_2413 RAW_DATA_STRUCT_2316; +typedef RAW_DATA_PER_CHANNEL_2413 RAW_DATA_PER_CHANNEL_2316; +#define PWR_TABLE_SIZE_2316 PWR_TABLE_SIZE_2413 + +struct ar2316State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE_2316]; + + uint32_t Bank1Data[N(ar5212Bank1_2316)]; + uint32_t Bank2Data[N(ar5212Bank2_2316)]; + uint32_t Bank3Data[N(ar5212Bank3_2316)]; + uint32_t Bank6Data[N(ar5212Bank6_2316)]; + uint32_t Bank7Data[N(ar5212Bank7_2316)]; + + /* + * Private state for reduced stack usage. + */ + /* filled out Vpd table for all pdGains (chanL) */ + uint16_t vpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (chanR) */ + uint16_t vpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (interpolated) */ + uint16_t vpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; +}; +#define AR2316(ah) ((struct ar2316State *) AH5212(ah)->ah_rfHal) + +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar2316WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int regWrites) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_2316, modesIndex, regWrites); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_2316, 1, regWrites); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_2316, freqIndex, regWrites); + + /* For AP51 */ + if (!ahp->ah_cwCalRequire) { + OS_REG_WRITE(ah, 0xa358, (OS_REG_READ(ah, 0xa358) & ~0x2)); + } else { + ahp->ah_cwCalRequire = AH_FALSE; + } +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar2316SetChannel(struct ath_hal *ah, struct ieee80211_channel *chan) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + + OS_MARK(ah, AH_MARK_SETCHANNEL, freq); + + if (freq < 4800) { + uint32_t txctl; + + if (((freq - 2192) % 5) == 0) { + channelSel = ((freq - 672) * 2 - 3040)/10; + bModeSynth = 0; + } else if (((freq - 2224) % 5) == 0) { + channelSel = ((freq - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u MHz\n", + __func__, freq); + return AH_FALSE; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else if ((freq % 20) == 0 && freq >= 5120) { + channelSel = ath_hal_reverseBits( + ((freq - 4800) / 20 << 2), 8); + aModeRefSel = ath_hal_reverseBits(3, 2); + } else if ((freq % 10) == 0) { + channelSel = ath_hal_reverseBits( + ((freq - 4800) / 10 << 1), 8); + aModeRefSel = ath_hal_reverseBits(2, 2); + } else if ((freq % 5) == 0) { + channelSel = ath_hal_reverseBits( + (freq - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", + __func__, freq); + return AH_FALSE; + } + + reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 12) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); + + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar2316SetRfRegs(struct ath_hal *ah, const struct ieee80211_channel *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ +#define RF_BANK_SETUP(_priv, _ix, _col) do { \ + int i; \ + for (i = 0; i < N(ar5212Bank##_ix##_2316); i++) \ + (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2316[i][_col];\ +} while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t ob2GHz = 0, db2GHz = 0; + struct ar2316State *priv = AR2316(ah); + int regWrites = 0; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan %u/0x%x modesIndex %u\n", + __func__, chan->ic_freq, chan->ic_flags, modesIndex); + + HALASSERT(priv != AH_NULL); + + /* Setup rf parameters */ + if (IEEE80211_IS_CHAN_B(chan)) { + ob2GHz = ee->ee_obFor24; + db2GHz = ee->ee_dbFor24; + } else { + ob2GHz = ee->ee_obFor24g; + db2GHz = ee->ee_dbFor24g; + } + + /* Bank 1 Write */ + RF_BANK_SETUP(priv, 1, 1); + + /* Bank 2 Write */ + RF_BANK_SETUP(priv, 2, modesIndex); + + /* Bank 3 Write */ + RF_BANK_SETUP(priv, 3, modesIndex); + + /* Bank 6 Write */ + RF_BANK_SETUP(priv, 6, modesIndex); + + ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 178, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 175, 0); + + /* Bank 7 Setup */ + RF_BANK_SETUP(priv, 7, modesIndex); + + /* Write Analog registers */ + HAL_INI_WRITE_BANK(ah, ar5212Bank1_2316, priv->Bank1Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank2_2316, priv->Bank2Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank3_2316, priv->Bank3Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_2316, priv->Bank6Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank7_2316, priv->Bank7Data, regWrites); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar2316GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar2316State *priv = AR2316(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Return indices surrounding the value in sorted integer lists. + * + * NB: the input list is assumed to be sorted in ascending order + */ +static void +GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi) +{ + int16_t target = v; + const int16_t *ep = lp+listSize; + const int16_t *tp; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < lp[0]) { + *vlo = *vhi = 0; + return; + } + if (target >= ep[-1]) { + *vlo = *vhi = listSize - 1; + return; + } + + /* look for value being near or between 2 values in list */ + for (tp = lp; tp < ep; tp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (*tp == target) { + *vlo = *vhi = tp - (const int16_t *) lp; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < tp[1]) { + *vlo = tp - (const int16_t *) lp; + *vhi = *vlo + 1; + return; + } + } +} + +/* + * Fill the Vpdlist for indices Pmax-Pmin + */ +static HAL_BOOL +ar2316FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t Pmax, + const int16_t *pwrList, const int16_t *VpdList, + uint16_t numIntercepts, uint16_t retVpdList[][64]) +{ + uint16_t ii, jj, kk; + int16_t currPwr = (int16_t)(2*Pmin); + /* since Pmin is pwr*2 and pwrList is 4*pwr */ + uint32_t idxL, idxR; + + ii = 0; + jj = 0; + + if (numIntercepts < 2) + return AH_FALSE; + + while (ii <= (uint16_t)(Pmax - Pmin)) { + GetLowerUpperIndex(currPwr, pwrList, numIntercepts, + &(idxL), &(idxR)); + if (idxR < 1) + idxR = 1; /* extrapolate below */ + if (idxL == (uint32_t)(numIntercepts - 1)) + idxL = numIntercepts - 2; /* extrapolate above */ + if (pwrList[idxL] == pwrList[idxR]) + kk = VpdList[idxL]; + else + kk = (uint16_t) + (((currPwr - pwrList[idxL])*VpdList[idxR]+ + (pwrList[idxR] - currPwr)*VpdList[idxL])/ + (pwrList[idxR] - pwrList[idxL])); + retVpdList[pdGainIdx][ii] = kk; + ii++; + currPwr += 2; /* half dB steps */ + } + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static int16_t +interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight != srcLeft) { + rv = ((target - srcLeft)*targetRight + + (srcRight - target)*targetLeft) / (srcRight - srcLeft); + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Uses the data points read from EEPROM to reconstruct the pdadc power table + * Called by ar2316SetPowerTable() + */ +static int +ar2316getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel, + const RAW_DATA_STRUCT_2316 *pRawDataset, + uint16_t pdGainOverlap_t2, + int16_t *pMinCalPower, uint16_t pPdGainBoundaries[], + uint16_t pPdGainValues[], uint16_t pPDADCValues[]) +{ + struct ar2316State *priv = AR2316(ah); +#define VpdTable_L priv->vpdTable_L +#define VpdTable_R priv->vpdTable_R +#define VpdTable_I priv->vpdTable_I + uint32_t ii, jj, kk; + int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */ + uint32_t idxL, idxR; + uint32_t numPdGainsUsed = 0; + /* + * If desired to support -ve power levels in future, just + * change pwr_I_0 to signed 5-bits. + */ + int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on. */ + int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on */ + uint16_t numVpd = 0; + uint16_t Vpd_step; + int16_t tmpVal ; + uint32_t sizeCurrVpdTable, maxIndex, tgtIndex; + + /* Get upper lower index */ + GetLowerUpperIndex(channel, pRawDataset->pChannels, + pRawDataset->numChannels, &(idxL), &(idxR)); + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain; + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]; + if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) { + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]; + } + Pmin_t2[numPdGainsUsed] = (int16_t) + (Pmin_t2[numPdGainsUsed] / 2); + Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]) + Pmax_t2[numPdGainsUsed] = + pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2); + ar2316FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L + ); + ar2316FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R + ); + for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) { + VpdTable_I[numPdGainsUsed][kk] = + interpolate_signed( + channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR], + (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]); + } + /* fill VpdTable_I for this pdGain */ + numPdGainsUsed++; + } + /* if this pdGain is used */ + } + + *pMinCalPower = Pmin_t2[0]; + kk = 0; /* index for the final table */ + for (ii = 0; ii < numPdGainsUsed; ii++) { + if (ii == (numPdGainsUsed - 1)) + pPdGainBoundaries[ii] = Pmax_t2[ii] + + PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB; + else + pPdGainBoundaries[ii] = (uint16_t) + ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 ); + if (pPdGainBoundaries[ii] > 63) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: clamp pPdGainBoundaries[%d] %d\n", + __func__, ii, pPdGainBoundaries[ii]);/*XXX*/ + pPdGainBoundaries[ii] = 63; + } + + /* Find starting index for this pdGain */ + if (ii == 0) + ss = 0; /* for the first pdGain, start from index 0 */ + else + ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) - + pdGainOverlap_t2; + Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + *-ve ss indicates need to extrapolate data below for this pdGain + */ + while (ss < 0) { + tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step); + pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii]; + tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii]; + maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; + + while (ss < (int16_t)maxIndex) + pPDADCValues[kk++] = VpdTable_I[ii][ss++]; + + Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] - + VpdTable_I[ii][sizeCurrVpdTable-2]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + * for last gain, pdGainBoundary == Pmax_t2, so will + * have to extrapolate + */ + if (tgtIndex > maxIndex) { /* need to extrapolate above */ + while(ss < (int16_t)tgtIndex) { + tmpVal = (uint16_t) + (VpdTable_I[ii][sizeCurrVpdTable-1] + + (ss-maxIndex)*Vpd_step); + pPDADCValues[kk++] = (tmpVal > 127) ? + 127 : tmpVal; + ss++; + } + } /* extrapolated above */ + } /* for all pdGainUsed */ + + while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) { + pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1]; + ii++; + } + while (kk < 128) { + pPDADCValues[kk] = pPDADCValues[kk-1]; + kk++; + } + + return numPdGainsUsed; +#undef VpdTable_L +#undef VpdTable_R +#undef VpdTable_I +} + +static HAL_BOOL +ar2316SetPowerTable(struct ath_hal *ah, + int16_t *minPower, int16_t *maxPower, + const struct ieee80211_channel *chan, + uint16_t *rfXpdGain) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2316 *pRawDataset = AH_NULL; + uint16_t pdGainOverlap_t2; + int16_t minCalPower2316_t2; + uint16_t *pdadcValues = ahp->ah_pcdacTable; + uint16_t gainBoundaries[4]; + uint32_t reg32, regoffset; + int i, numPdGainsUsed; +#ifndef AH_USE_INIPDGAIN + uint32_t tpcrg1; +#endif + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", + __func__, chan->ic_freq, chan->ic_flags); + + if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IEEE80211_IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: illegal mode\n", __func__); + return AH_FALSE; + } + + pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP); + + numPdGainsUsed = ar2316getGainBoundariesAndPdadcsForPowers(ah, + chan->channel, pRawDataset, pdGainOverlap_t2, + &minCalPower2316_t2,gainBoundaries, rfXpdGain, pdadcValues); + HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); + +#ifdef AH_USE_INIPDGAIN + /* + * Use pd_gains curve from eeprom; Atheros always uses + * the default curve from the ini file but some vendors + * (e.g. Zcomax) want to override this curve and not + * honoring their settings results in tx power 5dBm low. + */ + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (pRawDataset->pDataPerChannel[0].numPdGains - 1)); +#else + tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); + tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) + | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); + switch (numPdGainsUsed) { + case 3: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3; + tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3); + /* fall thru... */ + case 2: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2; + tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2); + /* fall thru... */ + case 1: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1; + tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1); + break; + } +#ifdef AH_DEBUG + if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1)) + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default " + "pd_gains (default 0x%x, calculated 0x%x)\n", + __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); +#endif + OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); +#endif + + /* + * Note the pdadc table may not start at 0 dBm power, could be + * negative or greater than 0. Need to offset the power + * values by the amount of minPower for griffin + */ + if (minCalPower2316_t2 != 0) + ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2316_t2); + else + ahp->ah_txPowerIndexOffset = 0; + + /* Finally, write the power values into the baseband power table */ + regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */ + for (i = 0; i < 32; i++) { + reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0) | + ((pdadcValues[4*i + 1] & 0xFF) << 8) | + ((pdadcValues[4*i + 2] & 0xFF) << 16) | + ((pdadcValues[4*i + 3] & 0xFF) << 24) ; + OS_REG_WRITE(ah, regoffset, reg32); + regoffset += 4; + } + + OS_REG_WRITE(ah, AR_PHY_TPCRG5, + SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + + return AH_TRUE; +} + +static int16_t +ar2316GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2316 *data) +{ + uint32_t ii,jj; + uint16_t Pmin=0,numVpd; + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = data->pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + Pmin = data->pDataPerPDGain[jj].pwr_t4[0]; + return(Pmin); + } + } + return(Pmin); +} + +static int16_t +ar2316GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2316 *data) +{ + uint32_t ii; + uint16_t Pmax=0,numVpd; + + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + /* work forwards cuase lowest pdGain for highest power */ + numVpd = data->pDataPerPDGain[ii].numVpd; + if (numVpd > 0) { + Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1]; + return(Pmax); + } + } + return(Pmax); +} + +static HAL_BOOL +ar2316GetChannelMaxMinPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *maxPow, int16_t *minPow) +{ + uint16_t freq = chan->ic_freq; /* NB: never mapped */ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2316 *pRawDataset = AH_NULL; + const RAW_DATA_PER_CHANNEL_2316 *data=AH_NULL; + uint16_t numChannels; + int totalD,totalF, totalMin,last, i; + + *maxPow = 0; + + if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IEEE80211_IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else + return(AH_FALSE); + + numChannels = pRawDataset->numChannels; + data = pRawDataset->pDataPerChannel; + + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if (numChannels < 1) + return(AH_FALSE); + + if ((freq < data[0].channelValue) || + (freq > data[numChannels-1].channelValue)) { + if (freq < data[0].channelValue) { + *maxPow = ar2316GetMaxPower(ah, &data[0]); + *minPow = ar2316GetMinPower(ah, &data[0]); + return(AH_TRUE); + } else { + *maxPow = ar2316GetMaxPower(ah, &data[numChannels - 1]); + *minPow = ar2316GetMinPower(ah, &data[numChannels - 1]); + return(AH_TRUE); + } + } + + /* Linearly interpolate the power value now */ + for (last=0,i=0; (i data[i].channelValue); + last = i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = ar2316GetMaxPower(ah, &data[i]) - ar2316GetMaxPower(ah, &data[last]); + *maxPow = (int8_t) ((totalF*(freq-data[last].channelValue) + + ar2316GetMaxPower(ah, &data[last])*totalD)/totalD); + totalMin = ar2316GetMinPower(ah, &data[i]) - ar2316GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(freq-data[last].channelValue) + + ar2316GetMinPower(ah, &data[last])*totalD)/totalD); + return(AH_TRUE); + } else { + if (freq == data[i].channelValue) { + *maxPow = ar2316GetMaxPower(ah, &data[i]); + *minPow = ar2316GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar2316RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for private state. + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar2316RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar2316State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar2316State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar2316RfDetach; + priv->base.writeRegs = ar2316WriteRegs; + priv->base.getRfBank = ar2316GetRfBank; + priv->base.setChannel = ar2316SetChannel; + priv->base.setRfRegs = ar2316SetRfRegs; + priv->base.setPowerTable = ar2316SetPowerTable; + priv->base.getChannelMaxMinPower = ar2316GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5212GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + ahp->ah_cwCalRequire = AH_TRUE; /* force initial cal */ + + return AH_TRUE; +} + +static HAL_BOOL +ar2316Probe(struct ath_hal *ah) +{ + return IS_2316(ah); +} +AH_RF(RF2316, ar2316Probe, ar2316RfAttach); diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar2317.c b/sys/external/isc/atheros_hal/dist/ar5212/ar2317.c new file mode 100644 index 0000000..fdf88e3 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar2317.c @@ -0,0 +1,741 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +#define AH_5212_2317 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +typedef RAW_DATA_STRUCT_2413 RAW_DATA_STRUCT_2317; +typedef RAW_DATA_PER_CHANNEL_2413 RAW_DATA_PER_CHANNEL_2317; +#define PWR_TABLE_SIZE_2317 PWR_TABLE_SIZE_2413 + +struct ar2317State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE_2317]; + + uint32_t Bank1Data[N(ar5212Bank1_2317)]; + uint32_t Bank2Data[N(ar5212Bank2_2317)]; + uint32_t Bank3Data[N(ar5212Bank3_2317)]; + uint32_t Bank6Data[N(ar5212Bank6_2317)]; + uint32_t Bank7Data[N(ar5212Bank7_2317)]; + + /* + * Private state for reduced stack usage. + */ + /* filled out Vpd table for all pdGains (chanL) */ + uint16_t vpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (chanR) */ + uint16_t vpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (interpolated) */ + uint16_t vpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; +}; +#define AR2317(ah) ((struct ar2317State *) AH5212(ah)->ah_rfHal) + +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar2317WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_2317, modesIndex, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_2317, 1, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_2317, freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar2317SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + + OS_MARK(ah, AH_MARK_SETCHANNEL, freq); + + if (freq < 4800) { + uint32_t txctl; + channelSel = freq - 2272 ; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else if ((freq % 20) == 0 && freq >= 5120) { + channelSel = ath_hal_reverseBits( + ((freq - 4800) / 20 << 2), 8); + aModeRefSel = ath_hal_reverseBits(3, 2); + } else if ((freq % 10) == 0) { + channelSel = ath_hal_reverseBits( + ((freq - 4800) / 10 << 1), 8); + aModeRefSel = ath_hal_reverseBits(2, 2); + } else if ((freq % 5) == 0) { + channelSel = ath_hal_reverseBits( + (freq - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", + __func__, freq); + return AH_FALSE; + } + + reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 12) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); + + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar2317SetRfRegs(struct ath_hal *ah, + const struct ieee80211_channel *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ +#define RF_BANK_SETUP(_priv, _ix, _col) do { \ + int i; \ + for (i = 0; i < N(ar5212Bank##_ix##_2317); i++) \ + (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2317[i][_col];\ +} while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t ob2GHz = 0, db2GHz = 0; + struct ar2317State *priv = AR2317(ah); + int regWrites = 0; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan %u/0x%x modesIndex %u\n", + __func__, chan->ic_freq, chan->ic_flags, modesIndex); + + HALASSERT(priv); + + /* Setup rf parameters */ + if (IEEE80211_IS_CHAN_B(chan)) { + ob2GHz = ee->ee_obFor24; + db2GHz = ee->ee_dbFor24; + } else { + ob2GHz = ee->ee_obFor24g; + db2GHz = ee->ee_dbFor24g; + } + + /* Bank 1 Write */ + RF_BANK_SETUP(priv, 1, 1); + + /* Bank 2 Write */ + RF_BANK_SETUP(priv, 2, modesIndex); + + /* Bank 3 Write */ + RF_BANK_SETUP(priv, 3, modesIndex); + + /* Bank 6 Write */ + RF_BANK_SETUP(priv, 6, modesIndex); + + ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 193, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 190, 0); + + /* Bank 7 Setup */ + RF_BANK_SETUP(priv, 7, modesIndex); + + /* Write Analog registers */ + HAL_INI_WRITE_BANK(ah, ar5212Bank1_2317, priv->Bank1Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank2_2317, priv->Bank2Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank3_2317, priv->Bank3Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_2317, priv->Bank6Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank7_2317, priv->Bank7Data, regWrites); + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar2317GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar2317State *priv = AR2317(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Return indices surrounding the value in sorted integer lists. + * + * NB: the input list is assumed to be sorted in ascending order + */ +static void +GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi) +{ + int16_t target = v; + const int16_t *ep = lp+listSize; + const int16_t *tp; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < lp[0]) { + *vlo = *vhi = 0; + return; + } + if (target >= ep[-1]) { + *vlo = *vhi = listSize - 1; + return; + } + + /* look for value being near or between 2 values in list */ + for (tp = lp; tp < ep; tp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (*tp == target) { + *vlo = *vhi = tp - (const int16_t *) lp; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < tp[1]) { + *vlo = tp - (const int16_t *) lp; + *vhi = *vlo + 1; + return; + } + } +} + +/* + * Fill the Vpdlist for indices Pmax-Pmin + */ +static HAL_BOOL +ar2317FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t Pmax, + const int16_t *pwrList, const int16_t *VpdList, + uint16_t numIntercepts, uint16_t retVpdList[][64]) +{ + uint16_t ii, jj, kk; + int16_t currPwr = (int16_t)(2*Pmin); + /* since Pmin is pwr*2 and pwrList is 4*pwr */ + uint32_t idxL, idxR; + + ii = 0; + jj = 0; + + if (numIntercepts < 2) + return AH_FALSE; + + while (ii <= (uint16_t)(Pmax - Pmin)) { + GetLowerUpperIndex(currPwr, pwrList, numIntercepts, + &(idxL), &(idxR)); + if (idxR < 1) + idxR = 1; /* extrapolate below */ + if (idxL == (uint32_t)(numIntercepts - 1)) + idxL = numIntercepts - 2; /* extrapolate above */ + if (pwrList[idxL] == pwrList[idxR]) + kk = VpdList[idxL]; + else + kk = (uint16_t) + (((currPwr - pwrList[idxL])*VpdList[idxR]+ + (pwrList[idxR] - currPwr)*VpdList[idxL])/ + (pwrList[idxR] - pwrList[idxL])); + retVpdList[pdGainIdx][ii] = kk; + ii++; + currPwr += 2; /* half dB steps */ + } + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static int16_t +interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight != srcLeft) { + rv = ((target - srcLeft)*targetRight + + (srcRight - target)*targetLeft) / (srcRight - srcLeft); + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Uses the data points read from EEPROM to reconstruct the pdadc power table + * Called by ar2317SetPowerTable() + */ +static int +ar2317getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel, + const RAW_DATA_STRUCT_2317 *pRawDataset, + uint16_t pdGainOverlap_t2, + int16_t *pMinCalPower, uint16_t pPdGainBoundaries[], + uint16_t pPdGainValues[], uint16_t pPDADCValues[]) +{ + struct ar2317State *priv = AR2317(ah); +#define VpdTable_L priv->vpdTable_L +#define VpdTable_R priv->vpdTable_R +#define VpdTable_I priv->vpdTable_I + /* XXX excessive stack usage? */ + uint32_t ii, jj, kk; + int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */ + uint32_t idxL, idxR; + uint32_t numPdGainsUsed = 0; + /* + * If desired to support -ve power levels in future, just + * change pwr_I_0 to signed 5-bits. + */ + int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on. */ + int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on */ + uint16_t numVpd = 0; + uint16_t Vpd_step; + int16_t tmpVal ; + uint32_t sizeCurrVpdTable, maxIndex, tgtIndex; + + /* Get upper lower index */ + GetLowerUpperIndex(channel, pRawDataset->pChannels, + pRawDataset->numChannels, &(idxL), &(idxR)); + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain; + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]; + if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) { + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]; + } + Pmin_t2[numPdGainsUsed] = (int16_t) + (Pmin_t2[numPdGainsUsed] / 2); + Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]) + Pmax_t2[numPdGainsUsed] = + pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2); + ar2317FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L + ); + ar2317FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R + ); + for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) { + VpdTable_I[numPdGainsUsed][kk] = + interpolate_signed( + channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR], + (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]); + } + /* fill VpdTable_I for this pdGain */ + numPdGainsUsed++; + } + /* if this pdGain is used */ + } + + *pMinCalPower = Pmin_t2[0]; + kk = 0; /* index for the final table */ + for (ii = 0; ii < numPdGainsUsed; ii++) { + if (ii == (numPdGainsUsed - 1)) + pPdGainBoundaries[ii] = Pmax_t2[ii] + + PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB; + else + pPdGainBoundaries[ii] = (uint16_t) + ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 ); + if (pPdGainBoundaries[ii] > 63) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: clamp pPdGainBoundaries[%d] %d\n", + __func__, ii, pPdGainBoundaries[ii]);/*XXX*/ + pPdGainBoundaries[ii] = 63; + } + + /* Find starting index for this pdGain */ + if (ii == 0) + ss = 0; /* for the first pdGain, start from index 0 */ + else + ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) - + pdGainOverlap_t2; + Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + *-ve ss indicates need to extrapolate data below for this pdGain + */ + while (ss < 0) { + tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step); + pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii]; + tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii]; + maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; + + while (ss < (int16_t)maxIndex) + pPDADCValues[kk++] = VpdTable_I[ii][ss++]; + + Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] - + VpdTable_I[ii][sizeCurrVpdTable-2]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + * for last gain, pdGainBoundary == Pmax_t2, so will + * have to extrapolate + */ + if (tgtIndex > maxIndex) { /* need to extrapolate above */ + while(ss < (int16_t)tgtIndex) { + tmpVal = (uint16_t) + (VpdTable_I[ii][sizeCurrVpdTable-1] + + (ss-maxIndex)*Vpd_step); + pPDADCValues[kk++] = (tmpVal > 127) ? + 127 : tmpVal; + ss++; + } + } /* extrapolated above */ + } /* for all pdGainUsed */ + + while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) { + pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1]; + ii++; + } + while (kk < 128) { + pPDADCValues[kk] = pPDADCValues[kk-1]; + kk++; + } + + return numPdGainsUsed; +#undef VpdTable_L +#undef VpdTable_R +#undef VpdTable_I +} + +static HAL_BOOL +ar2317SetPowerTable(struct ath_hal *ah, + int16_t *minPower, int16_t *maxPower, + const struct ieee80211_channel *chan, + uint16_t *rfXpdGain) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2317 *pRawDataset = AH_NULL; + uint16_t pdGainOverlap_t2; + int16_t minCalPower2317_t2; + uint16_t *pdadcValues = ahp->ah_pcdacTable; + uint16_t gainBoundaries[4]; + uint32_t reg32, regoffset; + int i, numPdGainsUsed; +#ifndef AH_USE_INIPDGAIN + uint32_t tpcrg1; +#endif + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", + __func__, chan->ic_freq, chan->ic_flags); + + if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IEEE80211_IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: illegal mode\n", __func__); + return AH_FALSE; + } + + pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP); + + numPdGainsUsed = ar2317getGainBoundariesAndPdadcsForPowers(ah, + chan->channel, pRawDataset, pdGainOverlap_t2, + &minCalPower2317_t2,gainBoundaries, rfXpdGain, pdadcValues); + HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); + +#ifdef AH_USE_INIPDGAIN + /* + * Use pd_gains curve from eeprom; Atheros always uses + * the default curve from the ini file but some vendors + * (e.g. Zcomax) want to override this curve and not + * honoring their settings results in tx power 5dBm low. + */ + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (pRawDataset->pDataPerChannel[0].numPdGains - 1)); +#else + tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); + tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) + | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); + switch (numPdGainsUsed) { + case 3: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3; + tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3); + /* fall thru... */ + case 2: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2; + tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2); + /* fall thru... */ + case 1: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1; + tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1); + break; + } +#ifdef AH_DEBUG + if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1)) + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default " + "pd_gains (default 0x%x, calculated 0x%x)\n", + __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); +#endif + OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); +#endif + + /* + * Note the pdadc table may not start at 0 dBm power, could be + * negative or greater than 0. Need to offset the power + * values by the amount of minPower for griffin + */ + if (minCalPower2317_t2 != 0) + ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2317_t2); + else + ahp->ah_txPowerIndexOffset = 0; + + /* Finally, write the power values into the baseband power table */ + regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */ + for (i = 0; i < 32; i++) { + reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0) | + ((pdadcValues[4*i + 1] & 0xFF) << 8) | + ((pdadcValues[4*i + 2] & 0xFF) << 16) | + ((pdadcValues[4*i + 3] & 0xFF) << 24) ; + OS_REG_WRITE(ah, regoffset, reg32); + regoffset += 4; + } + + OS_REG_WRITE(ah, AR_PHY_TPCRG5, + SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + + return AH_TRUE; +} + +static int16_t +ar2317GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2317 *data) +{ + uint32_t ii,jj; + uint16_t Pmin=0,numVpd; + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = data->pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + Pmin = data->pDataPerPDGain[jj].pwr_t4[0]; + return(Pmin); + } + } + return(Pmin); +} + +static int16_t +ar2317GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2317 *data) +{ + uint32_t ii; + uint16_t Pmax=0,numVpd; + uint16_t vpdmax; + + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + /* work forwards cuase lowest pdGain for highest power */ + numVpd = data->pDataPerPDGain[ii].numVpd; + if (numVpd > 0) { + Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1]; + vpdmax = data->pDataPerPDGain[ii].Vpd[numVpd-1]; + return(Pmax); + } + } + return(Pmax); +} + +static HAL_BOOL +ar2317GetChannelMaxMinPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *maxPow, int16_t *minPow) +{ + uint16_t freq = chan->ic_freq; /* NB: never mapped */ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2317 *pRawDataset = AH_NULL; + const RAW_DATA_PER_CHANNEL_2317 *data=AH_NULL; + uint16_t numChannels; + int totalD,totalF, totalMin,last, i; + + *maxPow = 0; + + if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IEEE80211_IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else + return(AH_FALSE); + + numChannels = pRawDataset->numChannels; + data = pRawDataset->pDataPerChannel; + + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if (numChannels < 1) + return(AH_FALSE); + + if ((freq < data[0].channelValue) || + (freq > data[numChannels-1].channelValue)) { + if (freq < data[0].channelValue) { + *maxPow = ar2317GetMaxPower(ah, &data[0]); + *minPow = ar2317GetMinPower(ah, &data[0]); + return(AH_TRUE); + } else { + *maxPow = ar2317GetMaxPower(ah, &data[numChannels - 1]); + *minPow = ar2317GetMinPower(ah, &data[numChannels - 1]); + return(AH_TRUE); + } + } + + /* Linearly interpolate the power value now */ + for (last=0,i=0; (i data[i].channelValue); + last = i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = ar2317GetMaxPower(ah, &data[i]) - ar2317GetMaxPower(ah, &data[last]); + *maxPow = (int8_t) ((totalF*(freq-data[last].channelValue) + + ar2317GetMaxPower(ah, &data[last])*totalD)/totalD); + totalMin = ar2317GetMinPower(ah, &data[i]) - ar2317GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(freq-data[last].channelValue) + + ar2317GetMinPower(ah, &data[last])*totalD)/totalD); + return(AH_TRUE); + } else { + if (freq == data[i].channelValue) { + *maxPow = ar2317GetMaxPower(ah, &data[i]); + *minPow = ar2317GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar2317RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar2317RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar2317State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar2317State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar2317RfDetach; + priv->base.writeRegs = ar2317WriteRegs; + priv->base.getRfBank = ar2317GetRfBank; + priv->base.setChannel = ar2317SetChannel; + priv->base.setRfRegs = ar2317SetRfRegs; + priv->base.setPowerTable = ar2317SetPowerTable; + priv->base.getChannelMaxMinPower = ar2317GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5212GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + return AH_TRUE; +} + +static HAL_BOOL +ar2317Probe(struct ath_hal *ah) +{ + return IS_2317(ah); +} +AH_RF(RF2317, ar2317Probe, ar2317RfAttach); diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar2413.c b/sys/external/isc/atheros_hal/dist/ar5212/ar2413.c new file mode 100644 index 0000000..e069444 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar2413.c @@ -0,0 +1,756 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +#define AH_5212_2413 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar2413State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE_2413]; + + uint32_t Bank1Data[N(ar5212Bank1_2413)]; + uint32_t Bank2Data[N(ar5212Bank2_2413)]; + uint32_t Bank3Data[N(ar5212Bank3_2413)]; + uint32_t Bank6Data[N(ar5212Bank6_2413)]; + uint32_t Bank7Data[N(ar5212Bank7_2413)]; + + /* + * Private state for reduced stack usage. + */ + /* filled out Vpd table for all pdGains (chanL) */ + uint16_t vpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (chanR) */ + uint16_t vpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (interpolated) */ + uint16_t vpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; +}; +#define AR2413(ah) ((struct ar2413State *) AH5212(ah)->ah_rfHal) + +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar2413WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_2413, modesIndex, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_2413, 1, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_2413, freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar2413SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + + OS_MARK(ah, AH_MARK_SETCHANNEL, freq); + + if (freq < 4800) { + uint32_t txctl; + + if (((freq - 2192) % 5) == 0) { + channelSel = ((freq - 672) * 2 - 3040)/10; + bModeSynth = 0; + } else if (((freq - 2224) % 5) == 0) { + channelSel = ((freq - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u MHz\n", + __func__, freq); + return AH_FALSE; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else if (((freq % 5) == 2) && (freq <= 5435)) { + freq = freq - 2; /* Align to even 5MHz raster */ + channelSel = ath_hal_reverseBits( + (uint32_t)(((freq - 4800)*10)/25 + 1), 8); + aModeRefSel = ath_hal_reverseBits(0, 2); + } else if ((freq % 20) == 0 && freq >= 5120) { + channelSel = ath_hal_reverseBits( + ((freq - 4800) / 20 << 2), 8); + aModeRefSel = ath_hal_reverseBits(3, 2); + } else if ((freq % 10) == 0) { + channelSel = ath_hal_reverseBits( + ((freq - 4800) / 10 << 1), 8); + aModeRefSel = ath_hal_reverseBits(2, 2); + } else if ((freq % 5) == 0) { + channelSel = ath_hal_reverseBits( + (freq - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", + __func__, freq); + return AH_FALSE; + } + + reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 12) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); + + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); + + AH_PRIVATE(ah)->ah_curchan = chan; + + return AH_TRUE; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar2413SetRfRegs(struct ath_hal *ah, + const struct ieee80211_channel *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ +#define RF_BANK_SETUP(_priv, _ix, _col) do { \ + int i; \ + for (i = 0; i < N(ar5212Bank##_ix##_2413); i++) \ + (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2413[i][_col];\ +} while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t ob2GHz = 0, db2GHz = 0; + struct ar2413State *priv = AR2413(ah); + int regWrites = 0; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan %u/0x%x modesIndex %u\n", + __func__, chan->ic_freq, chan->ic_flags, modesIndex); + + HALASSERT(priv); + + /* Setup rf parameters */ + if (IEEE80211_IS_CHAN_B(chan)) { + ob2GHz = ee->ee_obFor24; + db2GHz = ee->ee_dbFor24; + } else { + ob2GHz = ee->ee_obFor24g; + db2GHz = ee->ee_dbFor24g; + } + + /* Bank 1 Write */ + RF_BANK_SETUP(priv, 1, 1); + + /* Bank 2 Write */ + RF_BANK_SETUP(priv, 2, modesIndex); + + /* Bank 3 Write */ + RF_BANK_SETUP(priv, 3, modesIndex); + + /* Bank 6 Write */ + RF_BANK_SETUP(priv, 6, modesIndex); + + ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 168, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 165, 0); + + /* Bank 7 Setup */ + RF_BANK_SETUP(priv, 7, modesIndex); + + /* Write Analog registers */ + HAL_INI_WRITE_BANK(ah, ar5212Bank1_2413, priv->Bank1Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank2_2413, priv->Bank2Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank3_2413, priv->Bank3Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_2413, priv->Bank6Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank7_2413, priv->Bank7Data, regWrites); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar2413GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar2413State *priv = AR2413(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Return indices surrounding the value in sorted integer lists. + * + * NB: the input list is assumed to be sorted in ascending order + */ +static void +GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi) +{ + int16_t target = v; + const uint16_t *ep = lp+listSize; + const uint16_t *tp; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < lp[0]) { + *vlo = *vhi = 0; + return; + } + if (target >= ep[-1]) { + *vlo = *vhi = listSize - 1; + return; + } + + /* look for value being near or between 2 values in list */ + for (tp = lp; tp < ep; tp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (*tp == target) { + *vlo = *vhi = tp - (const uint16_t *) lp; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < tp[1]) { + *vlo = tp - (const uint16_t *) lp; + *vhi = *vlo + 1; + return; + } + } +} + +/* + * Fill the Vpdlist for indices Pmax-Pmin + */ +static HAL_BOOL +ar2413FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t Pmax, + const int16_t *pwrList, const uint16_t *VpdList, + uint16_t numIntercepts, uint16_t retVpdList[][64]) +{ + uint16_t ii, jj, kk; + int16_t currPwr = (int16_t)(2*Pmin); + /* since Pmin is pwr*2 and pwrList is 4*pwr */ + uint32_t idxL, idxR; + + ii = 0; + jj = 0; + + if (numIntercepts < 2) + return AH_FALSE; + + while (ii <= (uint16_t)(Pmax - Pmin)) { + GetLowerUpperIndex(currPwr, (const uint16_t *) pwrList, + numIntercepts, &(idxL), &(idxR)); + if (idxR < 1) + idxR = 1; /* extrapolate below */ + if (idxL == (uint32_t)(numIntercepts - 1)) + idxL = numIntercepts - 2; /* extrapolate above */ + if (pwrList[idxL] == pwrList[idxR]) + kk = VpdList[idxL]; + else + kk = (uint16_t) + (((currPwr - pwrList[idxL])*VpdList[idxR]+ + (pwrList[idxR] - currPwr)*VpdList[idxL])/ + (pwrList[idxR] - pwrList[idxL])); + retVpdList[pdGainIdx][ii] = kk; + ii++; + currPwr += 2; /* half dB steps */ + } + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static int16_t +interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight != srcLeft) { + rv = ((target - srcLeft)*targetRight + + (srcRight - target)*targetLeft) / (srcRight - srcLeft); + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Uses the data points read from EEPROM to reconstruct the pdadc power table + * Called by ar2413SetPowerTable() + */ +static int +ar2413getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel, + const RAW_DATA_STRUCT_2413 *pRawDataset, + uint16_t pdGainOverlap_t2, + int16_t *pMinCalPower, uint16_t pPdGainBoundaries[], + uint16_t pPdGainValues[], uint16_t pPDADCValues[]) +{ + struct ar2413State *priv = AR2413(ah); +#define VpdTable_L priv->vpdTable_L +#define VpdTable_R priv->vpdTable_R +#define VpdTable_I priv->vpdTable_I + uint32_t ii, jj, kk; + int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */ + uint32_t idxL, idxR; + uint32_t numPdGainsUsed = 0; + /* + * If desired to support -ve power levels in future, just + * change pwr_I_0 to signed 5-bits. + */ + int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on. */ + int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on */ + uint16_t numVpd = 0; + uint16_t Vpd_step; + int16_t tmpVal ; + uint32_t sizeCurrVpdTable, maxIndex, tgtIndex; + + /* Get upper lower index */ + GetLowerUpperIndex(channel, pRawDataset->pChannels, + pRawDataset->numChannels, &(idxL), &(idxR)); + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain; + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]; + if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) { + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]; + } + Pmin_t2[numPdGainsUsed] = (int16_t) + (Pmin_t2[numPdGainsUsed] / 2); + Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]) + Pmax_t2[numPdGainsUsed] = + pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2); + ar2413FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L + ); + ar2413FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R + ); + for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) { + VpdTable_I[numPdGainsUsed][kk] = + interpolate_signed( + channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR], + (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]); + } + /* fill VpdTable_I for this pdGain */ + numPdGainsUsed++; + } + /* if this pdGain is used */ + } + + *pMinCalPower = Pmin_t2[0]; + kk = 0; /* index for the final table */ + for (ii = 0; ii < numPdGainsUsed; ii++) { + if (ii == (numPdGainsUsed - 1)) + pPdGainBoundaries[ii] = Pmax_t2[ii] + + PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB; + else + pPdGainBoundaries[ii] = (uint16_t) + ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 ); + if (pPdGainBoundaries[ii] > 63) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: clamp pPdGainBoundaries[%d] %d\n", + __func__, ii, pPdGainBoundaries[ii]);/*XXX*/ + pPdGainBoundaries[ii] = 63; + } + + /* Find starting index for this pdGain */ + if (ii == 0) + ss = 0; /* for the first pdGain, start from index 0 */ + else + ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) - + pdGainOverlap_t2; + Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + *-ve ss indicates need to extrapolate data below for this pdGain + */ + while (ss < 0) { + tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step); + pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii]; + tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii]; + maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; + + while (ss < (int16_t)maxIndex) + pPDADCValues[kk++] = VpdTable_I[ii][ss++]; + + Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] - + VpdTable_I[ii][sizeCurrVpdTable-2]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + * for last gain, pdGainBoundary == Pmax_t2, so will + * have to extrapolate + */ + if (tgtIndex > maxIndex) { /* need to extrapolate above */ + while(ss < (int16_t)tgtIndex) { + tmpVal = (uint16_t) + (VpdTable_I[ii][sizeCurrVpdTable-1] + + (ss-maxIndex)*Vpd_step); + pPDADCValues[kk++] = (tmpVal > 127) ? + 127 : tmpVal; + ss++; + } + } /* extrapolated above */ + } /* for all pdGainUsed */ + + while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) { + pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1]; + ii++; + } + while (kk < 128) { + pPDADCValues[kk] = pPDADCValues[kk-1]; + kk++; + } + + return numPdGainsUsed; +#undef VpdTable_L +#undef VpdTable_R +#undef VpdTable_I +} + +static HAL_BOOL +ar2413SetPowerTable(struct ath_hal *ah, + int16_t *minPower, int16_t *maxPower, + const struct ieee80211_channel *chan, + uint16_t *rfXpdGain) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; + uint16_t pdGainOverlap_t2; + int16_t minCalPower2413_t2; + uint16_t *pdadcValues = ahp->ah_pcdacTable; + uint16_t gainBoundaries[4]; + uint32_t reg32, regoffset; + int i, numPdGainsUsed; +#ifndef AH_USE_INIPDGAIN + uint32_t tpcrg1; +#endif + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", + __func__, freq, chan->ic_flags); + + if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IEEE80211_IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: illegal mode\n", __func__); + return AH_FALSE; + } + + pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP); + + numPdGainsUsed = ar2413getGainBoundariesAndPdadcsForPowers(ah, + freq, pRawDataset, pdGainOverlap_t2, + &minCalPower2413_t2,gainBoundaries, rfXpdGain, pdadcValues); + HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); + +#ifdef AH_USE_INIPDGAIN + /* + * Use pd_gains curve from eeprom; Atheros always uses + * the default curve from the ini file but some vendors + * (e.g. Zcomax) want to override this curve and not + * honoring their settings results in tx power 5dBm low. + */ + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (pRawDataset->pDataPerChannel[0].numPdGains - 1)); +#else + tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); + tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) + | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); + switch (numPdGainsUsed) { + case 3: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3; + tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3); + /* fall thru... */ + case 2: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2; + tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2); + /* fall thru... */ + case 1: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1; + tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1); + break; + } +#ifdef AH_DEBUG + if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1)) + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default " + "pd_gains (default 0x%x, calculated 0x%x)\n", + __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); +#endif + OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); +#endif + + /* + * Note the pdadc table may not start at 0 dBm power, could be + * negative or greater than 0. Need to offset the power + * values by the amount of minPower for griffin + */ + if (minCalPower2413_t2 != 0) + ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2413_t2); + else + ahp->ah_txPowerIndexOffset = 0; + + /* Finally, write the power values into the baseband power table */ + regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */ + for (i = 0; i < 32; i++) { + reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0) | + ((pdadcValues[4*i + 1] & 0xFF) << 8) | + ((pdadcValues[4*i + 2] & 0xFF) << 16) | + ((pdadcValues[4*i + 3] & 0xFF) << 24) ; + OS_REG_WRITE(ah, regoffset, reg32); + regoffset += 4; + } + + OS_REG_WRITE(ah, AR_PHY_TPCRG5, + SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + + return AH_TRUE; +} + +static int16_t +ar2413GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) +{ + uint32_t ii,jj; + uint16_t Pmin=0,numVpd; + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = data->pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + Pmin = data->pDataPerPDGain[jj].pwr_t4[0]; + return(Pmin); + } + } + return(Pmin); +} + +static int16_t +ar2413GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) +{ + uint32_t ii; + uint16_t Pmax=0,numVpd; + + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + /* work forwards cuase lowest pdGain for highest power */ + numVpd = data->pDataPerPDGain[ii].numVpd; + if (numVpd > 0) { + Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1]; + return(Pmax); + } + } + return(Pmax); +} + +static HAL_BOOL +ar2413GetChannelMaxMinPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *maxPow, int16_t *minPow) +{ + uint16_t freq = chan->ic_freq; /* NB: never mapped */ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; + const RAW_DATA_PER_CHANNEL_2413 *data = AH_NULL; + uint16_t numChannels; + int totalD,totalF, totalMin,last, i; + + *maxPow = 0; + + if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IEEE80211_IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else + return(AH_FALSE); + + numChannels = pRawDataset->numChannels; + data = pRawDataset->pDataPerChannel; + + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if (numChannels < 1) + return(AH_FALSE); + + if ((freq < data[0].channelValue) || + (freq > data[numChannels-1].channelValue)) { + if (freq < data[0].channelValue) { + *maxPow = ar2413GetMaxPower(ah, &data[0]); + *minPow = ar2413GetMinPower(ah, &data[0]); + return(AH_TRUE); + } else { + *maxPow = ar2413GetMaxPower(ah, &data[numChannels - 1]); + *minPow = ar2413GetMinPower(ah, &data[numChannels - 1]); + return(AH_TRUE); + } + } + + /* Linearly interpolate the power value now */ + for (last=0,i=0; (i data[i].channelValue); + last = i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = ar2413GetMaxPower(ah, &data[i]) - ar2413GetMaxPower(ah, &data[last]); + *maxPow = (int8_t) ((totalF*(freq-data[last].channelValue) + + ar2413GetMaxPower(ah, &data[last])*totalD)/totalD); + totalMin = ar2413GetMinPower(ah, &data[i]) - ar2413GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(freq-data[last].channelValue) + + ar2413GetMinPower(ah, &data[last])*totalD)/totalD); + return(AH_TRUE); + } else { + if (freq == data[i].channelValue) { + *maxPow = ar2413GetMaxPower(ah, &data[i]); + *minPow = ar2413GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar2413RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar2413RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar2413State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar2413State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar2413RfDetach; + priv->base.writeRegs = ar2413WriteRegs; + priv->base.getRfBank = ar2413GetRfBank; + priv->base.setChannel = ar2413SetChannel; + priv->base.setRfRegs = ar2413SetRfRegs; + priv->base.setPowerTable = ar2413SetPowerTable; + priv->base.getChannelMaxMinPower = ar2413GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5212GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + return AH_TRUE; +} + +static HAL_BOOL +ar2413Probe(struct ath_hal *ah) +{ + return IS_2413(ah); +} +AH_RF(RF2413, ar2413Probe, ar2413RfAttach); diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar2425.c b/sys/external/isc/atheros_hal/dist/ar5212/ar2425.c new file mode 100644 index 0000000..e487489 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar2425.c @@ -0,0 +1,719 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +#define AH_5212_2425 +#define AH_5212_2417 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar2425State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE_2413]; + + uint32_t Bank1Data[N(ar5212Bank1_2425)]; + uint32_t Bank2Data[N(ar5212Bank2_2425)]; + uint32_t Bank3Data[N(ar5212Bank3_2425)]; + uint32_t Bank6Data[N(ar5212Bank6_2425)]; /* 2417 is same size */ + uint32_t Bank7Data[N(ar5212Bank7_2425)]; +}; +#define AR2425(ah) ((struct ar2425State *) AH5212(ah)->ah_rfHal) + +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar2425WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_2425, modesIndex, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_2425, 1, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_2425, freqIndex, writes); +#if 0 + /* + * for SWAN similar to Condor + * Bit 0 enables link to go to L1 when MAC goes to sleep. + * Bit 3 enables the loop back the link down to reset. + */ + if (AH_PRIVATE(ah)->ah_ispcie && && ath_hal_pcieL1SKPEnable) { + OS_REG_WRITE(ah, AR_PCIE_PMC, + AR_PCIE_PMC_ENA_L1 | AR_PCIE_PMC_ENA_RESET); + } + /* + * for Standby issue in Swan/Condor. + * Bit 9 (MAC_WOW_PWR_STATE_MASK_D2)to be set to avoid skips + * before last Training Sequence 2 (TS2) + * Bit 8 (MAC_WOW_PWR_STATE_MASK_D1)to be unset to assert + * Power Reset along with PCI Reset + */ + OS_REG_SET_BIT(ah, AR_PCIE_PMC, MAC_WOW_PWR_STATE_MASK_D2); +#endif +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar2425SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + + OS_MARK(ah, AH_MARK_SETCHANNEL, freq); + + if (freq < 4800) { + uint32_t txctl; + + channelSel = freq - 2272; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + // Enable channel spreading for channel 14 + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + + } else if (((freq % 5) == 2) && (freq <= 5435)) { + freq = freq - 2; /* Align to even 5MHz raster */ + channelSel = ath_hal_reverseBits( + (uint32_t)(((freq - 4800)*10)/25 + 1), 8); + aModeRefSel = ath_hal_reverseBits(0, 2); + } else if ((freq % 20) == 0 && freq >= 5120) { + channelSel = ath_hal_reverseBits( + ((freq - 4800) / 20 << 2), 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else if ((freq % 10) == 0) { + channelSel = ath_hal_reverseBits( + ((freq - 4800) / 10 << 1), 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else if ((freq % 5) == 0) { + channelSel = ath_hal_reverseBits( + (freq - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", + __func__, freq); + return AH_FALSE; + } + + reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 12) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); + + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar2425SetRfRegs(struct ath_hal *ah, + const struct ieee80211_channel *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ +#define RF_BANK_SETUP(_priv, _ix, _col) do { \ + int i; \ + for (i = 0; i < N(ar5212Bank##_ix##_2425); i++) \ + (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2425[i][_col];\ +} while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ar2425State *priv = AR2425(ah); + uint16_t ob2GHz = 0, db2GHz = 0; + int regWrites = 0; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan %u/0x%x modesIndex %u\n", + __func__, chan->ic_freq, chan->ic_flags, modesIndex); + + HALASSERT(priv); + + /* Setup rf parameters */ + if (IEEE80211_IS_CHAN_B(chan)) { + ob2GHz = ee->ee_obFor24; + db2GHz = ee->ee_dbFor24; + } else { + ob2GHz = ee->ee_obFor24g; + db2GHz = ee->ee_dbFor24g; + } + + /* Bank 1 Write */ + RF_BANK_SETUP(priv, 1, 1); + + /* Bank 2 Write */ + RF_BANK_SETUP(priv, 2, modesIndex); + + /* Bank 3 Write */ + RF_BANK_SETUP(priv, 3, modesIndex); + + /* Bank 6 Write */ + RF_BANK_SETUP(priv, 6, modesIndex); + + ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 193, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 190, 0); + + /* Bank 7 Setup */ + RF_BANK_SETUP(priv, 7, modesIndex); + + /* Write Analog registers */ + HAL_INI_WRITE_BANK(ah, ar5212Bank1_2425, priv->Bank1Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank2_2425, priv->Bank2Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank3_2425, priv->Bank3Data, regWrites); + if (IS_2417(ah)) { + HALASSERT(N(ar5212Bank6_2425) == N(ar5212Bank6_2417)); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_2417, priv->Bank6Data, + regWrites); + } else + HAL_INI_WRITE_BANK(ah, ar5212Bank6_2425, priv->Bank6Data, + regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank7_2425, priv->Bank7Data, regWrites); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "<==%s\n", __func__); + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar2425GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar2425State *priv = AR2425(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Return indices surrounding the value in sorted integer lists. + * + * NB: the input list is assumed to be sorted in ascending order + */ +static void +GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi) +{ + int16_t target = v; + const uint16_t *ep = lp+listSize; + const uint16_t *tp; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < lp[0]) { + *vlo = *vhi = 0; + return; + } + if (target >= ep[-1]) { + *vlo = *vhi = listSize - 1; + return; + } + + /* look for value being near or between 2 values in list */ + for (tp = lp; tp < ep; tp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (*tp == target) { + *vlo = *vhi = tp - (const uint16_t *) lp; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < tp[1]) { + *vlo = tp - (const uint16_t *) lp; + *vhi = *vlo + 1; + return; + } + } +} + +/* + * Fill the Vpdlist for indices Pmax-Pmin + */ +static HAL_BOOL +ar2425FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t Pmax, + const int16_t *pwrList, const uint16_t *VpdList, + uint16_t numIntercepts, + uint16_t retVpdList[][64]) +{ + uint16_t ii, jj, kk; + int16_t currPwr = (int16_t)(2*Pmin); + /* since Pmin is pwr*2 and pwrList is 4*pwr */ + uint32_t idxL, idxR; + + ii = 0; + jj = 0; + + if (numIntercepts < 2) + return AH_FALSE; + + while (ii <= (uint16_t)(Pmax - Pmin)) { + GetLowerUpperIndex(currPwr, (const uint16_t *) pwrList, + numIntercepts, &(idxL), &(idxR)); + if (idxR < 1) + idxR = 1; /* extrapolate below */ + if (idxL == (uint32_t)(numIntercepts - 1)) + idxL = numIntercepts - 2; /* extrapolate above */ + if (pwrList[idxL] == pwrList[idxR]) + kk = VpdList[idxL]; + else + kk = (uint16_t) + (((currPwr - pwrList[idxL])*VpdList[idxR]+ + (pwrList[idxR] - currPwr)*VpdList[idxL])/ + (pwrList[idxR] - pwrList[idxL])); + retVpdList[pdGainIdx][ii] = kk; + ii++; + currPwr += 2; /* half dB steps */ + } + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static int16_t +interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight != srcLeft) { + rv = ((target - srcLeft)*targetRight + + (srcRight - target)*targetLeft) / (srcRight - srcLeft); + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Uses the data points read from EEPROM to reconstruct the pdadc power table + * Called by ar2425SetPowerTable() + */ +static void +ar2425getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel, + const RAW_DATA_STRUCT_2413 *pRawDataset, + uint16_t pdGainOverlap_t2, + int16_t *pMinCalPower, uint16_t pPdGainBoundaries[], + uint16_t pPdGainValues[], uint16_t pPDADCValues[]) +{ + /* Note the items statically allocated below are to reduce stack usage */ + uint32_t ii, jj, kk; + int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */ + uint32_t idxL, idxR; + uint32_t numPdGainsUsed = 0; + static uint16_t VpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (chanL) */ + static uint16_t VpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (chanR) */ + static uint16_t VpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (interpolated) */ + /* + * If desired to support -ve power levels in future, just + * change pwr_I_0 to signed 5-bits. + */ + static int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on. */ + static int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on */ + uint16_t numVpd = 0; + uint16_t Vpd_step; + int16_t tmpVal ; + uint32_t sizeCurrVpdTable, maxIndex, tgtIndex; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "==>%s:\n", __func__); + + /* Get upper lower index */ + GetLowerUpperIndex(channel, pRawDataset->pChannels, + pRawDataset->numChannels, &(idxL), &(idxR)); + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain; + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]; + if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) { + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]; + } + Pmin_t2[numPdGainsUsed] = (int16_t) + (Pmin_t2[numPdGainsUsed] / 2); + Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]) + Pmax_t2[numPdGainsUsed] = + pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2); + ar2425FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L + ); + ar2425FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R + ); + for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) { + VpdTable_I[numPdGainsUsed][kk] = + interpolate_signed( + channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR], + (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]); + } + /* fill VpdTable_I for this pdGain */ + numPdGainsUsed++; + } + /* if this pdGain is used */ + } + + *pMinCalPower = Pmin_t2[0]; + kk = 0; /* index for the final table */ + for (ii = 0; ii < numPdGainsUsed; ii++) { + if (ii == (numPdGainsUsed - 1)) + pPdGainBoundaries[ii] = Pmax_t2[ii] + + PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB; + else + pPdGainBoundaries[ii] = (uint16_t) + ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 ); + + /* Find starting index for this pdGain */ + if (ii == 0) + ss = 0; /* for the first pdGain, start from index 0 */ + else + ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) - + pdGainOverlap_t2; + Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + *-ve ss indicates need to extrapolate data below for this pdGain + */ + while (ss < 0) { + tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step); + pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii]; + tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii]; + maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; + + while (ss < (int16_t)maxIndex) + pPDADCValues[kk++] = VpdTable_I[ii][ss++]; + + Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] - + VpdTable_I[ii][sizeCurrVpdTable-2]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + * for last gain, pdGainBoundary == Pmax_t2, so will + * have to extrapolate + */ + if (tgtIndex > maxIndex) { /* need to extrapolate above */ + while(ss < (int16_t)tgtIndex) { + tmpVal = (uint16_t) + (VpdTable_I[ii][sizeCurrVpdTable-1] + + (ss-maxIndex)*Vpd_step); + pPDADCValues[kk++] = (tmpVal > 127) ? + 127 : tmpVal; + ss++; + } + } /* extrapolated above */ + } /* for all pdGainUsed */ + + while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) { + pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1]; + ii++; + } + while (kk < 128) { + pPDADCValues[kk] = pPDADCValues[kk-1]; + kk++; + } + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "<==%s\n", __func__); +} + + +/* Same as 2413 set power table */ +static HAL_BOOL +ar2425SetPowerTable(struct ath_hal *ah, + int16_t *minPower, int16_t *maxPower, + const struct ieee80211_channel *chan, + uint16_t *rfXpdGain) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; + uint16_t pdGainOverlap_t2; + int16_t minCalPower2413_t2; + uint16_t *pdadcValues = ahp->ah_pcdacTable; + uint16_t gainBoundaries[4]; + uint32_t i, reg32, regoffset; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s:chan 0x%x flag 0x%x\n", + __func__, freq, chan->ic_flags); + + if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IEEE80211_IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s:illegal mode\n", __func__); + return AH_FALSE; + } + + pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP); + + ar2425getGainBoundariesAndPdadcsForPowers(ah, freq, + pRawDataset, pdGainOverlap_t2,&minCalPower2413_t2,gainBoundaries, + rfXpdGain, pdadcValues); + + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (pRawDataset->pDataPerChannel[0].numPdGains - 1)); + + /* + * Note the pdadc table may not start at 0 dBm power, could be + * negative or greater than 0. Need to offset the power + * values by the amount of minPower for griffin + */ + if (minCalPower2413_t2 != 0) + ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2413_t2); + else + ahp->ah_txPowerIndexOffset = 0; + + /* Finally, write the power values into the baseband power table */ + regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */ + for (i = 0; i < 32; i++) { + reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0) | + ((pdadcValues[4*i + 1] & 0xFF) << 8) | + ((pdadcValues[4*i + 2] & 0xFF) << 16) | + ((pdadcValues[4*i + 3] & 0xFF) << 24) ; + OS_REG_WRITE(ah, regoffset, reg32); + regoffset += 4; + } + + OS_REG_WRITE(ah, AR_PHY_TPCRG5, + SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + + return AH_TRUE; +} + +static int16_t +ar2425GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) +{ + uint32_t ii,jj; + uint16_t Pmin=0,numVpd; + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = data->pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + Pmin = data->pDataPerPDGain[jj].pwr_t4[0]; + return(Pmin); + } + } + return(Pmin); +} + +static int16_t +ar2425GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) +{ + uint32_t ii; + uint16_t Pmax=0,numVpd; + + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + /* work forwards cuase lowest pdGain for highest power */ + numVpd = data->pDataPerPDGain[ii].numVpd; + if (numVpd > 0) { + Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1]; + return(Pmax); + } + } + return(Pmax); +} + +static +HAL_BOOL +ar2425GetChannelMaxMinPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *maxPow, int16_t *minPow) +{ + uint16_t freq = chan->ic_freq; /* NB: never mapped */ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; + const RAW_DATA_PER_CHANNEL_2413 *data = AH_NULL; + uint16_t numChannels; + int totalD,totalF, totalMin,last, i; + + *maxPow = 0; + + if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IEEE80211_IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else + return(AH_FALSE); + + numChannels = pRawDataset->numChannels; + data = pRawDataset->pDataPerChannel; + + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if (numChannels < 1) + return(AH_FALSE); + + if ((freq < data[0].channelValue) || + (freq > data[numChannels-1].channelValue)) { + if (freq < data[0].channelValue) { + *maxPow = ar2425GetMaxPower(ah, &data[0]); + *minPow = ar2425GetMinPower(ah, &data[0]); + return(AH_TRUE); + } else { + *maxPow = ar2425GetMaxPower(ah, &data[numChannels - 1]); + *minPow = ar2425GetMinPower(ah, &data[numChannels - 1]); + return(AH_TRUE); + } + } + + /* Linearly interpolate the power value now */ + for (last=0,i=0; (i data[i].channelValue); + last = i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = ar2425GetMaxPower(ah, &data[i]) - ar2425GetMaxPower(ah, &data[last]); + *maxPow = (int8_t) ((totalF*(freq-data[last].channelValue) + + ar2425GetMaxPower(ah, &data[last])*totalD)/totalD); + totalMin = ar2425GetMinPower(ah, &data[i]) - ar2425GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(freq-data[last].channelValue) + + ar2425GetMinPower(ah, &data[last])*totalD)/totalD); + return(AH_TRUE); + } else { + if (freq == data[i].channelValue) { + *maxPow = ar2425GetMaxPower(ah, &data[i]); + *minPow = ar2425GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar2425RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar2425RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar2425State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar2425State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar2425RfDetach; + priv->base.writeRegs = ar2425WriteRegs; + priv->base.getRfBank = ar2425GetRfBank; + priv->base.setChannel = ar2425SetChannel; + priv->base.setRfRegs = ar2425SetRfRegs; + priv->base.setPowerTable = ar2425SetPowerTable; + priv->base.getChannelMaxMinPower = ar2425GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5212GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + return AH_TRUE; +} + +static HAL_BOOL +ar2425Probe(struct ath_hal *ah) +{ + return IS_2425(ah) || IS_2417(ah); +} +AH_RF(RF2425, ar2425Probe, ar2425RfAttach); diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5111.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5111.c new file mode 100644 index 0000000..f9fd3f3 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5111.c @@ -0,0 +1,719 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v3.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#define AH_5212_5111 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar5111State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE]; + + uint32_t Bank0Data[N(ar5212Bank0_5111)]; + uint32_t Bank1Data[N(ar5212Bank1_5111)]; + uint32_t Bank2Data[N(ar5212Bank2_5111)]; + uint32_t Bank3Data[N(ar5212Bank3_5111)]; + uint32_t Bank6Data[N(ar5212Bank6_5111)]; + uint32_t Bank7Data[N(ar5212Bank7_5111)]; +}; +#define AR5111(ah) ((struct ar5111State *) AH5212(ah)->ah_rfHal) + +static uint16_t ar5212GetScaledPower(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct); +static HAL_BOOL ar5212FindValueInList(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue); +static void ar5212GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel, + const PCDACS_EEPROM *pSrcStruct, + uint16_t *pLowerPcdac, uint16_t *pUpperPcdac); + +extern void ar5212GetLowerUpperValues(uint16_t value, + const uint16_t *pList, uint16_t listSize, + uint16_t *pLowerValue, uint16_t *pUpperValue); +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar5111WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_5111, modesIndex, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_5111, 1, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_5111, freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar5111SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +#define CI_2GHZ_INDEX_CORRECTION 19 + uint16_t freq = ath_hal_gethwchannel(ah, chan); + uint32_t refClk, reg32, data2111; + int16_t chan5111, chanIEEE; + + /* + * Structure to hold 11b tuning information for 5111/2111 + * 16 MHz mode, divider ratio = 198 = NP+S. N=16, S=4 or 6, P=12 + */ + typedef struct { + uint32_t refClkSel; /* reference clock, 1 for 16 MHz */ + uint32_t channelSelect; /* P[7:4]S[3:0] bits */ + uint16_t channel5111; /* 11a channel for 5111 */ + } CHAN_INFO_2GHZ; + + static const CHAN_INFO_2GHZ chan2GHzData[] = { + { 1, 0x46, 96 }, /* 2312 -19 */ + { 1, 0x46, 97 }, /* 2317 -18 */ + { 1, 0x46, 98 }, /* 2322 -17 */ + { 1, 0x46, 99 }, /* 2327 -16 */ + { 1, 0x46, 100 }, /* 2332 -15 */ + { 1, 0x46, 101 }, /* 2337 -14 */ + { 1, 0x46, 102 }, /* 2342 -13 */ + { 1, 0x46, 103 }, /* 2347 -12 */ + { 1, 0x46, 104 }, /* 2352 -11 */ + { 1, 0x46, 105 }, /* 2357 -10 */ + { 1, 0x46, 106 }, /* 2362 -9 */ + { 1, 0x46, 107 }, /* 2367 -8 */ + { 1, 0x46, 108 }, /* 2372 -7 */ + /* index -6 to 0 are pad to make this a nolookup table */ + { 1, 0x46, 116 }, /* -6 */ + { 1, 0x46, 116 }, /* -5 */ + { 1, 0x46, 116 }, /* -4 */ + { 1, 0x46, 116 }, /* -3 */ + { 1, 0x46, 116 }, /* -2 */ + { 1, 0x46, 116 }, /* -1 */ + { 1, 0x46, 116 }, /* 0 */ + { 1, 0x46, 116 }, /* 2412 1 */ + { 1, 0x46, 117 }, /* 2417 2 */ + { 1, 0x46, 118 }, /* 2422 3 */ + { 1, 0x46, 119 }, /* 2427 4 */ + { 1, 0x46, 120 }, /* 2432 5 */ + { 1, 0x46, 121 }, /* 2437 6 */ + { 1, 0x46, 122 }, /* 2442 7 */ + { 1, 0x46, 123 }, /* 2447 8 */ + { 1, 0x46, 124 }, /* 2452 9 */ + { 1, 0x46, 125 }, /* 2457 10 */ + { 1, 0x46, 126 }, /* 2462 11 */ + { 1, 0x46, 127 }, /* 2467 12 */ + { 1, 0x46, 128 }, /* 2472 13 */ + { 1, 0x44, 124 }, /* 2484 14 */ + { 1, 0x46, 136 }, /* 2512 15 */ + { 1, 0x46, 140 }, /* 2532 16 */ + { 1, 0x46, 144 }, /* 2552 17 */ + { 1, 0x46, 148 }, /* 2572 18 */ + { 1, 0x46, 152 }, /* 2592 19 */ + { 1, 0x46, 156 }, /* 2612 20 */ + { 1, 0x46, 160 }, /* 2632 21 */ + { 1, 0x46, 164 }, /* 2652 22 */ + { 1, 0x46, 168 }, /* 2672 23 */ + { 1, 0x46, 172 }, /* 2692 24 */ + { 1, 0x46, 176 }, /* 2712 25 */ + { 1, 0x46, 180 } /* 2732 26 */ + }; + + OS_MARK(ah, AH_MARK_SETCHANNEL, freq); + + chanIEEE = chan->ic_ieee; + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + const CHAN_INFO_2GHZ* ci = + &chan2GHzData[chanIEEE + CI_2GHZ_INDEX_CORRECTION]; + uint32_t txctl; + + data2111 = ((ath_hal_reverseBits(ci->channelSelect, 8) & 0xff) + << 5) + | (ci->refClkSel << 4); + chan5111 = ci->channel5111; + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else { + chan5111 = chanIEEE; /* no conversion needed */ + data2111 = 0; + } + + /* Rest of the code is common for 5 GHz and 2.4 GHz. */ + if (chan5111 >= 145 || (chan5111 & 0x1)) { + reg32 = ath_hal_reverseBits(chan5111 - 24, 8) & 0xff; + refClk = 1; + } else { + reg32 = ath_hal_reverseBits(((chan5111 - 24)/2), 8) & 0xff; + refClk = 0; + } + + reg32 = (reg32 << 2) | (refClk << 1) | (1 << 10) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), ((data2111 & 0xff) << 8) | (reg32 & 0xff)); + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x34), (data2111 & 0xff00) | (reg32 & 0xff)); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +#undef CI_2GHZ_INDEX_CORRECTION +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar5111GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar5111State *priv = AR5111(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 0: return priv->Bank0Data; + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar5111SetRfRegs(struct ath_hal *ah, const struct ieee80211_channel *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t rfXpdGainFixed, rfPloSel, rfPwdXpd, gainI; + uint16_t tempOB, tempDB; + uint32_t ob2GHz, db2GHz, rfReg[N(ar5212Bank6_5111)]; + int i, regWrites = 0; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan %u/0x%x modesIndex %u\n", + __func__, chan->ic_freq, chan->ic_flags, modesIndex); + + /* Setup rf parameters */ + switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) { + case IEEE80211_CHAN_A: + if (4000 < freq && freq < 5260) { + tempOB = ee->ee_ob1; + tempDB = ee->ee_db1; + } else if (5260 <= freq && freq < 5500) { + tempOB = ee->ee_ob2; + tempDB = ee->ee_db2; + } else if (5500 <= freq && freq < 5725) { + tempOB = ee->ee_ob3; + tempDB = ee->ee_db3; + } else if (freq >= 5725) { + tempOB = ee->ee_ob4; + tempDB = ee->ee_db4; + } else { + /* XXX when does this happen??? */ + tempOB = tempDB = 0; + } + ob2GHz = db2GHz = 0; + + rfXpdGainFixed = ee->ee_xgain[headerInfo11A]; + rfPloSel = ee->ee_xpd[headerInfo11A]; + rfPwdXpd = !ee->ee_xpd[headerInfo11A]; + gainI = ee->ee_gainI[headerInfo11A]; + break; + case IEEE80211_CHAN_B: + tempOB = ee->ee_obFor24; + tempDB = ee->ee_dbFor24; + ob2GHz = ee->ee_ob2GHz[0]; + db2GHz = ee->ee_db2GHz[0]; + + rfXpdGainFixed = ee->ee_xgain[headerInfo11B]; + rfPloSel = ee->ee_xpd[headerInfo11B]; + rfPwdXpd = !ee->ee_xpd[headerInfo11B]; + gainI = ee->ee_gainI[headerInfo11B]; + break; + case IEEE80211_CHAN_G: + case IEEE80211_CHAN_PUREG: /* NB: really 108G */ + tempOB = ee->ee_obFor24g; + tempDB = ee->ee_dbFor24g; + ob2GHz = ee->ee_ob2GHz[1]; + db2GHz = ee->ee_db2GHz[1]; + + rfXpdGainFixed = ee->ee_xgain[headerInfo11G]; + rfPloSel = ee->ee_xpd[headerInfo11G]; + rfPwdXpd = !ee->ee_xpd[headerInfo11G]; + gainI = ee->ee_gainI[headerInfo11G]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->ic_flags); + return AH_FALSE; + } + + HALASSERT(1 <= tempOB && tempOB <= 5); + HALASSERT(1 <= tempDB && tempDB <= 5); + + /* Bank 0 Write */ + for (i = 0; i < N(ar5212Bank0_5111); i++) + rfReg[i] = ar5212Bank0_5111[i][modesIndex]; + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + ar5212ModifyRfBuffer(rfReg, ob2GHz, 3, 119, 0); + ar5212ModifyRfBuffer(rfReg, db2GHz, 3, 122, 0); + } + HAL_INI_WRITE_BANK(ah, ar5212Bank0_5111, rfReg, regWrites); + + /* Bank 1 Write */ + HAL_INI_WRITE_ARRAY(ah, ar5212Bank1_5111, 1, regWrites); + + /* Bank 2 Write */ + HAL_INI_WRITE_ARRAY(ah, ar5212Bank2_5111, modesIndex, regWrites); + + /* Bank 3 Write */ + HAL_INI_WRITE_ARRAY(ah, ar5212Bank3_5111, modesIndex, regWrites); + + /* Bank 6 Write */ + for (i = 0; i < N(ar5212Bank6_5111); i++) + rfReg[i] = ar5212Bank6_5111[i][modesIndex]; + if (IEEE80211_IS_CHAN_A(chan)) { /* NB: CHANNEL_A | CHANNEL_T */ + ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd84, 1, 51, 3); + ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd90, 1, 45, 3); + } + ar5212ModifyRfBuffer(rfReg, rfPwdXpd, 1, 95, 0); + ar5212ModifyRfBuffer(rfReg, rfXpdGainFixed, 4, 96, 0); + /* Set 5212 OB & DB */ + ar5212ModifyRfBuffer(rfReg, tempOB, 3, 104, 0); + ar5212ModifyRfBuffer(rfReg, tempDB, 3, 107, 0); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_5111, rfReg, regWrites); + + /* Bank 7 Write */ + for (i = 0; i < N(ar5212Bank7_5111); i++) + rfReg[i] = ar5212Bank7_5111[i][modesIndex]; + ar5212ModifyRfBuffer(rfReg, gainI, 6, 29, 0); + ar5212ModifyRfBuffer(rfReg, rfPloSel, 1, 4, 0); + + if (IEEE80211_IS_CHAN_QUARTER(chan) || IEEE80211_IS_CHAN_HALF(chan)) { + uint32_t rfWaitI, rfWaitS, rfMaxTime; + + rfWaitS = 0x1f; + rfWaitI = (IEEE80211_IS_CHAN_HALF(chan)) ? 0x10 : 0x1f; + rfMaxTime = 3; + ar5212ModifyRfBuffer(rfReg, rfWaitS, 5, 19, 0); + ar5212ModifyRfBuffer(rfReg, rfWaitI, 5, 24, 0); + ar5212ModifyRfBuffer(rfReg, rfMaxTime, 2, 49, 0); + + } + + HAL_INI_WRITE_BANK(ah, ar5212Bank7_5111, rfReg, regWrites); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static uint16_t +interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + uint16_t targetLeft, uint16_t targetRight) +{ + uint16_t rv; + int16_t lRatio; + + /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */ + if ((targetLeft * targetRight) == 0) + return 0; + + if (srcRight != srcLeft) { + /* + * Note the ratio always need to be scaled, + * since it will be a fraction. + */ + lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft); + if (lRatio < 0) { + /* Return as Left target if value would be negative */ + rv = targetLeft; + } else if (lRatio > EEP_SCALE) { + /* Return as Right target if Ratio is greater than 100% (SCALE) */ + rv = targetRight; + } else { + rv = (lRatio * targetRight + (EEP_SCALE - lRatio) * + targetLeft) / EEP_SCALE; + } + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Read the transmit power levels from the structures taken from EEPROM + * Interpolate read transmit power values for this channel + * Organize the transmit power values into a table for writing into the hardware + */ +static HAL_BOOL +ar5111SetPowerTable(struct ath_hal *ah, + int16_t *pMinPower, int16_t *pMaxPower, + const struct ieee80211_channel *chan, + uint16_t *rfXpdGain) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + FULL_PCDAC_STRUCT pcdacStruct; + int i, j; + + uint16_t *pPcdacValues; + int16_t *pScaledUpDbm; + int16_t minScaledPwr; + int16_t maxScaledPwr; + int16_t pwr; + uint16_t pcdacMin = 0; + uint16_t pcdacMax = PCDAC_STOP; + uint16_t pcdacTableIndex; + uint16_t scaledPcdac; + PCDACS_EEPROM *pSrcStruct; + PCDACS_EEPROM eepromPcdacs; + + /* setup the pcdac struct to point to the correct info, based on mode */ + switch (chan->ic_flags & IEEE80211_CHAN_ALLTURBOFULL) { + case IEEE80211_CHAN_A: + case IEEE80211_CHAN_ST: + eepromPcdacs.numChannels = ee->ee_numChannels11a; + eepromPcdacs.pChannelList = ee->ee_channels11a; + eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11a; + break; + case IEEE80211_CHAN_B: + eepromPcdacs.numChannels = ee->ee_numChannels2_4; + eepromPcdacs.pChannelList = ee->ee_channels11b; + eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11b; + break; + case IEEE80211_CHAN_G: + case IEEE80211_CHAN_108G: + eepromPcdacs.numChannels = ee->ee_numChannels2_4; + eepromPcdacs.pChannelList = ee->ee_channels11g; + eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11g; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->ic_flags); + return AH_FALSE; + } + + pSrcStruct = &eepromPcdacs; + + OS_MEMZERO(&pcdacStruct, sizeof(pcdacStruct)); + pPcdacValues = pcdacStruct.PcdacValues; + pScaledUpDbm = pcdacStruct.PwrValues; + + /* Initialize the pcdacs to dBM structs pcdacs to be 1 to 63 */ + for (i = PCDAC_START, j = 0; i <= PCDAC_STOP; i+= PCDAC_STEP, j++) + pPcdacValues[j] = i; + + pcdacStruct.numPcdacValues = j; + pcdacStruct.pcdacMin = PCDAC_START; + pcdacStruct.pcdacMax = PCDAC_STOP; + + /* Fill out the power values for this channel */ + for (j = 0; j < pcdacStruct.numPcdacValues; j++ ) + pScaledUpDbm[j] = ar5212GetScaledPower(freq, + pPcdacValues[j], pSrcStruct); + + /* Now scale the pcdac values to fit in the 64 entry power table */ + minScaledPwr = pScaledUpDbm[0]; + maxScaledPwr = pScaledUpDbm[pcdacStruct.numPcdacValues - 1]; + + /* find minimum and make monotonic */ + for (j = 0; j < pcdacStruct.numPcdacValues; j++) { + if (minScaledPwr >= pScaledUpDbm[j]) { + minScaledPwr = pScaledUpDbm[j]; + pcdacMin = j; + } + /* + * Make the full_hsh monotonically increasing otherwise + * interpolation algorithm will get fooled gotta start + * working from the top, hence i = 63 - j. + */ + i = (uint16_t)(pcdacStruct.numPcdacValues - 1 - j); + if (i == 0) + break; + if (pScaledUpDbm[i-1] > pScaledUpDbm[i]) { + /* + * It could be a glitch, so make the power for + * this pcdac the same as the power from the + * next highest pcdac. + */ + pScaledUpDbm[i - 1] = pScaledUpDbm[i]; + } + } + + for (j = 0; j < pcdacStruct.numPcdacValues; j++) + if (maxScaledPwr < pScaledUpDbm[j]) { + maxScaledPwr = pScaledUpDbm[j]; + pcdacMax = j; + } + + /* Find the first power level with a pcdac */ + pwr = (uint16_t)(PWR_STEP * + ((minScaledPwr - PWR_MIN + PWR_STEP / 2) / PWR_STEP) + PWR_MIN); + + /* Write all the first pcdac entries based off the pcdacMin */ + pcdacTableIndex = 0; + for (i = 0; i < (2 * (pwr - PWR_MIN) / EEP_SCALE + 1); i++) { + HALASSERT(pcdacTableIndex < PWR_TABLE_SIZE); + ahp->ah_pcdacTable[pcdacTableIndex++] = pcdacMin; + } + + i = 0; + while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] && + pcdacTableIndex < PWR_TABLE_SIZE) { + pwr += PWR_STEP; + /* stop if dbM > max_power_possible */ + while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] && + (pwr - pScaledUpDbm[i])*(pwr - pScaledUpDbm[i+1]) > 0) + i++; + /* scale by 2 and add 1 to enable round up or down as needed */ + scaledPcdac = (uint16_t)(interpolate(pwr, + pScaledUpDbm[i], pScaledUpDbm[i + 1], + (uint16_t)(pPcdacValues[i] * 2), + (uint16_t)(pPcdacValues[i + 1] * 2)) + 1); + + HALASSERT(pcdacTableIndex < PWR_TABLE_SIZE); + ahp->ah_pcdacTable[pcdacTableIndex] = scaledPcdac / 2; + if (ahp->ah_pcdacTable[pcdacTableIndex] > pcdacMax) + ahp->ah_pcdacTable[pcdacTableIndex] = pcdacMax; + pcdacTableIndex++; + } + + /* Write all the last pcdac entries based off the last valid pcdac */ + while (pcdacTableIndex < PWR_TABLE_SIZE) { + ahp->ah_pcdacTable[pcdacTableIndex] = + ahp->ah_pcdacTable[pcdacTableIndex - 1]; + pcdacTableIndex++; + } + + /* No power table adjustment for 5111 */ + ahp->ah_txPowerIndexOffset = 0; + + return AH_TRUE; +} + +/* + * Get or interpolate the pcdac value from the calibrated data. + */ +static uint16_t +ar5212GetScaledPower(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct) +{ + uint16_t powerValue; + uint16_t lFreq, rFreq; /* left and right frequency values */ + uint16_t llPcdac, ulPcdac; /* lower and upper left pcdac values */ + uint16_t lrPcdac, urPcdac; /* lower and upper right pcdac values */ + uint16_t lPwr, uPwr; /* lower and upper temp pwr values */ + uint16_t lScaledPwr, rScaledPwr; /* left and right scaled power */ + + if (ar5212FindValueInList(channel, pcdacValue, pSrcStruct, &powerValue)) { + /* value was copied from srcStruct */ + return powerValue; + } + + ar5212GetLowerUpperValues(channel, + pSrcStruct->pChannelList, pSrcStruct->numChannels, + &lFreq, &rFreq); + ar5212GetLowerUpperPcdacs(pcdacValue, + lFreq, pSrcStruct, &llPcdac, &ulPcdac); + ar5212GetLowerUpperPcdacs(pcdacValue, + rFreq, pSrcStruct, &lrPcdac, &urPcdac); + + /* get the power index for the pcdac value */ + ar5212FindValueInList(lFreq, llPcdac, pSrcStruct, &lPwr); + ar5212FindValueInList(lFreq, ulPcdac, pSrcStruct, &uPwr); + lScaledPwr = interpolate(pcdacValue, llPcdac, ulPcdac, lPwr, uPwr); + + ar5212FindValueInList(rFreq, lrPcdac, pSrcStruct, &lPwr); + ar5212FindValueInList(rFreq, urPcdac, pSrcStruct, &uPwr); + rScaledPwr = interpolate(pcdacValue, lrPcdac, urPcdac, lPwr, uPwr); + + return interpolate(channel, lFreq, rFreq, lScaledPwr, rScaledPwr); +} + +/* + * Find the value from the calibrated source data struct + */ +static HAL_BOOL +ar5212FindValueInList(uint16_t channel, uint16_t pcdacValue, + const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue) +{ + const DATA_PER_CHANNEL *pChannelData = pSrcStruct->pDataPerChannel; + int i; + + for (i = 0; i < pSrcStruct->numChannels; i++ ) { + if (pChannelData->channelValue == channel) { + const uint16_t* pPcdac = pChannelData->PcdacValues; + int j; + + for (j = 0; j < pChannelData->numPcdacValues; j++ ) { + if (*pPcdac == pcdacValue) { + *powerValue = pChannelData->PwrValues[j]; + return AH_TRUE; + } + pPcdac++; + } + } + pChannelData++; + } + return AH_FALSE; +} + +/* + * Get the upper and lower pcdac given the channel and the pcdac + * used in the search + */ +static void +ar5212GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel, + const PCDACS_EEPROM *pSrcStruct, + uint16_t *pLowerPcdac, uint16_t *pUpperPcdac) +{ + const DATA_PER_CHANNEL *pChannelData = pSrcStruct->pDataPerChannel; + int i; + + /* Find the channel information */ + for (i = 0; i < pSrcStruct->numChannels; i++) { + if (pChannelData->channelValue == channel) + break; + pChannelData++; + } + ar5212GetLowerUpperValues(pcdac, pChannelData->PcdacValues, + pChannelData->numPcdacValues, + pLowerPcdac, pUpperPcdac); +} + +static HAL_BOOL +ar5111GetChannelMaxMinPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *maxPow, int16_t *minPow) +{ + /* XXX - Get 5111 power limits! */ + /* NB: caller will cope */ + return AH_FALSE; +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + */ +static int16_t +ar5111GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + static const struct { + uint16_t freqLow; + int16_t adjust; + } adjust5111[] = { + { 5790, 6 }, /* NB: ordered high -> low */ + { 5730, 4 }, + { 5690, 3 }, + { 5660, 2 }, + { 5610, 1 }, + { 5530, 0 }, + { 5450, 0 }, + { 5379, 1 }, + { 5209, 3 }, + { 3000, 5 }, + { 0, 0 }, + }; + int i; + + for (i = 0; c->channel <= adjust5111[i].freqLow; i++) + ; + return adjust5111[i].adjust; +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar5111RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar5111RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5111State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar5111State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar5111RfDetach; + priv->base.writeRegs = ar5111WriteRegs; + priv->base.getRfBank = ar5111GetRfBank; + priv->base.setChannel = ar5111SetChannel; + priv->base.setRfRegs = ar5111SetRfRegs; + priv->base.setPowerTable = ar5111SetPowerTable; + priv->base.getChannelMaxMinPower = ar5111GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5111GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + return AH_TRUE; +} + +static HAL_BOOL +ar5111Probe(struct ath_hal *ah) +{ + return IS_RAD5111(ah); +} +AH_RF(RF5111, ar5111Probe, ar5111RfAttach); diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5112.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5112.c new file mode 100644 index 0000000..c1920b9 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5112.c @@ -0,0 +1,889 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v3.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#define AH_5212_5112 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar5112State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE]; + + uint32_t Bank1Data[N(ar5212Bank1_5112)]; + uint32_t Bank2Data[N(ar5212Bank2_5112)]; + uint32_t Bank3Data[N(ar5212Bank3_5112)]; + uint32_t Bank6Data[N(ar5212Bank6_5112)]; + uint32_t Bank7Data[N(ar5212Bank7_5112)]; +}; +#define AR5112(ah) ((struct ar5112State *) AH5212(ah)->ah_rfHal) + +static void ar5212GetLowerUpperIndex(uint16_t v, + uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi); +static HAL_BOOL getFullPwrTable(uint16_t numPcdacs, uint16_t *pcdacs, + int16_t *power, int16_t maxPower, int16_t *retVals); +static int16_t getPminAndPcdacTableFromPowerTable(int16_t *pwrTableT4, + uint16_t retVals[]); +static int16_t getPminAndPcdacTableFromTwoPowerTables(int16_t *pwrTableLXpdT4, + int16_t *pwrTableHXpdT4, uint16_t retVals[], int16_t *pMid); +static int16_t interpolate_signed(uint16_t target, + uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight); + +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar5112WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_5112, modesIndex, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_5112, 1, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_5112, freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar5112SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + + OS_MARK(ah, AH_MARK_SETCHANNEL, freq); + + if (freq < 4800) { + uint32_t txctl; + + if (((freq - 2192) % 5) == 0) { + channelSel = ((freq - 672) * 2 - 3040)/10; + bModeSynth = 0; + } else if (((freq - 2224) % 5) == 0) { + channelSel = ((freq - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u MHz\n", + __func__, freq); + return AH_FALSE; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else if (((freq % 5) == 2) && (freq <= 5435)) { + freq = freq - 2; /* Align to even 5MHz raster */ + channelSel = ath_hal_reverseBits( + (uint32_t)(((freq - 4800)*10)/25 + 1), 8); + aModeRefSel = ath_hal_reverseBits(0, 2); + } else if ((freq % 20) == 0 && freq >= 5120) { + channelSel = ath_hal_reverseBits( + ((freq - 4800) / 20 << 2), 8); + aModeRefSel = ath_hal_reverseBits(3, 2); + } else if ((freq % 10) == 0) { + channelSel = ath_hal_reverseBits( + ((freq - 4800) / 10 << 1), 8); + aModeRefSel = ath_hal_reverseBits(2, 2); + } else if ((freq % 5) == 0) { + channelSel = ath_hal_reverseBits( + (freq - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", + __func__, freq); + return AH_FALSE; + } + + reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 12) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); + + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar5112GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar5112State *priv = AR5112(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar5112SetRfRegs(struct ath_hal *ah, + const struct ieee80211_channel *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ +#define RF_BANK_SETUP(_priv, _ix, _col) do { \ + int i; \ + for (i = 0; i < N(ar5212Bank##_ix##_5112); i++) \ + (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_5112[i][_col];\ +} while (0) + uint16_t freq = ath_hal_gethwchannel(ah, chan); + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t rfXpdSel, gainI; + uint16_t ob5GHz = 0, db5GHz = 0; + uint16_t ob2GHz = 0, db2GHz = 0; + struct ar5112State *priv = AR5112(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + int regWrites = 0; + + HALASSERT(priv); + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan %u/0x%x modesIndex %u\n", + __func__, chan->ic_freq, chan->ic_flags, modesIndex); + + /* Setup rf parameters */ + switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) { + case IEEE80211_CHAN_A: + if (freq > 4000 && freq < 5260) { + ob5GHz = ee->ee_ob1; + db5GHz = ee->ee_db1; + } else if (freq >= 5260 && freq < 5500) { + ob5GHz = ee->ee_ob2; + db5GHz = ee->ee_db2; + } else if (freq >= 5500 && freq < 5725) { + ob5GHz = ee->ee_ob3; + db5GHz = ee->ee_db3; + } else if (freq >= 5725) { + ob5GHz = ee->ee_ob4; + db5GHz = ee->ee_db4; + } else { + /* XXX else */ + } + rfXpdSel = ee->ee_xpd[headerInfo11A]; + gainI = ee->ee_gainI[headerInfo11A]; + break; + case IEEE80211_CHAN_B: + ob2GHz = ee->ee_ob2GHz[0]; + db2GHz = ee->ee_db2GHz[0]; + rfXpdSel = ee->ee_xpd[headerInfo11B]; + gainI = ee->ee_gainI[headerInfo11B]; + break; + case IEEE80211_CHAN_G: + case IEEE80211_CHAN_PUREG: /* NB: really 108G */ + ob2GHz = ee->ee_ob2GHz[1]; + db2GHz = ee->ee_ob2GHz[1]; + rfXpdSel = ee->ee_xpd[headerInfo11G]; + gainI = ee->ee_gainI[headerInfo11G]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->ic_flags); + return AH_FALSE; + } + + /* Setup Bank 1 Write */ + RF_BANK_SETUP(priv, 1, 1); + + /* Setup Bank 2 Write */ + RF_BANK_SETUP(priv, 2, modesIndex); + + /* Setup Bank 3 Write */ + RF_BANK_SETUP(priv, 3, modesIndex); + + /* Setup Bank 6 Write */ + RF_BANK_SETUP(priv, 6, modesIndex); + + ar5212ModifyRfBuffer(priv->Bank6Data, rfXpdSel, 1, 302, 0); + + ar5212ModifyRfBuffer(priv->Bank6Data, rfXpdGain[0], 2, 270, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, rfXpdGain[1], 2, 257, 0); + + if (IEEE80211_IS_CHAN_OFDM(chan)) { + ar5212ModifyRfBuffer(priv->Bank6Data, + gv->currStep->paramVal[GP_PWD_138], 1, 168, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, + gv->currStep->paramVal[GP_PWD_137], 1, 169, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, + gv->currStep->paramVal[GP_PWD_136], 1, 170, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, + gv->currStep->paramVal[GP_PWD_132], 1, 174, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, + gv->currStep->paramVal[GP_PWD_131], 1, 175, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, + gv->currStep->paramVal[GP_PWD_130], 1, 176, 3); + } + + /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 287, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 290, 0); + } else { + ar5212ModifyRfBuffer(priv->Bank6Data, ob5GHz, 3, 279, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db5GHz, 3, 282, 0); + } + + /* Lower synth voltage for X112 Rev 2.0 only */ + if (IS_RADX112_REV2(ah)) { + /* Non-Reversed analyg registers - so values are pre-reversed */ + ar5212ModifyRfBuffer(priv->Bank6Data, 2, 2, 90, 2); + ar5212ModifyRfBuffer(priv->Bank6Data, 2, 2, 92, 2); + ar5212ModifyRfBuffer(priv->Bank6Data, 2, 2, 94, 2); + ar5212ModifyRfBuffer(priv->Bank6Data, 2, 1, 254, 2); + } + + /* Decrease Power Consumption for 5312/5213 and up */ + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) { + ar5212ModifyRfBuffer(priv->Bank6Data, 1, 1, 281, 1); + ar5212ModifyRfBuffer(priv->Bank6Data, 1, 2, 1, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, 1, 2, 3, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, 1, 1, 139, 3); + ar5212ModifyRfBuffer(priv->Bank6Data, 1, 1, 140, 3); + } + + /* Setup Bank 7 Setup */ + RF_BANK_SETUP(priv, 7, modesIndex); + if (IEEE80211_IS_CHAN_OFDM(chan)) + ar5212ModifyRfBuffer(priv->Bank7Data, + gv->currStep->paramVal[GP_MIXGAIN_OVR], 2, 37, 0); + + ar5212ModifyRfBuffer(priv->Bank7Data, gainI, 6, 14, 0); + + /* Adjust params for Derby TX power control */ + if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan)) { + uint32_t rfDelay, rfPeriod; + + rfDelay = 0xf; + rfPeriod = (IEEE80211_IS_CHAN_HALF(chan)) ? 0x8 : 0xf; + ar5212ModifyRfBuffer(priv->Bank7Data, rfDelay, 4, 58, 0); + ar5212ModifyRfBuffer(priv->Bank7Data, rfPeriod, 4, 70, 0); + } + +#ifdef notyet + /* Analog registers are setup - EAR can modify */ + if (ar5212IsEarEngaged(pDev, chan)) + uint32_t modifier; + ar5212EarModify(pDev, EAR_LC_RF_WRITE, chan, &modifier); +#endif + /* Write Analog registers */ + HAL_INI_WRITE_BANK(ah, ar5212Bank1_5112, priv->Bank1Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank2_5112, priv->Bank2Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank3_5112, priv->Bank3Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_5112, priv->Bank6Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank7_5112, priv->Bank7Data, regWrites); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Read the transmit power levels from the structures taken from EEPROM + * Interpolate read transmit power values for this channel + * Organize the transmit power values into a table for writing into the hardware + */ +static HAL_BOOL +ar5112SetPowerTable(struct ath_hal *ah, + int16_t *pPowerMin, int16_t *pPowerMax, + const struct ieee80211_channel *chan, + uint16_t *rfXpdGain) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint32_t numXpdGain = IS_RADX112_REV2(ah) ? 2 : 1; + uint32_t xpdGainMask = 0; + int16_t powerMid, *pPowerMid = &powerMid; + + const EXPN_DATA_PER_CHANNEL_5112 *pRawCh; + const EEPROM_POWER_EXPN_5112 *pPowerExpn = AH_NULL; + + uint32_t ii, jj, kk; + int16_t minPwr_t4, maxPwr_t4, Pmin, Pmid; + + uint32_t chan_idx_L = 0, chan_idx_R = 0; + uint16_t chan_L, chan_R; + + int16_t pwr_table0[64]; + int16_t pwr_table1[64]; + uint16_t pcdacs[10]; + int16_t powers[10]; + uint16_t numPcd; + int16_t powTableLXPD[2][64]; + int16_t powTableHXPD[2][64]; + int16_t tmpPowerTable[64]; + uint16_t xgainList[2]; + uint16_t xpdMask; + + switch (chan->ic_flags & IEEE80211_CHAN_ALLTURBOFULL) { + case IEEE80211_CHAN_A: + case IEEE80211_CHAN_ST: + pPowerExpn = &ee->ee_modePowerArray5112[headerInfo11A]; + xpdGainMask = ee->ee_xgain[headerInfo11A]; + break; + case IEEE80211_CHAN_B: + pPowerExpn = &ee->ee_modePowerArray5112[headerInfo11B]; + xpdGainMask = ee->ee_xgain[headerInfo11B]; + break; + case IEEE80211_CHAN_G: + case IEEE80211_CHAN_108G: + pPowerExpn = &ee->ee_modePowerArray5112[headerInfo11G]; + xpdGainMask = ee->ee_xgain[headerInfo11G]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown channel flags 0x%x\n", + __func__, chan->ic_flags); + return AH_FALSE; + } + + if ((xpdGainMask & pPowerExpn->xpdMask) < 1) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: desired xpdGainMask 0x%x not supported by " + "calibrated xpdMask 0x%x\n", __func__, + xpdGainMask, pPowerExpn->xpdMask); + return AH_FALSE; + } + + maxPwr_t4 = (int16_t)(2*(*pPowerMax)); /* pwr_t2 -> pwr_t4 */ + minPwr_t4 = (int16_t)(2*(*pPowerMin)); /* pwr_t2 -> pwr_t4 */ + + xgainList[0] = 0xDEAD; + xgainList[1] = 0xDEAD; + + kk = 0; + xpdMask = pPowerExpn->xpdMask; + for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) { + if (((xpdMask >> jj) & 1) > 0) { + if (kk > 1) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "A maximum of 2 xpdGains supported" + "in pExpnPower data\n"); + return AH_FALSE; + } + xgainList[kk++] = (uint16_t)jj; + } + } + + ar5212GetLowerUpperIndex(freq, &pPowerExpn->pChannels[0], + pPowerExpn->numChannels, &chan_idx_L, &chan_idx_R); + + kk = 0; + for (ii = chan_idx_L; ii <= chan_idx_R; ii++) { + pRawCh = &(pPowerExpn->pDataPerChannel[ii]); + if (xgainList[1] == 0xDEAD) { + jj = xgainList[0]; + numPcd = pRawCh->pDataPerXPD[jj].numPcdacs; + OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0], + numPcd * sizeof(uint16_t)); + OS_MEMCPY(&powers[0], &pRawCh->pDataPerXPD[jj].pwr_t4[0], + numPcd * sizeof(int16_t)); + if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0], + pRawCh->maxPower_t4, &tmpPowerTable[0])) { + return AH_FALSE; + } + OS_MEMCPY(&powTableLXPD[kk][0], &tmpPowerTable[0], + 64*sizeof(int16_t)); + } else { + jj = xgainList[0]; + numPcd = pRawCh->pDataPerXPD[jj].numPcdacs; + OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0], + numPcd*sizeof(uint16_t)); + OS_MEMCPY(&powers[0], + &pRawCh->pDataPerXPD[jj].pwr_t4[0], + numPcd*sizeof(int16_t)); + if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0], + pRawCh->maxPower_t4, &tmpPowerTable[0])) { + return AH_FALSE; + } + OS_MEMCPY(&powTableLXPD[kk][0], &tmpPowerTable[0], + 64 * sizeof(int16_t)); + + jj = xgainList[1]; + numPcd = pRawCh->pDataPerXPD[jj].numPcdacs; + OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0], + numPcd * sizeof(uint16_t)); + OS_MEMCPY(&powers[0], + &pRawCh->pDataPerXPD[jj].pwr_t4[0], + numPcd * sizeof(int16_t)); + if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0], + pRawCh->maxPower_t4, &tmpPowerTable[0])) { + return AH_FALSE; + } + OS_MEMCPY(&powTableHXPD[kk][0], &tmpPowerTable[0], + 64 * sizeof(int16_t)); + } + kk++; + } + + chan_L = pPowerExpn->pChannels[chan_idx_L]; + chan_R = pPowerExpn->pChannels[chan_idx_R]; + kk = chan_idx_R - chan_idx_L; + + if (xgainList[1] == 0xDEAD) { + for (jj = 0; jj < 64; jj++) { + pwr_table0[jj] = interpolate_signed( + freq, chan_L, chan_R, + powTableLXPD[0][jj], powTableLXPD[kk][jj]); + } + Pmin = getPminAndPcdacTableFromPowerTable(&pwr_table0[0], + ahp->ah_pcdacTable); + *pPowerMin = (int16_t) (Pmin / 2); + *pPowerMid = (int16_t) (pwr_table0[63] / 2); + *pPowerMax = (int16_t) (pwr_table0[63] / 2); + rfXpdGain[0] = xgainList[0]; + rfXpdGain[1] = rfXpdGain[0]; + } else { + for (jj = 0; jj < 64; jj++) { + pwr_table0[jj] = interpolate_signed( + freq, chan_L, chan_R, + powTableLXPD[0][jj], powTableLXPD[kk][jj]); + pwr_table1[jj] = interpolate_signed( + freq, chan_L, chan_R, + powTableHXPD[0][jj], powTableHXPD[kk][jj]); + } + if (numXpdGain == 2) { + Pmin = getPminAndPcdacTableFromTwoPowerTables( + &pwr_table0[0], &pwr_table1[0], + ahp->ah_pcdacTable, &Pmid); + *pPowerMin = (int16_t) (Pmin / 2); + *pPowerMid = (int16_t) (Pmid / 2); + *pPowerMax = (int16_t) (pwr_table0[63] / 2); + rfXpdGain[0] = xgainList[0]; + rfXpdGain[1] = xgainList[1]; + } else if (minPwr_t4 <= pwr_table1[63] && + maxPwr_t4 <= pwr_table1[63]) { + Pmin = getPminAndPcdacTableFromPowerTable( + &pwr_table1[0], ahp->ah_pcdacTable); + rfXpdGain[0] = xgainList[1]; + rfXpdGain[1] = rfXpdGain[0]; + *pPowerMin = (int16_t) (Pmin / 2); + *pPowerMid = (int16_t) (pwr_table1[63] / 2); + *pPowerMax = (int16_t) (pwr_table1[63] / 2); + } else { + Pmin = getPminAndPcdacTableFromPowerTable( + &pwr_table0[0], ahp->ah_pcdacTable); + rfXpdGain[0] = xgainList[0]; + rfXpdGain[1] = rfXpdGain[0]; + *pPowerMin = (int16_t) (Pmin/2); + *pPowerMid = (int16_t) (pwr_table0[63] / 2); + *pPowerMax = (int16_t) (pwr_table0[63] / 2); + } + } + + /* + * Move 5112 rates to match power tables where the max + * power table entry corresponds with maxPower. + */ + HALASSERT(*pPowerMax <= PCDAC_STOP); + ahp->ah_txPowerIndexOffset = PCDAC_STOP - *pPowerMax; + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static int16_t +interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight != srcLeft) { + rv = ((target - srcLeft)*targetRight + + (srcRight - target)*targetLeft) / (srcRight - srcLeft); + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Return indices surrounding the value in sorted integer lists. + * + * NB: the input list is assumed to be sorted in ascending order + */ +static void +ar5212GetLowerUpperIndex(uint16_t v, uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi) +{ + uint32_t target = v; + uint16_t *ep = lp+listSize; + uint16_t *tp; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < lp[0]) { + *vlo = *vhi = 0; + return; + } + if (target >= ep[-1]) { + *vlo = *vhi = listSize - 1; + return; + } + + /* look for value being near or between 2 values in list */ + for (tp = lp; tp < ep; tp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (*tp == target) { + *vlo = *vhi = tp - lp; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < tp[1]) { + *vlo = tp - lp; + *vhi = *vlo + 1; + return; + } + } +} + +static HAL_BOOL +getFullPwrTable(uint16_t numPcdacs, uint16_t *pcdacs, int16_t *power, int16_t maxPower, int16_t *retVals) +{ + uint16_t ii; + uint16_t idxL = 0; + uint16_t idxR = 1; + + if (numPcdacs < 2) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: at least 2 pcdac values needed [%d]\n", + __func__, numPcdacs); + return AH_FALSE; + } + for (ii = 0; ii < 64; ii++) { + if (ii>pcdacs[idxR] && idxR < numPcdacs-1) { + idxL++; + idxR++; + } + retVals[ii] = interpolate_signed(ii, + pcdacs[idxL], pcdacs[idxR], power[idxL], power[idxR]); + if (retVals[ii] >= maxPower) { + while (ii < 64) + retVals[ii++] = maxPower; + } + } + return AH_TRUE; +} + +/* + * Takes a single calibration curve and creates a power table. + * Adjusts the new power table so the max power is relative + * to the maximum index in the power table. + * + * WARNING: rates must be adjusted for this relative power table + */ +static int16_t +getPminAndPcdacTableFromPowerTable(int16_t *pwrTableT4, uint16_t retVals[]) +{ + int16_t ii, jj, jjMax; + int16_t pMin, currPower, pMax; + + /* If the spread is > 31.5dB, keep the upper 31.5dB range */ + if ((pwrTableT4[63] - pwrTableT4[0]) > 126) { + pMin = pwrTableT4[63] - 126; + } else { + pMin = pwrTableT4[0]; + } + + pMax = pwrTableT4[63]; + jjMax = 63; + + /* Search for highest pcdac 0.25dB below maxPower */ + while ((pwrTableT4[jjMax] > (pMax - 1) ) && (jjMax >= 0)) { + jjMax--; + } + + jj = jjMax; + currPower = pMax; + for (ii = 63; ii >= 0; ii--) { + while ((jj < 64) && (jj > 0) && (pwrTableT4[jj] >= currPower)) { + jj--; + } + if (jj == 0) { + while (ii >= 0) { + retVals[ii] = retVals[ii + 1]; + ii--; + } + break; + } + retVals[ii] = jj; + currPower -= 2; // corresponds to a 0.5dB step + } + return pMin; +} + +/* + * Combines the XPD curves from two calibration sets into a single + * power table and adjusts the power table so the max power is relative + * to the maximum index in the power table + * + * WARNING: rates must be adjusted for this relative power table + */ +static int16_t +getPminAndPcdacTableFromTwoPowerTables(int16_t *pwrTableLXpdT4, + int16_t *pwrTableHXpdT4, uint16_t retVals[], int16_t *pMid) +{ + int16_t ii, jj, jjMax; + int16_t pMin, pMax, currPower; + int16_t *pwrTableT4; + uint16_t msbFlag = 0x40; // turns on the 7th bit of the pcdac + + /* If the spread is > 31.5dB, keep the upper 31.5dB range */ + if ((pwrTableLXpdT4[63] - pwrTableHXpdT4[0]) > 126) { + pMin = pwrTableLXpdT4[63] - 126; + } else { + pMin = pwrTableHXpdT4[0]; + } + + pMax = pwrTableLXpdT4[63]; + jjMax = 63; + /* Search for highest pcdac 0.25dB below maxPower */ + while ((pwrTableLXpdT4[jjMax] > (pMax - 1) ) && (jjMax >= 0)){ + jjMax--; + } + + *pMid = pwrTableHXpdT4[63]; + jj = jjMax; + ii = 63; + currPower = pMax; + pwrTableT4 = &(pwrTableLXpdT4[0]); + while (ii >= 0) { + if ((currPower <= *pMid) || ( (jj == 0) && (msbFlag == 0x40))){ + msbFlag = 0x00; + pwrTableT4 = &(pwrTableHXpdT4[0]); + jj = 63; + } + while ((jj > 0) && (pwrTableT4[jj] >= currPower)) { + jj--; + } + if ((jj == 0) && (msbFlag == 0x00)) { + while (ii >= 0) { + retVals[ii] = retVals[ii+1]; + ii--; + } + break; + } + retVals[ii] = jj | msbFlag; + currPower -= 2; // corresponds to a 0.5dB step + ii--; + } + return pMin; +} + +static int16_t +ar5112GetMinPower(struct ath_hal *ah, const EXPN_DATA_PER_CHANNEL_5112 *data) +{ + int i, minIndex; + int16_t minGain,minPwr,minPcdac,retVal; + + /* Assume NUM_POINTS_XPD0 > 0 */ + minGain = data->pDataPerXPD[0].xpd_gain; + for (minIndex=0,i=1; ipDataPerXPD[i].xpd_gain < minGain) { + minIndex = i; + minGain = data->pDataPerXPD[i].xpd_gain; + } + } + minPwr = data->pDataPerXPD[minIndex].pwr_t4[0]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[0]; + for (i=1; ipDataPerXPD[minIndex].pwr_t4[i] < minPwr) { + minPwr = data->pDataPerXPD[minIndex].pwr_t4[i]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[i]; + } + } + retVal = minPwr - (minPcdac*2); + return(retVal); +} + +static HAL_BOOL +ar5112GetChannelMaxMinPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *maxPow, int16_t *minPow) +{ + uint16_t freq = chan->ic_freq; /* NB: never mapped */ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + int numChannels=0,i,last; + int totalD, totalF,totalMin; + const EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL; + const EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL; + + *maxPow = 0; + if (IEEE80211_IS_CHAN_A(chan)) { + powerArray = ee->ee_modePowerArray5112; + data = powerArray[headerInfo11A].pDataPerChannel; + numChannels = powerArray[headerInfo11A].numChannels; + } else if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan)) { + /* XXX - is this correct? Should we also use the same power for turbo G? */ + powerArray = ee->ee_modePowerArray5112; + data = powerArray[headerInfo11G].pDataPerChannel; + numChannels = powerArray[headerInfo11G].numChannels; + } else if (IEEE80211_IS_CHAN_B(chan)) { + powerArray = ee->ee_modePowerArray5112; + data = powerArray[headerInfo11B].pDataPerChannel; + numChannels = powerArray[headerInfo11B].numChannels; + } else { + return (AH_TRUE); + } + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if (numChannels < 1) + return(AH_FALSE); + + if ((freq < data[0].channelValue) || + (freq > data[numChannels-1].channelValue)) { + if (freq < data[0].channelValue) { + *maxPow = data[0].maxPower_t4; + *minPow = ar5112GetMinPower(ah, &data[0]); + return(AH_TRUE); + } else { + *maxPow = data[numChannels - 1].maxPower_t4; + *minPow = ar5112GetMinPower(ah, &data[numChannels - 1]); + return(AH_TRUE); + } + } + + /* Linearly interpolate the power value now */ + for (last=0,i=0; + (i data[i].channelValue); + last=i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = data[i].maxPower_t4 - data[last].maxPower_t4; + *maxPow = (int8_t) ((totalF*(freq-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD); + + totalMin = ar5112GetMinPower(ah,&data[i]) - ar5112GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(freq-data[last].channelValue) + ar5112GetMinPower(ah, &data[last])*totalD)/totalD); + return (AH_TRUE); + } else { + if (freq == data[i].channelValue) { + *maxPow = data[i].maxPower_t4; + *minPow = ar5112GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar5112RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar5112RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5112State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar5112State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar5112RfDetach; + priv->base.writeRegs = ar5112WriteRegs; + priv->base.getRfBank = ar5112GetRfBank; + priv->base.setChannel = ar5112SetChannel; + priv->base.setRfRegs = ar5112SetRfRegs; + priv->base.setPowerTable = ar5112SetPowerTable; + priv->base.getChannelMaxMinPower = ar5112GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5212GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + return AH_TRUE; +} + +static HAL_BOOL +ar5112Probe(struct ath_hal *ah) +{ + return IS_RAD5112(ah); +} +AH_RF(RF5112, ar5112Probe, ar5112RfAttach); diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212.h b/sys/external/isc/atheros_hal/dist/ar5212/ar5212.h new file mode 100644 index 0000000..bab061d --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212.h @@ -0,0 +1,659 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AR5212_H_ +#define _ATH_AR5212_H_ + +#include "ah_eeprom.h" + +#define AR5212_MAGIC 0x19541014 + +/* DCU Transmit Filter macros */ +#define CALC_MMR(dcu, idx) \ + ( (4 * dcu) + (idx < 32 ? 0 : (idx < 64 ? 1 : (idx < 96 ? 2 : 3))) ) +#define TXBLK_FROM_MMR(mmr) \ + (AR_D_TXBLK_BASE + ((mmr & 0x1f) << 6) + ((mmr & 0x20) >> 3)) +#define CALC_TXBLK_ADDR(dcu, idx) (TXBLK_FROM_MMR(CALC_MMR(dcu, idx))) +#define CALC_TXBLK_VALUE(idx) (1 << (idx & 0x1f)) + +/* MAC register values */ + +#define INIT_INTERRUPT_MASK \ + ( AR_IMR_TXERR | AR_IMR_TXOK | AR_IMR_RXORN | \ + AR_IMR_RXERR | AR_IMR_RXOK | AR_IMR_TXURN | \ + AR_IMR_HIUERR ) +#define INIT_BEACON_CONTROL \ + ((INIT_RESET_TSF << 24) | (INIT_BEACON_EN << 23) | \ + (INIT_TIM_OFFSET << 16) | INIT_BEACON_PERIOD) + +#define INIT_CONFIG_STATUS 0x00000000 +#define INIT_RSSI_THR 0x00000781 /* Missed beacon counter initialized to 0x7 (max is 0xff) */ +#define INIT_IQCAL_LOG_COUNT_MAX 0xF +#define INIT_BCON_CNTRL_REG 0x00000000 + +#define INIT_USEC 40 +#define HALF_RATE_USEC 19 /* ((40 / 2) - 1 ) */ +#define QUARTER_RATE_USEC 9 /* ((40 / 4) - 1 ) */ + +#define RX_NON_FULL_RATE_LATENCY 63 +#define TX_HALF_RATE_LATENCY 108 +#define TX_QUARTER_RATE_LATENCY 216 + +#define IFS_SLOT_FULL_RATE 0x168 /* 9 us half, 40 MHz core clock (9*40) */ +#define IFS_SLOT_HALF_RATE 0x104 /* 13 us half, 20 MHz core clock (13*20) */ +#define IFS_SLOT_QUARTER_RATE 0xD2 /* 21 us quarter, 10 MHz core clock (21*10) */ +#define IFS_EIFS_FULL_RATE 0xE60 /* (74 + (2 * 9)) * 40MHz core clock */ +#define IFS_EIFS_HALF_RATE 0xDAC /* (149 + (2 * 13)) * 20MHz core clock */ +#define IFS_EIFS_QUARTER_RATE 0xD48 /* (298 + (2 * 21)) * 10MHz core clock */ + +#define ACK_CTS_TIMEOUT_11A 0x3E8 /* ACK timeout in 11a core clocks */ + +/* Tx frame start to tx data start delay */ +#define TX_FRAME_D_START_HALF_RATE 0xc +#define TX_FRAME_D_START_QUARTER_RATE 0xd + +/* + * Various fifo fill before Tx start, in 64-byte units + * i.e. put the frame in the air while still DMAing + */ +#define MIN_TX_FIFO_THRESHOLD 0x1 +#define MAX_TX_FIFO_THRESHOLD ((IEEE80211_MAX_LEN / 64) + 1) +#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD + +#define HAL_DECOMP_MASK_SIZE 128 /* 1 byte per key */ + +/* + * Gain support. + */ +#define NUM_CORNER_FIX_BITS 4 +#define NUM_CORNER_FIX_BITS_5112 7 +#define DYN_ADJ_UP_MARGIN 15 +#define DYN_ADJ_LO_MARGIN 20 +#define PHY_PROBE_CCK_CORRECTION 5 +#define CCK_OFDM_GAIN_DELTA 15 + +enum GAIN_PARAMS { + GP_TXCLIP, + GP_PD90, + GP_PD84, + GP_GSEL, +}; + +enum GAIN_PARAMS_5112 { + GP_MIXGAIN_OVR, + GP_PWD_138, + GP_PWD_137, + GP_PWD_136, + GP_PWD_132, + GP_PWD_131, + GP_PWD_130, +}; + +typedef struct _gainOptStep { + int16_t paramVal[NUM_CORNER_FIX_BITS_5112]; + int32_t stepGain; + int8_t stepName[16]; +} GAIN_OPTIMIZATION_STEP; + +typedef struct { + uint32_t numStepsInLadder; + uint32_t defaultStepNum; + GAIN_OPTIMIZATION_STEP optStep[10]; +} GAIN_OPTIMIZATION_LADDER; + +typedef struct { + uint32_t currStepNum; + uint32_t currGain; + uint32_t targetGain; + uint32_t loTrig; + uint32_t hiTrig; + uint32_t active; + const GAIN_OPTIMIZATION_STEP *currStep; +} GAIN_VALUES; + +/* RF HAL structures */ +typedef struct RfHalFuncs { + void *priv; /* private state */ + + void (*rfDetach)(struct ath_hal *ah); + void (*writeRegs)(struct ath_hal *, + u_int modeIndex, u_int freqIndex, int regWrites); + uint32_t *(*getRfBank)(struct ath_hal *ah, int bank); + HAL_BOOL (*setChannel)(struct ath_hal *, + const struct ieee80211_channel *); + HAL_BOOL (*setRfRegs)(struct ath_hal *, + const struct ieee80211_channel *, uint16_t modesIndex, + uint16_t *rfXpdGain); + HAL_BOOL (*setPowerTable)(struct ath_hal *ah, + int16_t *minPower, int16_t *maxPower, + const struct ieee80211_channel *, uint16_t *rfXpdGain); + HAL_BOOL (*getChannelMaxMinPower)(struct ath_hal *ah, + const struct ieee80211_channel *, + int16_t *maxPow, int16_t *minPow); + int16_t (*getNfAdjust)(struct ath_hal *, const HAL_CHANNEL_INTERNAL*); +} RF_HAL_FUNCS; + +struct ar5212AniParams { + int maxNoiseImmunityLevel; /* [0..4] */ + int totalSizeDesired[5]; + int coarseHigh[5]; + int coarseLow[5]; + int firpwr[5]; + + int maxSpurImmunityLevel; /* [0..7] */ + int cycPwrThr1[8]; + + int maxFirstepLevel; /* [0..2] */ + int firstep[3]; + + uint32_t ofdmTrigHigh; + uint32_t ofdmTrigLow; + uint32_t cckTrigHigh; + uint32_t cckTrigLow; + int32_t rssiThrLow; + uint32_t rssiThrHigh; + + int period; /* update listen period */ + + /* NB: intentionally ordered so data exported to user space is first */ + uint32_t ofdmPhyErrBase; /* Base value for ofdm err counter */ + uint32_t cckPhyErrBase; /* Base value for cck err counters */ +}; + +/* + * Per-channel ANI state private to the driver. + */ +struct ar5212AniState { + uint8_t noiseImmunityLevel; + uint8_t spurImmunityLevel; + uint8_t firstepLevel; + uint8_t ofdmWeakSigDetectOff; + uint8_t cckWeakSigThreshold; + uint32_t listenTime; + + /* NB: intentionally ordered so data exported to user space is first */ + uint32_t txFrameCount; /* Last txFrameCount */ + uint32_t rxFrameCount; /* Last rx Frame count */ + uint32_t cycleCount; /* Last cycleCount + (to detect wrap-around) */ + uint32_t ofdmPhyErrCount;/* OFDM err count since last reset */ + uint32_t cckPhyErrCount; /* CCK err count since last reset */ + + const struct ar5212AniParams *params; +}; + +#define HAL_ANI_ENA 0x00000001 /* ANI operation enabled */ +#define HAL_RSSI_ANI_ENA 0x00000002 /* rssi-based processing ena'd*/ + +#if 0 +struct ar5212Stats { + uint32_t ast_ani_niup; /* ANI increased noise immunity */ + uint32_t ast_ani_nidown; /* ANI decreased noise immunity */ + uint32_t ast_ani_spurup; /* ANI increased spur immunity */ + uint32_t ast_ani_spurdown;/* ANI descreased spur immunity */ + uint32_t ast_ani_ofdmon; /* ANI OFDM weak signal detect on */ + uint32_t ast_ani_ofdmoff;/* ANI OFDM weak signal detect off */ + uint32_t ast_ani_cckhigh;/* ANI CCK weak signal threshold high */ + uint32_t ast_ani_ccklow; /* ANI CCK weak signal threshold low */ + uint32_t ast_ani_stepup; /* ANI increased first step level */ + uint32_t ast_ani_stepdown;/* ANI decreased first step level */ + uint32_t ast_ani_ofdmerrs;/* ANI cumulative ofdm phy err count */ + uint32_t ast_ani_cckerrs;/* ANI cumulative cck phy err count */ + uint32_t ast_ani_reset; /* ANI parameters zero'd for non-STA */ + uint32_t ast_ani_lzero; /* ANI listen time forced to zero */ + uint32_t ast_ani_lneg; /* ANI listen time calculated < 0 */ + HAL_MIB_STATS ast_mibstats; /* MIB counter stats */ + HAL_NODE_STATS ast_nodestats; /* Latest rssi stats from driver */ +}; +#endif + +/* + * NF Cal history buffer + */ +#define AR5212_CCA_MAX_GOOD_VALUE -95 +#define AR5212_CCA_MAX_HIGH_VALUE -62 +#define AR5212_CCA_MIN_BAD_VALUE -125 + +#define AR512_NF_CAL_HIST_MAX 5 + +struct ar5212NfCalHist { + int16_t nfCalBuffer[AR512_NF_CAL_HIST_MAX]; + int16_t privNF; + uint8_t currIndex; + uint8_t first_run; + uint8_t invalidNFcount; +}; + +struct ath_hal_5212 { + struct ath_hal_private ah_priv; /* base class */ + + /* + * Per-chip common Initialization data. + * NB: RF backends have their own ini data. + */ + HAL_INI_ARRAY ah_ini_modes; + HAL_INI_ARRAY ah_ini_common; + + GAIN_VALUES ah_gainValues; + + uint8_t ah_macaddr[IEEE80211_ADDR_LEN]; + uint8_t ah_bssid[IEEE80211_ADDR_LEN]; + uint8_t ah_bssidmask[IEEE80211_ADDR_LEN]; + uint16_t ah_assocId; + + /* + * Runtime state. + */ + uint32_t ah_maskReg; /* copy of AR_IMR */ + HAL_ANI_STATS ah_stats; /* various statistics */ + RF_HAL_FUNCS *ah_rfHal; + uint32_t ah_txDescMask; /* mask for TXDESC */ + uint32_t ah_txOkInterruptMask; + uint32_t ah_txErrInterruptMask; + uint32_t ah_txDescInterruptMask; + uint32_t ah_txEolInterruptMask; + uint32_t ah_txUrnInterruptMask; + HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; + uint32_t ah_intrTxqs; /* tx q interrupt state */ + /* decomp mask array */ + uint8_t ah_decompMask[HAL_DECOMP_MASK_SIZE]; + HAL_ANT_SETTING ah_antControl; /* antenna setting */ + HAL_BOOL ah_diversity; /* fast diversity setting */ + enum { + IQ_CAL_INACTIVE, + IQ_CAL_RUNNING, + IQ_CAL_DONE + } ah_bIQCalibration; /* IQ calibrate state */ + HAL_RFGAIN ah_rfgainState; /* RF gain calibrartion state */ + uint32_t ah_tx6PowerInHalfDbm; /* power output for 6Mb tx */ + uint32_t ah_staId1Defaults; /* STA_ID1 default settings */ + uint32_t ah_miscMode; /* MISC_MODE settings */ + uint32_t ah_rssiThr; /* RSSI_THR settings */ + HAL_BOOL ah_cwCalRequire; /* for ap51 */ + HAL_BOOL ah_tpcEnabled; /* per-packet tpc enabled */ + HAL_BOOL ah_phyPowerOn; /* PHY power state */ + HAL_BOOL ah_isHb63; /* cached HB63 check */ + uint32_t ah_macTPC; /* tpc register */ + uint32_t ah_beaconInterval; /* XXX */ + enum { + AUTO_32KHZ, /* use it if 32kHz crystal present */ + USE_32KHZ, /* do it regardless */ + DONT_USE_32KHZ, /* don't use it regardless */ + } ah_enable32kHzClock; /* whether to sleep at 32kHz */ + uint32_t ah_ofdmTxPower; + int16_t ah_txPowerIndexOffset; + /* + * Noise floor cal histogram support. + */ + struct ar5212NfCalHist ah_nfCalHist; + + u_int ah_slottime; /* user-specified slot time */ + u_int ah_acktimeout; /* user-specified ack timeout */ + u_int ah_ctstimeout; /* user-specified cts timeout */ + u_int ah_sifstime; /* user-specified sifs time */ + /* + * RF Silent handling; setup according to the EEPROM. + */ + uint32_t ah_gpioSelect; /* GPIO pin to use */ + uint32_t ah_polarity; /* polarity to disable RF */ + uint32_t ah_gpioBit; /* after init, prev value */ + /* + * ANI support. + */ + uint32_t ah_procPhyErr; /* Process Phy errs */ + HAL_BOOL ah_hasHwPhyCounters; /* Hardware has phy counters */ + struct ar5212AniParams ah_aniParams24; /* 2.4GHz parameters */ + struct ar5212AniParams ah_aniParams5; /* 5GHz parameters */ + struct ar5212AniState *ah_curani; /* cached last reference */ + struct ar5212AniState ah_ani[AH_MAXCHAN]; /* per-channel state */ + + /* AR5416 uses some of the AR5212 ANI code; these are the ANI methods */ + HAL_BOOL (*ah_aniControl) (struct ath_hal *, HAL_ANI_CMD cmd, int param); + + /* + * Transmit power state. Note these are maintained + * here so they can be retrieved by diagnostic tools. + */ + uint16_t *ah_pcdacTable; + u_int ah_pcdacTableSize; + uint16_t ah_ratesArray[37]; + + uint8_t ah_txTrigLev; /* current Tx trigger level */ + uint8_t ah_maxTxTrigLev; /* max tx trigger level */ + + /* + * Channel Tx, Rx, Rx Clear State + */ + uint32_t ah_cycleCount; + uint32_t ah_ctlBusy; + uint32_t ah_rxBusy; + uint32_t ah_txBusy; + uint32_t ah_rx_chainmask; + uint32_t ah_tx_chainmask; + + /* Used to return ANI statistics to the diagnostic API */ + HAL_ANI_STATS ext_ani_stats; +}; +#define AH5212(_ah) ((struct ath_hal_5212 *)(_ah)) + +/* + * IS_XXXX macros test the MAC version + * IS_RADXXX macros test the radio/RF version (matching both 2G-only and 2/5G) + * + * Some single chip radios have equivalent radio/RF (e.g. 5112) + * for those use IS_RADXXX_ANY macros. + */ +#define IS_2317(ah) \ + ((AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV1) || \ + (AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV2)) +#define IS_2316(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2415) +#define IS_2413(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2413 || IS_2316(ah)) +#define IS_5424(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_5424 || \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_5413 && \ + AH_PRIVATE(ah)->ah_macRev <= AR_SREV_D2PLUS_MS)) +#define IS_5413(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_5413 || IS_5424(ah)) +#define IS_2425(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2425) +#define IS_2417(ah) \ + ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_2417) +#define IS_HB63(ah) (AH5212(ah)->ah_isHb63 == AH_TRUE) + +#define AH_RADIO_MAJOR(ah) \ + (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) +#define AH_RADIO_MINOR(ah) \ + (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MINOR) +#define IS_RAD5111(ah) \ + (AH_RADIO_MAJOR(ah) == AR_RAD5111_SREV_MAJOR || \ + AH_RADIO_MAJOR(ah) == AR_RAD2111_SREV_MAJOR) +#define IS_RAD5112(ah) \ + (AH_RADIO_MAJOR(ah) == AR_RAD5112_SREV_MAJOR || \ + AH_RADIO_MAJOR(ah) == AR_RAD2112_SREV_MAJOR) +/* NB: does not include 5413 as Atheros' IS_5112 macro does */ +#define IS_RAD5112_ANY(ah) \ + (AR_RAD5112_SREV_MAJOR <= AH_RADIO_MAJOR(ah) && \ + AH_RADIO_MAJOR(ah) <= AR_RAD2413_SREV_MAJOR) +#define IS_RAD5112_REV1(ah) \ + (IS_RAD5112(ah) && \ + AH_RADIO_MINOR(ah) < (AR_RAD5112_SREV_2_0 & AR_RADIO_SREV_MINOR)) +#define IS_RADX112_REV2(ah) \ + (AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD5112_SREV_2_0 || \ + AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD2112_SREV_2_0 || \ + AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD2112_SREV_2_1 || \ + AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD5112_SREV_2_1) + +#define ar5212RfDetach(ah) do { \ + if (AH5212(ah)->ah_rfHal != AH_NULL) \ + AH5212(ah)->ah_rfHal->rfDetach(ah); \ +} while (0) +#define ar5212GetRfBank(ah, b) \ + AH5212(ah)->ah_rfHal->getRfBank(ah, b) + +/* + * Hack macros for Nala/San: 11b is handled + * using 11g; flip the channel flags to accomplish this. + */ +#define SAVE_CCK(_ah, _chan, _flag) do { \ + if ((IS_2425(_ah) || IS_2417(_ah)) && \ + (((_chan)->ic_flags) & IEEE80211_CHAN_CCK)) { \ + (_chan)->ic_flags &= ~IEEE80211_CHAN_CCK; \ + (_chan)->ic_flags |= IEEE80211_CHAN_DYN; \ + (_flag) = AH_TRUE; \ + } else \ + (_flag) = AH_FALSE; \ +} while (0) +#define RESTORE_CCK(_ah, _chan, _flag) do { \ + if ((_flag) && (IS_2425(_ah) || IS_2417(_ah))) { \ + (_chan)->ic_flags &= ~IEEE80211_CHAN_DYN; \ + (_chan)->ic_flags |= IEEE80211_CHAN_CCK; \ + } \ +} while (0) + +struct ath_hal; + +extern uint32_t ar5212GetRadioRev(struct ath_hal *ah); +extern void ar5212InitState(struct ath_hal_5212 *, uint16_t devid, HAL_SOFTC, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status); +extern void ar5212Detach(struct ath_hal *ah); +extern HAL_BOOL ar5212ChipTest(struct ath_hal *ah); +extern HAL_BOOL ar5212GetChannelEdges(struct ath_hal *ah, + uint16_t flags, uint16_t *low, uint16_t *high); +extern HAL_BOOL ar5212FillCapabilityInfo(struct ath_hal *ah); + +extern void ar5212SetBeaconTimers(struct ath_hal *ah, + const HAL_BEACON_TIMERS *); +extern void ar5212BeaconInit(struct ath_hal *ah, + uint32_t next_beacon, uint32_t beacon_period); +extern void ar5212ResetStaBeaconTimers(struct ath_hal *ah); +extern void ar5212SetStaBeaconTimers(struct ath_hal *ah, + const HAL_BEACON_STATE *); +extern uint64_t ar5212GetNextTBTT(struct ath_hal *); + +extern HAL_BOOL ar5212IsInterruptPending(struct ath_hal *ah); +extern HAL_BOOL ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *); +extern HAL_INT ar5212GetInterrupts(struct ath_hal *ah); +extern HAL_INT ar5212SetInterrupts(struct ath_hal *ah, HAL_INT ints); + +extern uint32_t ar5212GetKeyCacheSize(struct ath_hal *); +extern HAL_BOOL ar5212IsKeyCacheEntryValid(struct ath_hal *, uint16_t entry); +extern HAL_BOOL ar5212ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry); +extern HAL_BOOL ar5212SetKeyCacheEntryMac(struct ath_hal *, + uint16_t entry, const uint8_t *mac); +extern HAL_BOOL ar5212SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, + const HAL_KEYVAL *k, const uint8_t *mac, int xorKey); + +extern void ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac); +extern HAL_BOOL ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *); +extern void ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mac); +extern HAL_BOOL ar5212SetBssIdMask(struct ath_hal *, const uint8_t *); +extern HAL_BOOL ar5212EepromRead(struct ath_hal *, u_int off, uint16_t *data); +extern HAL_BOOL ar5212EepromWrite(struct ath_hal *, u_int off, uint16_t data); +extern HAL_BOOL ar5212SetRegulatoryDomain(struct ath_hal *ah, + uint16_t regDomain, HAL_STATUS *stats); +extern u_int ar5212GetWirelessModes(struct ath_hal *ah); +extern void ar5212EnableRfKill(struct ath_hal *); +extern HAL_BOOL ar5212GpioCfgOutput(struct ath_hal *, uint32_t gpio, + HAL_GPIO_MUX_TYPE); +extern HAL_BOOL ar5212GpioCfgInput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5212GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val); +extern uint32_t ar5212GpioGet(struct ath_hal *ah, uint32_t gpio); +extern void ar5212GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel); +extern void ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state); +extern void ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, + uint16_t assocId); +extern uint32_t ar5212GetTsf32(struct ath_hal *ah); +extern uint64_t ar5212GetTsf64(struct ath_hal *ah); +extern void ar5212SetTsf64(struct ath_hal *ah, uint64_t tsf64); +extern void ar5212ResetTsf(struct ath_hal *ah); +extern void ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *pSet); +extern uint32_t ar5212GetRandomSeed(struct ath_hal *ah); +extern HAL_BOOL ar5212DetectCardPresent(struct ath_hal *ah); +extern void ar5212EnableMibCounters(struct ath_hal *); +extern void ar5212DisableMibCounters(struct ath_hal *); +extern void ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats); +extern HAL_BOOL ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah); +extern uint32_t ar5212GetCurRssi(struct ath_hal *ah); +extern u_int ar5212GetDefAntenna(struct ath_hal *ah); +extern void ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna); +extern HAL_ANT_SETTING ar5212GetAntennaSwitch(struct ath_hal *); +extern HAL_BOOL ar5212SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); +extern HAL_BOOL ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah); +extern HAL_BOOL ar5212SetSifsTime(struct ath_hal *, u_int); +extern u_int ar5212GetSifsTime(struct ath_hal *); +extern HAL_BOOL ar5212SetSlotTime(struct ath_hal *, u_int); +extern u_int ar5212GetSlotTime(struct ath_hal *); +extern HAL_BOOL ar5212SetAckTimeout(struct ath_hal *, u_int); +extern u_int ar5212GetAckTimeout(struct ath_hal *); +extern HAL_BOOL ar5212SetAckCTSRate(struct ath_hal *, u_int); +extern u_int ar5212GetAckCTSRate(struct ath_hal *); +extern HAL_BOOL ar5212SetCTSTimeout(struct ath_hal *, u_int); +extern u_int ar5212GetCTSTimeout(struct ath_hal *); +extern HAL_BOOL ar5212SetDecompMask(struct ath_hal *, uint16_t, int); +void ar5212SetCoverageClass(struct ath_hal *, uint8_t, int); +extern void ar5212SetPCUConfig(struct ath_hal *); +extern HAL_BOOL ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode); +extern void ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode); +extern void ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode); +extern int16_t ar5212GetNfAdjust(struct ath_hal *, + const HAL_CHANNEL_INTERNAL *); +extern void ar5212SetCompRegs(struct ath_hal *ah); +extern HAL_STATUS ar5212GetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, + uint32_t, uint32_t *); +extern HAL_BOOL ar5212SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, + uint32_t, uint32_t, HAL_STATUS *); +extern HAL_BOOL ar5212GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); +extern HAL_STATUS ar5212SetQuiet(struct ath_hal *ah, uint32_t period, + uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag); +extern HAL_BOOL ar5212GetMibCycleCounts(struct ath_hal *, + HAL_SURVEY_SAMPLE *); +extern void ar5212SetChainMasks(struct ath_hal *, uint32_t, uint32_t); + +extern HAL_BOOL ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, + int setChip); +extern HAL_POWER_MODE ar5212GetPowerMode(struct ath_hal *ah); +extern HAL_BOOL ar5212GetPowerStatus(struct ath_hal *ah); + +extern uint32_t ar5212GetRxDP(struct ath_hal *ath, HAL_RX_QUEUE); +extern void ar5212SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE); +extern void ar5212EnableReceive(struct ath_hal *ah); +extern HAL_BOOL ar5212StopDmaReceive(struct ath_hal *ah); +extern void ar5212StartPcuReceive(struct ath_hal *ah); +extern void ar5212StopPcuReceive(struct ath_hal *ah); +extern void ar5212SetMulticastFilter(struct ath_hal *ah, + uint32_t filter0, uint32_t filter1); +extern HAL_BOOL ar5212ClrMulticastFilterIndex(struct ath_hal *, uint32_t ix); +extern HAL_BOOL ar5212SetMulticastFilterIndex(struct ath_hal *, uint32_t ix); +extern uint32_t ar5212GetRxFilter(struct ath_hal *ah); +extern void ar5212SetRxFilter(struct ath_hal *ah, uint32_t bits); +extern HAL_BOOL ar5212SetupRxDesc(struct ath_hal *, + struct ath_desc *, uint32_t size, u_int flags); +extern HAL_STATUS ar5212ProcRxDesc(struct ath_hal *ah, struct ath_desc *, + uint32_t, struct ath_desc *, uint64_t, + struct ath_rx_status *); + +extern HAL_BOOL ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode, + struct ieee80211_channel *chan, HAL_BOOL bChannelChange, + HAL_RESET_TYPE, HAL_STATUS *status); +extern HAL_BOOL ar5212SetChannel(struct ath_hal *, + const struct ieee80211_channel *); +extern void ar5212SetOperatingMode(struct ath_hal *ah, int opmode); +extern HAL_BOOL ar5212PhyDisable(struct ath_hal *ah); +extern HAL_BOOL ar5212Disable(struct ath_hal *ah); +extern HAL_BOOL ar5212ChipReset(struct ath_hal *ah, + const struct ieee80211_channel *); +extern HAL_BOOL ar5212PerCalibration(struct ath_hal *ah, + struct ieee80211_channel *chan, HAL_BOOL *isIQdone); +extern HAL_BOOL ar5212PerCalibrationN(struct ath_hal *ah, + struct ieee80211_channel *chan, u_int chainMask, + HAL_BOOL longCal, HAL_BOOL *isCalDone); +extern HAL_BOOL ar5212ResetCalValid(struct ath_hal *ah, + const struct ieee80211_channel *); +extern int16_t ar5212GetNoiseFloor(struct ath_hal *ah); +extern void ar5212InitNfCalHistBuffer(struct ath_hal *); +extern int16_t ar5212GetNfHistMid(const int16_t calData[]); +extern void ar5212SetSpurMitigation(struct ath_hal *, + const struct ieee80211_channel *); +extern HAL_BOOL ar5212SetAntennaSwitchInternal(struct ath_hal *ah, + HAL_ANT_SETTING settings, const struct ieee80211_channel *); +extern HAL_BOOL ar5212SetTxPowerLimit(struct ath_hal *ah, uint32_t limit); +extern HAL_BOOL ar5212GetChipPowerLimits(struct ath_hal *ah, + struct ieee80211_channel *chan); +extern void ar5212InitializeGainValues(struct ath_hal *); +extern HAL_RFGAIN ar5212GetRfgain(struct ath_hal *ah); +extern void ar5212RequestRfgain(struct ath_hal *); + +extern HAL_BOOL ar5212UpdateTxTrigLevel(struct ath_hal *, + HAL_BOOL IncTrigLevel); +extern HAL_BOOL ar5212SetTxQueueProps(struct ath_hal *ah, int q, + const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ar5212GetTxQueueProps(struct ath_hal *ah, int q, + HAL_TXQ_INFO *qInfo); +extern int ar5212SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo); +extern HAL_BOOL ar5212ReleaseTxQueue(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5212ResetTxQueue(struct ath_hal *ah, u_int q); +extern uint32_t ar5212GetTxDP(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5212SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp); +extern HAL_BOOL ar5212StartTxDma(struct ath_hal *ah, u_int q); +extern uint32_t ar5212NumTxPending(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5212StopTxDma(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5212SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, + u_int txRate0, u_int txTries0, + u_int keyIx, u_int antMode, u_int flags, + u_int rtsctsRate, u_int rtsctsDuration, + u_int compicvLen, u_int compivLen, u_int comp); +extern HAL_BOOL ar5212SetupXTxDesc(struct ath_hal *, struct ath_desc *, + u_int txRate1, u_int txRetries1, + u_int txRate2, u_int txRetries2, + u_int txRate3, u_int txRetries3); +extern HAL_BOOL ar5212FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, + HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, + u_int descId, u_int qcuId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0); +extern HAL_STATUS ar5212ProcTxDesc(struct ath_hal *ah, + struct ath_desc *, struct ath_tx_status *); +extern void ar5212GetTxIntrQueue(struct ath_hal *ah, uint32_t *); +extern void ar5212IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); +extern HAL_BOOL ar5212GetTxCompletionRates(struct ath_hal *ah, + const struct ath_desc *ds0, int *rates, int *tries); +extern void ar5212SetTxDescLink(struct ath_hal *ah, void *ds, + uint32_t link); +extern void ar5212GetTxDescLink(struct ath_hal *ah, void *ds, + uint32_t *link); +extern void ar5212GetTxDescLinkPtr(struct ath_hal *ah, void *ds, + uint32_t **linkptr); + +extern const HAL_RATE_TABLE *ar5212GetRateTable(struct ath_hal *, u_int mode); + +extern void ar5212AniAttach(struct ath_hal *, const struct ar5212AniParams *, + const struct ar5212AniParams *, HAL_BOOL ena); +extern void ar5212AniDetach(struct ath_hal *); +extern struct ar5212AniState *ar5212AniGetCurrentState(struct ath_hal *); +extern HAL_ANI_STATS *ar5212AniGetCurrentStats(struct ath_hal *); +extern HAL_BOOL ar5212AniControl(struct ath_hal *, HAL_ANI_CMD cmd, int param); +extern HAL_BOOL ar5212AniSetParams(struct ath_hal *, + const struct ar5212AniParams *, const struct ar5212AniParams *); +struct ath_rx_status; +extern void ar5212AniPhyErrReport(struct ath_hal *ah, + const struct ath_rx_status *rs); +extern void ar5212ProcessMibIntr(struct ath_hal *, const HAL_NODE_STATS *); +extern void ar5212RxMonitor(struct ath_hal *, const HAL_NODE_STATS *, + const struct ieee80211_channel *); +extern void ar5212AniPoll(struct ath_hal *, const struct ieee80211_channel *); +extern void ar5212AniReset(struct ath_hal *, const struct ieee80211_channel *, + HAL_OPMODE, int); + +extern HAL_BOOL ar5212IsNFCalInProgress(struct ath_hal *ah); +extern HAL_BOOL ar5212WaitNFCalComplete(struct ath_hal *ah, int i); +extern void ar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); +extern HAL_BOOL ar5212GetDfsDefaultThresh(struct ath_hal *ah, + HAL_PHYERR_PARAM *pe); +extern void ar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); +extern HAL_BOOL ar5212ProcessRadarEvent(struct ath_hal *ah, + struct ath_rx_status *rxs, uint64_t fulltsf, const char *buf, + HAL_DFS_EVENT *event); +extern HAL_BOOL ar5212IsFastClockEnabled(struct ath_hal *ah); +extern uint32_t ar5212Get11nExtBusy(struct ath_hal *ah); + +#endif /* _ATH_AR5212_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212.ini b/sys/external/isc/atheros_hal/dist/ar5212/ar5212.ini new file mode 100644 index 0000000..608f91f --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212.ini @@ -0,0 +1,2171 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +/* Auto Generated PCI Register Writes. Created: 09/01/04 */ + +#ifdef AH_5212_COMMON +static const uint32_t ar5212Modes[][6] = { + { 0x00001040, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f }, + { 0x00001030, 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 }, + { 0x00008014, 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 }, + { 0x00009804, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e }, + { 0x00009844, 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 }, + { 0x00009860, 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 }, + { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, + { 0x00009918, 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 }, + { 0x00009924, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 }, +}; +#endif /* AH_5212_COMMON */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Modes_5111[][6] = { + { 0x00000030, 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 }, + { 0x0000801c, 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b }, + { 0x00009848, 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 }, + { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 }, + { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e }, + { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 }, + { 0x00009914, 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 }, + { 0x00009944, 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 }, + { 0x0000a20c, 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Modes_5112[][6] = { + { 0x00000030, 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 }, + { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b }, + { 0x00009848, 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 }, + { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 }, + { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e }, + { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 }, + { 0x00009944, 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 }, + { 0x0000a204, 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 }, + { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 }, + { 0x0000a20c, 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Modes_2413[][6] = { + { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 }, + { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 }, + { 0x00009838, 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a }, + { 0x00009848, 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 }, + { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da }, + { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e }, + { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 }, + { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 }, + { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 }, + { 0x0000a20c, 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Modes_2316[][6] = { + { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 }, + { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 }, + { 0x00009838, 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a }, + { 0x00009848, 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 }, + { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da }, + { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e }, + { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 }, + { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 }, + { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 }, + { 0x0000a20c, 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Modes_5413[][6] = { + { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 }, + { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b }, + { 0x00009848, 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 }, + { 0x00009850, 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da }, + { 0x00009858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 }, + { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 }, + { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 }, + { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f }, + { 0x0000a314, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b }, + { 0x0000a318, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a }, + { 0x0000a31c, 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b }, + { 0x0000a320, 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f }, + { 0x0000a324, 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f }, + { 0x0000a328, 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f }, + { 0x0000a32c, 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f }, + { 0x0000a330, 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f }, + { 0x0000a334, 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Modes_2425[][6] = { + { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 }, + { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf }, + { 0x00009804, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b }, + { 0x00009844, 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 }, + { 0x00009848, 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 }, + { 0x00009850, 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da }, + { 0x00009858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 }, + { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 }, + { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 }, + { 0x0000a20c, 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a }, + { 0x0000a324, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf }, + { 0x0000a328, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf }, + { 0x0000a32c, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf }, + { 0x0000a330, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf }, + { 0x0000a334, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_COMMON +static const uint32_t ar5212Common[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008020, 0x00000000 }, + { 0x00008024, 0x00000000 }, + { 0x00008028, 0x00000030 }, + { 0x0000802c, 0x0007ffff }, + { 0x00008030, 0x01ffffff }, + { 0x00008034, 0x00000031 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x00000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e1c }, + { 0x000080d4, 0x0002aaaa }, + { 0x000080d8, 0x02005555 }, + { 0x000080dc, 0x00000000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x00000000 }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00000088 }, + { 0x00008700, 0x00000000 }, + { 0x00008704, 0x0000008c }, + { 0x00008708, 0x000000e4 }, + { 0x0000870c, 0x000002d5 }, + { 0x00008710, 0x00000000 }, + { 0x00008714, 0x00000000 }, + { 0x00008718, 0x000000a0 }, + { 0x0000871c, 0x000001c9 }, + { 0x00008720, 0x0000002c }, + { 0x00008724, 0x0000002c }, + { 0x00008728, 0x00000030 }, + { 0x0000872c, 0x0000003c }, + { 0x00008730, 0x0000002c }, + { 0x00008734, 0x0000002c }, + { 0x00008738, 0x00000030 }, + { 0x0000873c, 0x0000003c }, + { 0x00008740, 0x00000000 }, + { 0x00008744, 0x00000000 }, + { 0x00008748, 0x00000000 }, + { 0x0000874c, 0x00000000 }, + { 0x00008750, 0x00000000 }, + { 0x00008754, 0x00000000 }, + { 0x00008758, 0x00000000 }, + { 0x0000875c, 0x00000000 }, + { 0x00008760, 0x000000d5 }, + { 0x00008764, 0x000000df }, + { 0x00008768, 0x00000102 }, + { 0x0000876c, 0x0000013a }, + { 0x00008770, 0x00000075 }, + { 0x00008774, 0x0000007f }, + { 0x00008778, 0x000000a2 }, + { 0x0000877c, 0x00000000 }, + { 0x00008100, 0x00010002 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x000000c0 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008114, 0x00000000 }, + { 0x000087c0, 0x03020100 }, + { 0x000087c4, 0x07060504 }, + { 0x000087c8, 0x0b0a0908 }, + { 0x000087cc, 0x0f0e0d0c }, + { 0x000087d0, 0x13121110 }, + { 0x000087d4, 0x17161514 }, + { 0x000087d8, 0x1b1a1918 }, + { 0x000087dc, 0x1f1e1d1c }, + { 0x000087e0, 0x03020100 }, + { 0x000087e4, 0x07060504 }, + { 0x000087e8, 0x0b0a0908 }, + { 0x000087ec, 0x0f0e0d0c }, + { 0x000087f0, 0x13121110 }, + { 0x000087f4, 0x17161514 }, + { 0x000087f8, 0x1b1a1918 }, + { 0x000087fc, 0x1f1e1d1c }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d28e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x00009840, 0x206a017a }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00800000 }, + { 0x00009910, 0x00000001 }, + { 0x0000991c, 0x00000c80 }, + { 0x00009920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x0000003f }, + { 0x00009948, 0x9280b212 }, + { 0x00009954, 0x5d50e188 }, + { 0x0000995c, 0x004b6a8e }, + { 0x00009968, 0x000003ce }, + { 0x00009970, 0x192fb515 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x0000a210, 0x00806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x00009b00, 0x00000000 }, + { 0x00009b28, 0x0000000c }, + { 0x00009b38, 0x00000012 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b9c, 0x00000033 }, +}; +#endif /* AH_5212_COMMON */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Common_5111[][2] = { + { 0x00001230, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000982c, 0x00022ffe }, + { 0x0000983c, 0x00020100 }, + { 0x0000984c, 0x1284613c }, + { 0x00009930, 0x00004883 }, + { 0x00009940, 0x00000004 }, + { 0x00009958, 0x000000ff }, + { 0x00009974, 0x00000000 }, + { 0x000099f8, 0x00000018 }, + { 0x0000a204, 0x00000000 }, + { 0x0000a208, 0xd03e6788 }, + { 0x0000a228, 0x000001b5 }, + { 0x0000a23c, 0x13c889af }, + { 0x00009b04, 0x00000020 }, + { 0x00009b08, 0x00000010 }, + { 0x00009b0c, 0x00000030 }, + { 0x00009b10, 0x00000008 }, + { 0x00009b14, 0x00000028 }, + { 0x00009b18, 0x00000004 }, + { 0x00009b1c, 0x00000024 }, + { 0x00009b20, 0x00000014 }, + { 0x00009b24, 0x00000034 }, + { 0x00009b2c, 0x0000002c }, + { 0x00009b30, 0x00000002 }, + { 0x00009b34, 0x00000022 }, + { 0x00009b3c, 0x00000032 }, + { 0x00009b40, 0x0000000a }, + { 0x00009b44, 0x0000002a }, + { 0x00009b48, 0x00000006 }, + { 0x00009b4c, 0x00000026 }, + { 0x00009b50, 0x00000016 }, + { 0x00009b54, 0x00000036 }, + { 0x00009b58, 0x0000000e }, + { 0x00009b5c, 0x0000002e }, + { 0x00009b60, 0x00000001 }, + { 0x00009b68, 0x00000011 }, + { 0x00009b6c, 0x00000031 }, + { 0x00009b70, 0x00000009 }, + { 0x00009b74, 0x00000029 }, + { 0x00009b78, 0x00000005 }, + { 0x00009b7c, 0x00000025 }, + { 0x00009b80, 0x00000015 }, + { 0x00009b84, 0x00000035 }, + { 0x00009b88, 0x0000000d }, + { 0x00009b90, 0x00000003 }, + { 0x00009b94, 0x00000023 }, + { 0x00009b98, 0x00000013 }, + { 0x00009ba0, 0x0000000b }, + { 0x00009ba4, 0x0000002b }, + { 0x00009ba8, 0x0000002b }, + { 0x00009bac, 0x0000002b }, + { 0x00009bb0, 0x0000002b }, + { 0x00009bb4, 0x0000002b }, + { 0x00009bb8, 0x0000002b }, + { 0x00009bbc, 0x0000002b }, + { 0x00009bc0, 0x0000002b }, + { 0x00009bc4, 0x0000002b }, + { 0x00009bc8, 0x0000002b }, + { 0x00009bcc, 0x0000002b }, + { 0x00009bd0, 0x0000002b }, + { 0x00009bd4, 0x0000002b }, + { 0x00009bd8, 0x0000002b }, + { 0x00009bdc, 0x0000002b }, + { 0x00009be0, 0x0000002b }, + { 0x00009be4, 0x0000002b }, + { 0x00009be8, 0x0000002b }, + { 0x00009bec, 0x0000002b }, + { 0x00009bf0, 0x0000002b }, + { 0x00009bf4, 0x0000002b }, + { 0x00009bf8, 0x00000002 }, + { 0x00009bfc, 0x00000016 }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Common_5112[][2] = { + { 0x00001230, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000982c, 0x00022ffe }, + { 0x0000983c, 0x00020100 }, + { 0x0000984c, 0x1284613c }, + { 0x00009930, 0x00004882 }, + { 0x00009940, 0x00000004 }, + { 0x00009958, 0x000000ff }, + { 0x00009974, 0x00000000 }, + { 0x0000a228, 0x000001b5 }, + { 0x0000a23c, 0x13c889af }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Common_2413[][2] = { + { 0x00001230, 0x000003e0 }, + { 0x00008060, 0x0000000f }, + { 0x00008118, 0x00000000 }, + { 0x0000811c, 0x00000000 }, + { 0x00008120, 0x00000000 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008140, 0x800000a8 }, + { 0x00008144, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x1284233c }, + { 0x00009870, 0x0000001f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x0000000e }, + { 0x00009958, 0x000000ff }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x02800000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099f0, 0x0000000c }, + { 0x000099f4, 0x000000ff }, + { 0x000099f8, 0x00000014 }, + { 0x0000a228, 0x000009b5 }, + { 0x0000a23c, 0x93c889af }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0x5f690f01 }, + { 0x0000a264, 0x00418a11 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0c30c16a }, + { 0x0000a270, 0x00820820 }, + { 0x0000a274, 0x001b7caa }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a300, 0x18010000 }, + { 0x0000a304, 0x30032602 }, + { 0x0000a308, 0x48073e06 }, + { 0x0000a30c, 0x560b4c0a }, + { 0x0000a310, 0x641a600f }, + { 0x0000a314, 0x784f6e1b }, + { 0x0000a318, 0x868f7c5a }, + { 0x0000a31c, 0x8ecf865b }, + { 0x0000a320, 0x9d4f970f }, + { 0x0000a324, 0xa5cfa18f }, + { 0x0000a328, 0xb55faf1f }, + { 0x0000a32c, 0xbddfb99f }, + { 0x0000a330, 0xcd7fc73f }, + { 0x0000a334, 0xd5ffd1bf }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000a35c, 0x066c420f }, + { 0x0000a360, 0x0f282207 }, + { 0x0000a364, 0x17601685 }, + { 0x0000a368, 0x1f801104 }, + { 0x0000a36c, 0x37a00c03 }, + { 0x0000a370, 0x3fc40883 }, + { 0x0000a374, 0x57c00803 }, + { 0x0000a378, 0x5fd80682 }, + { 0x0000a37c, 0x7fe00482 }, + { 0x0000a380, 0x7f3c7bba }, + { 0x0000a384, 0xf3307ff0 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Common_2316[][2] = { + { 0x00001230, 0x000003e0 }, + { 0x00008060, 0x0000000f }, + { 0x00008118, 0x00000000 }, + { 0x0000811c, 0x00000000 }, + { 0x00008120, 0x00000000 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008140, 0x800000a8 }, + { 0x00008144, 0x00000000 }, + { 0x00009808, 0x00004000 }, + { 0x0000982c, 0x0000a000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x1284233c }, + { 0x00009870, 0x0000001f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x0000000e }, + { 0x00009958, 0x000000ff }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x02800000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099f0, 0x0000000c }, + { 0x000099f4, 0x000000ff }, + { 0x000099f8, 0x00000014 }, + { 0x0000a228, 0x000009b5 }, + { 0x0000a23c, 0x93c889af }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0x5f690f01 }, + { 0x0000a264, 0x00418a11 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0c30c16a }, + { 0x0000a270, 0x00820820 }, + { 0x0000a274, 0x081b7caa }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a300, 0x18010000 }, + { 0x0000a304, 0x30032602 }, + { 0x0000a308, 0x48073e06 }, + { 0x0000a30c, 0x560b4c0a }, + { 0x0000a310, 0x641a600f }, + { 0x0000a314, 0x784f6e1b }, + { 0x0000a318, 0x868f7c5a }, + { 0x0000a31c, 0x8ecf865b }, + { 0x0000a320, 0x9d4f970f }, + { 0x0000a324, 0xa5cfa18f }, + { 0x0000a328, 0xb55faf1f }, + { 0x0000a32c, 0xbddfb99f }, + { 0x0000a330, 0xcd7fc73f }, + { 0x0000a334, 0xd5ffd1bf }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000a35c, 0x066c420f }, + { 0x0000a360, 0x0f282207 }, + { 0x0000a364, 0x17601685 }, + { 0x0000a368, 0x1f801104 }, + { 0x0000a36c, 0x37a00c03 }, + { 0x0000a370, 0x3fc40883 }, + { 0x0000a374, 0x57c00803 }, + { 0x0000a378, 0x5fd80682 }, + { 0x0000a37c, 0x7fe00482 }, + { 0x0000a380, 0x7f3c7bba }, + { 0x0000a384, 0xf3307ff0 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Common_5413[][2] = { + { 0x00001230, 0x000003e0 }, + { 0x00004068, 0x00000010 }, + { 0x00008060, 0x0000000f }, + { 0x0000809c, 0x00000000 }, + { 0x000080a0, 0x00000000 }, + { 0x00008118, 0x00000000 }, + { 0x0000811c, 0x00000000 }, + { 0x00008120, 0x00000000 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008140, 0x800003f9 }, + { 0x00008144, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x1284233c }, + { 0x00009870, 0x0000001f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x0000000e }, + { 0x00009958, 0x00081fff }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x02800000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099f0, 0x0000000c }, + { 0x000099f4, 0x000000ff }, + { 0x000099f8, 0x00000014 }, + { 0x0000a228, 0x000009b5 }, + { 0x0000a23c, 0x93c889af }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0x5f690f01 }, + { 0x0000a264, 0x00418a11 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0c30c16a }, + { 0x0000a270, 0x00820820 }, + { 0x0000a274, 0x081b7caa }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000a35c, 0x066c420f }, + { 0x0000a360, 0x0f282207 }, + { 0x0000a364, 0x17601685 }, + { 0x0000a368, 0x1f801104 }, + { 0x0000a36c, 0x37a00c03 }, + { 0x0000a370, 0x3fc40883 }, + { 0x0000a374, 0x57c00803 }, + { 0x0000a378, 0x5fd80682 }, + { 0x0000a37c, 0x7fe00482 }, + { 0x0000a380, 0x7f3c7bba }, + { 0x0000a384, 0xf3307ff0 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Common_2425[][2] = { + { 0x00001230, 0x000003e0 }, + { 0x00008060, 0x0000000f }, + { 0x0000809c, 0x00000000 }, + { 0x000080a0, 0x00000000 }, + { 0x00008118, 0x00000000 }, + { 0x0000811c, 0x00000000 }, + { 0x00008120, 0x00000000 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008140, 0x800003f9 }, + { 0x00008144, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x1284233c }, + { 0x00009870, 0x0000001f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x0000000e }, + { 0x00009958, 0x00081fff }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x02800000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099dc, 0xfebadbe8 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099f0, 0x0000000c }, + { 0x000099f4, 0x000000ff }, + { 0x000099f8, 0x00000014 }, + { 0x0000a228, 0x000009b5 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x93c889af }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0x5f690f01 }, + { 0x0000a264, 0x00418a11 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0c30c166 }, + { 0x0000a270, 0x00820820 }, + { 0x0000a274, 0x081a3caa }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a300, 0x16010000 }, + { 0x0000a304, 0x2c032402 }, + { 0x0000a308, 0x48433e42 }, + { 0x0000a30c, 0x5a0f500b }, + { 0x0000a310, 0x6c4b624a }, + { 0x0000a314, 0x7e8b748a }, + { 0x0000a318, 0x96cf8ccb }, + { 0x0000a31c, 0xa34f9d0f }, + { 0x0000a320, 0xa7cfa58f }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000a35c, 0x066c420f }, + { 0x0000a360, 0x0f282207 }, + { 0x0000a364, 0x17601685 }, + { 0x0000a368, 0x1f801104 }, + { 0x0000a36c, 0x37a00c03 }, + { 0x0000a370, 0x3fc40883 }, + { 0x0000a374, 0x57c00803 }, + { 0x0000a378, 0x5fd80682 }, + { 0x0000a37c, 0x7fe00482 }, + { 0x0000a380, 0x7f3c7bba }, + { 0x0000a384, 0xf3307ff0 }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Bank0_5111[][6] = { + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 }, + { 0x0000989c, 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd }, + { 0x000098d4, 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 }, +}; + +static const uint32_t ar5212BB_RfGain_5111[][3] = { + { 0x00009a00, 0x000001a9, 0x00000000 }, + { 0x00009a04, 0x000001e9, 0x00000040 }, + { 0x00009a08, 0x00000029, 0x00000080 }, + { 0x00009a0c, 0x00000069, 0x00000150 }, + { 0x00009a10, 0x00000199, 0x00000190 }, + { 0x00009a14, 0x000001d9, 0x000001d0 }, + { 0x00009a18, 0x00000019, 0x00000010 }, + { 0x00009a1c, 0x00000059, 0x00000044 }, + { 0x00009a20, 0x00000099, 0x00000084 }, + { 0x00009a24, 0x000001a5, 0x00000148 }, + { 0x00009a28, 0x000001e5, 0x00000188 }, + { 0x00009a2c, 0x00000025, 0x000001c8 }, + { 0x00009a30, 0x000001c8, 0x00000014 }, + { 0x00009a34, 0x00000008, 0x00000042 }, + { 0x00009a38, 0x00000048, 0x00000082 }, + { 0x00009a3c, 0x00000088, 0x00000178 }, + { 0x00009a40, 0x00000198, 0x000001b8 }, + { 0x00009a44, 0x000001d8, 0x000001f8 }, + { 0x00009a48, 0x00000018, 0x00000012 }, + { 0x00009a4c, 0x00000058, 0x00000052 }, + { 0x00009a50, 0x00000098, 0x00000092 }, + { 0x00009a54, 0x000001a4, 0x0000017c }, + { 0x00009a58, 0x000001e4, 0x000001bc }, + { 0x00009a5c, 0x00000024, 0x000001fc }, + { 0x00009a60, 0x00000064, 0x0000000a }, + { 0x00009a64, 0x000000a4, 0x0000004a }, + { 0x00009a68, 0x000000e4, 0x0000008a }, + { 0x00009a6c, 0x0000010a, 0x0000015a }, + { 0x00009a70, 0x0000014a, 0x0000019a }, + { 0x00009a74, 0x0000018a, 0x000001da }, + { 0x00009a78, 0x000001ca, 0x0000000e }, + { 0x00009a7c, 0x0000000a, 0x0000004e }, + { 0x00009a80, 0x0000004a, 0x0000008e }, + { 0x00009a84, 0x0000008a, 0x0000015e }, + { 0x00009a88, 0x000001ba, 0x0000019e }, + { 0x00009a8c, 0x000001fa, 0x000001de }, + { 0x00009a90, 0x0000003a, 0x00000009 }, + { 0x00009a94, 0x0000007a, 0x00000049 }, + { 0x00009a98, 0x00000186, 0x00000089 }, + { 0x00009a9c, 0x000001c6, 0x00000179 }, + { 0x00009aa0, 0x00000006, 0x000001b9 }, + { 0x00009aa4, 0x00000046, 0x000001f9 }, + { 0x00009aa8, 0x00000086, 0x00000039 }, + { 0x00009aac, 0x000000c6, 0x00000079 }, + { 0x00009ab0, 0x000000c6, 0x000000b9 }, + { 0x00009ab4, 0x000000c6, 0x000001bd }, + { 0x00009ab8, 0x000000c6, 0x000001fd }, + { 0x00009abc, 0x000000c6, 0x0000003d }, + { 0x00009ac0, 0x000000c6, 0x0000007d }, + { 0x00009ac4, 0x000000c6, 0x000000bd }, + { 0x00009ac8, 0x000000c6, 0x000000fd }, + { 0x00009acc, 0x000000c6, 0x000000fd }, + { 0x00009ad0, 0x000000c6, 0x000000fd }, + { 0x00009ad4, 0x000000c6, 0x000000fd }, + { 0x00009ad8, 0x000000c6, 0x000000fd }, + { 0x00009adc, 0x000000c6, 0x000000fd }, + { 0x00009ae0, 0x000000c6, 0x000000fd }, + { 0x00009ae4, 0x000000c6, 0x000000fd }, + { 0x00009ae8, 0x000000c6, 0x000000fd }, + { 0x00009aec, 0x000000c6, 0x000000fd }, + { 0x00009af0, 0x000000c6, 0x000000fd }, + { 0x00009af4, 0x000000c6, 0x000000fd }, + { 0x00009af8, 0x000000c6, 0x000000fd }, + { 0x00009afc, 0x000000c6, 0x000000fd }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212BB_RfGain_5112[][3] = { + { 0x00009a00, 0x00000007, 0x00000007 }, + { 0x00009a04, 0x00000047, 0x00000047 }, + { 0x00009a08, 0x00000087, 0x00000087 }, + { 0x00009a0c, 0x000001a0, 0x000001a0 }, + { 0x00009a10, 0x000001e0, 0x000001e0 }, + { 0x00009a14, 0x00000020, 0x00000020 }, + { 0x00009a18, 0x00000060, 0x00000060 }, + { 0x00009a1c, 0x000001a1, 0x000001a1 }, + { 0x00009a20, 0x000001e1, 0x000001e1 }, + { 0x00009a24, 0x00000021, 0x00000021 }, + { 0x00009a28, 0x00000061, 0x00000061 }, + { 0x00009a2c, 0x00000162, 0x00000162 }, + { 0x00009a30, 0x000001a2, 0x000001a2 }, + { 0x00009a34, 0x000001e2, 0x000001e2 }, + { 0x00009a38, 0x00000022, 0x00000022 }, + { 0x00009a3c, 0x00000062, 0x00000062 }, + { 0x00009a40, 0x00000163, 0x00000163 }, + { 0x00009a44, 0x000001a3, 0x000001a3 }, + { 0x00009a48, 0x000001e3, 0x000001e3 }, + { 0x00009a4c, 0x00000023, 0x00000023 }, + { 0x00009a50, 0x00000063, 0x00000063 }, + { 0x00009a54, 0x00000184, 0x00000184 }, + { 0x00009a58, 0x000001c4, 0x000001c4 }, + { 0x00009a5c, 0x00000004, 0x00000004 }, + { 0x00009a60, 0x000001ea, 0x0000000b }, + { 0x00009a64, 0x0000002a, 0x0000004b }, + { 0x00009a68, 0x0000006a, 0x0000008b }, + { 0x00009a6c, 0x000000aa, 0x000001ac }, + { 0x00009a70, 0x000001ab, 0x000001ec }, + { 0x00009a74, 0x000001eb, 0x0000002c }, + { 0x00009a78, 0x0000002b, 0x00000012 }, + { 0x00009a7c, 0x0000006b, 0x00000052 }, + { 0x00009a80, 0x000000ab, 0x00000092 }, + { 0x00009a84, 0x000001ac, 0x00000193 }, + { 0x00009a88, 0x000001ec, 0x000001d3 }, + { 0x00009a8c, 0x0000002c, 0x00000013 }, + { 0x00009a90, 0x0000003a, 0x00000053 }, + { 0x00009a94, 0x0000007a, 0x00000093 }, + { 0x00009a98, 0x000000ba, 0x00000194 }, + { 0x00009a9c, 0x000001bb, 0x000001d4 }, + { 0x00009aa0, 0x000001fb, 0x00000014 }, + { 0x00009aa4, 0x0000003b, 0x0000003a }, + { 0x00009aa8, 0x0000007b, 0x0000007a }, + { 0x00009aac, 0x000000bb, 0x000000ba }, + { 0x00009ab0, 0x000001bc, 0x000001bb }, + { 0x00009ab4, 0x000001fc, 0x000001fb }, + { 0x00009ab8, 0x0000003c, 0x0000003b }, + { 0x00009abc, 0x0000007c, 0x0000007b }, + { 0x00009ac0, 0x000000bc, 0x000000bb }, + { 0x00009ac4, 0x000000fc, 0x000001bc }, + { 0x00009ac8, 0x000000fc, 0x000001fc }, + { 0x00009acc, 0x000000fc, 0x0000003c }, + { 0x00009ad0, 0x000000fc, 0x0000007c }, + { 0x00009ad4, 0x000000fc, 0x000000bc }, + { 0x00009ad8, 0x000000fc, 0x000000fc }, + { 0x00009adc, 0x000000fc, 0x000000fc }, + { 0x00009ae0, 0x000000fc, 0x000000fc }, + { 0x00009ae4, 0x000000fc, 0x000000fc }, + { 0x00009ae8, 0x000000fc, 0x000000fc }, + { 0x00009aec, 0x000000fc, 0x000000fc }, + { 0x00009af0, 0x000000fc, 0x000000fc }, + { 0x00009af4, 0x000000fc, 0x000000fc }, + { 0x00009af8, 0x000000fc, 0x000000fc }, + { 0x00009afc, 0x000000fc, 0x000000fc }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212BB_RfGain_2413[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000040 }, + { 0x00009a08, 0x00000000, 0x00000080 }, + { 0x00009a0c, 0x00000000, 0x00000181 }, + { 0x00009a10, 0x00000000, 0x000001c1 }, + { 0x00009a14, 0x00000000, 0x00000001 }, + { 0x00009a18, 0x00000000, 0x00000041 }, + { 0x00009a1c, 0x00000000, 0x00000081 }, + { 0x00009a20, 0x00000000, 0x00000168 }, + { 0x00009a24, 0x00000000, 0x000001a8 }, + { 0x00009a28, 0x00000000, 0x000001e8 }, + { 0x00009a2c, 0x00000000, 0x00000028 }, + { 0x00009a30, 0x00000000, 0x00000068 }, + { 0x00009a34, 0x00000000, 0x00000189 }, + { 0x00009a38, 0x00000000, 0x000001c9 }, + { 0x00009a3c, 0x00000000, 0x00000009 }, + { 0x00009a40, 0x00000000, 0x00000049 }, + { 0x00009a44, 0x00000000, 0x00000089 }, + { 0x00009a48, 0x00000000, 0x00000190 }, + { 0x00009a4c, 0x00000000, 0x000001d0 }, + { 0x00009a50, 0x00000000, 0x00000010 }, + { 0x00009a54, 0x00000000, 0x00000050 }, + { 0x00009a58, 0x00000000, 0x00000090 }, + { 0x00009a5c, 0x00000000, 0x00000191 }, + { 0x00009a60, 0x00000000, 0x000001d1 }, + { 0x00009a64, 0x00000000, 0x00000011 }, + { 0x00009a68, 0x00000000, 0x00000051 }, + { 0x00009a6c, 0x00000000, 0x00000091 }, + { 0x00009a70, 0x00000000, 0x00000178 }, + { 0x00009a74, 0x00000000, 0x000001b8 }, + { 0x00009a78, 0x00000000, 0x000001f8 }, + { 0x00009a7c, 0x00000000, 0x00000038 }, + { 0x00009a80, 0x00000000, 0x00000078 }, + { 0x00009a84, 0x00000000, 0x00000199 }, + { 0x00009a88, 0x00000000, 0x000001d9 }, + { 0x00009a8c, 0x00000000, 0x00000019 }, + { 0x00009a90, 0x00000000, 0x00000059 }, + { 0x00009a94, 0x00000000, 0x00000099 }, + { 0x00009a98, 0x00000000, 0x000000d9 }, + { 0x00009a9c, 0x00000000, 0x000000f9 }, + { 0x00009aa0, 0x00000000, 0x000000f9 }, + { 0x00009aa4, 0x00000000, 0x000000f9 }, + { 0x00009aa8, 0x00000000, 0x000000f9 }, + { 0x00009aac, 0x00000000, 0x000000f9 }, + { 0x00009ab0, 0x00000000, 0x000000f9 }, + { 0x00009ab4, 0x00000000, 0x000000f9 }, + { 0x00009ab8, 0x00000000, 0x000000f9 }, + { 0x00009abc, 0x00000000, 0x000000f9 }, + { 0x00009ac0, 0x00000000, 0x000000f9 }, + { 0x00009ac4, 0x00000000, 0x000000f9 }, + { 0x00009ac8, 0x00000000, 0x000000f9 }, + { 0x00009acc, 0x00000000, 0x000000f9 }, + { 0x00009ad0, 0x00000000, 0x000000f9 }, + { 0x00009ad4, 0x00000000, 0x000000f9 }, + { 0x00009ad8, 0x00000000, 0x000000f9 }, + { 0x00009adc, 0x00000000, 0x000000f9 }, + { 0x00009ae0, 0x00000000, 0x000000f9 }, + { 0x00009ae4, 0x00000000, 0x000000f9 }, + { 0x00009ae8, 0x00000000, 0x000000f9 }, + { 0x00009aec, 0x00000000, 0x000000f9 }, + { 0x00009af0, 0x00000000, 0x000000f9 }, + { 0x00009af4, 0x00000000, 0x000000f9 }, + { 0x00009af8, 0x00000000, 0x000000f9 }, + { 0x00009afc, 0x00000000, 0x000000f9 }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212BB_RfGain_2316[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000040 }, + { 0x00009a08, 0x00000000, 0x00000080 }, + { 0x00009a0c, 0x00000000, 0x00000161 }, + { 0x00009a10, 0x00000000, 0x000001a1 }, + { 0x00009a14, 0x00000000, 0x000001e1 }, + { 0x00009a18, 0x00000000, 0x00000021 }, + { 0x00009a1c, 0x00000000, 0x00000061 }, + { 0x00009a20, 0x00000000, 0x000000a1 }, + { 0x00009a24, 0x00000000, 0x00000168 }, + { 0x00009a28, 0x00000000, 0x000001a8 }, + { 0x00009a2c, 0x00000000, 0x000001e8 }, + { 0x00009a30, 0x00000000, 0x00000028 }, + { 0x00009a34, 0x00000000, 0x00000068 }, + { 0x00009a38, 0x00000000, 0x000000a8 }, + { 0x00009a3c, 0x00000000, 0x00000189 }, + { 0x00009a40, 0x00000000, 0x000001c9 }, + { 0x00009a44, 0x00000000, 0x00000009 }, + { 0x00009a48, 0x00000000, 0x00000049 }, + { 0x00009a4c, 0x00000000, 0x00000089 }, + { 0x00009a50, 0x00000000, 0x000001b0 }, + { 0x00009a54, 0x00000000, 0x000001f0 }, + { 0x00009a58, 0x00000000, 0x00000030 }, + { 0x00009a5c, 0x00000000, 0x00000070 }, + { 0x00009a60, 0x00000000, 0x000000b0 }, + { 0x00009a64, 0x00000000, 0x000001b1 }, + { 0x00009a68, 0x00000000, 0x000001f1 }, + { 0x00009a6c, 0x00000000, 0x00000031 }, + { 0x00009a70, 0x00000000, 0x00000071 }, + { 0x00009a74, 0x00000000, 0x00000198 }, + { 0x00009a78, 0x00000000, 0x000001d8 }, + { 0x00009a7c, 0x00000000, 0x00000018 }, + { 0x00009a80, 0x00000000, 0x00000058 }, + { 0x00009a84, 0x00000000, 0x00000098 }, + { 0x00009a88, 0x00000000, 0x00000199 }, + { 0x00009a8c, 0x00000000, 0x000001d9 }, + { 0x00009a90, 0x00000000, 0x00000019 }, + { 0x00009a94, 0x00000000, 0x00000059 }, + { 0x00009a98, 0x00000000, 0x00000099 }, + { 0x00009a9c, 0x00000000, 0x000000d9 }, + { 0x00009aa0, 0x00000000, 0x000000f9 }, + { 0x00009aa4, 0x00000000, 0x000000f9 }, + { 0x00009aa8, 0x00000000, 0x000000f9 }, + { 0x00009aac, 0x00000000, 0x000000f9 }, + { 0x00009ab0, 0x00000000, 0x000000f9 }, + { 0x00009ab4, 0x00000000, 0x000000f9 }, + { 0x00009ab8, 0x00000000, 0x000000f9 }, + { 0x00009abc, 0x00000000, 0x000000f9 }, + { 0x00009ac0, 0x00000000, 0x000000f9 }, + { 0x00009ac4, 0x00000000, 0x000000f9 }, + { 0x00009ac8, 0x00000000, 0x000000f9 }, + { 0x00009acc, 0x00000000, 0x000000f9 }, + { 0x00009ad0, 0x00000000, 0x000000f9 }, + { 0x00009ad4, 0x00000000, 0x000000f9 }, + { 0x00009ad8, 0x00000000, 0x000000f9 }, + { 0x00009adc, 0x00000000, 0x000000f9 }, + { 0x00009ae0, 0x00000000, 0x000000f9 }, + { 0x00009ae4, 0x00000000, 0x000000f9 }, + { 0x00009ae8, 0x00000000, 0x000000f9 }, + { 0x00009aec, 0x00000000, 0x000000f9 }, + { 0x00009af0, 0x00000000, 0x000000f9 }, + { 0x00009af4, 0x00000000, 0x000000f9 }, + { 0x00009af8, 0x00000000, 0x000000f9 }, + { 0x00009afc, 0x00000000, 0x000000f9 }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212BB_RfGain_5413[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000161 }, + { 0x00009a10, 0x000001e1, 0x000001a1 }, + { 0x00009a14, 0x00000021, 0x000001e1 }, + { 0x00009a18, 0x00000061, 0x00000021 }, + { 0x00009a1c, 0x00000188, 0x00000061 }, + { 0x00009a20, 0x000001c8, 0x00000188 }, + { 0x00009a24, 0x00000008, 0x000001c8 }, + { 0x00009a28, 0x00000048, 0x00000008 }, + { 0x00009a2c, 0x00000088, 0x00000048 }, + { 0x00009a30, 0x000001a9, 0x00000088 }, + { 0x00009a34, 0x000001e9, 0x00000169 }, + { 0x00009a38, 0x00000029, 0x000001a9 }, + { 0x00009a3c, 0x00000069, 0x000001e9 }, + { 0x00009a40, 0x000001d0, 0x00000029 }, + { 0x00009a44, 0x00000010, 0x00000069 }, + { 0x00009a48, 0x00000050, 0x00000190 }, + { 0x00009a4c, 0x00000090, 0x000001d0 }, + { 0x00009a50, 0x000001b1, 0x00000010 }, + { 0x00009a54, 0x000001f1, 0x00000050 }, + { 0x00009a58, 0x00000031, 0x00000090 }, + { 0x00009a5c, 0x00000071, 0x00000171 }, + { 0x00009a60, 0x000001b8, 0x000001b1 }, + { 0x00009a64, 0x000001f8, 0x000001f1 }, + { 0x00009a68, 0x00000038, 0x00000031 }, + { 0x00009a6c, 0x00000078, 0x00000071 }, + { 0x00009a70, 0x00000199, 0x00000198 }, + { 0x00009a74, 0x000001d9, 0x000001d8 }, + { 0x00009a78, 0x00000019, 0x00000018 }, + { 0x00009a7c, 0x00000059, 0x00000058 }, + { 0x00009a80, 0x00000099, 0x00000098 }, + { 0x00009a84, 0x000000d9, 0x00000179 }, + { 0x00009a88, 0x000000f9, 0x000001b9 }, + { 0x00009a8c, 0x000000f9, 0x000001f9 }, + { 0x00009a90, 0x000000f9, 0x00000039 }, + { 0x00009a94, 0x000000f9, 0x00000079 }, + { 0x00009a98, 0x000000f9, 0x000000b9 }, + { 0x00009a9c, 0x000000f9, 0x000000f9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212BB_RfGain_2425[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000040 }, + { 0x00009a08, 0x00000000, 0x00000080 }, + { 0x00009a0c, 0x00000000, 0x00000181 }, + { 0x00009a10, 0x00000000, 0x000001c1 }, + { 0x00009a14, 0x00000000, 0x00000001 }, + { 0x00009a18, 0x00000000, 0x00000041 }, + { 0x00009a1c, 0x00000000, 0x00000081 }, + { 0x00009a20, 0x00000000, 0x00000188 }, + { 0x00009a24, 0x00000000, 0x000001c8 }, + { 0x00009a28, 0x00000000, 0x00000008 }, + { 0x00009a2c, 0x00000000, 0x00000048 }, + { 0x00009a30, 0x00000000, 0x00000088 }, + { 0x00009a34, 0x00000000, 0x00000189 }, + { 0x00009a38, 0x00000000, 0x000001c9 }, + { 0x00009a3c, 0x00000000, 0x00000009 }, + { 0x00009a40, 0x00000000, 0x00000049 }, + { 0x00009a44, 0x00000000, 0x00000089 }, + { 0x00009a48, 0x00000000, 0x000001b0 }, + { 0x00009a4c, 0x00000000, 0x000001f0 }, + { 0x00009a50, 0x00000000, 0x00000030 }, + { 0x00009a54, 0x00000000, 0x00000070 }, + { 0x00009a58, 0x00000000, 0x00000171 }, + { 0x00009a5c, 0x00000000, 0x000001b1 }, + { 0x00009a60, 0x00000000, 0x000001f1 }, + { 0x00009a64, 0x00000000, 0x00000031 }, + { 0x00009a68, 0x00000000, 0x00000071 }, + { 0x00009a6c, 0x00000000, 0x000001b8 }, + { 0x00009a70, 0x00000000, 0x000001f8 }, + { 0x00009a74, 0x00000000, 0x00000038 }, + { 0x00009a78, 0x00000000, 0x00000078 }, + { 0x00009a7c, 0x00000000, 0x000000b8 }, + { 0x00009a80, 0x00000000, 0x000001b9 }, + { 0x00009a84, 0x00000000, 0x000001f9 }, + { 0x00009a88, 0x00000000, 0x00000039 }, + { 0x00009a8c, 0x00000000, 0x00000079 }, + { 0x00009a90, 0x00000000, 0x000000b9 }, + { 0x00009a94, 0x00000000, 0x000000f9 }, + { 0x00009a98, 0x00000000, 0x000000f9 }, + { 0x00009a9c, 0x00000000, 0x000000f9 }, + { 0x00009aa0, 0x00000000, 0x000000f9 }, + { 0x00009aa4, 0x00000000, 0x000000f9 }, + { 0x00009aa8, 0x00000000, 0x000000f9 }, + { 0x00009aac, 0x00000000, 0x000000f9 }, + { 0x00009ab0, 0x00000000, 0x000000f9 }, + { 0x00009ab4, 0x00000000, 0x000000f9 }, + { 0x00009ab8, 0x00000000, 0x000000f9 }, + { 0x00009abc, 0x00000000, 0x000000f9 }, + { 0x00009ac0, 0x00000000, 0x000000f9 }, + { 0x00009ac4, 0x00000000, 0x000000f9 }, + { 0x00009ac8, 0x00000000, 0x000000f9 }, + { 0x00009acc, 0x00000000, 0x000000f9 }, + { 0x00009ad0, 0x00000000, 0x000000f9 }, + { 0x00009ad4, 0x00000000, 0x000000f9 }, + { 0x00009ad8, 0x00000000, 0x000000f9 }, + { 0x00009adc, 0x00000000, 0x000000f9 }, + { 0x00009ae0, 0x00000000, 0x000000f9 }, + { 0x00009ae4, 0x00000000, 0x000000f9 }, + { 0x00009ae8, 0x00000000, 0x000000f9 }, + { 0x00009aec, 0x00000000, 0x000000f9 }, + { 0x00009af0, 0x00000000, 0x000000f9 }, + { 0x00009af4, 0x00000000, 0x000000f9 }, + { 0x00009af8, 0x00000000, 0x000000f9 }, + { 0x00009afc, 0x00000000, 0x000000f9 }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Bank1_5111[][2] = { + { 0x000098d4, 0x00000020 }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Bank1_5112[][2] = { + { 0x000098d4, 0x00000020 }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Bank1_2413[][2] = { + { 0x000098d4, 0x00000020 }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Bank1_2316[][2] = { + { 0x000098d4, 0x00000020 }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Bank1_5413[][2] = { + { 0x000098d4, 0x00000020 }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Bank1_2425[][2] = { + { 0x000098d4, 0x00000020 }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Bank2_5111[][6] = { + { 0x000098d4, 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Bank2_5112[][6] = { + { 0x000098d0, 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Bank2_2413[][6] = { + { 0x000098d0, 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Bank2_2316[][6] = { + { 0x000098d0, 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Bank2_5413[][6] = { + { 0x000098d0, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Bank2_2425[][6] = { + { 0x000098d0, 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Bank3_5111[][6] = { + { 0x000098d8, 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Bank3_5112[][6] = { + { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Bank3_2413[][6] = { + { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Bank3_2316[][6] = { + { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Bank3_5413[][6] = { + { 0x000098dc, 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Bank3_2425[][6] = { + { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Bank6_5111[][6] = { + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 }, + { 0x0000989c, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 }, + { 0x0000989c, 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 }, + { 0x0000989c, 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 }, + { 0x0000989c, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 }, + { 0x0000989c, 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 }, + { 0x000098d4, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Bank6_5112[][6] = { + { 0x0000989c, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 }, + { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 }, + { 0x0000989c, 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 }, + { 0x0000989c, 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 }, + { 0x0000989c, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 }, + { 0x0000989c, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 }, + { 0x0000989c, 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 }, + { 0x0000989c, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 }, + { 0x0000989c, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 }, + { 0x0000989c, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 }, + { 0x0000989c, 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 }, + { 0x0000989c, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 }, + { 0x0000989c, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 }, + { 0x0000989c, 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 }, + { 0x0000989c, 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 }, + { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 }, + { 0x0000989c, 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 }, + { 0x0000989c, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 }, + { 0x0000989c, 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 }, + { 0x0000989c, 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 }, + { 0x0000989c, 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 }, + { 0x0000989c, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 }, + { 0x0000989c, 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 }, + { 0x0000989c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 }, + { 0x0000989c, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 }, + { 0x0000989c, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 }, + { 0x0000989c, 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 }, + { 0x0000989c, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 }, + { 0x000098d8, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Bank6_2413[][6] = { + { 0x0000989c, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 }, + { 0x0000989c, 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 }, + { 0x0000989c, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 }, + { 0x0000989c, 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 }, + { 0x0000989c, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 }, + { 0x0000989c, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 }, + { 0x0000989c, 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 }, + { 0x0000989c, 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 }, + { 0x0000989c, 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 }, + { 0x0000989c, 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 }, + { 0x0000989c, 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 }, + { 0x0000989c, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f }, + { 0x0000989c, 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 }, + { 0x000098d8, 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Bank6_2316[][6] = { + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 }, + { 0x0000989c, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 }, + { 0x0000989c, 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 }, + { 0x0000989c, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 }, + { 0x0000989c, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 }, + { 0x0000989c, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 }, + { 0x0000989c, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 }, + { 0x0000989c, 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 }, + { 0x0000989c, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 }, + { 0x0000989c, 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 }, + { 0x0000989c, 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d }, + { 0x0000989c, 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 }, + { 0x0000989c, 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 }, + { 0x0000989c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 }, + { 0x0000989c, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 }, + { 0x0000989c, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 }, + { 0x000098c0, 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Bank6_5413[][6] = { + { 0x0000989c, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 }, + { 0x0000989c, 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 }, + { 0x0000989c, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 }, + { 0x0000989c, 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 }, + { 0x0000989c, 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 }, + { 0x0000989c, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 }, + { 0x0000989c, 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 }, + { 0x0000989c, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 }, + { 0x0000989c, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 }, + { 0x0000989c, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 }, + { 0x0000989c, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 }, + { 0x0000989c, 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 }, + { 0x0000989c, 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 }, + { 0x0000989c, 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 }, + { 0x0000989c, 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 }, + { 0x0000989c, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 }, + { 0x0000989c, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 }, + { 0x0000989c, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f }, + { 0x0000989c, 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 }, + { 0x0000989c, 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 }, + { 0x0000989c, 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 }, + { 0x000098c8, 0x00000403, 0x00000403, 0x00000403, 0x00000403, 0x00000403 }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Bank6_2425[][6] = { + { 0x0000989c, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 }, + { 0x0000989c, 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 }, + { 0x0000989c, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 }, + { 0x0000989c, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 }, + { 0x0000989c, 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 }, + { 0x0000989c, 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 }, + { 0x0000989c, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a }, + { 0x0000989c, 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 }, + { 0x0000989c, 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 }, + { 0x0000989c, 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 }, + { 0x0000989c, 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 }, + { 0x000098c4, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 }, +}; +#endif /* AH_5212_2425 */ + +#ifdef AH_5212_2417 +static const uint32_t ar5212Bank6_2417[][6] = { + { 0x0000989c, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 }, + { 0x0000989c, 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 }, + { 0x0000989c, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 }, + { 0x0000989c, 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 }, + { 0x0000989c, 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 }, + { 0x0000989c, 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 }, + { 0x0000989c, 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a }, + { 0x0000989c, 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 }, + { 0x0000989c, 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 }, + { 0x0000989c, 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 }, + { 0x0000989c, 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 }, + { 0x000098c4, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 }, +}; +#endif /* AH_5212_2417 */ + +#ifdef AH_5212_5111 +static const uint32_t ar5212Bank7_5111[][6] = { + { 0x0000989c, 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 }, + { 0x0000989c, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x0000989c, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 }, + { 0x0000989c, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f }, + { 0x0000989c, 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 }, + { 0x0000989c, 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f }, + { 0x0000989c, 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a }, + { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e }, +}; +#endif /* AH_5212_5111 */ + +#ifdef AH_5212_5112 +static const uint32_t ar5212Bank7_5112[][6] = { + { 0x0000989c, 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 }, + { 0x0000989c, 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 }, + { 0x0000989c, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 }, + { 0x0000989c, 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 }, + { 0x0000989c, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 }, + { 0x0000989c, 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 }, + { 0x0000989c, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 }, + { 0x0000989c, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 }, + { 0x0000989c, 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 }, + { 0x0000989c, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 }, + { 0x0000989c, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc }, + { 0x0000989c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c }, + { 0x000098c4, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 }, +}; +#endif /* AH_5212_5112 */ + +#ifdef AH_5212_2413 +static const uint32_t ar5212Bank7_2413[][6] = { + { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 }, + { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 }, + { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e }, +}; +#endif /* AH_5212_2413 */ + +#ifdef AH_5212_2316 +static const uint32_t ar5212Bank7_2316[][6] = { + { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 }, + { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 }, + { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e }, +}; +#endif + +#ifdef AH_5212_5413 +static const uint32_t ar5212Bank7_5413[][6] = { + { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 }, + { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 }, + { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e }, +}; +#endif /* AH_5212_5413 */ + +#ifdef AH_5212_2317 +static const uint32_t ar5212Modes_2317[][6] = { + { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 }, + { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 }, + { 0x00009838, 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a }, + { 0x00009848, 0x0018da6d, 0x0018da6d, 0x001a6a67, 0x001a6a67, 0x001a6a67 }, + { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da }, + { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e }, + { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 }, + { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 }, + { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 }, + { 0x0000a20c, 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a }, +}; + +static const uint32_t ar5212Common_2317[][2] = { + { 0x00001230, 0x000003e0 }, + { 0x00008060, 0x0000000f }, + { 0x00008118, 0x00000000 }, + { 0x0000811c, 0x00000000 }, + { 0x00008120, 0x00000000 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008140, 0x800000a8 }, + { 0x00008144, 0x00000000 }, + { 0x00009808, 0x00004000 }, + { 0x0000982c, 0x0000a000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x1284233c }, + { 0x00009870, 0x0000001f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x0000000e }, + { 0x00009958, 0x000000ff }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x02800000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099e0, 0x00000001 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099f0, 0x0000000c }, + { 0x000099f4, 0x000000ff }, + { 0x000099f8, 0x00000014 }, + { 0x0000a228, 0x000009b5 }, + { 0x0000a23c, 0x93c889af }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0x5f690f01 }, + { 0x0000a264, 0x00418a11 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0c30c16a }, + { 0x0000a270, 0x00820820 }, + { 0x0000a274, 0x081a3caa }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a300, 0x16010000 }, + { 0x0000a304, 0x2c032402 }, + { 0x0000a308, 0x48433e42 }, + { 0x0000a30c, 0x5a0f500b }, + { 0x0000a310, 0x6c4b624a }, + { 0x0000a314, 0x7e8b748a }, + { 0x0000a318, 0x96cf8ccb }, + { 0x0000a31c, 0xa34f9d0f }, + { 0x0000a320, 0xa7cfa58f }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000a35c, 0x066c420f }, + { 0x0000a360, 0x0f282207 }, + { 0x0000a364, 0x17601685 }, + { 0x0000a368, 0x1f801104 }, + { 0x0000a36c, 0x37a00c03 }, + { 0x0000a370, 0x3fc40883 }, + { 0x0000a374, 0x57c00803 }, + { 0x0000a378, 0x5fd80682 }, + { 0x0000a37c, 0x7fe00482 }, + { 0x0000a380, 0x7f3c7bba }, + { 0x0000a384, 0xf3307ff0 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, +}; + +static const uint32_t ar5212BB_RfGain_2317[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000040 }, + { 0x00009a08, 0x00000000, 0x00000080 }, + { 0x00009a0c, 0x00000000, 0x00000181 }, + { 0x00009a10, 0x00000000, 0x000001c1 }, + { 0x00009a14, 0x00000000, 0x00000001 }, + { 0x00009a18, 0x00000000, 0x00000041 }, + { 0x00009a1c, 0x00000000, 0x00000081 }, + { 0x00009a20, 0x00000000, 0x00000188 }, + { 0x00009a24, 0x00000000, 0x000001c8 }, + { 0x00009a28, 0x00000000, 0x00000008 }, + { 0x00009a2c, 0x00000000, 0x00000048 }, + { 0x00009a30, 0x00000000, 0x00000088 }, + { 0x00009a34, 0x00000000, 0x00000189 }, + { 0x00009a38, 0x00000000, 0x000001c9 }, + { 0x00009a3c, 0x00000000, 0x00000009 }, + { 0x00009a40, 0x00000000, 0x00000049 }, + { 0x00009a44, 0x00000000, 0x00000089 }, + { 0x00009a48, 0x00000000, 0x00000190 }, + { 0x00009a4c, 0x00000000, 0x000001d0 }, + { 0x00009a50, 0x00000000, 0x00000010 }, + { 0x00009a54, 0x00000000, 0x00000050 }, + { 0x00009a58, 0x00000000, 0x00000090 }, + { 0x00009a5c, 0x00000000, 0x00000191 }, + { 0x00009a60, 0x00000000, 0x000001d1 }, + { 0x00009a64, 0x00000000, 0x00000011 }, + { 0x00009a68, 0x00000000, 0x00000051 }, + { 0x00009a6c, 0x00000000, 0x00000091 }, + { 0x00009a70, 0x00000000, 0x00000178 }, + { 0x00009a74, 0x00000000, 0x000001b8 }, + { 0x00009a78, 0x00000000, 0x000001f8 }, + { 0x00009a7c, 0x00000000, 0x00000038 }, + { 0x00009a80, 0x00000000, 0x00000078 }, + { 0x00009a84, 0x00000000, 0x00000179 }, + { 0x00009a88, 0x00000000, 0x000001b9 }, + { 0x00009a8c, 0x00000000, 0x000001f9 }, + { 0x00009a90, 0x00000000, 0x00000039 }, + { 0x00009a94, 0x00000000, 0x00000079 }, + { 0x00009a98, 0x00000000, 0x000000b9 }, + { 0x00009a9c, 0x00000000, 0x000000f9 }, + { 0x00009aa0, 0x00000000, 0x000000f9 }, + { 0x00009aa4, 0x00000000, 0x000000f9 }, + { 0x00009aa8, 0x00000000, 0x000000f9 }, + { 0x00009aac, 0x00000000, 0x000000f9 }, + { 0x00009ab0, 0x00000000, 0x000000f9 }, + { 0x00009ab4, 0x00000000, 0x000000f9 }, + { 0x00009ab8, 0x00000000, 0x000000f9 }, + { 0x00009abc, 0x00000000, 0x000000f9 }, + { 0x00009ac0, 0x00000000, 0x000000f9 }, + { 0x00009ac4, 0x00000000, 0x000000f9 }, + { 0x00009ac8, 0x00000000, 0x000000f9 }, + { 0x00009acc, 0x00000000, 0x000000f9 }, + { 0x00009ad0, 0x00000000, 0x000000f9 }, + { 0x00009ad4, 0x00000000, 0x000000f9 }, + { 0x00009ad8, 0x00000000, 0x000000f9 }, + { 0x00009adc, 0x00000000, 0x000000f9 }, + { 0x00009ae0, 0x00000000, 0x000000f9 }, + { 0x00009ae4, 0x00000000, 0x000000f9 }, + { 0x00009ae8, 0x00000000, 0x000000f9 }, + { 0x00009aec, 0x00000000, 0x000000f9 }, + { 0x00009af0, 0x00000000, 0x000000f9 }, + { 0x00009af4, 0x00000000, 0x000000f9 }, + { 0x00009af8, 0x00000000, 0x000000f9 }, + { 0x00009afc, 0x00000000, 0x000000f9 }, +}; + +static const uint32_t ar5212Bank1_2317[][2] = { + { 0x000098d4, 0x00000020 }, +}; + +static const uint32_t ar5212Bank2_2317[][6] = { + { 0x000098d0, 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 }, +}; + +static const uint32_t ar5212Bank3_2317[][6] = { + { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 }, +}; + +static const uint32_t ar5212Bank6_2317[][6] = { + { 0x0000989c, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 }, + { 0x0000989c, 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 }, + { 0x0000989c, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 }, + { 0x0000989c, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 }, + { 0x0000989c, 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 }, + { 0x0000989c, 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 }, + { 0x0000989c, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a }, + { 0x0000989c, 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 }, + { 0x0000989c, 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 }, + { 0x0000989c, 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 }, + { 0x0000989c, 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 }, + { 0x000098c4, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 }, +}; + +static const uint32_t ar5212Bank7_2317[][6] = { + { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 }, + { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 }, + { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e }, +}; +#endif /* AH_5212_2317 */ + +#ifdef AH_5212_2425 +static const uint32_t ar5212Bank7_2425[][6] = { + { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 }, + { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 }, + { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e }, +}; +#endif /* AH_5212_2425 */ diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_ani.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_ani.c new file mode 100644 index 0000000..c7b5932 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_ani.c @@ -0,0 +1,1041 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +/* + * Anti noise immunity support. We track phy errors and react + * to excessive errors by adjusting the noise immunity parameters. + */ + +#define HAL_EP_RND(x, mul) \ + ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) +#define BEACON_RSSI(ahp) \ + HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgbrssi, \ + HAL_RSSI_EP_MULTIPLIER) + +/* + * ANI processing tunes radio parameters according to PHY errors + * and related information. This is done for for noise and spur + * immunity in all operating modes if the device indicates it's + * capable at attach time. In addition, when there is a reference + * rssi value (e.g. beacon frames from an ap in station mode) + * further tuning is done. + * + * ANI_ENA indicates whether any ANI processing should be done; + * this is specified at attach time. + * + * ANI_ENA_RSSI indicates whether rssi-based processing should + * done, this is enabled based on operating mode and is meaningful + * only if ANI_ENA is true. + * + * ANI parameters are typically controlled only by the hal. The + * AniControl interface however permits manual tuning through the + * diagnostic api. + */ +#define ANI_ENA(ah) \ + (AH5212(ah)->ah_procPhyErr & HAL_ANI_ENA) +#define ANI_ENA_RSSI(ah) \ + (AH5212(ah)->ah_procPhyErr & HAL_RSSI_ANI_ENA) + +#define ah_mibStats ah_stats.ast_mibstats + +static void +enableAniMIBCounters(struct ath_hal *ah, const struct ar5212AniParams *params) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: Enable mib counters: " + "OfdmPhyErrBase 0x%x cckPhyErrBase 0x%x\n", + __func__, params->ofdmPhyErrBase, params->cckPhyErrBase); + + OS_REG_WRITE(ah, AR_FILTOFDM, 0); + OS_REG_WRITE(ah, AR_FILTCCK, 0); + + OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase); + OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase); + OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING); + OS_REG_WRITE(ah, AR_PHYCNTMASK2, AR_PHY_ERR_CCK_TIMING); + + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save+clear counters*/ + ar5212EnableMibCounters(ah); /* enable everything */ +} + +static void +disableAniMIBCounters(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_ANI, "Disable MIB counters\n"); + + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save stats */ + ar5212DisableMibCounters(ah); /* disable everything */ + + OS_REG_WRITE(ah, AR_PHYCNTMASK1, 0); + OS_REG_WRITE(ah, AR_PHYCNTMASK2, 0); +} + +/* + * Return the current ANI state of the channel we're on + */ +struct ar5212AniState * +ar5212AniGetCurrentState(struct ath_hal *ah) +{ + return AH5212(ah)->ah_curani; +} + +/* + * Return the current statistics. + */ +HAL_ANI_STATS * +ar5212AniGetCurrentStats(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* update mib stats so we return current data */ + /* XXX? side-effects to doing this here? */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + return &ahp->ah_stats; +} + +static void +setPhyErrBase(struct ath_hal *ah, struct ar5212AniParams *params) +{ + if (params->ofdmTrigHigh >= AR_PHY_COUNTMAX) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "OFDM Trigger %d is too high for hw counters, using max\n", + params->ofdmTrigHigh); + params->ofdmPhyErrBase = 0; + } else + params->ofdmPhyErrBase = AR_PHY_COUNTMAX - params->ofdmTrigHigh; + if (params->cckTrigHigh >= AR_PHY_COUNTMAX) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "CCK Trigger %d is too high for hw counters, using max\n", + params->cckTrigHigh); + params->cckPhyErrBase = 0; + } else + params->cckPhyErrBase = AR_PHY_COUNTMAX - params->cckTrigHigh; +} + +/* + * Setup ANI handling. Sets all thresholds and reset the + * channel statistics. Note that ar5212AniReset should be + * called by ar5212Reset before anything else happens and + * that's where we force initial settings. + */ +void +ar5212AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24, + const struct ar5212AniParams *params5, HAL_BOOL enable) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + ahp->ah_hasHwPhyCounters = + AH_PRIVATE(ah)->ah_caps.halHwPhyCounterSupport; + + if (params24 != AH_NULL) { + OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24)); + setPhyErrBase(ah, &ahp->ah_aniParams24); + } + if (params5 != AH_NULL) { + OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5)); + setPhyErrBase(ah, &ahp->ah_aniParams5); + } + + OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani)); + if (ahp->ah_hasHwPhyCounters) { + /* Enable MIB Counters */ + enableAniMIBCounters(ah, &ahp->ah_aniParams24 /*XXX*/); + } + if (enable) { /* Enable ani now */ + HALASSERT(params24 != AH_NULL && params5 != AH_NULL); + ahp->ah_procPhyErr |= HAL_ANI_ENA; + } else { + ahp->ah_procPhyErr &= ~HAL_ANI_ENA; + } +} + +HAL_BOOL +ar5212AniSetParams(struct ath_hal *ah, const struct ar5212AniParams *params24, + const struct ar5212AniParams *params5) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_BOOL ena = (ahp->ah_procPhyErr & HAL_ANI_ENA) != 0; + + ar5212AniControl(ah, HAL_ANI_MODE, AH_FALSE); + + OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24)); + setPhyErrBase(ah, &ahp->ah_aniParams24); + OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5)); + setPhyErrBase(ah, &ahp->ah_aniParams5); + + OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani)); + ar5212AniReset(ah, AH_PRIVATE(ah)->ah_curchan, + AH_PRIVATE(ah)->ah_opmode, AH_FALSE); + + ar5212AniControl(ah, HAL_ANI_MODE, ena); + + return AH_TRUE; +} + +/* + * Cleanup any ANI state setup. + */ +void +ar5212AniDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_ANI, "Detaching Ani\n"); + if (ahp->ah_hasHwPhyCounters) + disableAniMIBCounters(ah); +} + +/* + * Control Adaptive Noise Immunity Parameters + */ +HAL_BOOL +ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) +{ + typedef int TABLE[]; + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState = ahp->ah_curani; + const struct ar5212AniParams *params = AH_NULL; + + /* + * This function may be called before there's a current + * channel (eg to disable ANI.) + */ + if (aniState != AH_NULL) + params = aniState->params; + + OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd); + + switch (cmd) { + case HAL_ANI_NOISE_IMMUNITY_LEVEL: { + u_int level = param; + + if (level > params->maxNoiseImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: level out of range (%u > %u)\n", + __func__, level, params->maxNoiseImmunityLevel); + return AH_FALSE; + } + + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_TOT_DES, params->totalSizeDesired[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_LOW, params->coarseLow[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_HIGH, params->coarseHigh[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRPWR, params->firpwr[level]); + + if (level > aniState->noiseImmunityLevel) + ahp->ah_stats.ast_ani_niup++; + else if (level < aniState->noiseImmunityLevel) + ahp->ah_stats.ast_ani_nidown++; + aniState->noiseImmunityLevel = level; + break; + } + case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: { + static const TABLE m1ThreshLow = { 127, 50 }; + static const TABLE m2ThreshLow = { 127, 40 }; + static const TABLE m1Thresh = { 127, 0x4d }; + static const TABLE m2Thresh = { 127, 0x40 }; + static const TABLE m2CountThr = { 31, 16 }; + static const TABLE m2CountThrLow = { 63, 48 }; + u_int on = param ? 1 : 0; + + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]); + + if (on) { + OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + ahp->ah_stats.ast_ani_ofdmon++; + } else { + OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + ahp->ah_stats.ast_ani_ofdmoff++; + } + aniState->ofdmWeakSigDetectOff = !on; + break; + } + case HAL_ANI_CCK_WEAK_SIGNAL_THR: { + static const TABLE weakSigThrCck = { 8, 6 }; + u_int high = param ? 1 : 0; + + OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, + AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, weakSigThrCck[high]); + if (high) + ahp->ah_stats.ast_ani_cckhigh++; + else + ahp->ah_stats.ast_ani_ccklow++; + aniState->cckWeakSigThreshold = high; + break; + } + case HAL_ANI_FIRSTEP_LEVEL: { + u_int level = param; + + if (level > params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: level out of range (%u > %u)\n", + __func__, level, params->maxFirstepLevel); + return AH_FALSE; + } + OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRSTEP, params->firstep[level]); + if (level > aniState->firstepLevel) + ahp->ah_stats.ast_ani_stepup++; + else if (level < aniState->firstepLevel) + ahp->ah_stats.ast_ani_stepdown++; + aniState->firstepLevel = level; + break; + } + case HAL_ANI_SPUR_IMMUNITY_LEVEL: { + u_int level = param; + + if (level > params->maxSpurImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: level out of range (%u > %u)\n", + __func__, level, params->maxSpurImmunityLevel); + return AH_FALSE; + } + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5, + AR_PHY_TIMING5_CYCPWR_THR1, params->cycPwrThr1[level]); + if (level > aniState->spurImmunityLevel) + ahp->ah_stats.ast_ani_spurup++; + else if (level < aniState->spurImmunityLevel) + ahp->ah_stats.ast_ani_spurdown++; + aniState->spurImmunityLevel = level; + break; + } + case HAL_ANI_PRESENT: + break; + case HAL_ANI_MODE: + if (param == 0) { + ahp->ah_procPhyErr &= ~HAL_ANI_ENA; + /* Turn off HW counters if we have them */ + ar5212AniDetach(ah); + ah->ah_setRxFilter(ah, + ah->ah_getRxFilter(ah) &~ HAL_RX_FILTER_PHYERR); + } else { /* normal/auto mode */ + /* don't mess with state if already enabled */ + if (ahp->ah_procPhyErr & HAL_ANI_ENA) + break; + if (ahp->ah_hasHwPhyCounters) { + ar5212SetRxFilter(ah, + ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR); + /* Enable MIB Counters */ + enableAniMIBCounters(ah, + ahp->ah_curani != AH_NULL ? + ahp->ah_curani->params: + &ahp->ah_aniParams24 /*XXX*/); + } else { + ah->ah_setRxFilter(ah, + ah->ah_getRxFilter(ah) | HAL_RX_FILTER_PHYERR); + } + ahp->ah_procPhyErr |= HAL_ANI_ENA; + } + break; +#ifdef AH_PRIVATE_DIAG + case HAL_ANI_PHYERR_RESET: + ahp->ah_stats.ast_ani_ofdmerrs = 0; + ahp->ah_stats.ast_ani_cckerrs = 0; + break; +#endif /* AH_PRIVATE_DIAG */ + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid cmd %u\n", + __func__, cmd); + return AH_FALSE; + } + return AH_TRUE; +} + +static void +ar5212AniOfdmErrTrigger(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(chan != AH_NULL); + + if (!ANI_ENA(ah)) + return; + + aniState = ahp->ah_curani; + params = aniState->params; + /* First, raise noise immunity level, up to max */ + if (aniState->noiseImmunityLevel+1 <= params->maxNoiseImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__, + aniState->noiseImmunityLevel + 1); + ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel + 1); + return; + } + /* then, raise spur immunity level, up to max */ + if (aniState->spurImmunityLevel+1 <= params->maxSpurImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise SI to %u\n", __func__, + aniState->spurImmunityLevel + 1); + ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel + 1); + return; + } + + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrHigh) { + /* + * Beacon rssi is high, can turn off ofdm + * weak sig detect. + */ + if (!aniState->ofdmWeakSigDetectOff) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d OWSD off\n", __func__, rssi); + ar5212AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_FALSE); + ar5212AniControl(ah, + HAL_ANI_SPUR_IMMUNITY_LEVEL, 0); + return; + } + /* + * If weak sig detect is already off, as last resort, + * raise firstep level + */ + if (aniState->firstepLevel+1 <= params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d raise ST %u\n", __func__, rssi, + aniState->firstepLevel+1); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + return; + } + } else if (rssi > params->rssiThrLow) { + /* + * Beacon rssi in mid range, need ofdm weak signal + * detect, but we can raise firststepLevel. + */ + if (aniState->ofdmWeakSigDetectOff) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d OWSD on\n", __func__, rssi); + ar5212AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE); + } + if (aniState->firstepLevel+1 <= params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d raise ST %u\n", __func__, rssi, + aniState->firstepLevel+1); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + } + return; + } else { + /* + * Beacon rssi is low, if in 11b/g mode, turn off ofdm + * weak signal detection and zero firstepLevel to + * maximize CCK sensitivity + */ + if (IEEE80211_IS_CHAN_CCK(chan)) { + if (!aniState->ofdmWeakSigDetectOff) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d OWSD off\n", + __func__, rssi); + ar5212AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_FALSE); + } + if (aniState->firstepLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d zero ST (was %u)\n", + __func__, rssi, + aniState->firstepLevel); + ar5212AniControl(ah, + HAL_ANI_FIRSTEP_LEVEL, 0); + } + return; + } + } + } +} + +static void +ar5212AniCckErrTrigger(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(chan != AH_NULL); + + if (!ANI_ENA(ah)) + return; + + /* first, raise noise immunity level, up to max */ + aniState = ahp->ah_curani; + params = aniState->params; + if (aniState->noiseImmunityLevel+1 <= params->maxNoiseImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__, + aniState->noiseImmunityLevel + 1); + ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel + 1); + return; + } + + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrLow) { + /* + * Beacon signal in mid and high range, + * raise firstep level. + */ + if (aniState->firstepLevel+1 <= params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d raise ST %u\n", __func__, rssi, + aniState->firstepLevel+1); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + } + } else { + /* + * Beacon rssi is low, zero firstep level to maximize + * CCK sensitivity in 11b/g mode. + */ + /* XXX can optimize */ + if (IEEE80211_IS_CHAN_B(chan) || + IEEE80211_IS_CHAN_G(chan)) { + if (aniState->firstepLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d zero ST (was %u)\n", + __func__, rssi, + aniState->firstepLevel); + ar5212AniControl(ah, + HAL_ANI_FIRSTEP_LEVEL, 0); + } + } + } + } +} + +static void +ar5212AniRestart(struct ath_hal *ah, struct ar5212AniState *aniState) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + aniState->listenTime = 0; + if (ahp->ah_hasHwPhyCounters) { + const struct ar5212AniParams *params = aniState->params; + /* + * NB: these are written on reset based on the + * ini so we must re-write them! + */ + OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase); + OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase); + OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING); + OS_REG_WRITE(ah, AR_PHYCNTMASK2, AR_PHY_ERR_CCK_TIMING); + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + } + aniState->ofdmPhyErrCount = 0; + aniState->cckPhyErrCount = 0; +} + +/* + * Restore/reset the ANI parameters and reset the statistics. + * This routine must be called for every channel change. + */ +void +ar5212AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan, + HAL_OPMODE opmode, int restore) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); + /* XXX bounds check ic_devdata */ + struct ar5212AniState *aniState = &ahp->ah_ani[chan->ic_devdata]; + uint32_t rxfilter; + + if ((ichan->privFlags & CHANNEL_ANI_INIT) == 0) { + OS_MEMZERO(aniState, sizeof(*aniState)); + if (IEEE80211_IS_CHAN_2GHZ(chan)) + aniState->params = &ahp->ah_aniParams24; + else + aniState->params = &ahp->ah_aniParams5; + ichan->privFlags |= CHANNEL_ANI_INIT; + HALASSERT((ichan->privFlags & CHANNEL_ANI_SETUP) == 0); + } + ahp->ah_curani = aniState; +#if 0 + ath_hal_printf(ah,"%s: chan %u/0x%x restore %d opmode %u%s\n", + __func__, chan->ic_freq, chan->ic_flags, restore, opmode, + ichan->privFlags & CHANNEL_ANI_SETUP ? " setup" : ""); +#else + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: chan %u/0x%x restore %d opmode %u%s\n", + __func__, chan->ic_freq, chan->ic_flags, restore, opmode, + ichan->privFlags & CHANNEL_ANI_SETUP ? " setup" : ""); +#endif + OS_MARK(ah, AH_MARK_ANI_RESET, opmode); + + /* + * Turn off PHY error frame delivery while we futz with settings. + */ + rxfilter = ah->ah_getRxFilter(ah); + ah->ah_setRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR); + + /* + * If ANI is disabled at this point, don't set the default + * ANI parameter settings - leave the HAL settings there. + * This is (currently) needed for reliable radar detection. + */ + if (! ANI_ENA(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ANI disabled\n", + __func__); + goto finish; + } + + /* + * Automatic processing is done only in station mode right now. + */ + if (opmode == HAL_M_STA) + ahp->ah_procPhyErr |= HAL_RSSI_ANI_ENA; + else + ahp->ah_procPhyErr &= ~HAL_RSSI_ANI_ENA; + /* + * Set all ani parameters. We either set them to initial + * values or restore the previous ones for the channel. + * XXX if ANI follows hardware, we don't care what mode we're + * XXX in, we should keep the ani parameters + */ + if (restore && (ichan->privFlags & CHANNEL_ANI_SETUP)) { + ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel); + ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel); + ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + !aniState->ofdmWeakSigDetectOff); + ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, + aniState->cckWeakSigThreshold); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel); + } else { + ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0); + ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0); + ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE); + ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); + ichan->privFlags |= CHANNEL_ANI_SETUP; + } + /* + * In case the counters haven't yet been setup; set them up. + */ + enableAniMIBCounters(ah, ahp->ah_curani->params); + ar5212AniRestart(ah, aniState); + +finish: + /* restore RX filter mask */ + ah->ah_setRxFilter(ah, rxfilter); +} + +/* + * Process a MIB interrupt. We may potentially be invoked because + * any of the MIB counters overflow/trigger so don't assume we're + * here because a PHY error counter triggered. + */ +void +ar5212ProcessMibIntr(struct ath_hal *ah, const HAL_NODE_STATS *stats) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t phyCnt1, phyCnt2; + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: mibc 0x%x phyCnt1 0x%x phyCnt2 0x%x " + "filtofdm 0x%x filtcck 0x%x\n", + __func__, OS_REG_READ(ah, AR_MIBC), + OS_REG_READ(ah, AR_PHYCNT1), OS_REG_READ(ah, AR_PHYCNT2), + OS_REG_READ(ah, AR_FILTOFDM), OS_REG_READ(ah, AR_FILTCCK)); + + /* + * First order of business is to clear whatever caused + * the interrupt so we don't keep getting interrupted. + * We have the usual mib counters that are reset-on-read + * and the additional counters that appeared starting in + * Hainan. We collect the mib counters and explicitly + * zero additional counters we are not using. Anything + * else is reset only if it caused the interrupt. + */ + /* NB: these are not reset-on-read */ + phyCnt1 = OS_REG_READ(ah, AR_PHYCNT1); + phyCnt2 = OS_REG_READ(ah, AR_PHYCNT2); + /* not used, always reset them in case they are the cause */ + OS_REG_WRITE(ah, AR_FILTOFDM, 0); + OS_REG_WRITE(ah, AR_FILTCCK, 0); + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + ahp->ah_stats.ast_nodestats = *stats; + + /* + * Check for an ani stat hitting the trigger threshold. + * When this happens we get a MIB interrupt and the top + * 2 bits of the counter register will be 0b11, hence + * the mask check of phyCnt?. + */ + if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || + ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { + struct ar5212AniState *aniState = ahp->ah_curani; + const struct ar5212AniParams *params = aniState->params; + uint32_t ofdmPhyErrCnt, cckPhyErrCnt; + + ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase; + ahp->ah_stats.ast_ani_ofdmerrs += + ofdmPhyErrCnt - aniState->ofdmPhyErrCount; + aniState->ofdmPhyErrCount = ofdmPhyErrCnt; + + cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase; + ahp->ah_stats.ast_ani_cckerrs += + cckPhyErrCnt - aniState->cckPhyErrCount; + aniState->cckPhyErrCount = cckPhyErrCnt; + + /* + * NB: figure out which counter triggered. If both + * trigger we'll only deal with one as the processing + * clobbers the error counter so the trigger threshold + * check will never be true. + */ + if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh) + ar5212AniOfdmErrTrigger(ah); + if (aniState->cckPhyErrCount > params->cckTrigHigh) + ar5212AniCckErrTrigger(ah); + /* NB: always restart to insure the h/w counters are reset */ + ar5212AniRestart(ah, aniState); + } +} + +void +ar5212AniPhyErrReport(struct ath_hal *ah, const struct ath_rx_status *rs) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(!ahp->ah_hasHwPhyCounters && rs != AH_NULL); + + aniState = ahp->ah_curani; + params = aniState->params; + if (rs->rs_phyerr == HAL_PHYERR_OFDM_TIMING) { + aniState->ofdmPhyErrCount++; + ahp->ah_stats.ast_ani_ofdmerrs++; + if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh) { + ar5212AniOfdmErrTrigger(ah); + ar5212AniRestart(ah, aniState); + } + } else if (rs->rs_phyerr == HAL_PHYERR_CCK_TIMING) { + aniState->cckPhyErrCount++; + ahp->ah_stats.ast_ani_cckerrs++; + if (aniState->cckPhyErrCount > params->cckTrigHigh) { + ar5212AniCckErrTrigger(ah); + ar5212AniRestart(ah, aniState); + } + } +} + +static void +ar5212AniLowerImmunity(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(ANI_ENA(ah)); + + aniState = ahp->ah_curani; + params = aniState->params; + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrHigh) { + /* + * Beacon signal is high, leave ofdm weak signal + * detection off or it may oscillate. Let it fall + * through. + */ + } else if (rssi > params->rssiThrLow) { + /* + * Beacon rssi in mid range, turn on ofdm weak signal + * detection or lower firstep level. + */ + if (aniState->ofdmWeakSigDetectOff) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d OWSD on\n", __func__, rssi); + ar5212AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE); + return; + } + if (aniState->firstepLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d lower ST %u\n", __func__, rssi, + aniState->firstepLevel-1); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1); + return; + } + } else { + /* + * Beacon rssi is low, reduce firstep level. + */ + if (aniState->firstepLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d lower ST %u\n", __func__, rssi, + aniState->firstepLevel-1); + ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1); + return; + } + } + } + /* then lower spur immunity level, down to zero */ + if (aniState->spurImmunityLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: lower SI %u\n", + __func__, aniState->spurImmunityLevel-1); + ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel - 1); + return; + } + /* + * if all else fails, lower noise immunity level down to a min value + * zero for now + */ + if (aniState->noiseImmunityLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: lower NI %u\n", + __func__, aniState->noiseImmunityLevel-1); + ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel - 1); + return; + } +} + +#define CLOCK_RATE 44000 /* XXX use mac_usec or similar */ +/* convert HW counter values to ms using 11g clock rate, goo9d enough + for 11a and Turbo */ + +/* + * Return an approximation of the time spent ``listening'' by + * deducting the cycles spent tx'ing and rx'ing from the total + * cycle count since our last call. A return value <0 indicates + * an invalid/inconsistent time. + */ +static int32_t +ar5212AniGetListenTime(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState = NULL; + int32_t listenTime = 0; + int good; + HAL_SURVEY_SAMPLE hs; + + /* + * We shouldn't see ah_curchan be NULL, but just in case.. + */ + if (AH_PRIVATE(ah)->ah_curchan == AH_NULL) { + ath_hal_printf(ah, "%s: ah_curchan = NULL?\n", __func__); + return (0); + } + + /* + * Fetch the current statistics, squirrel away the current + * sample, bump the sequence/sample counter. + */ + OS_MEMZERO(&hs, sizeof(hs)); + good = ar5212GetMibCycleCounts(ah, &hs); + ath_hal_survey_add_sample(ah, &hs); + + if (ANI_ENA(ah)) + aniState = ahp->ah_curani; + + if (good == AH_FALSE) { + /* + * Cycle counter wrap (or initial call); it's not possible + * to accurately calculate a value because the registers + * right shift rather than wrap--so punt and return 0. + */ + listenTime = 0; + ahp->ah_stats.ast_ani_lzero++; + } else if (ANI_ENA(ah)) { + /* + * Only calculate and update the cycle count if we have + * an ANI state. + */ + int32_t ccdelta = + AH5212(ah)->ah_cycleCount - aniState->cycleCount; + int32_t rfdelta = + AH5212(ah)->ah_rxBusy - aniState->rxFrameCount; + int32_t tfdelta = + AH5212(ah)->ah_txBusy - aniState->txFrameCount; + listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE; + } + + /* + * Again, only update ANI state if we have it. + */ + if (ANI_ENA(ah)) { + aniState->cycleCount = AH5212(ah)->ah_cycleCount; + aniState->rxFrameCount = AH5212(ah)->ah_rxBusy; + aniState->txFrameCount = AH5212(ah)->ah_txBusy; + } + + return listenTime; +} + +/* + * Update ani stats in preparation for listen time processing. + */ +static void +updateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const struct ar5212AniParams *params = aniState->params; + uint32_t phyCnt1, phyCnt2; + int32_t ofdmPhyErrCnt, cckPhyErrCnt; + + HALASSERT(ahp->ah_hasHwPhyCounters); + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + + /* NB: these are not reset-on-read */ + phyCnt1 = OS_REG_READ(ah, AR_PHYCNT1); + phyCnt2 = OS_REG_READ(ah, AR_PHYCNT2); + + /* NB: these are spec'd to never roll-over */ + ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase; + if (ofdmPhyErrCnt < 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "OFDM phyErrCnt %d phyCnt1 0x%x\n", + ofdmPhyErrCnt, phyCnt1); + ofdmPhyErrCnt = AR_PHY_COUNTMAX; + } + ahp->ah_stats.ast_ani_ofdmerrs += + ofdmPhyErrCnt - aniState->ofdmPhyErrCount; + aniState->ofdmPhyErrCount = ofdmPhyErrCnt; + + cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase; + if (cckPhyErrCnt < 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "CCK phyErrCnt %d phyCnt2 0x%x\n", + cckPhyErrCnt, phyCnt2); + cckPhyErrCnt = AR_PHY_COUNTMAX; + } + ahp->ah_stats.ast_ani_cckerrs += + cckPhyErrCnt - aniState->cckPhyErrCount; + aniState->cckPhyErrCount = cckPhyErrCnt; +} + +void +ar5212RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats, + const struct ieee80211_channel *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi; +} + +/* + * Do periodic processing. This routine is called from the + * driver's rx interrupt handler after processing frames. + */ +void +ar5212AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState = ahp->ah_curani; + const struct ar5212AniParams *params; + int32_t listenTime; + + /* Always update from the MIB, for statistics gathering */ + listenTime = ar5212AniGetListenTime(ah); + + /* XXX can aniState be null? */ + if (aniState == AH_NULL) + return; + if (!ANI_ENA(ah)) + return; + + if (listenTime < 0) { + ahp->ah_stats.ast_ani_lneg++; + /* restart ANI period if listenTime is invalid */ + ar5212AniRestart(ah, aniState); + } + /* XXX beware of overflow? */ + aniState->listenTime += listenTime; + + OS_MARK(ah, AH_MARK_ANI_POLL, aniState->listenTime); + + params = aniState->params; + if (aniState->listenTime > 5*params->period) { + /* + * Check to see if need to lower immunity if + * 5 aniPeriods have passed + */ + if (ahp->ah_hasHwPhyCounters) + updateMIBStats(ah, aniState); + if (aniState->ofdmPhyErrCount <= aniState->listenTime * + params->ofdmTrigLow/1000 && + aniState->cckPhyErrCount <= aniState->listenTime * + params->cckTrigLow/1000) + ar5212AniLowerImmunity(ah); + ar5212AniRestart(ah, aniState); + } else if (aniState->listenTime > params->period) { + if (ahp->ah_hasHwPhyCounters) + updateMIBStats(ah, aniState); + /* check to see if need to raise immunity */ + if (aniState->ofdmPhyErrCount > aniState->listenTime * + params->ofdmTrigHigh / 1000) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: OFDM err %u listenTime %u\n", __func__, + aniState->ofdmPhyErrCount, aniState->listenTime); + ar5212AniOfdmErrTrigger(ah); + ar5212AniRestart(ah, aniState); + } else if (aniState->cckPhyErrCount > aniState->listenTime * + params->cckTrigHigh / 1000) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: CCK err %u listenTime %u\n", __func__, + aniState->cckPhyErrCount, aniState->listenTime); + ar5212AniCckErrTrigger(ah); + ar5212AniRestart(ah, aniState); + } + } +} diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_attach.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_attach.c new file mode 100644 index 0000000..a95f244 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_attach.c @@ -0,0 +1,947 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#define AH_5212_COMMON +#include "ar5212/ar5212.ini" + +static void ar5212ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, + HAL_BOOL power_off); +static void ar5212DisablePCIE(struct ath_hal *ah); + +static const struct ath_hal_private ar5212hal = {{ + .ah_magic = AR5212_MAGIC, + + .ah_getRateTable = ar5212GetRateTable, + .ah_detach = ar5212Detach, + + /* Reset Functions */ + .ah_reset = ar5212Reset, + .ah_phyDisable = ar5212PhyDisable, + .ah_disable = ar5212Disable, + .ah_configPCIE = ar5212ConfigPCIE, + .ah_disablePCIE = ar5212DisablePCIE, + .ah_setPCUConfig = ar5212SetPCUConfig, + .ah_perCalibration = ar5212PerCalibration, + .ah_perCalibrationN = ar5212PerCalibrationN, + .ah_resetCalValid = ar5212ResetCalValid, + .ah_setTxPowerLimit = ar5212SetTxPowerLimit, + .ah_getChanNoise = ath_hal_getChanNoise, + + /* Transmit functions */ + .ah_updateTxTrigLevel = ar5212UpdateTxTrigLevel, + .ah_setupTxQueue = ar5212SetupTxQueue, + .ah_setTxQueueProps = ar5212SetTxQueueProps, + .ah_getTxQueueProps = ar5212GetTxQueueProps, + .ah_releaseTxQueue = ar5212ReleaseTxQueue, + .ah_resetTxQueue = ar5212ResetTxQueue, + .ah_getTxDP = ar5212GetTxDP, + .ah_setTxDP = ar5212SetTxDP, + .ah_numTxPending = ar5212NumTxPending, + .ah_startTxDma = ar5212StartTxDma, + .ah_stopTxDma = ar5212StopTxDma, + .ah_setupTxDesc = ar5212SetupTxDesc, + .ah_setupXTxDesc = ar5212SetupXTxDesc, + .ah_fillTxDesc = ar5212FillTxDesc, + .ah_procTxDesc = ar5212ProcTxDesc, + .ah_getTxIntrQueue = ar5212GetTxIntrQueue, + .ah_reqTxIntrDesc = ar5212IntrReqTxDesc, + .ah_getTxCompletionRates = ar5212GetTxCompletionRates, + .ah_setTxDescLink = ar5212SetTxDescLink, + .ah_getTxDescLink = ar5212GetTxDescLink, + .ah_getTxDescLinkPtr = ar5212GetTxDescLinkPtr, + + /* RX Functions */ + .ah_getRxDP = ar5212GetRxDP, + .ah_setRxDP = ar5212SetRxDP, + .ah_enableReceive = ar5212EnableReceive, + .ah_stopDmaReceive = ar5212StopDmaReceive, + .ah_startPcuReceive = ar5212StartPcuReceive, + .ah_stopPcuReceive = ar5212StopPcuReceive, + .ah_setMulticastFilter = ar5212SetMulticastFilter, + .ah_setMulticastFilterIndex = ar5212SetMulticastFilterIndex, + .ah_clrMulticastFilterIndex = ar5212ClrMulticastFilterIndex, + .ah_getRxFilter = ar5212GetRxFilter, + .ah_setRxFilter = ar5212SetRxFilter, + .ah_setupRxDesc = ar5212SetupRxDesc, + .ah_procRxDesc = ar5212ProcRxDesc, + .ah_rxMonitor = ar5212RxMonitor, + .ah_aniPoll = ar5212AniPoll, + .ah_procMibEvent = ar5212ProcessMibIntr, + + /* Misc Functions */ + .ah_getCapability = ar5212GetCapability, + .ah_setCapability = ar5212SetCapability, + .ah_getDiagState = ar5212GetDiagState, + .ah_getMacAddress = ar5212GetMacAddress, + .ah_setMacAddress = ar5212SetMacAddress, + .ah_getBssIdMask = ar5212GetBssIdMask, + .ah_setBssIdMask = ar5212SetBssIdMask, + .ah_setRegulatoryDomain = ar5212SetRegulatoryDomain, + .ah_setLedState = ar5212SetLedState, + .ah_writeAssocid = ar5212WriteAssocid, + .ah_gpioCfgInput = ar5212GpioCfgInput, + .ah_gpioCfgOutput = ar5212GpioCfgOutput, + .ah_gpioGet = ar5212GpioGet, + .ah_gpioSet = ar5212GpioSet, + .ah_gpioSetIntr = ar5212GpioSetIntr, + .ah_getTsf32 = ar5212GetTsf32, + .ah_getTsf64 = ar5212GetTsf64, + .ah_setTsf64 = ar5212SetTsf64, + .ah_resetTsf = ar5212ResetTsf, + .ah_detectCardPresent = ar5212DetectCardPresent, + .ah_updateMibCounters = ar5212UpdateMibCounters, + .ah_getRfGain = ar5212GetRfgain, + .ah_getDefAntenna = ar5212GetDefAntenna, + .ah_setDefAntenna = ar5212SetDefAntenna, + .ah_getAntennaSwitch = ar5212GetAntennaSwitch, + .ah_setAntennaSwitch = ar5212SetAntennaSwitch, + .ah_setSifsTime = ar5212SetSifsTime, + .ah_getSifsTime = ar5212GetSifsTime, + .ah_setSlotTime = ar5212SetSlotTime, + .ah_getSlotTime = ar5212GetSlotTime, + .ah_setAckTimeout = ar5212SetAckTimeout, + .ah_getAckTimeout = ar5212GetAckTimeout, + .ah_setAckCTSRate = ar5212SetAckCTSRate, + .ah_getAckCTSRate = ar5212GetAckCTSRate, + .ah_setCTSTimeout = ar5212SetCTSTimeout, + .ah_getCTSTimeout = ar5212GetCTSTimeout, + .ah_setDecompMask = ar5212SetDecompMask, + .ah_setCoverageClass = ar5212SetCoverageClass, + .ah_setQuiet = ar5212SetQuiet, + .ah_getMibCycleCounts = ar5212GetMibCycleCounts, + .ah_setChainMasks = ar5212SetChainMasks, + + /* DFS Functions */ + .ah_enableDfs = ar5212EnableDfs, + .ah_getDfsThresh = ar5212GetDfsThresh, + .ah_getDfsDefaultThresh = ar5212GetDfsDefaultThresh, + .ah_procRadarEvent = ar5212ProcessRadarEvent, + .ah_isFastClockEnabled = ar5212IsFastClockEnabled, + .ah_get11nExtBusy = ar5212Get11nExtBusy, + + /* Key Cache Functions */ + .ah_getKeyCacheSize = ar5212GetKeyCacheSize, + .ah_resetKeyCacheEntry = ar5212ResetKeyCacheEntry, + .ah_isKeyCacheEntryValid = ar5212IsKeyCacheEntryValid, + .ah_setKeyCacheEntry = ar5212SetKeyCacheEntry, + .ah_setKeyCacheEntryMac = ar5212SetKeyCacheEntryMac, + + /* Power Management Functions */ + .ah_setPowerMode = ar5212SetPowerMode, + .ah_getPowerMode = ar5212GetPowerMode, + + /* Beacon Functions */ + .ah_setBeaconTimers = ar5212SetBeaconTimers, + .ah_beaconInit = ar5212BeaconInit, + .ah_setStationBeaconTimers = ar5212SetStaBeaconTimers, + .ah_resetStationBeaconTimers = ar5212ResetStaBeaconTimers, + .ah_getNextTBTT = ar5212GetNextTBTT, + + /* Interrupt Functions */ + .ah_isInterruptPending = ar5212IsInterruptPending, + .ah_getPendingInterrupts = ar5212GetPendingInterrupts, + .ah_getInterrupts = ar5212GetInterrupts, + .ah_setInterrupts = ar5212SetInterrupts }, + + .ah_getChannelEdges = ar5212GetChannelEdges, + .ah_getWirelessModes = ar5212GetWirelessModes, + .ah_eepromRead = ar5212EepromRead, +#ifdef AH_SUPPORT_WRITE_EEPROM + .ah_eepromWrite = ar5212EepromWrite, +#endif + .ah_getChipPowerLimits = ar5212GetChipPowerLimits, +}; + +uint32_t +ar5212GetRadioRev(struct ath_hal *ah) +{ + uint32_t val; + int i; + + /* Read Radio Chip Rev Extract */ + OS_REG_WRITE(ah, AR_PHY(0x34), 0x00001c16); + for (i = 0; i < 8; i++) + OS_REG_WRITE(ah, AR_PHY(0x20), 0x00010000); + val = (OS_REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; + val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); + return ath_hal_reverseBits(val, 8); +} + +static void +ar5212AniSetup(struct ath_hal *ah) +{ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -55, -55, -55, -55, -62 }, + .coarseHigh = { -14, -14, -14, -14, -12 }, + .coarseLow = { -64, -64, -64, -64, -70 }, + .firpwr = { -78, -78, -78, -78, -80 }, + .maxSpurImmunityLevel = 2, /* NB: depends on chip rev */ + .cycPwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN) { + struct ar5212AniParams tmp; + OS_MEMCPY(&tmp, &aniparams, sizeof(struct ar5212AniParams)); + tmp.maxSpurImmunityLevel = 7; /* Venice and earlier */ + ar5212AniAttach(ah, &tmp, &tmp, AH_TRUE); + } else + ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE); + + /* Set overridable ANI methods */ + AH5212(ah)->ah_aniControl = ar5212AniControl; +} + +/* + * Attach for an AR5212 part. + */ +void +ar5212InitState(struct ath_hal_5212 *ahp, uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + static const uint8_t defbssidmask[IEEE80211_ADDR_LEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + struct ath_hal *ah; + + ah = &ahp->ah_priv.h; + /* set initial values */ + OS_MEMCPY(&ahp->ah_priv, &ar5212hal, sizeof(struct ath_hal_private)); + ah->ah_sc = sc; + ah->ah_st = st; + ah->ah_sh = sh; + + ah->ah_devid = devid; /* NB: for alq */ + AH_PRIVATE(ah)->ah_devid = devid; + AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */ + + AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER; + AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ + + ahp->ah_antControl = HAL_ANT_VARIABLE; + ahp->ah_diversity = AH_TRUE; + ahp->ah_bIQCalibration = AH_FALSE; + /* + * Enable MIC handling. + */ + ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE; + ahp->ah_rssiThr = INIT_RSSI_THR; + ahp->ah_tpcEnabled = AH_FALSE; /* disabled by default */ + ahp->ah_phyPowerOn = AH_FALSE; + ahp->ah_macTPC = SM(MAX_RATE_POWER, AR_TPC_ACK) + | SM(MAX_RATE_POWER, AR_TPC_CTS) + | SM(MAX_RATE_POWER, AR_TPC_CHIRP); + ahp->ah_beaconInterval = 100; /* XXX [20..1000] */ + ahp->ah_enable32kHzClock = DONT_USE_32KHZ;/* XXX */ + ahp->ah_slottime = (u_int) -1; + ahp->ah_acktimeout = (u_int) -1; + ahp->ah_ctstimeout = (u_int) -1; + ahp->ah_sifstime = (u_int) -1; + ahp->ah_txTrigLev = INIT_TX_FIFO_THRESHOLD, + ahp->ah_maxTxTrigLev = MAX_TX_FIFO_THRESHOLD, + + OS_MEMCPY(&ahp->ah_bssidmask, defbssidmask, IEEE80211_ADDR_LEN); +#undef N +} + +/* + * Validate MAC version and revision. + */ +static HAL_BOOL +ar5212IsMacSupported(uint8_t macVersion, uint8_t macRev) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + static const struct { + uint8_t version; + uint8_t revMin, revMax; + } macs[] = { + { AR_SREV_VERSION_VENICE, + AR_SREV_D2PLUS, AR_SREV_REVISION_MAX }, + { AR_SREV_VERSION_GRIFFIN, + AR_SREV_D2PLUS, AR_SREV_REVISION_MAX }, + { AR_SREV_5413, + AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX }, + { AR_SREV_5424, + AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX }, + { AR_SREV_2425, + AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX }, + { AR_SREV_2417, + AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX }, + }; + int i; + + for (i = 0; i < N(macs); i++) + if (macs[i].version == macVersion && + macs[i].revMin <= macRev && macRev <= macs[i].revMax) + return AH_TRUE; + return AH_FALSE; +#undef N +} + +/* + * Attach for an AR5212 part. + */ +static struct ath_hal * +ar5212Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) +{ +#define AH_EEPROM_PROTECT(ah) \ + (AH_PRIVATE(ah)->ah_ispcie)? AR_EEPROM_PROTECT_PCIE : AR_EEPROM_PROTECT) + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + struct ath_hal_rf *rf; + uint32_t val; + uint16_t eeval; + HAL_STATUS ecode; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp = ath_hal_malloc(sizeof (struct ath_hal_5212)); + if (ahp == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ar5212InitState(ahp, devid, sc, st, sh, status); + ah = &ahp->ah_priv.h; + + if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + /* Read Revisions from Chips before taking out of reset */ + val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID; + AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S; + AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION; + AH_PRIVATE(ah)->ah_ispcie = IS_5424(ah) || IS_2425(ah); + + if (!ar5212IsMacSupported(AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Mac Chip Rev 0x%02x.%x not supported\n" , + __func__, AH_PRIVATE(ah)->ah_macVersion, + AH_PRIVATE(ah)->ah_macRev); + ecode = HAL_ENOTSUPP; + goto bad; + } + + /* setup common ini data; rf backends handle remainder */ + HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2); + + if (!ar5212ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + ecode = HAL_EIO; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (AH_PRIVATE(ah)->ah_ispcie) { + /* XXX: build flag to disable this? */ + ath_hal_configPCIE(ah, AH_FALSE, AH_FALSE); + } + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* Enable PCI core retry fix in software for Hainan and up */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_VENICE) + OS_REG_SET_BIT(ah, AR_PCICFG, AR_PCICFG_RETRYFIXEN); + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah); + + rf = ath_hal_rfprobe(ah, &ecode); + if (rf == AH_NULL) + goto bad; + + /* NB: silently accept anything in release code per Atheros */ + switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { + case AR_RAD5111_SREV_MAJOR: + case AR_RAD5112_SREV_MAJOR: + case AR_RAD2112_SREV_MAJOR: + case AR_RAD2111_SREV_MAJOR: + case AR_RAD2413_SREV_MAJOR: + case AR_RAD5413_SREV_MAJOR: + case AR_RAD5424_SREV_MAJOR: + break; + default: + if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { + /* + * When RF_Silent is used, the + * analog chip is reset. So when the system boots + * up with the radio switch off we cannot determine + * the RF chip rev. To workaround this check the + * mac+phy revs and if Hainan, set the radio rev + * to Derby. + */ + if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && + AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN && + AH_PRIVATE(ah)->ah_phyRev == AR_PHYREV_HAINAN) { + AH_PRIVATE(ah)->ah_analog5GhzRev = AR_ANALOG5REV_HAINAN; + break; + } + if (IS_2413(ah)) { /* Griffin */ + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD2413_SREV_MAJOR | 0x1; + break; + } + if (IS_5413(ah)) { /* Eagle */ + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5413_SREV_MAJOR | 0x2; + break; + } + if (IS_2425(ah) || IS_2417(ah)) {/* Swan or Nala */ + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5424_SREV_MAJOR | 0x2; + break; + } + } +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by " + "this driver\n", + __func__, AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; +#endif + } + if (IS_RAD5112_REV1(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5112 Rev 1 is not supported by this " + "driver (analog5GhzRev 0x%x)\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; + } + + val = OS_REG_READ(ah, AR_PCICFG); + val = MS(val, AR_PCICFG_EEPROM_SIZE); + if (val == 0) { + if (!AH_PRIVATE(ah)->ah_ispcie) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unsupported EEPROM size %u (0x%x) found\n", + __func__, val, val); + ecode = HAL_EESIZE; + goto bad; + } + /* XXX AH_PRIVATE(ah)->ah_isPciExpress = AH_TRUE; */ + } else if (val != AR_PCICFG_EEPROM_SIZE_16K) { + if (AR_PCICFG_EEPROM_SIZE_FAILED == val) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unsupported EEPROM size %u (0x%x) found\n", + __func__, val, val); + ecode = HAL_EESIZE; + goto bad; + } + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: EEPROM size = %d. Must be %d (16k).\n", + __func__, val, AR_PCICFG_EEPROM_SIZE_16K); + ecode = HAL_EESIZE; + goto bad; + } + ecode = ath_hal_legacyEepromAttach(ah); + if (ecode != HAL_OK) { + goto bad; + } + ahp->ah_isHb63 = IS_2425(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_ISTALON); + + /* + * If Bmode and AR5212, verify 2.4 analog exists + */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) && + (AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD5111_SREV_MAJOR) { + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00004007); + OS_DELAY(2000); + AH_PRIVATE(ah)->ah_analog2GhzRev = ar5212GetRadioRev(ah); + + /* Set baseband for 5GHz chip */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + OS_DELAY(2000); + if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != AR_RAD2111_SREV_MAJOR) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 2G Radio Chip Rev 0x%02X is not " + "supported by this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog2GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; + } + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read regulatory domain from EEPROM\n", + __func__); + goto bad; + } + AH_PRIVATE(ah)->ah_currentRD = eeval; + /* XXX record serial number */ + + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar5212FillCapabilityInfo(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: failed ar5212FillCapabilityInfo\n", __func__); + ecode = HAL_EEREAD; + goto bad; + } + + if (!rf->attach(ah, &ecode)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + /* + * Set noise floor adjust method; we arrange a + * direct call instead of thunking. + */ + AH_PRIVATE(ah)->ah_getNfAdjust = ahp->ah_rfHal->getNfAdjust; + + /* Initialize gain ladder thermal calibration structure */ + ar5212InitializeGainValues(ah); + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + + ar5212AniSetup(ah); + /* Setup of Radar/AR structures happens in ath_hal_initchannels*/ + ar5212InitNfCalHistBuffer(ah); + + /* XXX EAR stuff goes here */ + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; + +bad: + if (ahp) + ar5212Detach((struct ath_hal *) ahp); + if (status) + *status = ecode; + return AH_NULL; +#undef AH_EEPROM_PROTECT +} + +void +ar5212Detach(struct ath_hal *ah) +{ + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); + + HALASSERT(ah != AH_NULL); + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + ar5212AniDetach(ah); + ar5212RfDetach(ah); + ar5212Disable(ah); + ar5212SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE); + + ath_hal_eepromDetach(ah); + ath_hal_free(ah); +} + +HAL_BOOL +ar5212ChipTest(struct ath_hal *ah) +{ + uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) }; + uint32_t regHold[2]; + uint32_t patternData[4] = + { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 }; + int i, j; + + /* Test PHY & MAC registers */ + for (i = 0; i < 2; i++) { + uint32_t addr = regAddr[i]; + uint32_t wrData, rdData; + + regHold[i] = OS_REG_READ(ah, addr); + for (j = 0; j < 0x100; j++) { + wrData = (j << 16) | j; + OS_REG_WRITE(ah, addr, wrData); + rdData = OS_REG_READ(ah, addr); + if (rdData != wrData) { + HALDEBUG(ah, HAL_DEBUG_ANY, +"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", + __func__, addr, wrData, rdData); + return AH_FALSE; + } + } + for (j = 0; j < 4; j++) { + wrData = patternData[j]; + OS_REG_WRITE(ah, addr, wrData); + rdData = OS_REG_READ(ah, addr); + if (wrData != rdData) { + HALDEBUG(ah, HAL_DEBUG_ANY, +"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", + __func__, addr, wrData, rdData); + return AH_FALSE; + } + } + OS_REG_WRITE(ah, regAddr[i], regHold[i]); + } + OS_DELAY(100); + return AH_TRUE; +} + +/* + * Store the channel edges for the requested operational mode + */ +HAL_BOOL +ar5212GetChannelEdges(struct ath_hal *ah, + uint16_t flags, uint16_t *low, uint16_t *high) +{ + if (flags & IEEE80211_CHAN_5GHZ) { + *low = 4915; + *high = 6100; + return AH_TRUE; + } + if ((flags & IEEE80211_CHAN_2GHZ) && + (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) || + ath_hal_eepromGetFlag(ah, AR_EEP_GMODE))) { + *low = 2312; + *high = 2732; + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Disable PLL when in L0s as well as receiver clock when in L1. + * This power saving option must be enabled through the Serdes. + * + * Programming the Serdes must go through the same 288 bit serial shift + * register as the other analog registers. Hence the 9 writes. + * + * XXX Clean up the magic numbers. + */ +static void +ar5212ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) +{ + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); + + /* RX shut off when elecidle is asserted */ + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); + + /* Shut off PLL and CLKREQ active in L1 */ + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); + + /* Load the new settings */ + OS_REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); +} + +static void +ar5212DisablePCIE(struct ath_hal *ah) +{ + /* NB: fill in for 9100 */ +} + +/* + * Fill all software cached or static hardware state information. + * Return failure if capabilities are to come from EEPROM and + * cannot be read. + */ +HAL_BOOL +ar5212FillCapabilityInfo(struct ath_hal *ah) +{ +#define AR_KEYTABLE_SIZE 128 +#define IS_GRIFFIN_LITE(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_GRIFFIN && \ + AH_PRIVATE(ah)->ah_macRev == AR_SREV_GRIFFIN_LITE) +#define IS_COBRA(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_COBRA) +#define IS_2112(ah) \ + ((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD2112_SREV_MAJOR) + + struct ath_hal_private *ahpriv = AH_PRIVATE(ah); + HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; + uint16_t capField, val; + + /* Read the capability EEPROM location */ + if (ath_hal_eepromGet(ah, AR_EEP_OPCAP, &capField) != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to read caps from eeprom\n", __func__); + return AH_FALSE; + } + if (IS_2112(ah)) + ath_hal_eepromSet(ah, AR_EEP_AMODE, AH_FALSE); + if (capField == 0 && IS_GRIFFIN_LITE(ah)) { + /* + * For griffin-lite cards with unprogrammed capabilities. + */ + ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE); + ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE); + ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE); + ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE); + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: override caps for griffin-lite, now 0x%x (+!turbo)\n", + __func__, capField); + } + + /* Modify reg domain on newer cards that need to work with older sw */ + if (ahpriv->ah_opmode != HAL_M_HOSTAP && + ahpriv->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) { + if (ahpriv->ah_currentRD == 0x64 || + ahpriv->ah_currentRD == 0x65) + ahpriv->ah_currentRD += 5; + else if (ahpriv->ah_currentRD == 0x41) + ahpriv->ah_currentRD = 0x43; + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: regdomain mapped to 0x%x\n", + __func__, ahpriv->ah_currentRD); + } + + if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2417 || + AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2425) { + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: enable Bmode and disable turbo for Swan/Nala\n", + __func__); + ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_TRUE); + ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE); + ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE); + ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE); + ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE); + } + + /* Construct wireless mode from EEPROM */ + pCap->halWirelessModes = 0; + if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { + pCap->halWirelessModes |= HAL_MODE_11A; + if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) + pCap->halWirelessModes |= HAL_MODE_TURBO; + } + if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) + pCap->halWirelessModes |= HAL_MODE_11B; + if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) && + ahpriv->ah_subvendorid != AR_SUBVENDOR_ID_NOG) { + pCap->halWirelessModes |= HAL_MODE_11G; + if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE)) + pCap->halWirelessModes |= HAL_MODE_108G; + } + + pCap->halLow2GhzChan = 2312; + /* XXX 2417 too? */ + if (IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2425(ah) || IS_2417(ah)) + pCap->halHigh2GhzChan = 2500; + else + pCap->halHigh2GhzChan = 2732; + + /* + * For AR5111 version < 4, the lowest centre frequency supported is + * 5130MHz. For AR5111 version 4, the 4.9GHz channels are supported + * but only in 10MHz increments. + * + * In addition, the programming method is wrong - it uses the IEEE + * channel number to calculate the frequency, rather than the + * channel centre. Since half/quarter rates re-use some of the + * 5GHz channel IEEE numbers, this will result in a badly programmed + * synth. + * + * Until the relevant support is written, just limit lower frequency + * support for AR5111 so things aren't incorrectly programmed. + * + * XXX It's also possible this code doesn't correctly limit the + * centre frequencies of potential channels; this is very important + * for half/quarter rate! + */ + if (AH_RADIO_MAJOR(ah) == AR_RAD5111_SREV_MAJOR) { + pCap->halLow5GhzChan = 5120; /* XXX lowest centre = 5130MHz */ + } else { + pCap->halLow5GhzChan = 4915; + } + pCap->halHigh5GhzChan = 6100; + + pCap->halCipherCkipSupport = AH_FALSE; + pCap->halCipherTkipSupport = AH_TRUE; + pCap->halCipherAesCcmSupport = + (ath_hal_eepromGetFlag(ah, AR_EEP_AES) && + ((AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) || + ((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE) && + (AH_PRIVATE(ah)->ah_macRev >= AR_SREV_VERSION_OAHU)))); + + pCap->halMicCkipSupport = AH_FALSE; + pCap->halMicTkipSupport = AH_TRUE; + pCap->halMicAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES); + /* + * Starting with Griffin TX+RX mic keys can be combined + * in one key cache slot. + */ + if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_GRIFFIN) + pCap->halTkipMicTxRxKeySupport = AH_TRUE; + else + pCap->halTkipMicTxRxKeySupport = AH_FALSE; + pCap->halChanSpreadSupport = AH_TRUE; + pCap->halSleepAfterBeaconBroken = AH_TRUE; + + if (ahpriv->ah_macRev > 1 || IS_COBRA(ah)) { + pCap->halCompressSupport = + ath_hal_eepromGetFlag(ah, AR_EEP_COMPRESS) && + (pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0; + pCap->halBurstSupport = ath_hal_eepromGetFlag(ah, AR_EEP_BURST); + pCap->halFastFramesSupport = + ath_hal_eepromGetFlag(ah, AR_EEP_FASTFRAME) && + (pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0; + pCap->halChapTuningSupport = AH_TRUE; + pCap->halTurboPrimeSupport = AH_TRUE; + } + pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G; + + pCap->halPSPollBroken = AH_TRUE; /* XXX fixed in later revs? */ + pCap->halNumMRRetries = 4; /* Hardware supports 4 MRR */ + pCap->halNumTxMaps = 1; /* Single TX ptr per descr */ + pCap->halVEOLSupport = AH_TRUE; + pCap->halBssIdMaskSupport = AH_TRUE; + pCap->halMcastKeySrchSupport = AH_TRUE; + if ((ahpriv->ah_macVersion == AR_SREV_VERSION_VENICE && + ahpriv->ah_macRev == 8) || + ahpriv->ah_macVersion > AR_SREV_VERSION_VENICE) + pCap->halTsfAddSupport = AH_TRUE; + + if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK) + pCap->halTotalQueues = val; + else + pCap->halTotalQueues = HAL_NUM_TX_QUEUES; + + if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK) + pCap->halKeyCacheSize = val; + else + pCap->halKeyCacheSize = AR_KEYTABLE_SIZE; + + pCap->halChanHalfRate = AH_TRUE; + pCap->halChanQuarterRate = AH_TRUE; + + /* + * RSSI uses the combined field; some 11n NICs may use + * the control chain RSSI. + */ + pCap->halUseCombinedRadarRssi = AH_TRUE; + + if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) && + ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) { + /* NB: enabled by default */ + ahpriv->ah_rfkillEnabled = AH_TRUE; + pCap->halRfSilentSupport = AH_TRUE; + } + + /* NB: this is a guess, noone seems to know the answer */ + ahpriv->ah_rxornIsFatal = + (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_VENICE); + + /* enable features that first appeared in Hainan */ + if ((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && + AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN) || + AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) { + /* h/w phy counters */ + pCap->halHwPhyCounterSupport = AH_TRUE; + /* bssid match disable */ + pCap->halBssidMatchSupport = AH_TRUE; + } + + pCap->halTstampPrecision = 15; + pCap->halIntrMask = HAL_INT_COMMON + | HAL_INT_RX + | HAL_INT_TX + | HAL_INT_FATAL + | HAL_INT_BNR + | HAL_INT_BMISC + ; + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN) + pCap->halIntrMask &= ~HAL_INT_TBTT; + + pCap->hal4kbSplitTransSupport = AH_TRUE; + pCap->halHasRxSelfLinkedTail = AH_TRUE; + + return AH_TRUE; +#undef IS_COBRA +#undef IS_GRIFFIN_LITE +#undef AR_KEYTABLE_SIZE +} + +static const char* +ar5212Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID || + vendorid == ATHEROS_3COM_VENDOR_ID || + vendorid == ATHEROS_3COM2_VENDOR_ID) { + switch (devid) { + case AR5212_FPGA: + return "Atheros 5212 (FPGA)"; + case AR5212_DEVID: + case AR5212_DEVID_IBM: + case AR5212_DEFAULT: + return "Atheros 5212"; + case AR5212_AR2413: + return "Atheros 2413"; + case AR5212_AR2417: + return "Atheros 2417"; + case AR5212_AR5413: + return "Atheros 5413"; + case AR5212_AR5424: + return "Atheros 5424/2424"; + } + } + return AH_NULL; +} +AH_CHIP(AR5212, ar5212Probe, ar5212Attach); diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_beacon.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_beacon.c new file mode 100644 index 0000000..b52077f --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_beacon.c @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212desc.h" + +/* + * Return the hardware NextTBTT in TSF + */ +uint64_t +ar5212GetNextTBTT(struct ath_hal *ah) +{ +#define TU_TO_TSF(_tu) (((uint64_t)(_tu)) << 10) + return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0)); +#undef TU_TO_TSF +} + +/* + * Initialize all of the hardware registers used to + * send beacons. Note that for station operation the + * driver calls ar5212SetStaBeaconTimers instead. + */ +void +ar5212SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* + * Limit the timers to their specific resolutions: + * + * + Timer 0 - 0..15 0xffff TU + * + Timer 1 - 0..18 0x7ffff TU/8 + * + Timer 2 - 0..24 0x1ffffff TU/8 + * + Timer 3 - 0..15 0xffff TU + */ + OS_REG_WRITE(ah, AR_TIMER0, bt->bt_nexttbtt & 0xffff); + OS_REG_WRITE(ah, AR_TIMER1, bt->bt_nextdba & 0x7ffff); + OS_REG_WRITE(ah, AR_TIMER2, bt->bt_nextswba & 0x1ffffff); + /* XXX force nextatim to be non-zero? */ + OS_REG_WRITE(ah, AR_TIMER3, bt->bt_nextatim & 0xffff); + /* + * Set the Beacon register after setting all timers. + */ + if (bt->bt_intval & AR_BEACON_RESET_TSF) { + /* + * When resetting the TSF, + * write twice to the corresponding register; each + * write to the RESET_TSF bit toggles the internal + * signal to cause a reset of the TSF - but if the signal + * is left high, it will reset the TSF on the next + * chip reset also! writing the bit an even number + * of times fixes this issue + */ + OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_RESET_TSF); + } + OS_REG_WRITE(ah, AR_BEACON, bt->bt_intval); + ahp->ah_beaconInterval = (bt->bt_intval & HAL_BEACON_PERIOD); +} + +/* + * Old api for setting up beacon timer registers when + * operating in !station mode. Note the fixed constants + * adjusting the DBA and SWBA timers and the fixed ATIM + * window. + */ +void +ar5212BeaconInit(struct ath_hal *ah, + uint32_t next_beacon, uint32_t beacon_period) +{ + HAL_BEACON_TIMERS bt; + + bt.bt_nexttbtt = next_beacon; + /* + * TIMER1: in AP/adhoc mode this controls the DMA beacon + * alert timer; otherwise it controls the next wakeup time. + * TIMER2: in AP mode, it controls the SBA beacon alert + * interrupt; otherwise it sets the start of the next CFP. + */ + switch (AH_PRIVATE(ah)->ah_opmode) { + case HAL_M_STA: + case HAL_M_MONITOR: + bt.bt_nextdba = 0xffff; + bt.bt_nextswba = 0x7ffff; + break; + case HAL_M_HOSTAP: + case HAL_M_IBSS: + bt.bt_nextdba = (next_beacon - + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ + bt.bt_nextswba = (next_beacon - + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ + break; + } + /* + * Set the ATIM window + * Our hardware does not support an ATIM window of 0 + * (beacons will not work). If the ATIM windows is 0, + * force it to 1. + */ + bt.bt_nextatim = next_beacon + 1; + bt.bt_intval = beacon_period & + (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN); + ar5212SetBeaconTimers(ah, &bt); +} + +void +ar5212ResetStaBeaconTimers(struct ath_hal *ah) +{ + uint32_t val; + + OS_REG_WRITE(ah, AR_TIMER0, 0); /* no beacons */ + val = OS_REG_READ(ah, AR_STA_ID1); + val |= AR_STA_ID1_PWR_SAV; /* XXX */ + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + val & ~(AR_STA_ID1_USE_DEFANT | AR_STA_ID1_PCF)); + OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_PERIOD); +} + +/* + * Set all the beacon related bits on the h/w for stations + * i.e. initializes the corresponding h/w timers; + * also tells the h/w whether to anticipate PCF beacons + */ +void +ar5212SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t nextTbtt, nextdtim,beaconintval, dtimperiod; + + HALASSERT(bs->bs_intval != 0); + /* if the AP will do PCF */ + if (bs->bs_cfpmaxduration != 0) { + /* tell the h/w that the associated AP is PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PCF); + + /* set CFP_PERIOD(1.024ms) register */ + OS_REG_WRITE(ah, AR_CFP_PERIOD, bs->bs_cfpperiod); + + /* set CFP_DUR(1.024ms) register to max cfp duration */ + OS_REG_WRITE(ah, AR_CFP_DUR, bs->bs_cfpmaxduration); + + /* set TIMER2(128us) to anticipated time of next CFP */ + OS_REG_WRITE(ah, AR_TIMER2, bs->bs_cfpnext << 3); + } else { + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + OS_REG_READ(ah, AR_STA_ID1) &~ AR_STA_ID1_PCF); + } + + /* + * Set TIMER0(1.024ms) to the anticipated time of the next beacon. + */ + OS_REG_WRITE(ah, AR_TIMER0, bs->bs_nexttbtt); + + /* + * Start the beacon timers by setting the BEACON register + * to the beacon interval; also write the tim offset which + * we should know by now. The code, in ar5211WriteAssocid, + * also sets the tim offset once the AID is known which can + * be left as such for now. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_PERIOD|AR_BEACON_TIM)) + | SM(bs->bs_intval, AR_BEACON_PERIOD) + | SM(bs->bs_timoffset ? bs->bs_timoffset + 4 : 0, AR_BEACON_TIM) + ); + + /* + * Configure the BMISS interrupt. Note that we + * assume the caller blocks interrupts while enabling + * the threshold. + */ + HALASSERT(bs->bs_bmissthreshold <= MS(0xffffffff, AR_RSSI_THR_BM_THR)); + ahp->ah_rssiThr = (ahp->ah_rssiThr &~ AR_RSSI_THR_BM_THR) + | SM(bs->bs_bmissthreshold, AR_RSSI_THR_BM_THR); + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + + /* + * Program the sleep registers to correlate with the beacon setup. + */ + + /* + * Oahu beacons timers on the station were used for power + * save operation (waking up in anticipation of a beacon) + * and any CFP function; Venice does sleep/power-save timers + * differently - so this is the right place to set them up; + * don't think the beacon timers are used by venice sta hw + * for any useful purpose anymore + * Setup venice's sleep related timers + * Current implementation assumes sw processing of beacons - + * assuming an interrupt is generated every beacon which + * causes the hardware to become awake until the sw tells + * it to go to sleep again; beacon timeout is to allow for + * beacon jitter; cab timeout is max time to wait for cab + * after seeing the last DTIM or MORE CAB bit + */ +#define CAB_TIMEOUT_VAL 10 /* in TU */ +#define BEACON_TIMEOUT_VAL 10 /* in TU */ +#define SLEEP_SLOP 3 /* in TU */ + + /* + * For max powersave mode we may want to sleep for longer than a + * beacon period and not want to receive all beacons; modify the + * timers accordingly; make sure to align the next TIM to the + * next DTIM if we decide to wake for DTIMs only + */ + beaconintval = bs->bs_intval & HAL_BEACON_PERIOD; + HALASSERT(beaconintval != 0); + if (bs->bs_sleepduration > beaconintval) { + HALASSERT(roundup(bs->bs_sleepduration, beaconintval) == + bs->bs_sleepduration); + beaconintval = bs->bs_sleepduration; + } + dtimperiod = bs->bs_dtimperiod; + if (bs->bs_sleepduration > dtimperiod) { + HALASSERT(dtimperiod == 0 || + roundup(bs->bs_sleepduration, dtimperiod) == + bs->bs_sleepduration); + dtimperiod = bs->bs_sleepduration; + } + HALASSERT(beaconintval <= dtimperiod); + if (beaconintval == dtimperiod) + nextTbtt = bs->bs_nextdtim; + else + nextTbtt = bs->bs_nexttbtt; + nextdtim = bs->bs_nextdtim; + + OS_REG_WRITE(ah, AR_SLEEP1, + SM((nextdtim - SLEEP_SLOP) << 3, AR_SLEEP1_NEXT_DTIM) + | SM(CAB_TIMEOUT_VAL, AR_SLEEP1_CAB_TIMEOUT) + | AR_SLEEP1_ASSUME_DTIM + | AR_SLEEP1_ENH_SLEEP_ENA + ); + OS_REG_WRITE(ah, AR_SLEEP2, + SM((nextTbtt - SLEEP_SLOP) << 3, AR_SLEEP2_NEXT_TIM) + | SM(BEACON_TIMEOUT_VAL, AR_SLEEP2_BEACON_TIMEOUT) + ); + OS_REG_WRITE(ah, AR_SLEEP3, + SM(beaconintval, AR_SLEEP3_TIM_PERIOD) + | SM(dtimperiod, AR_SLEEP3_DTIM_PERIOD) + ); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n", + __func__, bs->bs_nextdtim); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next beacon %d\n", + __func__, nextTbtt); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: beacon period %d\n", + __func__, beaconintval); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: DTIM period %d\n", + __func__, dtimperiod); +#undef CAB_TIMEOUT_VAL +#undef BEACON_TIMEOUT_VAL +#undef SLEEP_SLOP +} diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_eeprom.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_eeprom.c new file mode 100644 index 0000000..f4b6771 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_eeprom.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#ifdef AH_DEBUG +#include "ah_desc.h" /* NB: for HAL_PHYERR* */ +#endif + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +/* + * Read 16 bits of data from offset into *data + */ +HAL_BOOL +ar5212EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) +{ + OS_REG_WRITE(ah, AR_EEPROM_ADDR, off); + OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_READ); + + if (!ath_hal_wait(ah, AR_EEPROM_STS, + AR_EEPROM_STS_READ_COMPLETE | AR_EEPROM_STS_READ_ERROR, + AR_EEPROM_STS_READ_COMPLETE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n", + __func__, off); + return AH_FALSE; + } + *data = OS_REG_READ(ah, AR_EEPROM_DATA) & 0xffff; + return AH_TRUE; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_gpio.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_gpio.c new file mode 100644 index 0000000..b2363af --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_gpio.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#ifdef AH_DEBUG +#include "ah_desc.h" /* NB: for HAL_PHYERR* */ +#endif + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#define AR_NUM_GPIO 6 /* 6 GPIO pins */ +#define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */ + +/* + * Configure GPIO Output lines + */ +HAL_BOOL +ar5212GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) +{ + HALASSERT(gpio < AR_NUM_GPIO); + + /* + * NB: AR_GPIOCR_CR_A(pin) is all 1's so there's no need + * to clear the field before or'ing in the new value. + */ + OS_REG_WRITE(ah, AR_GPIOCR, + OS_REG_READ(ah, AR_GPIOCR) | AR_GPIOCR_CR_A(gpio)); + + return AH_TRUE; +} + +/* + * Configure GPIO Input lines + */ +HAL_BOOL +ar5212GpioCfgInput(struct ath_hal *ah, uint32_t gpio) +{ + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, AR_GPIOCR, + (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_CR_A(gpio)) + | AR_GPIOCR_CR_N(gpio)); + + return AH_TRUE; +} + +/* + * Once configured for I/O - set output lines + */ +HAL_BOOL +ar5212GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) +{ + uint32_t reg; + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, AR_GPIODO); + reg &= ~(1 << gpio); + reg |= (val&1) << gpio; + + OS_REG_WRITE(ah, AR_GPIODO, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - get input lines + */ +uint32_t +ar5212GpioGet(struct ath_hal *ah, uint32_t gpio) +{ + if (gpio < AR_NUM_GPIO) { + uint32_t val = OS_REG_READ(ah, AR_GPIODI); + val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1; + return val; + } else { + return 0xffffffff; + } +} + +/* + * Set the GPIO Interrupt + */ +void +ar5212GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) +{ + uint32_t val; + + /* XXX bounds check gpio */ + val = OS_REG_READ(ah, AR_GPIOCR); + val &= ~(AR_GPIOCR_CR_A(gpio) | + AR_GPIOCR_INT_MASK | AR_GPIOCR_INT_ENA | AR_GPIOCR_INT_SEL); + val |= AR_GPIOCR_CR_N(gpio) | AR_GPIOCR_INT(gpio) | AR_GPIOCR_INT_ENA; + if (ilevel) + val |= AR_GPIOCR_INT_SELH; /* interrupt on pin high */ + else + val |= AR_GPIOCR_INT_SELL; /* interrupt on pin low */ + + /* Don't need to change anything for low level interrupt. */ + OS_REG_WRITE(ah, AR_GPIOCR, val); + + /* Change the interrupt mask. */ + (void) ar5212SetInterrupts(ah, AH5212(ah)->ah_maskReg | HAL_INT_GPIO); +} diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_interrupts.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_interrupts.c new file mode 100644 index 0000000..47f9e74 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_interrupts.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + + +/* + * Checks to see if an interrupt is pending on our NIC + * + * Returns: TRUE if an interrupt is pending + * FALSE if not + */ +HAL_BOOL +ar5212IsInterruptPending(struct ath_hal *ah) +{ + /* + * Some platforms trigger our ISR before applying power to + * the card, so make sure the INTPEND is really 1, not 0xffffffff. + */ + return (OS_REG_READ(ah, AR_INTPEND) == AR_INTPEND_TRUE); +} + +/* + * Reads the Interrupt Status Register value from the NIC, thus deasserting + * the interrupt line, and returns both the masked and unmasked mapped ISR + * values. The value returned is mapped to abstract the hw-specific bit + * locations in the Interrupt Status Register. + * + * Returns: A hardware-abstracted bitmap of all non-masked-out + * interrupts pending, as well as an unmasked value + */ +HAL_BOOL +ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) +{ + uint32_t isr, isr0, isr1; + uint32_t mask2; + struct ath_hal_5212 *ahp = AH5212(ah); + + isr = OS_REG_READ(ah, AR_ISR); + mask2 = 0; + if (isr & AR_ISR_BCNMISC) { + uint32_t isr2 = OS_REG_READ(ah, AR_ISR_S2); + if (isr2 & AR_ISR_S2_TIM) + mask2 |= HAL_INT_TIM; + if (isr2 & AR_ISR_S2_DTIM) + mask2 |= HAL_INT_DTIM; + if (isr2 & AR_ISR_S2_DTIMSYNC) + mask2 |= HAL_INT_DTIMSYNC; + if (isr2 & AR_ISR_S2_CABEND) + mask2 |= HAL_INT_CABEND; + if (isr2 & AR_ISR_S2_TBTT) + mask2 |= HAL_INT_TBTT; + } + isr = OS_REG_READ(ah, AR_ISR_RAC); + if (isr == 0xffffffff) { + *masked = 0; + return AH_FALSE; + } + + *masked = isr & HAL_INT_COMMON; + + if (isr & AR_ISR_HIUERR) + *masked |= HAL_INT_FATAL; + if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) + *masked |= HAL_INT_RX; + if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) { + *masked |= HAL_INT_TX; + isr0 = OS_REG_READ(ah, AR_ISR_S0_S); + ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXOK); + ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXDESC); + isr1 = OS_REG_READ(ah, AR_ISR_S1_S); + ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXERR); + ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL); + } + + /* + * Receive overrun is usually non-fatal on Oahu/Spirit. + * BUT on some parts rx could fail and the chip must be reset. + * So we force a hardware reset in all cases. + */ + if ((isr & AR_ISR_RXORN) && AH_PRIVATE(ah)->ah_rxornIsFatal) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: receive FIFO overrun interrupt\n", __func__); + *masked |= HAL_INT_FATAL; + } + *masked |= mask2; + + /* + * On fatal errors collect ISR state for debugging. + */ + if (*masked & HAL_INT_FATAL) { + AH_PRIVATE(ah)->ah_fatalState[0] = isr; + AH_PRIVATE(ah)->ah_fatalState[1] = OS_REG_READ(ah, AR_ISR_S0_S); + AH_PRIVATE(ah)->ah_fatalState[2] = OS_REG_READ(ah, AR_ISR_S1_S); + AH_PRIVATE(ah)->ah_fatalState[3] = OS_REG_READ(ah, AR_ISR_S2_S); + AH_PRIVATE(ah)->ah_fatalState[4] = OS_REG_READ(ah, AR_ISR_S3_S); + AH_PRIVATE(ah)->ah_fatalState[5] = OS_REG_READ(ah, AR_ISR_S4_S); + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: fatal error, ISR_RAC=0x%x ISR_S2_S=0x%x\n", + __func__, isr, AH_PRIVATE(ah)->ah_fatalState[3]); + } + return AH_TRUE; +} + +HAL_INT +ar5212GetInterrupts(struct ath_hal *ah) +{ + return AH5212(ah)->ah_maskReg; +} + +/* + * Atomically enables NIC interrupts. Interrupts are passed in + * via the enumerated bitmask in ints. + */ +HAL_INT +ar5212SetInterrupts(struct ath_hal *ah, HAL_INT ints) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t omask = ahp->ah_maskReg; + uint32_t mask, mask2; + + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n", + __func__, omask, ints); + + if (omask & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + (void) OS_REG_READ(ah, AR_IER); /* flush write to HW */ + } + + mask = ints & HAL_INT_COMMON; + mask2 = 0; + if (ints & HAL_INT_TX) { + if (ahp->ah_txOkInterruptMask) + mask |= AR_IMR_TXOK; + if (ahp->ah_txErrInterruptMask) + mask |= AR_IMR_TXERR; + if (ahp->ah_txDescInterruptMask) + mask |= AR_IMR_TXDESC; + if (ahp->ah_txEolInterruptMask) + mask |= AR_IMR_TXEOL; + } + if (ints & HAL_INT_RX) + mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC; + if (ints & (HAL_INT_BMISC)) { + mask |= AR_IMR_BCNMISC; + if (ints & HAL_INT_TIM) + mask2 |= AR_IMR_S2_TIM; + if (ints & HAL_INT_DTIM) + mask2 |= AR_IMR_S2_DTIM; + if (ints & HAL_INT_DTIMSYNC) + mask2 |= AR_IMR_S2_DTIMSYNC; + if (ints & HAL_INT_CABEND) + mask2 |= AR_IMR_S2_CABEND; + if (ints & HAL_INT_TBTT) + mask2 |= AR_IMR_S2_TBTT; + } + if (ints & HAL_INT_FATAL) { + /* + * NB: ar5212Reset sets MCABT+SSERR+DPERR in AR_IMR_S2 + * so enabling HIUERR enables delivery. + */ + mask |= AR_IMR_HIUERR; + } + + /* Write the new IMR and store off our SW copy. */ + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); + OS_REG_WRITE(ah, AR_IMR, mask); + OS_REG_WRITE(ah, AR_IMR_S2, + (OS_REG_READ(ah, AR_IMR_S2) &~ AR_IMR_SR2_BCNMISC) | mask2); + ahp->ah_maskReg = ints; + + /* Re-enable interrupts if they were enabled before. */ + if (ints & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + } + return omask; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_keycache.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_keycache.c new file mode 100644 index 0000000..bf7db49 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_keycache.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212desc.h" + +/* + * Note: The key cache hardware requires that each double-word + * pair be written in even/odd order (since the destination is + * a 64-bit register). Don't reorder the writes in this code + * w/o considering this! + */ +#define KEY_XOR 0xaa + +#define IS_MIC_ENABLED(ah) \ + (AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_CRPT_MIC_ENABLE) + +/* + * Return the size of the hardware key cache. + */ +uint32_t +ar5212GetKeyCacheSize(struct ath_hal *ah) +{ + return AH_PRIVATE(ah)->ah_caps.halKeyCacheSize; +} + +/* + * Return true if the specific key cache entry is valid. + */ +HAL_BOOL +ar5212IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry) +{ + if (entry < AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) { + uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry)); + if (val & AR_KEYTABLE_VALID) + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Clear the specified key cache entry and any associated MIC entry. + */ +HAL_BOOL +ar5212ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry) +{ + uint32_t keyType; + + if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n", + __func__, entry); + return AH_FALSE; + } + keyType = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)); + + /* XXX why not clear key type/valid bit first? */ + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); + if (keyType == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) { + uint16_t micentry = entry+64; /* MIC goes at slot+64 */ + + HALASSERT(micentry < AH_PRIVATE(ah)->ah_caps.halKeyCacheSize); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); + /* NB: key type and MAC are known to be ok */ + } + return AH_TRUE; +} + +/* + * Sets the mac part of the specified key cache entry (and any + * associated MIC entry) and mark them valid. + * + * Since mac[0] is shifted off and not presented to the hardware, + * it does double duty as a "don't use for unicast, use for multicast + * matching" flag. This interface should later be extended to + * explicitly do that rather than overloading a bit in the MAC + * address. + */ +HAL_BOOL +ar5212SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac) +{ + uint32_t macHi, macLo; + uint32_t unicast_flag = AR_KEYTABLE_VALID; + + if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n", + __func__, entry); + return AH_FALSE; + } + /* + * Set MAC address -- shifted right by 1. MacLo is + * the 4 MSBs, and MacHi is the 2 LSBs. + */ + if (mac != AH_NULL) { + /* + * AR_KEYTABLE_VALID indicates that the address is a unicast + * address, which must match the transmitter address for + * decrypting frames. + * Not setting this bit allows the hardware to use the key + * for multicast frame decryption. + */ + if (mac[0] & 0x01) + unicast_flag = 0; + + macHi = (mac[5] << 8) | mac[4]; + macLo = (mac[3] << 24)| (mac[2] << 16) + | (mac[1] << 8) | mac[0]; + macLo >>= 1; + macLo |= (macHi & 1) << 31; /* carry */ + macHi >>= 1; + } else { + macLo = macHi = 0; + } + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag); + return AH_TRUE; +} + +/* + * Sets the contents of the specified key cache entry + * and any associated MIC entry. + */ +HAL_BOOL +ar5212SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, + const HAL_KEYVAL *k, const uint8_t *mac, + int xorKey) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + uint32_t key0, key1, key2, key3, key4; + uint32_t keyType; + uint32_t xorMask = xorKey ? + (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0; + + if (entry >= pCap->halKeyCacheSize) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n", + __func__, entry); + return AH_FALSE; + } + switch (k->kv_type) { + case HAL_CIPHER_AES_OCB: + keyType = AR_KEYTABLE_TYPE_AES; + break; + case HAL_CIPHER_AES_CCM: + if (!pCap->halCipherAesCcmSupport) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: AES-CCM not supported by mac rev 0x%x\n", + __func__, AH_PRIVATE(ah)->ah_macRev); + return AH_FALSE; + } + keyType = AR_KEYTABLE_TYPE_CCM; + break; + case HAL_CIPHER_TKIP: + keyType = AR_KEYTABLE_TYPE_TKIP; + if (IS_MIC_ENABLED(ah) && entry+64 >= pCap->halKeyCacheSize) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: entry %u inappropriate for TKIP\n", + __func__, entry); + return AH_FALSE; + } + break; + case HAL_CIPHER_WEP: + if (k->kv_len < 40 / NBBY) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: WEP key length %u too small\n", + __func__, k->kv_len); + return AH_FALSE; + } + if (k->kv_len <= 40 / NBBY) + keyType = AR_KEYTABLE_TYPE_40; + else if (k->kv_len <= 104 / NBBY) + keyType = AR_KEYTABLE_TYPE_104; + else + keyType = AR_KEYTABLE_TYPE_128; + break; + case HAL_CIPHER_CLR: + keyType = AR_KEYTABLE_TYPE_CLR; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n", + __func__, k->kv_type); + return AH_FALSE; + } + + key0 = LE_READ_4(k->kv_val+0) ^ xorMask; + key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff; + key2 = LE_READ_4(k->kv_val+6) ^ xorMask; + key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff; + key4 = LE_READ_4(k->kv_val+12) ^ xorMask; + if (k->kv_len <= 104 / NBBY) + key4 &= 0xff; + + /* + * Note: key cache hardware requires that each double-word + * pair be written in even/odd order (since the destination is + * a 64-bit register). Don't reorder these writes w/o + * considering this! + */ + if (keyType == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) { + uint16_t micentry = entry+64; /* MIC goes at slot+64 */ + uint32_t mic0, mic1, mic2, mic3, mic4; + + /* + * Invalidate the encrypt/decrypt key until the MIC + * key is installed so pending rx frames will fail + * with decrypt errors rather than a MIC error. + */ + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); + (void) ar5212SetKeyCacheEntryMac(ah, entry, mac); + + + /* + * Write MIC entry according to new or old key layout. + * The MISC_MODE register is assumed already set so + * these writes will be handled properly (happens on + * attach and at every reset). + */ + /* RX mic */ + mic0 = LE_READ_4(k->kv_mic+0); + mic2 = LE_READ_4(k->kv_mic+4); + if (ahp->ah_miscMode & AR_MISC_MODE_MIC_NEW_LOC_ENABLE) { + /* + * Both RX and TX mic values can be combined into + * one cache slot entry: + * 8*N + 800 31:0 RX Michael key 0 + * 8*N + 804 15:0 TX Michael key 0 [31:16] + * 8*N + 808 31:0 RX Michael key 1 + * 8*N + 80C 15:0 TX Michael key 0 [15:0] + * 8*N + 810 31:0 TX Michael key 1 + * 8*N + 814 15:0 reserved + * 8*N + 818 31:0 reserved + * 8*N + 81C 14:0 reserved + * 15 key valid == 0 + */ + /* TX mic */ + mic1 = LE_READ_2(k->kv_txmic+2) & 0xffff; + mic3 = LE_READ_2(k->kv_txmic+0) & 0xffff; + mic4 = LE_READ_4(k->kv_txmic+4); + } else { + mic1 = mic3 = mic4 = 0; + } + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), + AR_KEYTABLE_TYPE_CLR); + /* NB: MIC key is not marked valid and has no MAC address */ + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); + + /* correct intentionally corrupted key */ + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); + } else { + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); + + (void) ar5212SetKeyCacheEntryMac(ah, entry, mac); + } + return AH_TRUE; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_misc.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_misc.c new file mode 100644 index 0000000..e2f1eb7 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_misc.c @@ -0,0 +1,1459 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#include "ah_desc.h" /* NB: for HAL_PHYERR* */ + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +#define AR_NUM_GPIO 6 /* 6 GPIO pins */ +#define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */ + +void +ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *mac) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); + return AH_TRUE; +} + +void +ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mask) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + OS_MEMCPY(mask, ahp->ah_bssidmask, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5212SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* save it since it must be rewritten on reset */ + OS_MEMCPY(ahp->ah_bssidmask, mask, IEEE80211_ADDR_LEN); + + OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); + OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); + return AH_TRUE; +} + +/* + * Attempt to change the cards operating regulatory domain to the given value + */ +HAL_BOOL +ar5212SetRegulatoryDomain(struct ath_hal *ah, + uint16_t regDomain, HAL_STATUS *status) +{ + HAL_STATUS ecode; + + if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { + ecode = HAL_EINVAL; + goto bad; + } + if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { + ecode = HAL_EEWRITE; + goto bad; + } +#ifdef AH_SUPPORT_WRITE_REGDOMAIN + if (ath_hal_eepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: set regulatory domain to %u (0x%x)\n", + __func__, regDomain, regDomain); + AH_PRIVATE(ah)->ah_currentRD = regDomain; + return AH_TRUE; + } +#endif + ecode = HAL_EIO; +bad: + if (status) + *status = ecode; + return AH_FALSE; +} + +/* + * Return the wireless modes (a,b,g,t) supported by hardware. + * + * This value is what is actually supported by the hardware + * and is unaffected by regulatory/country code settings. + */ +u_int +ar5212GetWirelessModes(struct ath_hal *ah) +{ + u_int mode = 0; + + if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { + mode = HAL_MODE_11A; + if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) + mode |= HAL_MODE_TURBO | HAL_MODE_108A; + if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) + mode |= HAL_MODE_11A_HALF_RATE; + if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) + mode |= HAL_MODE_11A_QUARTER_RATE; + } + if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) + mode |= HAL_MODE_11B; + if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) && + AH_PRIVATE(ah)->ah_subvendorid != AR_SUBVENDOR_ID_NOG) { + mode |= HAL_MODE_11G; + if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE)) + mode |= HAL_MODE_108G; + if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) + mode |= HAL_MODE_11G_HALF_RATE; + if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) + mode |= HAL_MODE_11G_QUARTER_RATE; + } + return mode; +} + +/* + * Set the interrupt and GPIO values so the ISR can disable RF + * on a switch signal. Assumes GPIO port and interrupt polarity + * are set prior to call. + */ +void +ar5212EnableRfKill(struct ath_hal *ah) +{ + uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; + int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); + int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); + + /* + * Configure the desired GPIO port for input + * and enable baseband rf silence. + */ + ath_hal_gpioCfgInput(ah, select); + OS_REG_SET_BIT(ah, AR_PHY(0), 0x00002000); + /* + * If radio disable switch connection to GPIO bit x is enabled + * program GPIO interrupt. + * If rfkill bit on eeprom is 1, setupeeprommap routine has already + * verified that it is a later version of eeprom, it has a place for + * rfkill bit and it is set to 1, indicating that GPIO bit x hardware + * connection is present. + */ + ath_hal_gpioSetIntr(ah, select, + (ath_hal_gpioGet(ah, select) == polarity ? !polarity : polarity)); +} + +/* + * Change the LED blinking pattern to correspond to the connectivity + */ +void +ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state) +{ + static const uint32_t ledbits[8] = { + AR_PCICFG_LEDCTL_NONE, /* HAL_LED_INIT */ + AR_PCICFG_LEDCTL_PEND, /* HAL_LED_SCAN */ + AR_PCICFG_LEDCTL_PEND, /* HAL_LED_AUTH */ + AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_ASSOC*/ + AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_RUN */ + AR_PCICFG_LEDCTL_NONE, + AR_PCICFG_LEDCTL_NONE, + AR_PCICFG_LEDCTL_NONE, + }; + uint32_t bits; + + bits = OS_REG_READ(ah, AR_PCICFG); + if (IS_2417(ah)) { + /* + * Enable LED for Nala. There is a bit marked reserved + * that must be set and we also turn on the power led. + * Because we mark s/w LED control setting the control + * status bits below is meangless (the driver must flash + * the LED(s) using the GPIO lines). + */ + bits = (bits &~ AR_PCICFG_LEDMODE) + | SM(AR_PCICFG_LEDMODE_POWON, AR_PCICFG_LEDMODE) +#if 0 + | SM(AR_PCICFG_LEDMODE_NETON, AR_PCICFG_LEDMODE) +#endif + | 0x08000000; + } + bits = (bits &~ AR_PCICFG_LEDCTL) + | SM(ledbits[state & 0x7], AR_PCICFG_LEDCTL); + OS_REG_WRITE(ah, AR_PCICFG, bits); +} + +/* + * Change association related fields programmed into the hardware. + * Writing a valid BSSID to the hardware effectively enables the hardware + * to synchronize its TSF to the correct beacons and receive frames coming + * from that BSSID. It is called by the SME JOIN operation. + */ +void +ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* save bssid for possible re-use on reset */ + OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); + ahp->ah_assocId = assocId; + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | + ((assocId & 0x3fff)<> 32) & 0xffffffff); +} + +/* + * Reset the current hardware tsf for stamlme. + */ +void +ar5212ResetTsf(struct ath_hal *ah) +{ + + uint32_t val = OS_REG_READ(ah, AR_BEACON); + + OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); + /* + * When resetting the TSF, write twice to the + * corresponding register; each write to the RESET_TSF bit toggles + * the internal signal to cause a reset of the TSF - but if the signal + * is left high, it will reset the TSF on the next chip reset also! + * writing the bit an even number of times fixes this issue + */ + OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); +} + +/* + * Set or clear hardware basic rate bit + * Set hardware basic rate set if basic rate is found + * and basic rate is equal or less than 2Mbps + */ +void +ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *rs) +{ + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + uint32_t reg; + uint8_t xset; + int i; + + if (chan == AH_NULL || !IEEE80211_IS_CHAN_CCK(chan)) + return; + xset = 0; + for (i = 0; i < rs->rs_count; i++) { + uint8_t rset = rs->rs_rates[i]; + /* Basic rate defined? */ + if ((rset & 0x80) && (rset &= 0x7f) >= xset) + xset = rset; + } + /* + * Set the h/w bit to reflect whether or not the basic + * rate is found to be equal or less than 2Mbps. + */ + reg = OS_REG_READ(ah, AR_STA_ID1); + if (xset && xset/2 <= 2) + OS_REG_WRITE(ah, AR_STA_ID1, reg | AR_STA_ID1_BASE_RATE_11B); + else + OS_REG_WRITE(ah, AR_STA_ID1, reg &~ AR_STA_ID1_BASE_RATE_11B); +} + +/* + * Grab a semi-random value from hardware registers - may not + * change often + */ +uint32_t +ar5212GetRandomSeed(struct ath_hal *ah) +{ + uint32_t nf; + + nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + return (OS_REG_READ(ah, AR_TSF_U32) ^ + OS_REG_READ(ah, AR_TSF_L32) ^ nf); +} + +/* + * Detect if our card is present + */ +HAL_BOOL +ar5212DetectCardPresent(struct ath_hal *ah) +{ + uint16_t macVersion, macRev; + uint32_t v; + + /* + * Read the Silicon Revision register and compare that + * to what we read at attach time. If the same, we say + * a card/device is present. + */ + v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID; + macVersion = v >> AR_SREV_ID_S; + macRev = v & AR_SREV_REVISION; + return (AH_PRIVATE(ah)->ah_macVersion == macVersion && + AH_PRIVATE(ah)->ah_macRev == macRev); +} + +void +ar5212EnableMibCounters(struct ath_hal *ah) +{ + /* NB: this just resets the mib counter machinery */ + OS_REG_WRITE(ah, AR_MIBC, + ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f); +} + +void +ar5212DisableMibCounters(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_MIBC, AR_MIBC | AR_MIBC_CMC); +} + +/* + * Update MIB Counters + */ +void +ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats) +{ + stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); + stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); + stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); + stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); + stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); +} + +/* + * Detect if the HW supports spreading a CCK signal on channel 14 + */ +HAL_BOOL +ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah) +{ + return AH_TRUE; +} + +/* + * Get the rssi of frame curently being received. + */ +uint32_t +ar5212GetCurRssi(struct ath_hal *ah) +{ + return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff); +} + +u_int +ar5212GetDefAntenna(struct ath_hal *ah) +{ + return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7); +} + +void +ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna) +{ + OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); +} + +HAL_ANT_SETTING +ar5212GetAntennaSwitch(struct ath_hal *ah) +{ + return AH5212(ah)->ah_antControl; +} + +HAL_BOOL +ar5212SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING setting) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + + if (!ahp->ah_phyPowerOn || chan == AH_NULL) { + /* PHY powered off, just stash settings */ + ahp->ah_antControl = setting; + ahp->ah_diversity = (setting == HAL_ANT_VARIABLE); + return AH_TRUE; + } + return ar5212SetAntennaSwitchInternal(ah, setting, chan); +} + +HAL_BOOL +ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah) +{ + return AH_TRUE; +} + +HAL_BOOL +ar5212SetSifsTime(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (us > ath_hal_mac_usec(ah, 0xffff)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", + __func__, us); + ahp->ah_sifstime = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us-2)); + ahp->ah_sifstime = us; + return AH_TRUE; + } +} + +u_int +ar5212GetSifsTime(struct ath_hal *ah) +{ + u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff; + return ath_hal_mac_usec(ah, clks)+2; /* convert from system clocks */ +} + +HAL_BOOL +ar5212SetSlotTime(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (us < HAL_SLOT_TIME_6 || us > ath_hal_mac_usec(ah, 0xffff)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", + __func__, us); + ahp->ah_slottime = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us)); + ahp->ah_slottime = us; + return AH_TRUE; + } +} + +u_int +ar5212GetSlotTime(struct ath_hal *ah) +{ + u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff; + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +HAL_BOOL +ar5212SetAckTimeout(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", + __func__, us); + ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); + ahp->ah_acktimeout = us; + return AH_TRUE; + } +} + +u_int +ar5212GetAckTimeout(struct ath_hal *ah) +{ + u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +u_int +ar5212GetAckCTSRate(struct ath_hal *ah) +{ + return ((AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); +} + +HAL_BOOL +ar5212SetAckCTSRate(struct ath_hal *ah, u_int high) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (high) { + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); + ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; + } else { + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); + ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; + } + return AH_TRUE; +} + +HAL_BOOL +ar5212SetCTSTimeout(struct ath_hal *ah, u_int us) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", + __func__, us); + ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ + return AH_FALSE; + } else { + /* convert to system clocks */ + OS_REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); + ahp->ah_ctstimeout = us; + return AH_TRUE; + } +} + +u_int +ar5212GetCTSTimeout(struct ath_hal *ah) +{ + u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); + return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ +} + +/* Setup decompression for given key index */ +HAL_BOOL +ar5212SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (keyidx >= HAL_DECOMP_MASK_SIZE) + return AH_FALSE; + OS_REG_WRITE(ah, AR_DCM_A, keyidx); + OS_REG_WRITE(ah, AR_DCM_D, en ? AR_DCM_D_EN : 0); + ahp->ah_decompMask[keyidx] = en; + + return AH_TRUE; +} + +/* Setup coverage class */ +void +ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) +{ + uint32_t slot, timeout, eifs; + u_int clkRate; + + AH_PRIVATE(ah)->ah_coverageClass = coverageclass; + + if (now) { + if (AH_PRIVATE(ah)->ah_coverageClass == 0) + return; + + /* Don't apply coverage class to non A channels */ + if (!IEEE80211_IS_CHAN_A(AH_PRIVATE(ah)->ah_curchan)) + return; + + /* Get core clock rate */ + clkRate = ath_hal_mac_clks(ah, 1); + + /* Compute EIFS */ + slot = coverageclass * 3 * clkRate; + eifs = coverageclass * 6 * clkRate; + if (IEEE80211_IS_CHAN_HALF(AH_PRIVATE(ah)->ah_curchan)) { + slot += IFS_SLOT_HALF_RATE; + eifs += IFS_EIFS_HALF_RATE; + } else if (IEEE80211_IS_CHAN_QUARTER(AH_PRIVATE(ah)->ah_curchan)) { + slot += IFS_SLOT_QUARTER_RATE; + eifs += IFS_EIFS_QUARTER_RATE; + } else { /* full rate */ + slot += IFS_SLOT_FULL_RATE; + eifs += IFS_EIFS_FULL_RATE; + } + + /* + * Add additional time for air propagation for ACK and CTS + * timeouts. This value is in core clocks. + */ + timeout = ACK_CTS_TIMEOUT_11A + (coverageclass * 3 * clkRate); + + /* + * Write the values: slot, eifs, ack/cts timeouts. + */ + OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot); + OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs); + OS_REG_WRITE(ah, AR_TIME_OUT, + SM(timeout, AR_TIME_OUT_CTS) + | SM(timeout, AR_TIME_OUT_ACK)); + } +} + +HAL_STATUS +ar5212SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration, + uint32_t nextStart, HAL_QUIET_FLAG flag) +{ + OS_REG_WRITE(ah, AR_QUIET2, period | (duration << AR_QUIET2_QUIET_DUR_S)); + if (flag & HAL_QUIET_ENABLE) { + OS_REG_WRITE(ah, AR_QUIET1, nextStart | (1 << 16)); + } + else { + OS_REG_WRITE(ah, AR_QUIET1, nextStart); + } + return HAL_OK; +} + +void +ar5212SetPCUConfig(struct ath_hal *ah) +{ + ar5212SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode); +} + +/* + * Return whether an external 32KHz crystal should be used + * to reduce power consumption when sleeping. We do so if + * the crystal is present (obtained from EEPROM) and if we + * are not running as an AP and are configured to use it. + */ +HAL_BOOL +ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode) +{ + if (opmode != HAL_M_HOSTAP) { + struct ath_hal_5212 *ahp = AH5212(ah); + return ath_hal_eepromGetFlag(ah, AR_EEP_32KHZCRYSTAL) && + (ahp->ah_enable32kHzClock == USE_32KHZ || + ahp->ah_enable32kHzClock == AUTO_32KHZ); + } else + return AH_FALSE; +} + +/* + * If 32KHz clock exists, use it to lower power consumption during sleep + * + * Note: If clock is set to 32 KHz, delays on accessing certain + * baseband registers (27-31, 124-127) are required. + */ +void +ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode) +{ + if (ar5212Use32KHzclock(ah, opmode)) { + /* + * Enable clocks to be turned OFF in BB during sleep + * and also enable turning OFF 32MHz/40MHz Refclk + * from A2. + */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1); + OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */ + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 1); + + if (IS_2413(ah) || IS_5413(ah) || IS_2417(ah)) { + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x26); + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0d); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x07); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x3f); + /* # Set sleep clock rate to 32 KHz. */ + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x2); + } else { + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x0a); + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0c); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x03); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x20); + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x3); + } + } else { + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x0); + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); + + OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32MHz TSF inc */ + + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); + + if (IS_2417(ah)) + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0a); + else if (IS_HB63(ah)) + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x32); + else + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2417(ah) ? 0x14 : 0x18); + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, + IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); + } +} + +/* + * If 32KHz clock exists, turn it off and turn back on the 32Mhz + */ +void +ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode) +{ + if (ar5212Use32KHzclock(ah, opmode)) { + /* # Set sleep clock rate back to 32 MHz. */ + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0); + OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); + + OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, + IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); + + /* + * Restore BB registers to power-on defaults + */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); + } +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + * Default method: this may be overridden by the rf backend. + */ +int16_t +ar5212GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + static const struct { + uint16_t freqLow; + int16_t adjust; + } adjustDef[] = { + { 5790, 11 }, /* NB: ordered high -> low */ + { 5730, 10 }, + { 5690, 9 }, + { 5660, 8 }, + { 5610, 7 }, + { 5530, 5 }, + { 5450, 4 }, + { 5379, 2 }, + { 5209, 0 }, + { 3000, 1 }, + { 0, 0 }, + }; + int i; + + for (i = 0; c->channel <= adjustDef[i].freqLow; i++) + ; + return adjustDef[i].adjust; +} + +HAL_STATUS +ar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t *result) +{ +#define MACVERSION(ah) AH_PRIVATE(ah)->ah_macVersion + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + const struct ar5212AniState *ani; + + switch (type) { + case HAL_CAP_CIPHER: /* cipher handled in hardware */ + switch (capability) { + case HAL_CIPHER_AES_CCM: + return pCap->halCipherAesCcmSupport ? + HAL_OK : HAL_ENOTSUPP; + case HAL_CIPHER_AES_OCB: + case HAL_CIPHER_TKIP: + case HAL_CIPHER_WEP: + case HAL_CIPHER_MIC: + case HAL_CIPHER_CLR: + return HAL_OK; + default: + return HAL_ENOTSUPP; + } + case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ + switch (capability) { + case 0: /* hardware capability */ + return HAL_OK; + case 1: + return (ahp->ah_staId1Defaults & + AR_STA_ID1_CRPT_MIC_ENABLE) ? HAL_OK : HAL_ENXIO; + } + return HAL_EINVAL; + case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ + switch (capability) { + case 0: /* hardware capability */ + return pCap->halTkipMicTxRxKeySupport ? + HAL_ENXIO : HAL_OK; + case 1: /* current setting */ + return (ahp->ah_miscMode & + AR_MISC_MODE_MIC_NEW_LOC_ENABLE) ? HAL_ENXIO : HAL_OK; + } + return HAL_EINVAL; + case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC w/ WMM */ + /* XXX move to capability bit */ + return MACVERSION(ah) > AR_SREV_VERSION_VENICE || + (MACVERSION(ah) == AR_SREV_VERSION_VENICE && + AH_PRIVATE(ah)->ah_macRev >= 8) ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */ + switch (capability) { + case 0: /* hardware capability */ + return HAL_OK; + case 1: /* current setting */ + return ahp->ah_diversity ? HAL_OK : HAL_ENXIO; + case HAL_CAP_STRONG_DIV: + *result = OS_REG_READ(ah, AR_PHY_RESTART); + *result = MS(*result, AR_PHY_RESTART_DIV_GC); + return HAL_OK; + } + return HAL_EINVAL; + case HAL_CAP_DIAG: + *result = AH_PRIVATE(ah)->ah_diagreg; + return HAL_OK; + case HAL_CAP_TPC: + switch (capability) { + case 0: /* hardware capability */ + return HAL_OK; + case 1: + return ahp->ah_tpcEnabled ? HAL_OK : HAL_ENXIO; + } + return HAL_OK; + case HAL_CAP_PHYDIAG: /* radar pulse detection capability */ + switch (capability) { + case HAL_CAP_RADAR: + return ath_hal_eepromGetFlag(ah, AR_EEP_AMODE) ? + HAL_OK: HAL_ENXIO; + case HAL_CAP_AR: + return (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) || + ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) ? + HAL_OK: HAL_ENXIO; + } + return HAL_ENXIO; + case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ + switch (capability) { + case 0: /* hardware capability */ + return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENXIO; + case 1: + return (ahp->ah_staId1Defaults & + AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO; + } + return HAL_EINVAL; + case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ + switch (capability) { + case 0: /* hardware capability */ + return pCap->halTsfAddSupport ? HAL_OK : HAL_ENOTSUPP; + case 1: + return (ahp->ah_miscMode & AR_MISC_MODE_TX_ADD_TSF) ? + HAL_OK : HAL_ENXIO; + } + return HAL_EINVAL; + case HAL_CAP_TPC_ACK: + *result = MS(ahp->ah_macTPC, AR_TPC_ACK); + return HAL_OK; + case HAL_CAP_TPC_CTS: + *result = MS(ahp->ah_macTPC, AR_TPC_CTS); + return HAL_OK; + case HAL_CAP_INTMIT: /* interference mitigation */ + switch (capability) { + case HAL_CAP_INTMIT_PRESENT: /* hardware capability */ + return HAL_OK; + case HAL_CAP_INTMIT_ENABLE: + return (ahp->ah_procPhyErr & HAL_ANI_ENA) ? + HAL_OK : HAL_ENXIO; + case HAL_CAP_INTMIT_NOISE_IMMUNITY_LEVEL: + case HAL_CAP_INTMIT_OFDM_WEAK_SIGNAL_LEVEL: + case HAL_CAP_INTMIT_CCK_WEAK_SIGNAL_THR: + case HAL_CAP_INTMIT_FIRSTEP_LEVEL: + case HAL_CAP_INTMIT_SPUR_IMMUNITY_LEVEL: + ani = ar5212AniGetCurrentState(ah); + if (ani == AH_NULL) + return HAL_ENXIO; + switch (capability) { + case 2: *result = ani->noiseImmunityLevel; break; + case 3: *result = !ani->ofdmWeakSigDetectOff; break; + case 4: *result = ani->cckWeakSigThreshold; break; + case 5: *result = ani->firstepLevel; break; + case 6: *result = ani->spurImmunityLevel; break; + } + return HAL_OK; + } + return HAL_EINVAL; + default: + return ath_hal_getcapability(ah, type, capability, result); + } +#undef MACVERSION +} + +HAL_BOOL +ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t setting, HAL_STATUS *status) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + uint32_t v; + + switch (type) { + case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ + if (setting) + ahp->ah_staId1Defaults |= AR_STA_ID1_CRPT_MIC_ENABLE; + else + ahp->ah_staId1Defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE; + return AH_TRUE; + case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ + if (!pCap->halTkipMicTxRxKeySupport) + return AH_FALSE; + /* NB: true =>'s use split key cache layout */ + if (setting) + ahp->ah_miscMode &= ~AR_MISC_MODE_MIC_NEW_LOC_ENABLE; + else + ahp->ah_miscMode |= AR_MISC_MODE_MIC_NEW_LOC_ENABLE; + /* NB: write here so keys can be setup w/o a reset */ + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); + return AH_TRUE; + case HAL_CAP_DIVERSITY: + switch (capability) { + case 0: + return AH_FALSE; + case 1: /* setting */ + if (ahp->ah_phyPowerOn) { + if (capability == HAL_CAP_STRONG_DIV) { + v = OS_REG_READ(ah, AR_PHY_CCK_DETECT); + if (setting) + v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; + else + v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; + OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v); + } + } + ahp->ah_diversity = (setting != 0); + return AH_TRUE; + + case HAL_CAP_STRONG_DIV: + if (! ahp->ah_phyPowerOn) + return AH_FALSE; + v = OS_REG_READ(ah, AR_PHY_RESTART); + v &= ~AR_PHY_RESTART_DIV_GC; + v |= SM(setting, AR_PHY_RESTART_DIV_GC); + OS_REG_WRITE(ah, AR_PHY_RESTART, v); + return AH_TRUE; + default: + return AH_FALSE; + } + case HAL_CAP_DIAG: /* hardware diagnostic support */ + /* + * NB: could split this up into virtual capabilities, + * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly + * seems worth the additional complexity. + */ + AH_PRIVATE(ah)->ah_diagreg = setting; + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); + return AH_TRUE; + case HAL_CAP_TPC: + ahp->ah_tpcEnabled = (setting != 0); + return AH_TRUE; + case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ + if (setting) + ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH; + else + ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH; + return AH_TRUE; + case HAL_CAP_TPC_ACK: + case HAL_CAP_TPC_CTS: + setting += ahp->ah_txPowerIndexOffset; + if (setting > 63) + setting = 63; + if (type == HAL_CAP_TPC_ACK) { + ahp->ah_macTPC &= AR_TPC_ACK; + ahp->ah_macTPC |= MS(setting, AR_TPC_ACK); + } else { + ahp->ah_macTPC &= AR_TPC_CTS; + ahp->ah_macTPC |= MS(setting, AR_TPC_CTS); + } + OS_REG_WRITE(ah, AR_TPC, ahp->ah_macTPC); + return AH_TRUE; + case HAL_CAP_INTMIT: { /* interference mitigation */ + /* This maps the public ANI commands to the internal ANI commands */ + /* Private: HAL_ANI_CMD; Public: HAL_CAP_INTMIT_CMD */ + static const HAL_ANI_CMD cmds[] = { + HAL_ANI_PRESENT, + HAL_ANI_MODE, + HAL_ANI_NOISE_IMMUNITY_LEVEL, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + HAL_ANI_CCK_WEAK_SIGNAL_THR, + HAL_ANI_FIRSTEP_LEVEL, + HAL_ANI_SPUR_IMMUNITY_LEVEL, + }; + return capability < N(cmds) ? + AH5212(ah)->ah_aniControl(ah, cmds[capability], setting) : + AH_FALSE; + } + case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ + if (pCap->halTsfAddSupport) { + if (setting) + ahp->ah_miscMode |= AR_MISC_MODE_TX_ADD_TSF; + else + ahp->ah_miscMode &= ~AR_MISC_MODE_TX_ADD_TSF; + return AH_TRUE; + } + /* fall thru... */ + default: + return ath_hal_setcapability(ah, type, capability, + setting, status); + } +#undef N +} + +HAL_BOOL +ar5212GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_ANI_STATS *astats; + + (void) ahp; + if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) + return AH_TRUE; + switch (request) { + case HAL_DIAG_EEPROM: + case HAL_DIAG_EEPROM_EXP_11A: + case HAL_DIAG_EEPROM_EXP_11B: + case HAL_DIAG_EEPROM_EXP_11G: + case HAL_DIAG_RFGAIN: + return ath_hal_eepromDiag(ah, request, + args, argsize, result, resultsize); + case HAL_DIAG_RFGAIN_CURSTEP: + *result = __DECONST(void *, ahp->ah_gainValues.currStep); + *resultsize = (*result == AH_NULL) ? + 0 : sizeof(GAIN_OPTIMIZATION_STEP); + return AH_TRUE; + case HAL_DIAG_PCDAC: + *result = ahp->ah_pcdacTable; + *resultsize = ahp->ah_pcdacTableSize; + return AH_TRUE; + case HAL_DIAG_TXRATES: + *result = &ahp->ah_ratesArray[0]; + *resultsize = sizeof(ahp->ah_ratesArray); + return AH_TRUE; + case HAL_DIAG_ANI_CURRENT: + *result = ar5212AniGetCurrentState(ah); + *resultsize = (*result == AH_NULL) ? + 0 : sizeof(struct ar5212AniState); + return AH_TRUE; + case HAL_DIAG_ANI_STATS: + OS_MEMZERO(&ahp->ext_ani_stats, sizeof(ahp->ext_ani_stats)); + astats = ar5212AniGetCurrentStats(ah); + if (astats == NULL) { + *result = NULL; + *resultsize = 0; + } else { + OS_MEMCPY(&ahp->ext_ani_stats, astats, sizeof(HAL_ANI_STATS)); + *result = &ahp->ext_ani_stats; + *resultsize = sizeof(ahp->ext_ani_stats); + } + return AH_TRUE; + case HAL_DIAG_ANI_CMD: + if (argsize != 2*sizeof(uint32_t)) + return AH_FALSE; + AH5212(ah)->ah_aniControl(ah, ((const uint32_t *)args)[0], + ((const uint32_t *)args)[1]); + return AH_TRUE; + case HAL_DIAG_ANI_PARAMS: + /* + * NB: We assume struct ar5212AniParams is identical + * to HAL_ANI_PARAMS; if they diverge then we'll need + * to handle it here + */ + if (argsize == 0 && args == AH_NULL) { + struct ar5212AniState *aniState = + ar5212AniGetCurrentState(ah); + if (aniState == AH_NULL) + return AH_FALSE; + *result = __DECONST(void *, aniState->params); + *resultsize = sizeof(struct ar5212AniParams); + return AH_TRUE; + } else { + if (argsize != sizeof(struct ar5212AniParams)) + return AH_FALSE; + return ar5212AniSetParams(ah, args, args); + } + break; + } + return AH_FALSE; +} + +/* + * Check whether there's an in-progress NF completion. + * + * Returns AH_TRUE if there's a in-progress NF calibration, AH_FALSE + * otherwise. + */ +HAL_BOOL +ar5212IsNFCalInProgress(struct ath_hal *ah) +{ + if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) + return AH_TRUE; + return AH_FALSE; +} + +/* + * Wait for an in-progress NF calibration to complete. + * + * The completion function waits "i" times 10uS. + * It returns AH_TRUE if the NF calibration completed (or was never + * in progress); AH_FALSE if it was still in progress after "i" checks. + */ +HAL_BOOL +ar5212WaitNFCalComplete(struct ath_hal *ah, int i) +{ + int j; + if (i <= 0) + i = 1; /* it should run at least once */ + for (j = 0; j < i; j++) { + if (! ar5212IsNFCalInProgress(ah)) + return AH_TRUE; + OS_DELAY(10); + } + return AH_FALSE; +} + +void +ar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ + uint32_t val; + val = OS_REG_READ(ah, AR_PHY_RADAR_0); + + if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_FIRPWR; + val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR); + } + if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_RRSSI; + val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI); + } + if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_HEIGHT; + val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT); + } + if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_PRSSI; + val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); + } + if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_INBAND; + val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND); + } + if (pe->pe_enabled) + val |= AR_PHY_RADAR_0_ENA; + else + val &= ~ AR_PHY_RADAR_0_ENA; + + if (IS_5413(ah)) { + + if (pe->pe_blockradar == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, + AR_PHY_RADAR_2_BLOCKOFDMWEAK); + else + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, + AR_PHY_RADAR_2_BLOCKOFDMWEAK); + + if (pe->pe_en_relstep_check == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, + AR_PHY_RADAR_2_ENRELSTEPCHK); + else + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, + AR_PHY_RADAR_2_ENRELSTEPCHK); + + if (pe->pe_usefir128 == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, + AR_PHY_RADAR_2_USEFIR128); + else + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, + AR_PHY_RADAR_2_USEFIR128); + + if (pe->pe_enmaxrssi == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, + AR_PHY_RADAR_2_ENMAXRSSI); + else + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, + AR_PHY_RADAR_2_ENMAXRSSI); + + if (pe->pe_enrelpwr == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, + AR_PHY_RADAR_2_ENRELPWRCHK); + else + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, + AR_PHY_RADAR_2_ENRELPWRCHK); + + if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) + OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2, + AR_PHY_RADAR_2_RELPWR, pe->pe_relpwr); + + if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) + OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2, + AR_PHY_RADAR_2_RELSTEP, pe->pe_relstep); + + if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) + OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2, + AR_PHY_RADAR_2_MAXLEN, pe->pe_maxlen); + } + + OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); +} + +/* + * Parameters for the AR5212 PHY. + */ +#define AR5212_DFS_FIRPWR -35 +#define AR5212_DFS_RRSSI 20 +#define AR5212_DFS_HEIGHT 14 +#define AR5212_DFS_PRSSI 6 +#define AR5212_DFS_INBAND 4 + +/* + * Default parameters for the AR5413 PHY. + */ +#define AR5413_DFS_FIRPWR -34 +#define AR5413_DFS_RRSSI 20 +#define AR5413_DFS_HEIGHT 10 +#define AR5413_DFS_PRSSI 15 +#define AR5413_DFS_INBAND 6 +#define AR5413_DFS_RELPWR 8 +#define AR5413_DFS_RELSTEP 31 +#define AR5413_DFS_MAXLEN 255 + +HAL_BOOL +ar5212GetDfsDefaultThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ + + if (IS_5413(ah)) { + pe->pe_firpwr = AR5413_DFS_FIRPWR; + pe->pe_rrssi = AR5413_DFS_RRSSI; + pe->pe_height = AR5413_DFS_HEIGHT; + pe->pe_prssi = AR5413_DFS_PRSSI; + pe->pe_inband = AR5413_DFS_INBAND; + pe->pe_relpwr = AR5413_DFS_RELPWR; + pe->pe_relstep = AR5413_DFS_RELSTEP; + pe->pe_maxlen = AR5413_DFS_MAXLEN; + pe->pe_usefir128 = 0; + pe->pe_blockradar = 1; + pe->pe_enmaxrssi = 1; + pe->pe_enrelpwr = 1; + pe->pe_en_relstep_check = 0; + } else { + pe->pe_firpwr = AR5212_DFS_FIRPWR; + pe->pe_rrssi = AR5212_DFS_RRSSI; + pe->pe_height = AR5212_DFS_HEIGHT; + pe->pe_prssi = AR5212_DFS_PRSSI; + pe->pe_inband = AR5212_DFS_INBAND; + pe->pe_relpwr = 0; + pe->pe_relstep = 0; + pe->pe_maxlen = 0; + pe->pe_usefir128 = 0; + pe->pe_blockradar = 0; + pe->pe_enmaxrssi = 0; + pe->pe_enrelpwr = 0; + pe->pe_en_relstep_check = 0; + } + + return (AH_TRUE); +} + +void +ar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ + uint32_t val,temp; + + val = OS_REG_READ(ah, AR_PHY_RADAR_0); + + temp = MS(val,AR_PHY_RADAR_0_FIRPWR); + temp |= 0xFFFFFF80; + pe->pe_firpwr = temp; + pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI); + pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT); + pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI); + pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND); + pe->pe_enabled = !! (val & AR_PHY_RADAR_0_ENA); + + pe->pe_relpwr = 0; + pe->pe_relstep = 0; + pe->pe_maxlen = 0; + pe->pe_usefir128 = 0; + pe->pe_blockradar = 0; + pe->pe_enmaxrssi = 0; + pe->pe_enrelpwr = 0; + pe->pe_en_relstep_check = 0; + pe->pe_extchannel = AH_FALSE; + + if (IS_5413(ah)) { + val = OS_REG_READ(ah, AR_PHY_RADAR_2); + pe->pe_relpwr = !! MS(val, AR_PHY_RADAR_2_RELPWR); + pe->pe_relstep = !! MS(val, AR_PHY_RADAR_2_RELSTEP); + pe->pe_maxlen = !! MS(val, AR_PHY_RADAR_2_MAXLEN); + + pe->pe_usefir128 = !! (val & AR_PHY_RADAR_2_USEFIR128); + pe->pe_blockradar = !! (val & AR_PHY_RADAR_2_BLOCKOFDMWEAK); + pe->pe_enmaxrssi = !! (val & AR_PHY_RADAR_2_ENMAXRSSI); + pe->pe_enrelpwr = !! (val & AR_PHY_RADAR_2_ENRELPWRCHK); + pe->pe_en_relstep_check = + !! (val & AR_PHY_RADAR_2_ENRELSTEPCHK); + } +} + +/* + * Process the radar phy error and extract the pulse duration. + */ +HAL_BOOL +ar5212ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs, + uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event) +{ + uint8_t dur; + uint8_t rssi; + + /* Check whether the given phy error is a radar event */ + if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) && + (rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) + return AH_FALSE; + + /* + * The first byte is the pulse width - if there's + * no data, simply set the duration to 0 + */ + if (rxs->rs_datalen >= 1) + /* The pulse width is byte 0 of the data */ + dur = ((uint8_t) buf[0]) & 0xff; + else + dur = 0; + + /* Pulse RSSI is the normal reported RSSI */ + rssi = (uint8_t) rxs->rs_rssi; + + /* 0 duration/rssi is not a valid radar event */ + if (dur == 0 && rssi == 0) + return AH_FALSE; + + HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", + __func__, rssi, dur); + + /* Record the event */ + event->re_full_ts = fulltsf; + event->re_ts = rxs->rs_tstamp; + event->re_rssi = rssi; + event->re_dur = dur; + event->re_flags = HAL_DFS_EVENT_PRICH; + + return AH_TRUE; +} + +/* + * Return whether 5GHz fast-clock (44MHz) is enabled. + * It's always disabled for AR5212 series NICs. + */ +HAL_BOOL +ar5212IsFastClockEnabled(struct ath_hal *ah) +{ + return AH_FALSE; +} + +/* + * Return what percentage of the extension channel is busy. + * This is always disabled for AR5212 series NICs. + */ +uint32_t +ar5212Get11nExtBusy(struct ath_hal *ah) +{ + return 0; +} + +/* + * Channel survey support. + */ +HAL_BOOL +ar5212GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + u_int32_t good = AH_TRUE; + + /* XXX freeze/unfreeze mib counters */ + uint32_t rc = OS_REG_READ(ah, AR_RCCNT); + uint32_t rf = OS_REG_READ(ah, AR_RFCNT); + uint32_t tf = OS_REG_READ(ah, AR_TFCNT); + uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */ + + if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) { + /* + * Cycle counter wrap (or initial call); it's not possible + * to accurately calculate a value because the registers + * right shift rather than wrap--so punt and return 0. + */ + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cycle counter wrap. ExtBusy = 0\n", __func__); + good = AH_FALSE; + } else { + hsample->cycle_count = cc - ahp->ah_cycleCount; + hsample->chan_busy = rc - ahp->ah_ctlBusy; + hsample->ext_chan_busy = 0; + hsample->rx_busy = rf - ahp->ah_rxBusy; + hsample->tx_busy = tf - ahp->ah_txBusy; + } + + /* + * Keep a copy of the MIB results so the next sample has something + * to work from. + */ + ahp->ah_cycleCount = cc; + ahp->ah_rxBusy = rf; + ahp->ah_ctlBusy = rc; + ahp->ah_txBusy = tf; + + return (good); +} + +void +ar5212SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask, + uint32_t rx_chainmask) +{ +} diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_phy.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_phy.c new file mode 100644 index 0000000..ac55be6 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_phy.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" + +/* shorthands to compact tables for readability */ +#define OFDM IEEE80211_T_OFDM +#define CCK IEEE80211_T_CCK +#define TURBO IEEE80211_T_TURBO +#define HALF IEEE80211_T_OFDM_HALF +#define QUART IEEE80211_T_OFDM_QUARTER + +HAL_RATE_TABLE ar5212_11a_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 } + }, +}; + +HAL_RATE_TABLE ar5212_half_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 3 Mb */ { AH_TRUE, HALF, 3000, 0x0b, 0x00, (0x80|6), 0 }, +/* 4.5 Mb */ { AH_TRUE, HALF, 4500, 0x0f, 0x00, 9, 0 }, +/* 6 Mb */ { AH_TRUE, HALF, 6000, 0x0a, 0x00, (0x80|12), 2 }, +/* 9 Mb */ { AH_TRUE, HALF, 9000, 0x0e, 0x00, 18, 2 }, +/* 12 Mb */ { AH_TRUE, HALF, 12000, 0x09, 0x00, (0x80|24), 4 }, +/* 18 Mb */ { AH_TRUE, HALF, 18000, 0x0d, 0x00, 36, 4 }, +/* 24 Mb */ { AH_TRUE, HALF, 24000, 0x08, 0x00, 48, 4 }, +/* 27 Mb */ { AH_TRUE, HALF, 27000, 0x0c, 0x00, 54, 4 } + }, +}; + +HAL_RATE_TABLE ar5212_quarter_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 1.5 Mb */ { AH_TRUE, QUART, 1500, 0x0b, 0x00, (0x80|3), 0 }, +/* 2 Mb */ { AH_TRUE, QUART, 2250, 0x0f, 0x00, 4, 0 }, +/* 3 Mb */ { AH_TRUE, QUART, 3000, 0x0a, 0x00, (0x80|6), 2 }, +/* 4.5 Mb */ { AH_TRUE, QUART, 4500, 0x0e, 0x00, 9, 2 }, +/* 6 Mb */ { AH_TRUE, QUART, 6000, 0x09, 0x00, (0x80|12), 4 }, +/* 9 Mb */ { AH_TRUE, QUART, 9000, 0x0d, 0x00, 18, 4 }, +/* 12 Mb */ { AH_TRUE, QUART, 12000, 0x08, 0x00, 24, 4 }, +/*13.5 Mb */ { AH_TRUE, QUART, 13500, 0x0c, 0x00, 27, 4 } + }, +}; + +HAL_RATE_TABLE ar5212_turbog_table = { + 7, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, TURBO, 12000, 0x0b, 0x00, (0x80|12), 0 }, +/* 12 Mb */ { AH_TRUE, TURBO, 24000, 0x0a, 0x00, (0x80|24), 1 }, +/* 18 Mb */ { AH_TRUE, TURBO, 36000, 0x0e, 0x00, 36, 1 }, +/* 24 Mb */ { AH_TRUE, TURBO, 48000, 0x09, 0x00, (0x80|48), 2 }, +/* 36 Mb */ { AH_TRUE, TURBO, 72000, 0x0d, 0x00, 72, 2 }, +/* 48 Mb */ { AH_TRUE, TURBO, 96000, 0x08, 0x00, 96, 2 }, +/* 54 Mb */ { AH_TRUE, TURBO, 108000, 0x0c, 0x00, 108, 2 } + }, +}; + +HAL_RATE_TABLE ar5212_turboa_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, TURBO, 12000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, TURBO, 18000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, TURBO, 24000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, TURBO, 36000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, TURBO, 48000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, TURBO, 72000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, TURBO, 96000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, TURBO, 108000, 0x0c, 0x00, 108, 4 } + }, +}; + +HAL_RATE_TABLE ar5212_11b_table = { + 4, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80| 2), 0 }, +/* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80| 4), 1 }, +/* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80|11), 1 }, +/* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80|22), 1 } + }, +}; + + +/* Venice TODO: roundUpRate() is broken when the rate table does not represent rates + * in increasing order e.g. 5.5, 11, 6, 9. + * An average rate of 6 Mbps will currently map to 11 Mbps. + */ +HAL_RATE_TABLE ar5212_11g_table = { + 12, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80| 2), 0 }, +/* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80| 4), 1 }, +/* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80|11), 2 }, +/* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80|22), 3 }, +/* remove rates 6, 9 from rate ctrl */ +/* 6 Mb */ { AH_FALSE, OFDM, 6000, 0x0b, 0x00, 12, 4 }, +/* 9 Mb */ { AH_FALSE, OFDM, 9000, 0x0f, 0x00, 18, 4 }, +/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, 24, 6 }, +/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 6 }, +/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, 48, 8 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8 } + }, +}; + +#undef OFDM +#undef CCK +#undef TURBO +#undef XR + +const HAL_RATE_TABLE * +ar5212GetRateTable(struct ath_hal *ah, u_int mode) +{ + HAL_RATE_TABLE *rt; + switch (mode) { + case HAL_MODE_11A: + rt = &ar5212_11a_table; + break; + case HAL_MODE_11B: + rt = &ar5212_11b_table; + break; + case HAL_MODE_11G: +#ifdef notdef + case HAL_MODE_PUREG: +#endif + rt = &ar5212_11g_table; + break; + case HAL_MODE_108A: + case HAL_MODE_TURBO: + rt = &ar5212_turboa_table; + break; + case HAL_MODE_108G: + rt = &ar5212_turbog_table; + break; + case HAL_MODE_11A_HALF_RATE: + case HAL_MODE_11G_HALF_RATE: + rt = &ar5212_half_table; + break; + case HAL_MODE_11A_QUARTER_RATE: + case HAL_MODE_11G_QUARTER_RATE: + rt = &ar5212_quarter_table; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", + __func__, mode); + return AH_NULL; + } + ath_hal_setupratetable(ah, rt); + return rt; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_power.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_power.c new file mode 100644 index 0000000..3068510 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_power.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212desc.h" + +/* + * Notify Power Mgt is enabled in self-generated frames. + * If requested, force chip awake. + * + * Returns A_OK if chip is awake or successfully forced awake. + * + * WARNING WARNING WARNING + * There is a problem with the chip where sometimes it will not wake up. + */ +static HAL_BOOL +ar5212SetPowerModeAwake(struct ath_hal *ah, int setChip) +{ +#define AR_SCR_MASK \ + (AR_SCR_SLDUR|AR_SCR_SLE|AR_SCR_SLDTP|AR_SCR_SLDWP|\ + AR_SCR_SLEPOL|AR_SCR_MIBIE|AR_SCR_UNKNOWN) +#define POWER_UP_TIME 2000 + uint32_t scr, val; + int i; + + if (setChip) { + /* + * Be careful setting the AWAKE mode. When we are called + * with the chip powered down the read returns 0xffffffff + * which when blindly written back with OS_REG_RMW_FIELD + * enables the MIB interrupt for the sleep performance + * counters. This can result in an interrupt storm when + * ANI is in operation as noone knows to turn off the MIB + * interrupt cause. + */ + scr = OS_REG_READ(ah, AR_SCR); + if (scr & ~AR_SCR_MASK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: bogus SCR 0x%x, PCICFG 0x%x\n", + __func__, scr, OS_REG_READ(ah, AR_PCICFG)); + scr = 0; + } + scr = (scr &~ AR_SCR_SLE) | AR_SCR_SLE_WAKE; + OS_REG_WRITE(ah, AR_SCR, scr); + OS_DELAY(10); /* Give chip the chance to awake */ + + for (i = POWER_UP_TIME / 50; i != 0; i--) { + val = OS_REG_READ(ah, AR_PCICFG); + if ((val & AR_PCICFG_SPWR_DN) == 0) + break; + OS_DELAY(50); + OS_REG_WRITE(ah, AR_SCR, scr); + } + if (i == 0) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n", + __func__, POWER_UP_TIME/50); +#endif + return AH_FALSE; + } + } + + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + return AH_TRUE; +#undef POWER_UP_TIME +#undef AR_SCR_MASK +} + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, force chip to sleep. + */ +static void +ar5212SetPowerModeSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_SLP); +} + +/* + * Notify Power Management is enabled in self-generating + * fames. If request, set power mode of chip to + * auto/normal. Duration in units of 128us (1/8 TU). + */ +static void +ar5212SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_NORM); +} + +/* + * Set power mgt to the requested mode, and conditionally set + * the chip as well + */ +HAL_BOOL +ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) +{ +#ifdef AH_DEBUG + static const char* modes[] = { + "AWAKE", + "FULL-SLEEP", + "NETWORK SLEEP", + "UNDEFINED" + }; +#endif + int status = AH_TRUE; + + HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, + modes[ah->ah_powerMode], modes[mode], + setChip ? "set chip " : ""); + switch (mode) { + case HAL_PM_AWAKE: + if (setChip) + ah->ah_powerMode = mode; + status = ar5212SetPowerModeAwake(ah, setChip); + break; + case HAL_PM_FULL_SLEEP: + ar5212SetPowerModeSleep(ah, setChip); + if (setChip) + ah->ah_powerMode = mode; + break; + case HAL_PM_NETWORK_SLEEP: + ar5212SetPowerModeNetworkSleep(ah, setChip); + if (setChip) + ah->ah_powerMode = mode; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n", + __func__, mode); + return AH_FALSE; + } + return status; +} + +/* + * Return the current sleep mode of the chip + */ +HAL_POWER_MODE +ar5212GetPowerMode(struct ath_hal *ah) +{ + /* Just so happens the h/w maps directly to the abstracted value */ + return MS(OS_REG_READ(ah, AR_SCR), AR_SCR_SLE); +} + +#if 0 +/* + * Return the current sleep state of the chip + * TRUE = sleeping + */ +HAL_BOOL +ar5212GetPowerStatus(struct ath_hal *ah) +{ + return (OS_REG_READ(ah, AR_PCICFG) & AR_PCICFG_SPWR_DN) != 0; +} +#endif diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_recv.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_recv.c new file mode 100644 index 0000000..958a954 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_recv.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212desc.h" + +/* + * Get the RXDP. + */ +uint32_t +ar5212GetRxDP(struct ath_hal *ath, HAL_RX_QUEUE qtype) +{ + + HALASSERT(qtype == HAL_RX_QUEUE_HP); + return OS_REG_READ(ath, AR_RXDP); +} + +/* + * Set the RxDP. + */ +void +ar5212SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE qtype) +{ + + HALASSERT(qtype == HAL_RX_QUEUE_HP); + OS_REG_WRITE(ah, AR_RXDP, rxdp); + HALASSERT(OS_REG_READ(ah, AR_RXDP) == rxdp); +} + +/* + * Set Receive Enable bits. + */ +void +ar5212EnableReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_CR, AR_CR_RXE); +} + +/* + * Stop Receive at the DMA engine + */ +HAL_BOOL +ar5212StopDmaReceive(struct ath_hal *ah) +{ + OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP); + OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */ + if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0)) { + OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP_ERR); +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: dma failed to stop in 10ms\n" + "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", + __func__, + OS_REG_READ(ah, AR_CR), + OS_REG_READ(ah, AR_DIAG_SW)); +#endif + return AH_FALSE; + } else { + return AH_TRUE; + } +} + +/* + * Start Transmit at the PCU engine (unpause receive) + */ +void +ar5212StartPcuReceive(struct ath_hal *ah) +{ + struct ath_hal_private *ahp = AH_PRIVATE(ah); + + OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_PCU_START); + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) &~ AR_DIAG_RX_DIS); + ar5212EnableMibCounters(ah); + /* NB: restore current settings */ + ar5212AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, AH_TRUE); +} + +/* + * Stop Transmit at the PCU engine (pause receive) + */ +void +ar5212StopPcuReceive(struct ath_hal *ah) +{ + OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_PCU_STOP); + OS_REG_WRITE(ah, AR_DIAG_SW, + OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_RX_DIS); + ar5212DisableMibCounters(ah); +} + +/* + * Set multicast filter 0 (lower 32-bits) + * filter 1 (upper 32-bits) + */ +void +ar5212SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1) +{ + OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0); + OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1); +} + +/* + * Clear multicast filter by index + */ +HAL_BOOL +ar5212ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix) +{ + uint32_t val; + + if (ix >= 64) + return AH_FALSE; + if (ix >= 32) { + val = OS_REG_READ(ah, AR_MCAST_FIL1); + OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32)))); + } else { + val = OS_REG_READ(ah, AR_MCAST_FIL0); + OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<= 64) + return AH_FALSE; + if (ix >= 32) { + val = OS_REG_READ(ah, AR_MCAST_FIL1); + OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32)))); + } else { + val = OS_REG_READ(ah, AR_MCAST_FIL0); + OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<ah_caps.halBssidMatchSupport && + (AH5212(ah)->ah_miscMode & AR_MISC_MODE_BSSID_MATCH_FORCE)) + bits |= HAL_RX_FILTER_BSSID; + return bits; +} + +/* + * Set the receive filter. + */ +void +ar5212SetRxFilter(struct ath_hal *ah, uint32_t bits) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t phybits; + + OS_REG_WRITE(ah, AR_RX_FILTER, + bits &~ (HAL_RX_FILTER_PHYRADAR|HAL_RX_FILTER_PHYERR| + HAL_RX_FILTER_BSSID)); + phybits = 0; + if (bits & HAL_RX_FILTER_PHYRADAR) + phybits |= AR_PHY_ERR_RADAR; + if (bits & HAL_RX_FILTER_PHYERR) + phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING; + OS_REG_WRITE(ah, AR_PHY_ERR, phybits); + if (phybits) { + OS_REG_WRITE(ah, AR_RXCFG, + OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); + } else { + OS_REG_WRITE(ah, AR_RXCFG, + OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA); + } + if (AH_PRIVATE(ah)->ah_caps.halBssidMatchSupport) { + if (bits & HAL_RX_FILTER_BSSID) + ahp->ah_miscMode |= AR_MISC_MODE_BSSID_MATCH_FORCE; + else + ahp->ah_miscMode &= ~AR_MISC_MODE_BSSID_MATCH_FORCE; + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); + } +} + +/* + * Initialize RX descriptor, by clearing the status and setting + * the size (and any other flags). + */ +HAL_BOOL +ar5212SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds, + uint32_t size, u_int flags) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + + HALASSERT((size &~ AR_BufLen) == 0); + + ads->ds_ctl0 = 0; + ads->ds_ctl1 = size & AR_BufLen; + + if (flags & HAL_RXDESC_INTREQ) + ads->ds_ctl1 |= AR_RxInterReq; + ads->ds_rxstatus0 = ads->ds_rxstatus1 = 0; + + return AH_TRUE; +} + +/* + * Process an RX descriptor, and return the status to the caller. + * Copy some hardware specific items into the software portion + * of the descriptor. + * + * NB: the caller is responsible for validating the memory contents + * of the descriptor (e.g. flushing any cached copy). + */ +HAL_STATUS +ar5212ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, + uint32_t pa, struct ath_desc *nds, uint64_t tsf, + struct ath_rx_status *rs) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + struct ar5212_desc *ands = AR5212DESC(nds); + + if ((ads->ds_rxstatus1 & AR_Done) == 0) + return HAL_EINPROGRESS; + /* + * Given the use of a self-linked tail be very sure that the hw is + * done with this descriptor; the hw may have done this descriptor + * once and picked it up again...make sure the hw has moved on. + */ + if ((ands->ds_rxstatus1&AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa) + return HAL_EINPROGRESS; + + rs->rs_datalen = ads->ds_rxstatus0 & AR_DataLen; + rs->rs_tstamp = MS(ads->ds_rxstatus1, AR_RcvTimestamp); + rs->rs_status = 0; + /* XXX what about KeyCacheMiss? */ + rs->rs_rssi = MS(ads->ds_rxstatus0, AR_RcvSigStrength); + /* discard invalid h/w rssi data */ + if (rs->rs_rssi == -128) + rs->rs_rssi = 0; + if (ads->ds_rxstatus1 & AR_KeyIdxValid) + rs->rs_keyix = MS(ads->ds_rxstatus1, AR_KeyIdx); + else + rs->rs_keyix = HAL_RXKEYIX_INVALID; + /* NB: caller expected to do rate table mapping */ + rs->rs_rate = MS(ads->ds_rxstatus0, AR_RcvRate); + rs->rs_antenna = MS(ads->ds_rxstatus0, AR_RcvAntenna); + rs->rs_more = (ads->ds_rxstatus0 & AR_More) ? 1 : 0; + + /* + * The AR5413 (at least) sometimes sets both AR_CRCErr and + * AR_PHYErr when reporting radar pulses. In this instance + * set HAL_RXERR_PHY as well as HAL_RXERR_CRC and + * let the driver layer figure out what to do. + * + * See PR kern/169362. + */ + if ((ads->ds_rxstatus1 & AR_FrmRcvOK) == 0) { + /* + * These four bits should not be set together. The + * 5212 spec states a Michael error can only occur if + * DecryptCRCErr not set (and TKIP is used). Experience + * indicates however that you can also get Michael errors + * when a CRC error is detected, but these are specious. + * Consequently we filter them out here so we don't + * confuse and/or complicate drivers. + */ + if (ads->ds_rxstatus1 & AR_PHYErr) { + u_int phyerr; + + rs->rs_status |= HAL_RXERR_PHY; + phyerr = MS(ads->ds_rxstatus1, AR_PHYErrCode); + rs->rs_phyerr = phyerr; + if (!AH5212(ah)->ah_hasHwPhyCounters && + phyerr != HAL_PHYERR_RADAR) + ar5212AniPhyErrReport(ah, rs); + } + + if (ads->ds_rxstatus1 & AR_CRCErr) + rs->rs_status |= HAL_RXERR_CRC; + else if (ads->ds_rxstatus1 & AR_DecryptCRCErr) + rs->rs_status |= HAL_RXERR_DECRYPT; + else if (ads->ds_rxstatus1 & AR_MichaelErr) + rs->rs_status |= HAL_RXERR_MIC; + } + return HAL_OK; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_reset.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_reset.c new file mode 100644 index 0000000..d53d86c --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_reset.c @@ -0,0 +1,2799 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +/* Additional Time delay to wait after activiting the Base band */ +#define BASE_ACTIVATE_DELAY 100 /* 100 usec */ +#define PLL_SETTLE_DELAY 300 /* 300 usec */ + +static HAL_BOOL ar5212SetResetReg(struct ath_hal *, uint32_t resetMask); +/* NB: public for 5312 use */ +HAL_BOOL ar5212IsSpurChannel(struct ath_hal *, + const struct ieee80211_channel *); +HAL_BOOL ar5212ChannelChange(struct ath_hal *, + const struct ieee80211_channel *); +int16_t ar5212GetNf(struct ath_hal *, struct ieee80211_channel *); +HAL_BOOL ar5212SetBoardValues(struct ath_hal *, + const struct ieee80211_channel *); +void ar5212SetDeltaSlope(struct ath_hal *, + const struct ieee80211_channel *); +HAL_BOOL ar5212SetTransmitPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain); +static HAL_BOOL ar5212SetRateTable(struct ath_hal *, + const struct ieee80211_channel *, int16_t tpcScaleReduction, + int16_t powerLimit, + HAL_BOOL commit, int16_t *minPower, int16_t *maxPower); +static void ar5212CorrectGainDelta(struct ath_hal *, int twiceOfdmCckDelta); +static void ar5212GetTargetPowers(struct ath_hal *, + const struct ieee80211_channel *, + const TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels, + TRGT_POWER_INFO *pNewPower); +static uint16_t ar5212GetMaxEdgePower(uint16_t channel, + const RD_EDGES_POWER *pRdEdgesPower); +void ar5212SetRateDurationTable(struct ath_hal *, + const struct ieee80211_channel *); +void ar5212SetIFSTiming(struct ath_hal *, + const struct ieee80211_channel *); + +/* NB: public for RF backend use */ +void ar5212GetLowerUpperValues(uint16_t value, + uint16_t *pList, uint16_t listSize, + uint16_t *pLowerValue, uint16_t *pUpperValue); +void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static int +write_common(struct ath_hal *ah, const HAL_INI_ARRAY *ia, + HAL_BOOL bChannelChange, int writes) +{ +#define IS_NO_RESET_TIMER_ADDR(x) \ + ( (((x) >= AR_BEACON) && ((x) <= AR_CFP_DUR)) || \ + (((x) >= AR_SLEEP1) && ((x) <= AR_SLEEP3))) +#define V(r, c) (ia)->data[((r)*(ia)->cols) + (c)] + int r; + + /* Write Common Array Parameters */ + for (r = 0; r < ia->rows; r++) { + uint32_t reg = V(r, 0); + /* XXX timer/beacon setup registers? */ + /* On channel change, don't reset the PCU registers */ + if (!(bChannelChange && IS_NO_RESET_TIMER_ADDR(reg))) { + OS_REG_WRITE(ah, reg, V(r, 1)); + DMA_YIELD(writes); + } + } + return writes; +#undef IS_NO_RESET_TIMER_ADDR +#undef V +} + +#define IS_DISABLE_FAST_ADC_CHAN(x) (((x) == 2462) || ((x) == 2467)) + +/* + * XXX NDIS 5.x code had MAX_RESET_WAIT set to 2000 for AP code + * and 10 for Client code + */ +#define MAX_RESET_WAIT 10 + +#define TX_QUEUEPEND_CHECK 1 +#define TX_ENABLE_CHECK 2 +#define RX_ENABLE_CHECK 4 + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + * + * bChannelChange is used to preserve DMA/PCU registers across + * a HW Reset during channel change. + */ +HAL_BOOL +ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode, + struct ieee80211_channel *chan, + HAL_BOOL bChannelChange, + HAL_RESET_TYPE resetType, + HAL_STATUS *status) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) +#define FAIL(_code) do { ecode = _code; goto bad; } while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *ichan = AH_NULL; + const HAL_EEPROM *ee; + uint32_t softLedCfg, softLedState; + uint32_t saveFrameSeqCount, saveDefAntenna, saveLedState; + uint32_t macStaId1, synthDelay, txFrm2TxDStart; + uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL]; + int16_t cckOfdmPwrDelta = 0; + u_int modesIndex, freqIndex; + HAL_STATUS ecode; + int i, regWrites; + uint32_t testReg, powerVal; + int8_t twiceAntennaGain, twiceAntennaReduction; + uint32_t ackTpcPow, ctsTpcPow, chirpTpcPow; + HAL_BOOL isBmode = AH_FALSE; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + ee = AH_PRIVATE(ah)->ah_eeprom; + + OS_MARK(ah, AH_MARK_RESET, bChannelChange); + + /* Bring out of sleep mode */ + if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip did not wakeup\n", + __func__); + FAIL(HAL_EIO); + } + + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) + FAIL(HAL_EINVAL); + switch (opmode) { + case HAL_M_STA: + case HAL_M_IBSS: + case HAL_M_HOSTAP: + case HAL_M_MONITOR: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n", + __func__, opmode); + FAIL(HAL_EINVAL); + break; + } + HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3); + + SAVE_CCK(ah, chan, isBmode); + + /* Preserve certain DMA hardware registers on a channel change */ + if (bChannelChange) { + /* + * On Venice, the TSF is almost preserved across a reset; + * it requires doubling writes to the RESET_TSF + * bit in the AR_BEACON register; it also has the quirk + * of the TSF going back in time on the station (station + * latches onto the last beacon's tsf during a reset 50% + * of the times); the latter is not a problem for adhoc + * stations since as long as the TSF is behind, it will + * get resynchronized on receiving the next beacon; the + * TSF going backwards in time could be a problem for the + * sleep operation (supported on infrastructure stations + * only) - the best and most general fix for this situation + * is to resynchronize the various sleep/beacon timers on + * the receipt of the next beacon i.e. when the TSF itself + * gets resynchronized to the AP's TSF - power save is + * needed to be temporarily disabled until that time + * + * Need to save the sequence number to restore it after + * the reset! + */ + saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM); + } else + saveFrameSeqCount = 0; /* NB: silence compiler */ + + /* Blank the channel survey statistics */ + ath_hal_survey_clear(ah); + +#if 0 + /* + * XXX disable for now; this appears to sometimes cause OFDM + * XXX timing error floods when ani is enabled and bg scanning + * XXX kicks in + */ + /* If the channel change is across the same mode - perform a fast channel change */ + if (IS_2413(ah) || IS_5413(ah)) { + /* + * Fast channel change can only be used when: + * -channel change requested - so it's not the initial reset. + * -it's not a change to the current channel - + * often called when switching modes on a channel + * -the modes of the previous and requested channel are the + * same + * XXX opmode shouldn't change either? + */ + if (bChannelChange && + (AH_PRIVATE(ah)->ah_curchan != AH_NULL) && + (chan->ic_freq != AH_PRIVATE(ah)->ah_curchan->ic_freq) && + ((chan->ic_flags & IEEE80211_CHAN_ALLTURBO) == + (AH_PRIVATE(ah)->ah_curchan->ic_flags & IEEE80211_CHAN_ALLTURBO))) { + if (ar5212ChannelChange(ah, chan)) { + /* If ChannelChange completed - skip the rest of reset */ + /* XXX ani? */ + goto done; + } + } + } +#endif + /* + * Preserve the antenna on a channel change + */ + saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA); + if (saveDefAntenna == 0) /* XXX magic constants */ + saveDefAntenna = 1; + + /* Save hardware flag before chip reset clears the register */ + macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & + (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT); + + /* Save led state from pci config register */ + saveLedState = OS_REG_READ(ah, AR_PCICFG) & + (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK | + AR_PCICFG_LEDSLOW); + softLedCfg = OS_REG_READ(ah, AR_GPIOCR); + softLedState = OS_REG_READ(ah, AR_GPIODO); + + ar5212RestoreClock(ah, opmode); /* move to refclk operation */ + + /* + * Adjust gain parameters before reset if + * there's an outstanding gain updated. + */ + (void) ar5212GetRfgain(ah); + + if (!ar5212ChipReset(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + FAIL(HAL_EIO); + } + + /* Setup the indices for the next set of register array writes */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + freqIndex = 2; + if (IEEE80211_IS_CHAN_108G(chan)) + modesIndex = 5; + else if (IEEE80211_IS_CHAN_G(chan)) + modesIndex = 4; + else if (IEEE80211_IS_CHAN_B(chan)) + modesIndex = 3; + else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x\n", + __func__, chan->ic_freq, chan->ic_flags); + FAIL(HAL_EINVAL); + } + } else { + freqIndex = 1; + if (IEEE80211_IS_CHAN_TURBO(chan)) + modesIndex = 2; + else if (IEEE80211_IS_CHAN_A(chan)) + modesIndex = 1; + else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x\n", + __func__, chan->ic_freq, chan->ic_flags); + FAIL(HAL_EINVAL); + } + } + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + /* Set correct Baseband to analog shift setting to access analog chips. */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0); + regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange, + regWrites); +#ifdef AH_RXCFG_SDMAMW_4BYTES + /* + * Nala doesn't work with 128 byte bursts on pb42(hydra) (ar71xx), + * use 4 instead. Enabling it on all platforms would hurt performance, + * so we only enable it on the ones that are affected by it. + */ + OS_REG_WRITE(ah, AR_RXCFG, 0); +#endif + ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan)) { + ar5212SetIFSTiming(ah, chan); + if (IS_5413(ah)) { + /* + * Force window_length for 1/2 and 1/4 rate channels, + * the ini file sets this to zero otherwise. + */ + OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, + AR_PHY_FRAME_CTL_WINLEN, 3); + } + } + + /* Overwrite INI values for revised chipsets */ + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) { + /* ADC_CTL */ + OS_REG_WRITE(ah, AR_PHY_ADC_CTL, + SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) | + SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) | + AR_PHY_ADC_CTL_OFF_PWDDAC | + AR_PHY_ADC_CTL_OFF_PWDADC); + + /* TX_PWR_ADJ */ + if (ichan->channel == 2484) { + cckOfdmPwrDelta = SCALE_OC_DELTA( + ee->ee_cckOfdmPwrDelta - + ee->ee_scaledCh14FilterCckDelta); + } else { + cckOfdmPwrDelta = SCALE_OC_DELTA( + ee->ee_cckOfdmPwrDelta); + } + + if (IEEE80211_IS_CHAN_G(chan)) { + OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, + SM((ee->ee_cckOfdmPwrDelta*-1), + AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) | + SM((cckOfdmPwrDelta*-1), + AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX)); + } else { + OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0); + } + + /* Add barker RSSI thresh enable as disabled */ + OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK, + AR_PHY_DAG_CTRLCCK_EN_RSSI_THR); + OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK, + AR_PHY_DAG_CTRLCCK_RSSI_THR, 2); + + /* Set the mute mask to the correct default */ + OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F); + } + + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) { + /* Clear reg to alllow RX_CLEAR line debug */ + OS_REG_WRITE(ah, AR_PHY_BLUETOOTH, 0); + } + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) { +#ifdef notyet + /* Enable burst prefetch for the data queues */ + OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... ); + /* Enable double-buffering */ + OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS); +#endif + } + + /* Set ADC/DAC select values */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); + + if (IS_5413(ah) || IS_2417(ah)) { + uint32_t newReg = 1; + if (IS_DISABLE_FAST_ADC_CHAN(ichan->channel)) + newReg = 0; + /* As it's a clock changing register, only write when the value needs to be changed */ + if (OS_REG_READ(ah, AR_PHY_FAST_ADC) != newReg) + OS_REG_WRITE(ah, AR_PHY_FAST_ADC, newReg); + } + + /* Setup the transmit power values. */ + if (!ar5212SetTransmitPower(ah, chan, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + FAIL(HAL_EIO); + } + + /* Write the analog registers */ + if (!ahp->ah_rfHal->setRfRegs(ah, chan, modesIndex, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n", + __func__); + FAIL(HAL_EIO); + } + + /* Write delta slope for OFDM enabled modes (A, G, Turbo) */ + if (IEEE80211_IS_CHAN_OFDM(chan)) { + if (IS_5413(ah) || + AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3) + ar5212SetSpurMitigation(ah, chan); + ar5212SetDeltaSlope(ah, chan); + } + + /* Setup board specific options for EEPROM version 3 */ + if (!ar5212SetBoardValues(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error setting board options\n", __func__); + FAIL(HAL_EIO); + } + + /* Restore certain DMA hardware registers on a channel change */ + if (bChannelChange) + OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); + OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4) + | macStaId1 + | AR_STA_ID1_RTS_USE_DEF + | ahp->ah_staId1Defaults + ); + ar5212SetOperatingMode(ah, opmode); + + /* Set Venice BSSID mask according to current state */ + OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); + OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); + + /* Restore previous led state */ + OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState); + + /* Restore soft Led state to GPIO */ + OS_REG_WRITE(ah, AR_GPIOCR, softLedCfg); + OS_REG_WRITE(ah, AR_GPIODO, softLedState); + + /* Restore previous antenna */ + OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); + + /* then our BSSID and associate id */ + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4) | + (ahp->ah_assocId & 0x3fff) << AR_BSS_ID1_AID_S); + + /* Restore bmiss rssi & count thresholds */ + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + + OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */ + + if (!ar5212SetChannel(ah, chan)) + FAIL(HAL_EIO); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1); + + ar5212SetRateDurationTable(ah, chan); + + /* Set Tx frame start to tx data start delay */ + if (IS_RAD5112_ANY(ah) && + (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))) { + txFrm2TxDStart = + IEEE80211_IS_CHAN_HALF(chan) ? + TX_FRAME_D_START_HALF_RATE: + TX_FRAME_D_START_QUARTER_RATE; + OS_REG_RMW_FIELD(ah, AR_PHY_TX_CTL, + AR_PHY_TX_FRAME_TO_TX_DATA_START, txFrm2TxDStart); + } + + /* + * Setup fast diversity. + * Fast diversity can be enabled or disabled via regadd.txt. + * Default is enabled. + * For reference, + * Disable: reg val + * 0x00009860 0x00009d18 (if 11a / 11g, else no change) + * 0x00009970 0x192bb514 + * 0x0000a208 0xd03e4648 + * + * Enable: 0x00009860 0x00009d10 (if 11a / 11g, else no change) + * 0x00009970 0x192fb514 + * 0x0000a208 0xd03e6788 + */ + + /* XXX Setup pre PHY ENABLE EAR additions */ + /* + * Wait for the frequency synth to settle (synth goes on + * via AR_PHY_ACTIVE_EN). Read the phy active delay register. + * Value is in 100ns increments. + */ + synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IEEE80211_IS_CHAN_B(chan)) { + synthDelay = (4 * synthDelay) / 22; + } else { + synthDelay /= 10; + } + + /* Activate the PHY (includes baseband activate and synthesizer on) */ + OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + + /* + * There is an issue if the AP starts the calibration before + * the base band timeout completes. This could result in the + * rx_clear false triggering. As a workaround we add delay an + * extra BASE_ACTIVATE_DELAY usecs to ensure this condition + * does not happen. + */ + if (IEEE80211_IS_CHAN_HALF(chan)) { + OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY); + } else if (IEEE80211_IS_CHAN_QUARTER(chan)) { + OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY); + } else { + OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY); + } + + /* + * The udelay method is not reliable with notebooks. + * Need to check to see if the baseband is ready + */ + testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL); + /* Selects the Tx hold */ + OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD); + i = 0; + while ((i++ < 20) && + (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */ OS_DELAY(200); + OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg); + + /* Calibrate the AGC and start a NF calculation */ + OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, + OS_REG_READ(ah, AR_PHY_AGC_CONTROL) + | AR_PHY_AGC_CONTROL_CAL + | AR_PHY_AGC_CONTROL_NF); + + if (!IEEE80211_IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) { + /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */ + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, + INIT_IQCAL_LOG_COUNT_MAX); + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_DO_IQCAL); + ahp->ah_bIQCalibration = IQ_CAL_RUNNING; + } else + ahp->ah_bIQCalibration = IQ_CAL_INACTIVE; + + /* Setup compression registers */ + ar5212SetCompRegs(ah); + + /* Set 1:1 QCU to DCU mapping for all queues */ + for (i = 0; i < AR_NUM_DCU; i++) + OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); + + ahp->ah_intrTxqs = 0; + for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++) + ar5212ResetTxQueue(ah, i); + + /* + * Setup interrupt handling. Note that ar5212ResetTxQueue + * manipulates the secondary IMR's as queues are enabled + * and disabled. This is done with RMW ops to insure the + * settings we make here are preserved. + */ + ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN + | AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN + | AR_IMR_HIUERR + ; + if (opmode == HAL_M_HOSTAP) + ahp->ah_maskReg |= AR_IMR_MIB; + OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg); + /* Enable bus errors that are OR'd to set the HIUERR bit */ + OS_REG_WRITE(ah, AR_IMR_S2, + OS_REG_READ(ah, AR_IMR_S2) + | AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR); + + if (AH_PRIVATE(ah)->ah_rfkillEnabled) + ar5212EnableRfKill(ah); + + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: offset calibration failed to complete in 1ms;" + " noisy environment?\n", __func__); + } + + /* + * Set clocks back to 32kHz if they had been using refClk, then + * use an external 32kHz crystal when sleeping, if one exists. + */ + ar5212SetupClock(ah, opmode); + + /* + * Writing to AR_BEACON will start timers. Hence it should + * be the last register to be written. Do not reset tsf, do + * not enable beacons at this point, but preserve other values + * like beaconInterval. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF))); + + /* XXX Setup post reset EAR additions */ + + /* QoS support */ + if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE || + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && + AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) { + OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa); /* XXX magic */ + OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210); /* XXX magic */ + } + + /* Turn on NOACK Support for QoS packets */ + OS_REG_WRITE(ah, AR_NOACK, + SM(2, AR_NOACK_2BIT_VALUE) | + SM(5, AR_NOACK_BIT_OFFSET) | + SM(0, AR_NOACK_BYTE_OFFSET)); + + /* Get Antenna Gain reduction */ + if (IEEE80211_IS_CHAN_5GHZ(chan)) { + ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_5, &twiceAntennaGain); + } else { + ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_2, &twiceAntennaGain); + } + twiceAntennaReduction = + ath_hal_getantennareduction(ah, chan, twiceAntennaGain); + + /* TPC for self-generated frames */ + + ackTpcPow = MS(ahp->ah_macTPC, AR_TPC_ACK); + if ((ackTpcPow-ahp->ah_txPowerIndexOffset) > chan->ic_maxpower) + ackTpcPow = chan->ic_maxpower+ahp->ah_txPowerIndexOffset; + + if (ackTpcPow > (2*chan->ic_maxregpower - twiceAntennaReduction)) + ackTpcPow = (2*chan->ic_maxregpower - twiceAntennaReduction) + + ahp->ah_txPowerIndexOffset; + + ctsTpcPow = MS(ahp->ah_macTPC, AR_TPC_CTS); + if ((ctsTpcPow-ahp->ah_txPowerIndexOffset) > chan->ic_maxpower) + ctsTpcPow = chan->ic_maxpower+ahp->ah_txPowerIndexOffset; + + if (ctsTpcPow > (2*chan->ic_maxregpower - twiceAntennaReduction)) + ctsTpcPow = (2*chan->ic_maxregpower - twiceAntennaReduction) + + ahp->ah_txPowerIndexOffset; + + chirpTpcPow = MS(ahp->ah_macTPC, AR_TPC_CHIRP); + if ((chirpTpcPow-ahp->ah_txPowerIndexOffset) > chan->ic_maxpower) + chirpTpcPow = chan->ic_maxpower+ahp->ah_txPowerIndexOffset; + + if (chirpTpcPow > (2*chan->ic_maxregpower - twiceAntennaReduction)) + chirpTpcPow = (2*chan->ic_maxregpower - twiceAntennaReduction) + + ahp->ah_txPowerIndexOffset; + + if (ackTpcPow > 63) + ackTpcPow = 63; + if (ctsTpcPow > 63) + ctsTpcPow = 63; + if (chirpTpcPow > 63) + chirpTpcPow = 63; + + powerVal = SM(ackTpcPow, AR_TPC_ACK) | + SM(ctsTpcPow, AR_TPC_CTS) | + SM(chirpTpcPow, AR_TPC_CHIRP); + + OS_REG_WRITE(ah, AR_TPC, powerVal); + + /* Restore user-specified settings */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + if (ahp->ah_sifstime != (u_int) -1) + ar5212SetSifsTime(ah, ahp->ah_sifstime); + if (ahp->ah_slottime != (u_int) -1) + ar5212SetSlotTime(ah, ahp->ah_slottime); + if (ahp->ah_acktimeout != (u_int) -1) + ar5212SetAckTimeout(ah, ahp->ah_acktimeout); + if (ahp->ah_ctstimeout != (u_int) -1) + ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout); + if (AH_PRIVATE(ah)->ah_diagreg != 0) + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); + + AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ +#if 0 +done: +#endif + if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan)) + chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT; + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); + + RESTORE_CCK(ah, chan, isBmode); + + OS_MARK(ah, AH_MARK_RESET_DONE, 0); + + return AH_TRUE; +bad: + RESTORE_CCK(ah, chan, isBmode); + + OS_MARK(ah, AH_MARK_RESET_DONE, ecode); + if (status != AH_NULL) + *status = ecode; + return AH_FALSE; +#undef FAIL +#undef N +} + +/* + * Call the rf backend to change the channel. + */ +HAL_BOOL +ar5212SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* Change the synth */ + if (!ahp->ah_rfHal->setChannel(ah, chan)) + return AH_FALSE; + return AH_TRUE; +} + +/* + * This channel change evaluates whether the selected hardware can + * perform a synthesizer-only channel change (no reset). If the + * TX is not stopped, or the RFBus cannot be granted in the given + * time, the function returns false as a reset is necessary + */ +HAL_BOOL +ar5212ChannelChange(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t ulCount; + uint32_t data, synthDelay, qnum; + uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL]; + HAL_BOOL txStopped = AH_TRUE; + HAL_CHANNEL_INTERNAL *ichan; + + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + + /* TX must be stopped or RF Bus grant will not work */ + for (qnum = 0; qnum < AH_PRIVATE(ah)->ah_caps.halTotalQueues; qnum++) { + if (ar5212NumTxPending(ah, qnum)) { + txStopped = AH_FALSE; + break; + } + } + if (!txStopped) + return AH_FALSE; + + /* Kill last Baseband Rx Frame */ + OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_REQUEST); /* Request analog bus grant */ + for (ulCount = 0; ulCount < 100; ulCount++) { + if (OS_REG_READ(ah, AR_PHY_RFBUS_GNT)) + break; + OS_DELAY(5); + } + if (ulCount >= 100) + return AH_FALSE; + + /* Change the synth */ + if (!ar5212SetChannel(ah, chan)) + return AH_FALSE; + + /* + * Wait for the frequency synth to settle (synth goes on via PHY_ACTIVE_EN). + * Read the phy active delay register. Value is in 100ns increments. + */ + data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IEEE80211_IS_CHAN_B(chan)) { + synthDelay = (4 * data) / 22; + } else { + synthDelay = data / 10; + } + OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY); + + /* Setup the transmit power values. */ + if (!ar5212SetTransmitPower(ah, chan, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + return AH_FALSE; + } + + /* Write delta slope for OFDM enabled modes (A, G, Turbo) */ + if (IEEE80211_IS_CHAN_OFDM(chan)) { + if (IS_5413(ah) || + AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3) + ar5212SetSpurMitigation(ah, chan); + ar5212SetDeltaSlope(ah, chan); + } + + /* Release the RFBus Grant */ + OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); + + /* Start Noise Floor Cal */ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + return AH_TRUE; +} + +void +ar5212SetOperatingMode(struct ath_hal *ah, int opmode) +{ + uint32_t val; + + val = OS_REG_READ(ah, AR_STA_ID1); + val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC); + switch (opmode) { + case HAL_M_HOSTAP: + OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP + | AR_STA_ID1_KSRCH_MODE); + OS_REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); + break; + case HAL_M_IBSS: + OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC + | AR_STA_ID1_KSRCH_MODE); + OS_REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); + break; + case HAL_M_STA: + case HAL_M_MONITOR: + OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); + break; + } +} + +/* + * Places the PHY and Radio chips into reset. A full reset + * must be called to leave this state. The PCI/MAC/PCU are + * not placed into reset as we must receive interrupt to + * re-enable the hardware. + */ +HAL_BOOL +ar5212PhyDisable(struct ath_hal *ah) +{ + return ar5212SetResetReg(ah, AR_RC_BB); +} + +/* + * Places all of hardware into reset + */ +HAL_BOOL +ar5212Disable(struct ath_hal *ah) +{ + if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + /* + * Reset the HW - PCI must be reset after the rest of the + * device has been reset. + */ + return ar5212SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI); +} + +/* + * Places the hardware into reset and then pulls it out of reset + * + * TODO: Only write the PLL if we're changing to or from CCK mode + * + * WARNING: The order of the PLL and mode registers must be correct. + */ +HAL_BOOL +ar5212ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + + OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0); + + /* + * Reset the HW - PCI must be reset after the rest of the + * device has been reset + */ + if (!ar5212SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI)) + return AH_FALSE; + + /* Bring out of sleep mode (AGAIN) */ + if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* Clear warm reset register */ + if (!ar5212SetResetReg(ah, 0)) + return AH_FALSE; + + /* + * Perform warm reset before the mode/PLL/turbo registers + * are changed in order to deactivate the radio. Mode changes + * with an active radio can result in corrupted shifts to the + * radio device. + */ + + /* + * Set CCK and Turbo modes correctly. + */ + if (chan != AH_NULL) { /* NB: can be null during attach */ + uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo; + + if (IS_5413(ah)) { /* NB: =>'s 5424 also */ + rfMode = AR_PHY_MODE_AR5112; + if (IEEE80211_IS_CHAN_HALF(chan)) + rfMode |= AR_PHY_MODE_HALF; + else if (IEEE80211_IS_CHAN_QUARTER(chan)) + rfMode |= AR_PHY_MODE_QUARTER; + + if (IEEE80211_IS_CHAN_CCK(chan)) + phyPLL = AR_PHY_PLL_CTL_44_5112; + else + phyPLL = AR_PHY_PLL_CTL_40_5413; + } else if (IS_RAD5111(ah)) { + rfMode = AR_PHY_MODE_AR5111; + if (IEEE80211_IS_CHAN_CCK(chan)) + phyPLL = AR_PHY_PLL_CTL_44; + else + phyPLL = AR_PHY_PLL_CTL_40; + if (IEEE80211_IS_CHAN_HALF(chan)) + phyPLL = AR_PHY_PLL_CTL_HALF; + else if (IEEE80211_IS_CHAN_QUARTER(chan)) + phyPLL = AR_PHY_PLL_CTL_QUARTER; + } else { /* 5112, 2413, 2316, 2317 */ + rfMode = AR_PHY_MODE_AR5112; + if (IEEE80211_IS_CHAN_CCK(chan)) + phyPLL = AR_PHY_PLL_CTL_44_5112; + else + phyPLL = AR_PHY_PLL_CTL_40_5112; + if (IEEE80211_IS_CHAN_HALF(chan)) + phyPLL |= AR_PHY_PLL_CTL_HALF; + else if (IEEE80211_IS_CHAN_QUARTER(chan)) + phyPLL |= AR_PHY_PLL_CTL_QUARTER; + } + if (IEEE80211_IS_CHAN_G(chan)) + rfMode |= AR_PHY_MODE_DYNAMIC; + else if (IEEE80211_IS_CHAN_OFDM(chan)) + rfMode |= AR_PHY_MODE_OFDM; + else + rfMode |= AR_PHY_MODE_CCK; + if (IEEE80211_IS_CHAN_5GHZ(chan)) + rfMode |= AR_PHY_MODE_RF5GHZ; + else + rfMode |= AR_PHY_MODE_RF2GHZ; + turbo = IEEE80211_IS_CHAN_TURBO(chan) ? + (AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0; + curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL); + /* + * PLL, Mode, and Turbo values must be written in the correct + * order to ensure: + * - The PLL cannot be set to 44 unless the CCK or DYNAMIC + * mode bit is set + * - Turbo cannot be set at the same time as CCK or DYNAMIC + */ + if (IEEE80211_IS_CHAN_CCK(chan)) { + OS_REG_WRITE(ah, AR_PHY_TURBO, turbo); + OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); + if (curPhyPLL != phyPLL) { + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, phyPLL); + /* Wait for the PLL to settle */ + OS_DELAY(PLL_SETTLE_DELAY); + } + } else { + if (curPhyPLL != phyPLL) { + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, phyPLL); + /* Wait for the PLL to settle */ + OS_DELAY(PLL_SETTLE_DELAY); + } + OS_REG_WRITE(ah, AR_PHY_TURBO, turbo); + OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); + } + } + return AH_TRUE; +} + +/* + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +HAL_BOOL +ar5212PerCalibrationN(struct ath_hal *ah, + struct ieee80211_channel *chan, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone) +{ +#define IQ_CAL_TRIES 10 + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *ichan; + int32_t qCoff, qCoffDenom; + int32_t iqCorrMeas, iCoff, iCoffDenom; + uint32_t powerMeasQ, powerMeasI; + HAL_BOOL isBmode = AH_FALSE; + + OS_MARK(ah, AH_MARK_PERCAL, chan->ic_freq); + *isCalDone = AH_FALSE; + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->ic_freq, chan->ic_flags); + return AH_FALSE; + } + SAVE_CCK(ah, chan, isBmode); + + if (ahp->ah_bIQCalibration == IQ_CAL_DONE || + ahp->ah_bIQCalibration == IQ_CAL_INACTIVE) + *isCalDone = AH_TRUE; + + /* IQ calibration in progress. Check to see if it has finished. */ + if (ahp->ah_bIQCalibration == IQ_CAL_RUNNING && + !(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_IQCAL)) { + int i; + + /* IQ Calibration has finished. */ + ahp->ah_bIQCalibration = IQ_CAL_INACTIVE; + *isCalDone = AH_TRUE; + + /* workaround for misgated IQ Cal results */ + i = 0; + do { + /* Read calibration results. */ + powerMeasI = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_I); + powerMeasQ = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_Q); + iqCorrMeas = OS_REG_READ(ah, AR_PHY_IQCAL_RES_IQ_CORR_MEAS); + if (powerMeasI && powerMeasQ) + break; + /* Do we really need this??? */ + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_DO_IQCAL); + } while (++i < IQ_CAL_TRIES); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: IQ cal finished: %d tries\n", __func__, i); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: powerMeasI %u powerMeasQ %u iqCorrMeas %d\n", + __func__, powerMeasI, powerMeasQ, iqCorrMeas); + + /* + * Prescale these values to remove 64-bit operation + * requirement at the loss of a little precision. + */ + iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; + qCoffDenom = powerMeasQ / 128; + + /* Protect against divide-by-0 and loss of sign bits. */ + if (iCoffDenom != 0 && qCoffDenom >= 2) { + iCoff = (int8_t)(-iqCorrMeas) / iCoffDenom; + /* IQCORR_Q_I_COFF is a signed 6 bit number */ + if (iCoff < -32) { + iCoff = -32; + } else if (iCoff > 31) { + iCoff = 31; + } + + /* IQCORR_Q_Q_COFF is a signed 5 bit number */ + qCoff = (powerMeasI / qCoffDenom) - 128; + if (qCoff < -16) { + qCoff = -16; + } else if (qCoff > 15) { + qCoff = 15; + } + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: iCoff %d qCoff %d\n", __func__, iCoff, qCoff); + + /* Write values and enable correction */ + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff); + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); + + ahp->ah_bIQCalibration = IQ_CAL_DONE; + ichan->privFlags |= CHANNEL_IQVALID; + ichan->iCoff = iCoff; + ichan->qCoff = qCoff; + } + } else if (!IEEE80211_IS_CHAN_B(chan) && + ahp->ah_bIQCalibration == IQ_CAL_DONE && + (ichan->privFlags & CHANNEL_IQVALID) == 0) { + /* + * Start IQ calibration if configured channel has changed. + * Use a magic number of 15 based on default value. + */ + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, + INIT_IQCAL_LOG_COUNT_MAX); + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_DO_IQCAL); + ahp->ah_bIQCalibration = IQ_CAL_RUNNING; + } + /* XXX EAR */ + + if (longCal) { + /* Check noise floor results */ + ar5212GetNf(ah, chan); + if (!IEEE80211_IS_CHAN_CWINT(chan)) { + /* Perform cal for 5Ghz channels and any OFDM on 5112 */ + if (IEEE80211_IS_CHAN_5GHZ(chan) || + (IS_RAD5112(ah) && IEEE80211_IS_CHAN_OFDM(chan))) + ar5212RequestRfgain(ah); + } + } + RESTORE_CCK(ah, chan, isBmode); + + return AH_TRUE; +#undef IQ_CAL_TRIES +} + +HAL_BOOL +ar5212PerCalibration(struct ath_hal *ah, struct ieee80211_channel *chan, + HAL_BOOL *isIQdone) +{ + return ar5212PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone); +} + +HAL_BOOL +ar5212ResetCalValid(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + HAL_CHANNEL_INTERNAL *ichan; + + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->ic_freq, chan->ic_flags); + return AH_FALSE; + } + ichan->privFlags &= ~CHANNEL_IQVALID; + return AH_TRUE; +} + +/************************************************************** + * ar5212MacStop + * + * Disables all active QCUs and ensure that the mac is in a + * quiessence state. + */ +static HAL_BOOL +ar5212MacStop(struct ath_hal *ah) +{ + HAL_BOOL status; + uint32_t count; + uint32_t pendFrameCount; + uint32_t macStateFlag; + uint32_t queue; + + status = AH_FALSE; + + /* Disable Rx Operation ***********************************/ + OS_REG_SET_BIT(ah, AR_CR, AR_CR_RXD); + + /* Disable TX Operation ***********************************/ +#ifdef NOT_YET + ar5212SetTxdpInvalid(ah); +#endif + OS_REG_SET_BIT(ah, AR_Q_TXD, AR_Q_TXD_M); + + /* Polling operation for completion of disable ************/ + macStateFlag = TX_ENABLE_CHECK | RX_ENABLE_CHECK; + + for (count = 0; count < MAX_RESET_WAIT; count++) { + if (macStateFlag & RX_ENABLE_CHECK) { + if (!OS_REG_IS_BIT_SET(ah, AR_CR, AR_CR_RXE)) { + macStateFlag &= ~RX_ENABLE_CHECK; + } + } + + if (macStateFlag & TX_ENABLE_CHECK) { + if (!OS_REG_IS_BIT_SET(ah, AR_Q_TXE, AR_Q_TXE_M)) { + macStateFlag &= ~TX_ENABLE_CHECK; + macStateFlag |= TX_QUEUEPEND_CHECK; + } + } + if (macStateFlag & TX_QUEUEPEND_CHECK) { + pendFrameCount = 0; + for (queue = 0; queue < AR_NUM_DCU; queue++) { + pendFrameCount += OS_REG_READ(ah, + AR_Q0_STS + (queue * 4)) & + AR_Q_STS_PEND_FR_CNT; + } + if (pendFrameCount == 0) { + macStateFlag &= ~TX_QUEUEPEND_CHECK; + } + } + if (macStateFlag == 0) { + status = AH_TRUE; + break; + } + OS_DELAY(50); + } + + if (status != AH_TRUE) { + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s:Failed to stop the MAC state 0x%x\n", + __func__, macStateFlag); + } + + return status; +} + + +/* + * Write the given reset bit mask into the reset register + */ +static HAL_BOOL +ar5212SetResetReg(struct ath_hal *ah, uint32_t resetMask) +{ + uint32_t mask = resetMask ? resetMask : ~0; + HAL_BOOL rt; + + /* Never reset the PCIE core */ + if (AH_PRIVATE(ah)->ah_ispcie) { + resetMask &= ~AR_RC_PCI; + } + + if (resetMask & (AR_RC_MAC | AR_RC_PCI)) { + /* + * To ensure that the driver can reset the + * MAC, wake up the chip + */ + rt = ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE); + + if (rt != AH_TRUE) { + return rt; + } + + /* + * Disable interrupts + */ + OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + OS_REG_READ(ah, AR_IER); + + if (ar5212MacStop(ah) != AH_TRUE) { + /* + * Failed to stop the MAC gracefully; let's be more forceful then + */ + + /* need some delay before flush any pending MMR writes */ + OS_DELAY(15); + OS_REG_READ(ah, AR_RXDP); + + resetMask |= AR_RC_MAC | AR_RC_BB; + /* _Never_ reset PCI Express core */ + if (! AH_PRIVATE(ah)->ah_ispcie) { + resetMask |= AR_RC_PCI; + } +#if 0 + /* + * Flush the park address of the PCI controller + */ + /* Read PCI slot information less than Hainan revision */ + if (AH_PRIVATE(ah)->ah_bustype == HAL_BUS_TYPE_PCI) { + if (!IS_5112_REV5_UP(ah)) { +#define PCI_COMMON_CONFIG_STATUS 0x06 + u_int32_t i; + u_int16_t reg16; + + for (i = 0; i < 32; i++) { + ath_hal_read_pci_config_space(ah, + PCI_COMMON_CONFIG_STATUS, + ®16, sizeof(reg16)); + } + } +#undef PCI_COMMON_CONFIG_STATUS + } +#endif + } else { + /* + * MAC stopped gracefully; no need to warm-reset the PCI bus + */ + + resetMask &= ~AR_RC_PCI; + + /* need some delay before flush any pending MMR writes */ + OS_DELAY(15); + OS_REG_READ(ah, AR_RXDP); + } + } + + (void) OS_REG_READ(ah, AR_RXDP);/* flush any pending MMR writes */ + OS_REG_WRITE(ah, AR_RC, resetMask); + OS_DELAY(15); /* need to wait at least 128 clocks + when reseting PCI before read */ + mask &= (AR_RC_MAC | AR_RC_BB); + resetMask &= (AR_RC_MAC | AR_RC_BB); + rt = ath_hal_wait(ah, AR_RC, mask, resetMask); + if ((resetMask & AR_RC_MAC) == 0) { + if (isBigEndian()) { + /* + * Set CFG, little-endian for descriptor accesses. + */ + mask = INIT_CONFIG_STATUS | AR_CFG_SWRD; +#ifndef AH_NEED_DESC_SWAP + mask |= AR_CFG_SWTD; +#endif + OS_REG_WRITE(ah, AR_CFG, mask); + } else + OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS); + if (ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + (void) OS_REG_READ(ah, AR_ISR_RAC); + } + + /* track PHY power state so we don't try to r/w BB registers */ + AH5212(ah)->ah_phyPowerOn = ((resetMask & AR_RC_BB) == 0); + return rt; +} + +int16_t +ar5212GetNoiseFloor(struct ath_hal *ah) +{ + int16_t nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + return nf; +} + +static HAL_BOOL +getNoiseFloorThresh(struct ath_hal *ah, const struct ieee80211_channel *chan, + int16_t *nft) +{ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) { + case IEEE80211_CHAN_A: + *nft = ee->ee_noiseFloorThresh[headerInfo11A]; + break; + case IEEE80211_CHAN_B: + *nft = ee->ee_noiseFloorThresh[headerInfo11B]; + break; + case IEEE80211_CHAN_G: + case IEEE80211_CHAN_PUREG: /* NB: really 108G */ + *nft = ee->ee_noiseFloorThresh[headerInfo11G]; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel flags %u/0x%x\n", + __func__, chan->ic_freq, chan->ic_flags); + return AH_FALSE; + } + return AH_TRUE; +} + +/* + * Setup the noise floor cal history buffer. + */ +void +ar5212InitNfCalHistBuffer(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + int i; + + ahp->ah_nfCalHist.first_run = 1; + ahp->ah_nfCalHist.currIndex = 0; + ahp->ah_nfCalHist.privNF = AR5212_CCA_MAX_GOOD_VALUE; + ahp->ah_nfCalHist.invalidNFcount = AR512_NF_CAL_HIST_MAX; + for (i = 0; i < AR512_NF_CAL_HIST_MAX; i ++) + ahp->ah_nfCalHist.nfCalBuffer[i] = AR5212_CCA_MAX_GOOD_VALUE; +} + +/* + * Add a noise floor value to the ring buffer. + */ +static __inline void +updateNFHistBuff(struct ar5212NfCalHist *h, int16_t nf) +{ + h->nfCalBuffer[h->currIndex] = nf; + if (++h->currIndex >= AR512_NF_CAL_HIST_MAX) + h->currIndex = 0; +} + +/* + * Return the median noise floor value in the ring buffer. + */ +int16_t +ar5212GetNfHistMid(const int16_t calData[AR512_NF_CAL_HIST_MAX]) +{ + int16_t sort[AR512_NF_CAL_HIST_MAX]; + int i, j; + + OS_MEMCPY(sort, calData, AR512_NF_CAL_HIST_MAX*sizeof(int16_t)); + for (i = 0; i < AR512_NF_CAL_HIST_MAX-1; i ++) { + for (j = 1; j < AR512_NF_CAL_HIST_MAX-i; j ++) { + if (sort[j] > sort[j-1]) { + int16_t nf = sort[j]; + sort[j] = sort[j-1]; + sort[j-1] = nf; + } + } + } + return sort[(AR512_NF_CAL_HIST_MAX-1)>>1]; +} + +/* + * Read the NF and check it against the noise floor threshhold + */ +int16_t +ar5212GetNf(struct ath_hal *ah, struct ieee80211_channel *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212NfCalHist *h = &ahp->ah_nfCalHist; + HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); + int16_t nf, nfThresh; + int32_t val; + + if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: NF did not complete in calibration window\n", __func__); + ichan->rawNoiseFloor = h->privNF; /* most recent value */ + return ichan->rawNoiseFloor; + } + + /* + * Finished NF cal, check against threshold. + */ + nf = ar5212GetNoiseFloor(ah); + if (getNoiseFloorThresh(ah, chan, &nfThresh)) { + if (nf > nfThresh) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: noise floor failed detected; detected %u, " + "threshold %u\n", __func__, nf, nfThresh); + /* + * NB: Don't discriminate 2.4 vs 5Ghz, if this + * happens it indicates a problem regardless + * of the band. + */ + chan->ic_state |= IEEE80211_CHANSTATE_CWINT; + nf = 0; + } + } else + nf = 0; + + /* + * Pass through histogram and write median value as + * calculated from the accrued window. We require a + * full window of in-range values to be seen before we + * start using the history. + */ + updateNFHistBuff(h, nf); + if (h->first_run) { + if (nf < AR5212_CCA_MIN_BAD_VALUE || + nf > AR5212_CCA_MAX_HIGH_VALUE) { + nf = AR5212_CCA_MAX_GOOD_VALUE; + h->invalidNFcount = AR512_NF_CAL_HIST_MAX; + } else if (--(h->invalidNFcount) == 0) { + h->first_run = 0; + h->privNF = nf = ar5212GetNfHistMid(h->nfCalBuffer); + } else { + nf = AR5212_CCA_MAX_GOOD_VALUE; + } + } else { + h->privNF = nf = ar5212GetNfHistMid(h->nfCalBuffer); + } + + val = OS_REG_READ(ah, AR_PHY(25)); + val &= 0xFFFFFE00; + val |= (((uint32_t)nf << 1) & 0x1FF); + OS_REG_WRITE(ah, AR_PHY(25), val); + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF, 0)) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: AGC not ready AGC_CONTROL 0x%x\n", + __func__, OS_REG_READ(ah, AR_PHY_AGC_CONTROL)); +#endif + } + + /* + * Now load a high maxCCAPower value again so that we're + * not capped by the median we just loaded + */ + val &= 0xFFFFFE00; + val |= (((uint32_t)(-50) << 1) & 0x1FF); + OS_REG_WRITE(ah, AR_PHY(25), val); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + + return (ichan->rawNoiseFloor = nf); +} + +/* + * Set up compression configuration registers + */ +void +ar5212SetCompRegs(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + int i; + + /* Check if h/w supports compression */ + if (!AH_PRIVATE(ah)->ah_caps.halCompressSupport) + return; + + OS_REG_WRITE(ah, AR_DCCFG, 1); + + OS_REG_WRITE(ah, AR_CCFG, + (AR_COMPRESSION_WINDOW_SIZE >> 8) & AR_CCFG_WIN_M); + + OS_REG_WRITE(ah, AR_CCFG, + OS_REG_READ(ah, AR_CCFG) | AR_CCFG_MIB_INT_EN); + OS_REG_WRITE(ah, AR_CCUCFG, + AR_CCUCFG_RESET_VAL | AR_CCUCFG_CATCHUP_EN); + + OS_REG_WRITE(ah, AR_CPCOVF, 0); + + /* reset decompression mask */ + for (i = 0; i < HAL_DECOMP_MASK_SIZE; i++) { + OS_REG_WRITE(ah, AR_DCM_A, i); + OS_REG_WRITE(ah, AR_DCM_D, ahp->ah_decompMask[i]); + } +} + +HAL_BOOL +ar5212SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings, + const struct ieee80211_channel *chan) +{ +#define ANT_SWITCH_TABLE1 AR_PHY(88) +#define ANT_SWITCH_TABLE2 AR_PHY(89) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint32_t antSwitchA, antSwitchB; + int ix; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + HALASSERT(ahp->ah_phyPowerOn); + + switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) { + case IEEE80211_CHAN_A: + ix = 0; + break; + case IEEE80211_CHAN_G: + case IEEE80211_CHAN_PUREG: /* NB: 108G */ + ix = 2; + break; + case IEEE80211_CHAN_B: + if (IS_2425(ah) || IS_2417(ah)) { + /* NB: Nala/Swan: 11b is handled using 11g */ + ix = 2; + } else + ix = 1; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->ic_flags); + return AH_FALSE; + } + + antSwitchA = ee->ee_antennaControl[1][ix] + | (ee->ee_antennaControl[2][ix] << 6) + | (ee->ee_antennaControl[3][ix] << 12) + | (ee->ee_antennaControl[4][ix] << 18) + | (ee->ee_antennaControl[5][ix] << 24) + ; + antSwitchB = ee->ee_antennaControl[6][ix] + | (ee->ee_antennaControl[7][ix] << 6) + | (ee->ee_antennaControl[8][ix] << 12) + | (ee->ee_antennaControl[9][ix] << 18) + | (ee->ee_antennaControl[10][ix] << 24) + ; + /* + * For fixed antenna, give the same setting for both switch banks + */ + switch (settings) { + case HAL_ANT_FIXED_A: + antSwitchB = antSwitchA; + break; + case HAL_ANT_FIXED_B: + antSwitchA = antSwitchB; + break; + case HAL_ANT_VARIABLE: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad antenna setting %u\n", + __func__, settings); + return AH_FALSE; + } + if (antSwitchB == antSwitchA) { + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Setting fast diversity off.\n", __func__); + OS_REG_CLR_BIT(ah,AR_PHY_CCK_DETECT, + AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + ahp->ah_diversity = AH_FALSE; + } else { + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Setting fast diversity on.\n", __func__); + OS_REG_SET_BIT(ah,AR_PHY_CCK_DETECT, + AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + ahp->ah_diversity = AH_TRUE; + } + ahp->ah_antControl = settings; + + OS_REG_WRITE(ah, ANT_SWITCH_TABLE1, antSwitchA); + OS_REG_WRITE(ah, ANT_SWITCH_TABLE2, antSwitchB); + + return AH_TRUE; +#undef ANT_SWITCH_TABLE2 +#undef ANT_SWITCH_TABLE1 +} + +HAL_BOOL +ar5212IsSpurChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + uint32_t clockFreq = + ((IS_5413(ah) || IS_RAD5112_ANY(ah) || IS_2417(ah)) ? 40 : 32); + return ( ((freq % clockFreq) != 0) + && (((freq % clockFreq) < 10) + || (((freq) % clockFreq) > 22)) ); +} + +/* + * Read EEPROM header info and program the device for correct operation + * given the channel value. + */ +HAL_BOOL +ar5212SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +#define NO_FALSE_DETECT_BACKOFF 2 +#define CB22_FALSE_DETECT_BACKOFF 6 +#define AR_PHY_BIS(_ah, _reg, _mask, _val) \ + OS_REG_WRITE(_ah, AR_PHY(_reg), \ + (OS_REG_READ(_ah, AR_PHY(_reg)) & _mask) | (_val)); + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + int arrayMode, falseDectectBackoff; + int is2GHz = IEEE80211_IS_CHAN_2GHZ(chan); + HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); + int8_t adcDesiredSize, pgaDesiredSize; + uint16_t switchSettling, txrxAtten, rxtxMargin; + int iCoff, qCoff; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + switch (chan->ic_flags & IEEE80211_CHAN_ALLTURBOFULL) { + case IEEE80211_CHAN_A: + case IEEE80211_CHAN_ST: + arrayMode = headerInfo11A; + if (!IS_RAD5112_ANY(ah) && !IS_2413(ah) && !IS_5413(ah)) + OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, + AR_PHY_FRAME_CTL_TX_CLIP, + ahp->ah_gainValues.currStep->paramVal[GP_TXCLIP]); + break; + case IEEE80211_CHAN_B: + arrayMode = headerInfo11B; + break; + case IEEE80211_CHAN_G: + case IEEE80211_CHAN_108G: + arrayMode = headerInfo11G; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->ic_flags); + return AH_FALSE; + } + + /* Set the antenna register(s) correctly for the chip revision */ + AR_PHY_BIS(ah, 68, 0xFFFFFC06, + (ee->ee_antennaControl[0][arrayMode] << 4) | 0x1); + + ar5212SetAntennaSwitchInternal(ah, ahp->ah_antControl, chan); + + /* Set the Noise Floor Thresh on ar5211 devices */ + OS_REG_WRITE(ah, AR_PHY(90), + (ee->ee_noiseFloorThresh[arrayMode] & 0x1FF) + | (1 << 9)); + + if (ee->ee_version >= AR_EEPROM_VER5_0 && IEEE80211_IS_CHAN_TURBO(chan)) { + switchSettling = ee->ee_switchSettlingTurbo[is2GHz]; + adcDesiredSize = ee->ee_adcDesiredSizeTurbo[is2GHz]; + pgaDesiredSize = ee->ee_pgaDesiredSizeTurbo[is2GHz]; + txrxAtten = ee->ee_txrxAttenTurbo[is2GHz]; + rxtxMargin = ee->ee_rxtxMarginTurbo[is2GHz]; + } else { + switchSettling = ee->ee_switchSettling[arrayMode]; + adcDesiredSize = ee->ee_adcDesiredSize[arrayMode]; + pgaDesiredSize = ee->ee_pgaDesiredSize[is2GHz]; + txrxAtten = ee->ee_txrxAtten[is2GHz]; + rxtxMargin = ee->ee_rxtxMargin[is2GHz]; + } + + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, + AR_PHY_SETTLING_SWITCH, switchSettling); + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_ADC, adcDesiredSize); + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_PGA, pgaDesiredSize); + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, + AR_PHY_RXGAIN_TXRX_ATTEN, txrxAtten); + OS_REG_WRITE(ah, AR_PHY(13), + (ee->ee_txEndToXPAOff[arrayMode] << 24) + | (ee->ee_txEndToXPAOff[arrayMode] << 16) + | (ee->ee_txFrameToXPAOn[arrayMode] << 8) + | ee->ee_txFrameToXPAOn[arrayMode]); + AR_PHY_BIS(ah, 10, 0xFFFF00FF, + ee->ee_txEndToXLNAOn[arrayMode] << 8); + AR_PHY_BIS(ah, 25, 0xFFF80FFF, + (ee->ee_thresh62[arrayMode] << 12) & 0x7F000); + + /* + * False detect backoff - suspected 32 MHz spur causes false + * detects in OFDM, causing Tx Hangs. Decrease weak signal + * sensitivity for this card. + */ + falseDectectBackoff = NO_FALSE_DETECT_BACKOFF; + if (ee->ee_version < AR_EEPROM_VER3_3) { + /* XXX magic number */ + if (AH_PRIVATE(ah)->ah_subvendorid == 0x1022 && + IEEE80211_IS_CHAN_OFDM(chan)) + falseDectectBackoff += CB22_FALSE_DETECT_BACKOFF; + } else { + if (ar5212IsSpurChannel(ah, chan)) + falseDectectBackoff += ee->ee_falseDetectBackoff[arrayMode]; + } + AR_PHY_BIS(ah, 73, 0xFFFFFF01, (falseDectectBackoff << 1) & 0xFE); + + if (ichan->privFlags & CHANNEL_IQVALID) { + iCoff = ichan->iCoff; + qCoff = ichan->qCoff; + } else { + iCoff = ee->ee_iqCalI[is2GHz]; + qCoff = ee->ee_iqCalQ[is2GHz]; + } + + /* write previous IQ results */ + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff); + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); + + if (ee->ee_version >= AR_EEPROM_VER4_1) { + if (!IEEE80211_IS_CHAN_108G(chan) || ee->ee_version >= AR_EEPROM_VER5_0) + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, + AR_PHY_GAIN_2GHZ_RXTX_MARGIN, rxtxMargin); + } + if (ee->ee_version >= AR_EEPROM_VER5_1) { + /* for now always disabled */ + OS_REG_WRITE(ah, AR_PHY_HEAVY_CLIP_ENABLE, 0); + } + + return AH_TRUE; +#undef AR_PHY_BIS +#undef NO_FALSE_DETECT_BACKOFF +#undef CB22_FALSE_DETECT_BACKOFF +} + +/* + * Apply Spur Immunity to Boards that require it. + * Applies only to OFDM RX operation. + */ + +void +ar5212SetSpurMitigation(struct ath_hal *ah, + const struct ieee80211_channel *chan) +{ + uint32_t pilotMask[2] = {0, 0}, binMagMask[4] = {0, 0, 0 , 0}; + uint16_t i, finalSpur, curChanAsSpur, binWidth = 0, spurDetectWidth, spurChan; + int32_t spurDeltaPhase = 0, spurFreqSd = 0, spurOffset, binOffsetNumT16, curBinOffset; + int16_t numBinOffsets; + static const uint16_t magMapFor4[4] = {1, 2, 2, 1}; + static const uint16_t magMapFor3[3] = {1, 2, 1}; + const uint16_t *pMagMap; + HAL_BOOL is2GHz = IEEE80211_IS_CHAN_2GHZ(chan); + HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); + uint32_t val; + +#define CHAN_TO_SPUR(_f, _freq) ( ((_freq) - ((_f) ? 2300 : 4900)) * 10 ) + if (IS_2417(ah)) { + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: no spur mitigation\n", + __func__); + return; + } + + curChanAsSpur = CHAN_TO_SPUR(is2GHz, ichan->channel); + + if (ichan->mainSpur) { + /* Pull out the saved spur value */ + finalSpur = ichan->mainSpur; + } else { + /* + * Check if spur immunity should be performed for this channel + * Should only be performed once per channel and then saved + */ + finalSpur = AR_NO_SPUR; + spurDetectWidth = HAL_SPUR_CHAN_WIDTH; + if (IEEE80211_IS_CHAN_TURBO(chan)) + spurDetectWidth *= 2; + + /* Decide if any spur affects the current channel */ + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { + spurChan = ath_hal_getSpurChan(ah, i, is2GHz); + if (spurChan == AR_NO_SPUR) { + break; + } + if ((curChanAsSpur - spurDetectWidth <= (spurChan & HAL_SPUR_VAL_MASK)) && + (curChanAsSpur + spurDetectWidth >= (spurChan & HAL_SPUR_VAL_MASK))) { + finalSpur = spurChan & HAL_SPUR_VAL_MASK; + break; + } + } + /* Save detected spur (or no spur) for this channel */ + ichan->mainSpur = finalSpur; + } + + /* Write spur immunity data */ + if (finalSpur == AR_NO_SPUR) { + /* Disable Spur Immunity Regs if they appear set */ + if (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER) { + /* Clear Spur Delta Phase, Spur Freq, and enable bits */ + OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_RATE, 0); + val = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4); + val &= ~(AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + OS_REG_WRITE(ah, AR_PHY_MASK_CTL, val); + OS_REG_WRITE(ah, AR_PHY_TIMING11, 0); + + /* Clear pilot masks */ + OS_REG_WRITE(ah, AR_PHY_TIMING7, 0); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING8, AR_PHY_TIMING8_PILOT_MASK_2, 0); + OS_REG_WRITE(ah, AR_PHY_TIMING9, 0); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING10, AR_PHY_TIMING10_PILOT_MASK_2, 0); + + /* Clear magnitude masks */ + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, 0); + OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_MASK_4, 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, 0); + OS_REG_RMW_FIELD(ah, AR_PHY_BIN_MASK2_4, AR_PHY_BIN_MASK2_4_MASK_4, 0); + } + } else { + spurOffset = finalSpur - curChanAsSpur; + /* + * Spur calculations: + * spurDeltaPhase is (spurOffsetIn100KHz / chipFrequencyIn100KHz) << 21 + * spurFreqSd is (spurOffsetIn100KHz / sampleFrequencyIn100KHz) << 11 + */ + if (IEEE80211_IS_CHAN_TURBO(chan)) { + /* Chip Frequency & sampleFrequency are 80 MHz */ + spurDeltaPhase = (spurOffset << 16) / 25; + spurFreqSd = spurDeltaPhase >> 10; + binWidth = HAL_BIN_WIDTH_TURBO_100HZ; + } else if (IEEE80211_IS_CHAN_G(chan)) { + /* Chip Frequency is 44MHz, sampleFrequency is 40 MHz */ + spurFreqSd = (spurOffset << 8) / 55; + spurDeltaPhase = (spurOffset << 17) / 25; + binWidth = HAL_BIN_WIDTH_BASE_100HZ; + } else { + HALASSERT(!IEEE80211_IS_CHAN_B(chan)); + /* Chip Frequency & sampleFrequency are 40 MHz */ + spurDeltaPhase = (spurOffset << 17) / 25; + spurFreqSd = spurDeltaPhase >> 10; + binWidth = HAL_BIN_WIDTH_BASE_100HZ; + } + + /* Compute Pilot Mask */ + binOffsetNumT16 = ((spurOffset * 1000) << 4) / binWidth; + /* The spur is on a bin if it's remainder at times 16 is 0 */ + if (binOffsetNumT16 & 0xF) { + numBinOffsets = 4; + pMagMap = magMapFor4; + } else { + numBinOffsets = 3; + pMagMap = magMapFor3; + } + for (i = 0; i < numBinOffsets; i++) { + if ((binOffsetNumT16 >> 4) > HAL_MAX_BINS_ALLOWED) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "Too man bins in spur mitigation\n"); + return; + } + + /* Get Pilot Mask values */ + curBinOffset = (binOffsetNumT16 >> 4) + i + 25; + if ((curBinOffset >= 0) && (curBinOffset <= 32)) { + if (curBinOffset <= 25) + pilotMask[0] |= 1 << curBinOffset; + else if (curBinOffset >= 27) + pilotMask[0] |= 1 << (curBinOffset - 1); + } else if ((curBinOffset >= 33) && (curBinOffset <= 52)) + pilotMask[1] |= 1 << (curBinOffset - 33); + + /* Get viterbi values */ + if ((curBinOffset >= -1) && (curBinOffset <= 14)) + binMagMask[0] |= pMagMap[i] << (curBinOffset + 1) * 2; + else if ((curBinOffset >= 15) && (curBinOffset <= 30)) + binMagMask[1] |= pMagMap[i] << (curBinOffset - 15) * 2; + else if ((curBinOffset >= 31) && (curBinOffset <= 46)) + binMagMask[2] |= pMagMap[i] << (curBinOffset -31) * 2; + else if((curBinOffset >= 47) && (curBinOffset <= 53)) + binMagMask[3] |= pMagMap[i] << (curBinOffset -47) * 2; + } + + /* Write Spur Delta Phase, Spur Freq, and enable bits */ + OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_RATE, 0xFF); + val = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4); + val |= (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4, val); + OS_REG_WRITE(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spurFreqSd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spurDeltaPhase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + + /* Write pilot masks */ + OS_REG_WRITE(ah, AR_PHY_TIMING7, pilotMask[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING8, AR_PHY_TIMING8_PILOT_MASK_2, pilotMask[1]); + OS_REG_WRITE(ah, AR_PHY_TIMING9, pilotMask[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING10, AR_PHY_TIMING10_PILOT_MASK_2, pilotMask[1]); + + /* Write magnitude masks */ + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, binMagMask[0]); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, binMagMask[1]); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, binMagMask[2]); + OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_MASK_4, binMagMask[3]); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, binMagMask[0]); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, binMagMask[1]); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, binMagMask[2]); + OS_REG_RMW_FIELD(ah, AR_PHY_BIN_MASK2_4, AR_PHY_BIN_MASK2_4_MASK_4, binMagMask[3]); + } +#undef CHAN_TO_SPUR +} + + +/* + * Delta slope coefficient computation. + * Required for OFDM operation. + */ +void +ar5212SetDeltaSlope(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +#define COEF_SCALE_S 24 +#define INIT_CLOCKMHZSCALED 0x64000000 + uint16_t freq = ath_hal_gethwchannel(ah, chan); + unsigned long coef_scaled, coef_exp, coef_man, ds_coef_exp, ds_coef_man; + unsigned long clockMhzScaled = INIT_CLOCKMHZSCALED; + + if (IEEE80211_IS_CHAN_TURBO(chan)) + clockMhzScaled *= 2; + /* half and quarter rate can divide the scaled clock by 2 or 4 respectively */ + /* scale for selected channel bandwidth */ + if (IEEE80211_IS_CHAN_HALF(chan)) { + clockMhzScaled = clockMhzScaled >> 1; + } else if (IEEE80211_IS_CHAN_QUARTER(chan)) { + clockMhzScaled = clockMhzScaled >> 2; + } + + /* + * ALGO -> coef = 1e8/fcarrier*fclock/40; + * scaled coef to provide precision for this floating calculation + */ + coef_scaled = clockMhzScaled / freq; + + /* + * ALGO -> coef_exp = 14-floor(log2(coef)); + * floor(log2(x)) is the highest set bit position + */ + for (coef_exp = 31; coef_exp > 0; coef_exp--) + if ((coef_scaled >> coef_exp) & 0x1) + break; + /* A coef_exp of 0 is a legal bit position but an unexpected coef_exp */ + HALASSERT(coef_exp); + coef_exp = 14 - (coef_exp - COEF_SCALE_S); + + /* + * ALGO -> coef_man = floor(coef* 2^coef_exp+0.5); + * The coefficient is already shifted up for scaling + */ + coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1)); + ds_coef_man = coef_man >> (COEF_SCALE_S - coef_exp); + ds_coef_exp = coef_exp - 16; + + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_MAN, ds_coef_man); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); +#undef INIT_CLOCKMHZSCALED +#undef COEF_SCALE_S +} + +/* + * Set a limit on the overall output power. Used for dynamic + * transmit power control and the like. + * + * NB: limit is in units of 0.5 dbM. + */ +HAL_BOOL +ar5212SetTxPowerLimit(struct ath_hal *ah, uint32_t limit) +{ + /* XXX blech, construct local writable copy */ + struct ieee80211_channel dummy = *AH_PRIVATE(ah)->ah_curchan; + uint16_t dummyXpdGains[2]; + HAL_BOOL isBmode; + + SAVE_CCK(ah, &dummy, isBmode); + AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER); + return ar5212SetTransmitPower(ah, &dummy, dummyXpdGains); +} + +/* + * Set the transmit power in the baseband for the given + * operating channel and mode. + */ +HAL_BOOL +ar5212SetTransmitPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain) +{ +#define POW_OFDM(_r, _s) (((0 & 1)<< ((_s)+6)) | (((_r) & 0x3f) << (_s))) +#define POW_CCK(_r, _s) (((_r) & 0x3f) << (_s)) +#define N(a) (sizeof (a) / sizeof (a[0])) + static const uint16_t tpcScaleReductionTable[5] = + { 0, 3, 6, 9, MAX_RATE_POWER }; + struct ath_hal_5212 *ahp = AH5212(ah); + uint16_t freq = ath_hal_gethwchannel(ah, chan); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + int16_t minPower, maxPower, tpcInDb, powerLimit; + int i; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + OS_MEMZERO(ahp->ah_pcdacTable, ahp->ah_pcdacTableSize); + OS_MEMZERO(ahp->ah_ratesArray, sizeof(ahp->ah_ratesArray)); + + powerLimit = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit); + if (powerLimit >= MAX_RATE_POWER || powerLimit == 0) + tpcInDb = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale]; + else + tpcInDb = 0; + if (!ar5212SetRateTable(ah, chan, tpcInDb, powerLimit, + AH_TRUE, &minPower, &maxPower)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set rate table\n", + __func__); + return AH_FALSE; + } + if (!ahp->ah_rfHal->setPowerTable(ah, + &minPower, &maxPower, chan, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n", + __func__); + return AH_FALSE; + } + + /* + * Adjust XR power/rate up by 2 dB to account for greater peak + * to avg ratio - except in newer avg power designs + */ + if (!IS_2413(ah) && !IS_5413(ah)) + ahp->ah_ratesArray[15] += 4; + /* + * txPowerIndexOffset is set by the SetPowerTable() call - + * adjust the rate table + */ + for (i = 0; i < N(ahp->ah_ratesArray); i++) { + ahp->ah_ratesArray[i] += ahp->ah_txPowerIndexOffset; + if (ahp->ah_ratesArray[i] > 63) + ahp->ah_ratesArray[i] = 63; + } + + if (ee->ee_eepMap < 2) { + /* + * Correct gain deltas for 5212 G operation - + * Removed with revised chipset + */ + if (AH_PRIVATE(ah)->ah_phyRev < AR_PHY_CHIP_ID_REV_2 && + IEEE80211_IS_CHAN_G(chan)) { + uint16_t cckOfdmPwrDelta; + + if (freq == 2484) + cckOfdmPwrDelta = SCALE_OC_DELTA( + ee->ee_cckOfdmPwrDelta - + ee->ee_scaledCh14FilterCckDelta); + else + cckOfdmPwrDelta = SCALE_OC_DELTA( + ee->ee_cckOfdmPwrDelta); + ar5212CorrectGainDelta(ah, cckOfdmPwrDelta); + } + /* + * Finally, write the power values into the + * baseband power table + */ + for (i = 0; i < (PWR_TABLE_SIZE/2); i++) { + OS_REG_WRITE(ah, AR_PHY_PCDAC_TX_POWER(i), + ((((ahp->ah_pcdacTable[2*i + 1] << 8) | 0xff) & 0xffff) << 16) + | (((ahp->ah_pcdacTable[2*i] << 8) | 0xff) & 0xffff) + ); + } + } + + /* Write the OFDM power per rate set */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, + POW_OFDM(ahp->ah_ratesArray[3], 24) + | POW_OFDM(ahp->ah_ratesArray[2], 16) + | POW_OFDM(ahp->ah_ratesArray[1], 8) + | POW_OFDM(ahp->ah_ratesArray[0], 0) + ); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, + POW_OFDM(ahp->ah_ratesArray[7], 24) + | POW_OFDM(ahp->ah_ratesArray[6], 16) + | POW_OFDM(ahp->ah_ratesArray[5], 8) + | POW_OFDM(ahp->ah_ratesArray[4], 0) + ); + + /* Write the CCK power per rate set */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, + POW_CCK(ahp->ah_ratesArray[10], 24) + | POW_CCK(ahp->ah_ratesArray[9], 16) + | POW_CCK(ahp->ah_ratesArray[15], 8) /* XR target power */ + | POW_CCK(ahp->ah_ratesArray[8], 0) + ); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, + POW_CCK(ahp->ah_ratesArray[14], 24) + | POW_CCK(ahp->ah_ratesArray[13], 16) + | POW_CCK(ahp->ah_ratesArray[12], 8) + | POW_CCK(ahp->ah_ratesArray[11], 0) + ); + + /* + * Set max power to 30 dBm and, optionally, + * enable TPC in tx descriptors. + */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER | + (ahp->ah_tpcEnabled ? AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE : 0)); + + return AH_TRUE; +#undef N +#undef POW_CCK +#undef POW_OFDM +} + +/* + * Sets the transmit power in the baseband for the given + * operating channel and mode. + */ +static HAL_BOOL +ar5212SetRateTable(struct ath_hal *ah, const struct ieee80211_channel *chan, + int16_t tpcScaleReduction, int16_t powerLimit, HAL_BOOL commit, + int16_t *pMinPower, int16_t *pMaxPower) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint16_t freq = ath_hal_gethwchannel(ah, chan); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t *rpow = ahp->ah_ratesArray; + uint16_t twiceMaxEdgePower = MAX_RATE_POWER; + uint16_t twiceMaxEdgePowerCck = MAX_RATE_POWER; + uint16_t twiceMaxRDPower = MAX_RATE_POWER; + int i; + uint8_t cfgCtl; + int8_t twiceAntennaGain, twiceAntennaReduction; + const RD_EDGES_POWER *rep; + TRGT_POWER_INFO targetPowerOfdm, targetPowerCck; + int16_t scaledPower, maxAvailPower = 0; + int16_t r13, r9, r7, r0; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + twiceMaxRDPower = chan->ic_maxregpower * 2; + *pMaxPower = -MAX_RATE_POWER; + *pMinPower = MAX_RATE_POWER; + + /* Get conformance test limit maximum for this channel */ + cfgCtl = ath_hal_getctl(ah, chan); + for (i = 0; i < ee->ee_numCtls; i++) { + uint16_t twiceMinEdgePower; + + if (ee->ee_ctl[i] == 0) + continue; + if (ee->ee_ctl[i] == cfgCtl || + cfgCtl == ((ee->ee_ctl[i] & CTL_MODE_M) | SD_NO_CTL)) { + rep = &ee->ee_rdEdgesPower[i * NUM_EDGES]; + twiceMinEdgePower = ar5212GetMaxEdgePower(freq, rep); + if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { + /* Find the minimum of all CTL edge powers that apply to this channel */ + twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower); + } else { + twiceMaxEdgePower = twiceMinEdgePower; + break; + } + } + } + + if (IEEE80211_IS_CHAN_G(chan)) { + /* Check for a CCK CTL for 11G CCK powers */ + cfgCtl = (cfgCtl & ~CTL_MODE_M) | CTL_11B; + for (i = 0; i < ee->ee_numCtls; i++) { + uint16_t twiceMinEdgePowerCck; + + if (ee->ee_ctl[i] == 0) + continue; + if (ee->ee_ctl[i] == cfgCtl || + cfgCtl == ((ee->ee_ctl[i] & CTL_MODE_M) | SD_NO_CTL)) { + rep = &ee->ee_rdEdgesPower[i * NUM_EDGES]; + twiceMinEdgePowerCck = ar5212GetMaxEdgePower(freq, rep); + if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { + /* Find the minimum of all CTL edge powers that apply to this channel */ + twiceMaxEdgePowerCck = AH_MIN(twiceMaxEdgePowerCck, twiceMinEdgePowerCck); + } else { + twiceMaxEdgePowerCck = twiceMinEdgePowerCck; + break; + } + } + } + } else { + /* Set the 11B cck edge power to the one found before */ + twiceMaxEdgePowerCck = twiceMaxEdgePower; + } + + /* Get Antenna Gain reduction */ + if (IEEE80211_IS_CHAN_5GHZ(chan)) { + ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_5, &twiceAntennaGain); + } else { + ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_2, &twiceAntennaGain); + } + twiceAntennaReduction = + ath_hal_getantennareduction(ah, chan, twiceAntennaGain); + + if (IEEE80211_IS_CHAN_OFDM(chan)) { + /* Get final OFDM target powers */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + ar5212GetTargetPowers(ah, chan, ee->ee_trgtPwr_11g, + ee->ee_numTargetPwr_11g, &targetPowerOfdm); + } else { + ar5212GetTargetPowers(ah, chan, ee->ee_trgtPwr_11a, + ee->ee_numTargetPwr_11a, &targetPowerOfdm); + } + + /* Get Maximum OFDM power */ + /* Minimum of target and edge powers */ + scaledPower = AH_MIN(twiceMaxEdgePower, + twiceMaxRDPower - twiceAntennaReduction); + + /* + * If turbo is set, reduce power to keep power + * consumption under 2 Watts. Note that we always do + * this unless specially configured. Then we limit + * power only for non-AP operation. + */ + if (IEEE80211_IS_CHAN_TURBO(chan) +#ifdef AH_ENABLE_AP_SUPPORT + && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP +#endif + ) { + /* + * If turbo is set, reduce power to keep power + * consumption under 2 Watts + */ + if (ee->ee_version >= AR_EEPROM_VER3_1) + scaledPower = AH_MIN(scaledPower, + ee->ee_turbo2WMaxPower5); + /* + * EEPROM version 4.0 added an additional + * constraint on 2.4GHz channels. + */ + if (ee->ee_version >= AR_EEPROM_VER4_0 && + IEEE80211_IS_CHAN_2GHZ(chan)) + scaledPower = AH_MIN(scaledPower, + ee->ee_turbo2WMaxPower2); + } + + maxAvailPower = AH_MIN(scaledPower, + targetPowerOfdm.twicePwr6_24); + + /* Reduce power by max regulatory domain allowed restrictions */ + scaledPower = maxAvailPower - (tpcScaleReduction * 2); + scaledPower = (scaledPower < 0) ? 0 : scaledPower; + scaledPower = AH_MIN(scaledPower, powerLimit); + + if (commit) { + /* Set OFDM rates 9, 12, 18, 24 */ + r0 = rpow[0] = rpow[1] = rpow[2] = rpow[3] = rpow[4] = scaledPower; + + /* Set OFDM rates 36, 48, 54, XR */ + rpow[5] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr36); + rpow[6] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr48); + r7 = rpow[7] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr54); + + if (ee->ee_version >= AR_EEPROM_VER4_0) { + /* Setup XR target power from EEPROM */ + rpow[15] = AH_MIN(scaledPower, IEEE80211_IS_CHAN_2GHZ(chan) ? + ee->ee_xrTargetPower2 : ee->ee_xrTargetPower5); + } else { + /* XR uses 6mb power */ + rpow[15] = rpow[0]; + } + ahp->ah_ofdmTxPower = *pMaxPower; + + } else { + r0 = scaledPower; + r7 = AH_MIN(r0, targetPowerOfdm.twicePwr54); + } + *pMinPower = r7; + *pMaxPower = r0; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: MaxRD: %d TurboMax: %d MaxCTL: %d " + "TPC_Reduction %d chan=%d (0x%x) maxAvailPower=%d pwr6_24=%d, maxPower=%d\n", + __func__, twiceMaxRDPower, ee->ee_turbo2WMaxPower5, + twiceMaxEdgePower, tpcScaleReduction * 2, + chan->ic_freq, chan->ic_flags, + maxAvailPower, targetPowerOfdm.twicePwr6_24, *pMaxPower); + } + + if (IEEE80211_IS_CHAN_CCK(chan)) { + /* Get final CCK target powers */ + ar5212GetTargetPowers(ah, chan, ee->ee_trgtPwr_11b, + ee->ee_numTargetPwr_11b, &targetPowerCck); + + /* Reduce power by max regulatory domain allowed restrictions */ + scaledPower = AH_MIN(twiceMaxEdgePowerCck, + twiceMaxRDPower - twiceAntennaReduction); + if (maxAvailPower < AH_MIN(scaledPower, targetPowerCck.twicePwr6_24)) + maxAvailPower = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24); + + /* Reduce power by user selection */ + scaledPower = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24) - (tpcScaleReduction * 2); + scaledPower = (scaledPower < 0) ? 0 : scaledPower; + scaledPower = AH_MIN(scaledPower, powerLimit); + + if (commit) { + /* Set CCK rates 2L, 2S, 5.5L, 5.5S, 11L, 11S */ + rpow[8] = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24); + r9 = rpow[9] = AH_MIN(scaledPower, targetPowerCck.twicePwr36); + rpow[10] = rpow[9]; + rpow[11] = AH_MIN(scaledPower, targetPowerCck.twicePwr48); + rpow[12] = rpow[11]; + r13 = rpow[13] = AH_MIN(scaledPower, targetPowerCck.twicePwr54); + rpow[14] = rpow[13]; + } else { + r9 = AH_MIN(scaledPower, targetPowerCck.twicePwr36); + r13 = AH_MIN(scaledPower, targetPowerCck.twicePwr54); + } + + /* Set min/max power based off OFDM values or initialization */ + if (r13 < *pMinPower) + *pMinPower = r13; + if (r9 > *pMaxPower) + *pMaxPower = r9; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: cck: MaxRD: %d MaxCTL: %d " + "TPC_Reduction %d chan=%d (0x%x) maxAvailPower=%d pwr6_24=%d, maxPower=%d\n", + __func__, twiceMaxRDPower, twiceMaxEdgePowerCck, + tpcScaleReduction * 2, chan->ic_freq, chan->ic_flags, + maxAvailPower, targetPowerCck.twicePwr6_24, *pMaxPower); + } + if (commit) { + ahp->ah_tx6PowerInHalfDbm = *pMaxPower; + AH_PRIVATE(ah)->ah_maxPowerLevel = ahp->ah_tx6PowerInHalfDbm; + } + return AH_TRUE; +} + +HAL_BOOL +ar5212GetChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); +#if 0 + static const uint16_t tpcScaleReductionTable[5] = + { 0, 3, 6, 9, MAX_RATE_POWER }; + int16_t tpcInDb, powerLimit; +#endif + int16_t minPower, maxPower; + + /* + * Get Pier table max and min powers. + */ + if (ahp->ah_rfHal->getChannelMaxMinPower(ah, chan, &maxPower, &minPower)) { + /* NB: rf code returns 1/4 dBm units, convert */ + chan->ic_maxpower = maxPower / 2; + chan->ic_minpower = minPower / 2; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: no min/max power for %u/0x%x\n", + __func__, chan->ic_freq, chan->ic_flags); + chan->ic_maxpower = MAX_RATE_POWER; + chan->ic_minpower = 0; + } +#if 0 + /* + * Now adjust to reflect any global scale and/or CTL's. + * (XXX is that correct?) + */ + powerLimit = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit); + if (powerLimit >= MAX_RATE_POWER || powerLimit == 0) + tpcInDb = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale]; + else + tpcInDb = 0; + if (!ar5212SetRateTable(ah, chan, tpcInDb, powerLimit, + AH_FALSE, &minPower, &maxPower)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to find max/min power\n",__func__); + return AH_FALSE; + } + if (maxPower < chan->ic_maxpower) + chan->ic_maxpower = maxPower; + if (minPower < chan->ic_minpower) + chan->ic_minpower = minPower; + HALDEBUG(ah, HAL_DEBUG_RESET, + "Chan %d: MaxPow = %d MinPow = %d\n", + chan->ic_freq, chan->ic_maxpower, chans->ic_minpower); +#endif + return AH_TRUE; +} + +/* + * Correct for the gain-delta between ofdm and cck mode target + * powers. Write the results to the rate table and the power table. + * + * Conventions : + * 1. rpow[ii] is the integer value of 2*(desired power + * for the rate ii in dBm) to provide 0.5dB resolution. rate + * mapping is as following : + * [0..7] --> ofdm 6, 9, .. 48, 54 + * [8..14] --> cck 1L, 2L, 2S, .. 11L, 11S + * [15] --> XR (all rates get the same power) + * 2. powv[ii] is the pcdac corresponding to ii/2 dBm. + */ +static void +ar5212CorrectGainDelta(struct ath_hal *ah, int twiceOfdmCckDelta) +{ +#define N(_a) (sizeof(_a) / sizeof(_a[0])) + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + int16_t ratesIndex[N(ahp->ah_ratesArray)]; + uint16_t ii, jj, iter; + int32_t cckIndex; + int16_t gainDeltaAdjust; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + gainDeltaAdjust = ee->ee_cckOfdmGainDelta; + + /* make a local copy of desired powers as initial indices */ + OS_MEMCPY(ratesIndex, ahp->ah_ratesArray, sizeof(ratesIndex)); + + /* fix only the CCK indices */ + for (ii = 8; ii < 15; ii++) { + /* apply a gain_delta correction of -15 for CCK */ + ratesIndex[ii] -= gainDeltaAdjust; + + /* Now check for contention with all ofdm target powers */ + jj = 0; + iter = 0; + /* indicates not all ofdm rates checked forcontention yet */ + while (jj < 16) { + if (ratesIndex[ii] < 0) + ratesIndex[ii] = 0; + if (jj == 8) { /* skip CCK rates */ + jj = 15; + continue; + } + if (ratesIndex[ii] == ahp->ah_ratesArray[jj]) { + if (ahp->ah_ratesArray[jj] == 0) + ratesIndex[ii]++; + else if (iter > 50) { + /* + * To avoid pathological case of of + * dm target powers 0 and 0.5dBm + */ + ratesIndex[ii]++; + } else + ratesIndex[ii]--; + /* check with all rates again */ + jj = 0; + iter++; + } else + jj++; + } + if (ratesIndex[ii] >= PWR_TABLE_SIZE) + ratesIndex[ii] = PWR_TABLE_SIZE -1; + cckIndex = ahp->ah_ratesArray[ii] - twiceOfdmCckDelta; + if (cckIndex < 0) + cckIndex = 0; + + /* + * Validate that the indexes for the powv are not + * out of bounds. + */ + HALASSERT(cckIndex < PWR_TABLE_SIZE); + HALASSERT(ratesIndex[ii] < PWR_TABLE_SIZE); + ahp->ah_pcdacTable[ratesIndex[ii]] = + ahp->ah_pcdacTable[cckIndex]; + } + /* Override rate per power table with new values */ + for (ii = 8; ii < 15; ii++) + ahp->ah_ratesArray[ii] = ratesIndex[ii]; +#undef N +} + +/* + * Find the maximum conformance test limit for the given channel and CTL info + */ +static uint16_t +ar5212GetMaxEdgePower(uint16_t channel, const RD_EDGES_POWER *pRdEdgesPower) +{ + /* temp array for holding edge channels */ + uint16_t tempChannelList[NUM_EDGES]; + uint16_t clo, chi, twiceMaxEdgePower; + int i, numEdges; + + /* Get the edge power */ + for (i = 0; i < NUM_EDGES; i++) { + if (pRdEdgesPower[i].rdEdge == 0) + break; + tempChannelList[i] = pRdEdgesPower[i].rdEdge; + } + numEdges = i; + + ar5212GetLowerUpperValues(channel, tempChannelList, + numEdges, &clo, &chi); + /* Get the index for the lower channel */ + for (i = 0; i < numEdges && clo != tempChannelList[i]; i++) + ; + /* Is lower channel ever outside the rdEdge? */ + HALASSERT(i != numEdges); + + if ((clo == chi && clo == channel) || (pRdEdgesPower[i].flag)) { + /* + * If there's an exact channel match or an inband flag set + * on the lower channel use the given rdEdgePower + */ + twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower; + HALASSERT(twiceMaxEdgePower > 0); + } else + twiceMaxEdgePower = MAX_RATE_POWER; + return twiceMaxEdgePower; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static uint16_t +interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + uint16_t targetLeft, uint16_t targetRight) +{ + uint16_t rv; + int16_t lRatio; + + /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */ + if ((targetLeft * targetRight) == 0) + return 0; + + if (srcRight != srcLeft) { + /* + * Note the ratio always need to be scaled, + * since it will be a fraction. + */ + lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft); + if (lRatio < 0) { + /* Return as Left target if value would be negative */ + rv = targetLeft; + } else if (lRatio > EEP_SCALE) { + /* Return as Right target if Ratio is greater than 100% (SCALE) */ + rv = targetRight; + } else { + rv = (lRatio * targetRight + (EEP_SCALE - lRatio) * + targetLeft) / EEP_SCALE; + } + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Return the four rates of target power for the given target power table + * channel, and number of channels + */ +static void +ar5212GetTargetPowers(struct ath_hal *ah, const struct ieee80211_channel *chan, + const TRGT_POWER_INFO *powInfo, + uint16_t numChannels, TRGT_POWER_INFO *pNewPower) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + /* temp array for holding target power channels */ + uint16_t tempChannelList[NUM_TEST_FREQUENCIES]; + uint16_t clo, chi, ixlo, ixhi; + int i; + + /* Copy the target powers into the temp channel list */ + for (i = 0; i < numChannels; i++) + tempChannelList[i] = powInfo[i].testChannel; + + ar5212GetLowerUpperValues(freq, tempChannelList, + numChannels, &clo, &chi); + + /* Get the indices for the channel */ + ixlo = ixhi = 0; + for (i = 0; i < numChannels; i++) { + if (clo == tempChannelList[i]) { + ixlo = i; + } + if (chi == tempChannelList[i]) { + ixhi = i; + break; + } + } + + /* + * Get the lower and upper channels, target powers, + * and interpolate between them. + */ + pNewPower->twicePwr6_24 = interpolate(freq, clo, chi, + powInfo[ixlo].twicePwr6_24, powInfo[ixhi].twicePwr6_24); + pNewPower->twicePwr36 = interpolate(freq, clo, chi, + powInfo[ixlo].twicePwr36, powInfo[ixhi].twicePwr36); + pNewPower->twicePwr48 = interpolate(freq, clo, chi, + powInfo[ixlo].twicePwr48, powInfo[ixhi].twicePwr48); + pNewPower->twicePwr54 = interpolate(freq, clo, chi, + powInfo[ixlo].twicePwr54, powInfo[ixhi].twicePwr54); +} + +static uint32_t +udiff(uint32_t u, uint32_t v) +{ + return (u >= v ? u - v : v - u); +} + +/* + * Search a list for a specified value v that is within + * EEP_DELTA of the search values. Return the closest + * values in the list above and below the desired value. + * EEP_DELTA is a factional value; everything is scaled + * so only integer arithmetic is used. + * + * NB: the input list is assumed to be sorted in ascending order + */ +void +ar5212GetLowerUpperValues(uint16_t v, uint16_t *lp, uint16_t listSize, + uint16_t *vlo, uint16_t *vhi) +{ + uint32_t target = v * EEP_SCALE; + uint16_t *ep = lp+listSize; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < (uint32_t)(lp[0] * EEP_SCALE - EEP_DELTA)) { + *vlo = *vhi = lp[0]; + return; + } + if (target > (uint32_t)(ep[-1] * EEP_SCALE + EEP_DELTA)) { + *vlo = *vhi = ep[-1]; + return; + } + + /* look for value being near or between 2 values in list */ + for (; lp < ep; lp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (udiff(lp[0] * EEP_SCALE, target) < EEP_DELTA) { + *vlo = *vhi = lp[0]; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < (uint32_t)(lp[1] * EEP_SCALE - EEP_DELTA)) { + *vlo = lp[0]; + *vhi = lp[1]; + return; + } + } + HALASSERT(AH_FALSE); /* should not reach here */ +} + +/* + * Perform analog "swizzling" of parameters into their location + * + * NB: used by RF backends + */ +void +ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, uint32_t numBits, + uint32_t firstBit, uint32_t column) +{ +#define MAX_ANALOG_START 319 /* XXX */ + uint32_t tmp32, mask, arrayEntry, lastBit; + int32_t bitPosition, bitsLeft; + + HALASSERT(column <= 3); + HALASSERT(numBits <= 32); + HALASSERT(firstBit + numBits <= MAX_ANALOG_START); + + tmp32 = ath_hal_reverseBits(reg32, numBits); + arrayEntry = (firstBit - 1) / 8; + bitPosition = (firstBit - 1) % 8; + bitsLeft = numBits; + while (bitsLeft > 0) { + lastBit = (bitPosition + bitsLeft > 8) ? + 8 : bitPosition + bitsLeft; + mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << + (column * 8); + rfBuf[arrayEntry] &= ~mask; + rfBuf[arrayEntry] |= ((tmp32 << bitPosition) << + (column * 8)) & mask; + bitsLeft -= 8 - bitPosition; + tmp32 = tmp32 >> (8 - bitPosition); + bitPosition = 0; + arrayEntry++; + } +#undef MAX_ANALOG_START +} + +/* + * Sets the rate to duration values in MAC - used for multi- + * rate retry. + * The rate duration table needs to cover all valid rate codes; + * the 11g table covers all ofdm rates, while the 11b table + * covers all cck rates => all valid rates get covered between + * these two mode's ratetables! + * But if we're turbo, the ofdm phy is replaced by the turbo phy + * and cck is not valid with turbo => all rates get covered + * by the turbo ratetable only + */ +void +ar5212SetRateDurationTable(struct ath_hal *ah, + const struct ieee80211_channel *chan) +{ + const HAL_RATE_TABLE *rt; + int i; + + /* NB: band doesn't matter for 1/2 and 1/4 rate */ + if (IEEE80211_IS_CHAN_HALF(chan)) { + rt = ar5212GetRateTable(ah, HAL_MODE_11A_HALF_RATE); + } else if (IEEE80211_IS_CHAN_QUARTER(chan)) { + rt = ar5212GetRateTable(ah, HAL_MODE_11A_QUARTER_RATE); + } else { + rt = ar5212GetRateTable(ah, + IEEE80211_IS_CHAN_TURBO(chan) ? HAL_MODE_TURBO : HAL_MODE_11G); + } + + for (i = 0; i < rt->rateCount; ++i) + OS_REG_WRITE(ah, + AR_RATE_DURATION(rt->info[i].rateCode), + ath_hal_computetxtime(ah, rt, + WLAN_CTRL_FRAME_SIZE, + rt->info[i].controlRate, AH_FALSE)); + if (!IEEE80211_IS_CHAN_TURBO(chan)) { + /* 11g Table is used to cover the CCK rates. */ + rt = ar5212GetRateTable(ah, HAL_MODE_11G); + for (i = 0; i < rt->rateCount; ++i) { + uint32_t reg = AR_RATE_DURATION(rt->info[i].rateCode); + + if (rt->info[i].phy != IEEE80211_T_CCK) + continue; + + OS_REG_WRITE(ah, reg, + ath_hal_computetxtime(ah, rt, + WLAN_CTRL_FRAME_SIZE, + rt->info[i].controlRate, AH_FALSE)); + /* cck rates have short preamble option also */ + if (rt->info[i].shortPreamble) { + reg += rt->info[i].shortPreamble << 2; + OS_REG_WRITE(ah, reg, + ath_hal_computetxtime(ah, rt, + WLAN_CTRL_FRAME_SIZE, + rt->info[i].controlRate, + AH_TRUE)); + } + } + } +} + +/* Adjust various register settings based on half/quarter rate clock setting. + * This includes: +USEC, TX/RX latency, + * + IFS params: slot, eifs, misc etc. + */ +void +ar5212SetIFSTiming(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t txLat, rxLat, usec, slot, refClock, eifs, init_usec; + + HALASSERT(IEEE80211_IS_CHAN_HALF(chan) || + IEEE80211_IS_CHAN_QUARTER(chan)); + + refClock = OS_REG_READ(ah, AR_USEC) & AR_USEC_USEC32; + if (IEEE80211_IS_CHAN_HALF(chan)) { + slot = IFS_SLOT_HALF_RATE; + rxLat = RX_NON_FULL_RATE_LATENCY << AR5212_USEC_RX_LAT_S; + txLat = TX_HALF_RATE_LATENCY << AR5212_USEC_TX_LAT_S; + usec = HALF_RATE_USEC; + eifs = IFS_EIFS_HALF_RATE; + init_usec = INIT_USEC >> 1; + } else { /* quarter rate */ + slot = IFS_SLOT_QUARTER_RATE; + rxLat = RX_NON_FULL_RATE_LATENCY << AR5212_USEC_RX_LAT_S; + txLat = TX_QUARTER_RATE_LATENCY << AR5212_USEC_TX_LAT_S; + usec = QUARTER_RATE_USEC; + eifs = IFS_EIFS_QUARTER_RATE; + init_usec = INIT_USEC >> 2; + } + + OS_REG_WRITE(ah, AR_USEC, (usec | refClock | txLat | rxLat)); + OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot); + OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs); + OS_REG_RMW_FIELD(ah, AR_D_GBL_IFS_MISC, + AR_D_GBL_IFS_MISC_USEC_DURATION, init_usec); +} diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_rfgain.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_rfgain.c new file mode 100644 index 0000000..f9fbc9c --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_rfgain.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +static const GAIN_OPTIMIZATION_LADDER gainLadder = { + 9, /* numStepsInLadder */ + 4, /* defaultStepNum */ + { { {4, 1, 1, 1}, 6, "FG8"}, + { {4, 0, 1, 1}, 4, "FG7"}, + { {3, 1, 1, 1}, 3, "FG6"}, + { {4, 0, 0, 1}, 1, "FG5"}, + { {4, 1, 1, 0}, 0, "FG4"}, /* noJack */ + { {4, 0, 1, 0}, -2, "FG3"}, /* halfJack */ + { {3, 1, 1, 0}, -3, "FG2"}, /* clip3 */ + { {4, 0, 0, 0}, -4, "FG1"}, /* noJack */ + { {2, 1, 1, 0}, -6, "FG0"} /* clip2 */ + } +}; + +static const GAIN_OPTIMIZATION_LADDER gainLadder5112 = { + 8, /* numStepsInLadder */ + 1, /* defaultStepNum */ + { { {3, 0,0,0, 0,0,0}, 6, "FG7"}, /* most fixed gain */ + { {2, 0,0,0, 0,0,0}, 0, "FG6"}, + { {1, 0,0,0, 0,0,0}, -3, "FG5"}, + { {0, 0,0,0, 0,0,0}, -6, "FG4"}, + { {0, 1,1,0, 0,0,0}, -8, "FG3"}, + { {0, 1,1,0, 1,1,0}, -10, "FG2"}, + { {0, 1,0,1, 1,1,0}, -13, "FG1"}, + { {0, 1,0,1, 1,0,1}, -16, "FG0"}, /* least fixed gain */ + } +}; + +/* + * Initialize the gain structure to good values + */ +void +ar5212InitializeGainValues(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + + /* initialize gain optimization values */ + if (IS_RAD5112_ANY(ah)) { + gv->currStepNum = gainLadder5112.defaultStepNum; + gv->currStep = + &gainLadder5112.optStep[gainLadder5112.defaultStepNum]; + gv->active = AH_TRUE; + gv->loTrig = 20; + gv->hiTrig = 85; + } else { + gv->currStepNum = gainLadder.defaultStepNum; + gv->currStep = &gainLadder.optStep[gainLadder.defaultStepNum]; + gv->active = AH_TRUE; + gv->loTrig = 20; + gv->hiTrig = 35; + } +} + +#define MAX_ANALOG_START 319 /* XXX */ + +/* + * Find analog bits of given parameter data and return a reversed value + */ +static uint32_t +ar5212GetRfField(uint32_t *rfBuf, uint32_t numBits, uint32_t firstBit, uint32_t column) +{ + uint32_t reg32 = 0, mask, arrayEntry, lastBit; + uint32_t bitPosition, bitsShifted; + int32_t bitsLeft; + + HALASSERT(column <= 3); + HALASSERT(numBits <= 32); + HALASSERT(firstBit + numBits <= MAX_ANALOG_START); + + arrayEntry = (firstBit - 1) / 8; + bitPosition = (firstBit - 1) % 8; + bitsLeft = numBits; + bitsShifted = 0; + while (bitsLeft > 0) { + lastBit = (bitPosition + bitsLeft > 8) ? + (8) : (bitPosition + bitsLeft); + mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << + (column * 8); + reg32 |= (((rfBuf[arrayEntry] & mask) >> (column * 8)) >> + bitPosition) << bitsShifted; + bitsShifted += lastBit - bitPosition; + bitsLeft -= (8 - bitPosition); + bitPosition = 0; + arrayEntry++; + } + reg32 = ath_hal_reverseBits(reg32, numBits); + return reg32; +} + +static HAL_BOOL +ar5212InvalidGainReadback(struct ath_hal *ah, GAIN_VALUES *gv) +{ + uint32_t gStep, g, mixOvr; + uint32_t L1, L2, L3, L4; + + if (IS_RAD5112_ANY(ah)) { + mixOvr = ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0); + L1 = 0; + L2 = 107; + L3 = 0; + L4 = 107; + if (mixOvr == 1) { + L2 = 83; + L4 = 83; + gv->hiTrig = 55; + } + } else { + gStep = ar5212GetRfField(ar5212GetRfBank(ah, 7), 6, 37, 0); + + L1 = 0; + L2 = (gStep == 0x3f) ? 50 : gStep + 4; + L3 = (gStep != 0x3f) ? 0x40 : L1; + L4 = L3 + 50; + + gv->loTrig = L1 + (gStep == 0x3f ? DYN_ADJ_LO_MARGIN : 0); + /* never adjust if != 0x3f */ + gv->hiTrig = L4 - (gStep == 0x3f ? DYN_ADJ_UP_MARGIN : -5); + } + g = gv->currGain; + + return !((g >= L1 && g<= L2) || (g >= L3 && g <= L4)); +} + +/* + * Enable the probe gain check on the next packet + */ +void +ar5212RequestRfgain(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t probePowerIndex; + + /* Enable the gain readback probe */ + probePowerIndex = ahp->ah_ofdmTxPower + ahp->ah_txPowerIndexOffset; + OS_REG_WRITE(ah, AR_PHY_PAPD_PROBE, + SM(probePowerIndex, AR_PHY_PAPD_PROBE_POWERTX) + | AR_PHY_PAPD_PROBE_NEXT_TX); + + ahp->ah_rfgainState = HAL_RFGAIN_READ_REQUESTED; +} + +/* + * Check to see if our readback gain level sits within the linear + * region of our current variable attenuation window + */ +static HAL_BOOL +ar5212IsGainAdjustNeeded(struct ath_hal *ah, const GAIN_VALUES *gv) +{ + return (gv->currGain <= gv->loTrig || gv->currGain >= gv->hiTrig); +} + +/* + * Move the rabbit ears in the correct direction. + */ +static int32_t +ar5212AdjustGain(struct ath_hal *ah, GAIN_VALUES *gv) +{ + const GAIN_OPTIMIZATION_LADDER *gl; + + if (IS_RAD5112_ANY(ah)) + gl = &gainLadder5112; + else + gl = &gainLadder; + gv->currStep = &gl->optStep[gv->currStepNum]; + if (gv->currGain >= gv->hiTrig) { + if (gv->currStepNum == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Max gain limit.\n", + __func__); + return -1; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Adding gain: currG=%d [%s] --> ", + __func__, gv->currGain, gv->currStep->stepName); + gv->targetGain = gv->currGain; + while (gv->targetGain >= gv->hiTrig && gv->currStepNum > 0) { + gv->targetGain -= 2 * (gl->optStep[--(gv->currStepNum)].stepGain - + gv->currStep->stepGain); + gv->currStep = &gl->optStep[gv->currStepNum]; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n", + gv->targetGain, gv->currStep->stepName); + return 1; + } + if (gv->currGain <= gv->loTrig) { + if (gv->currStepNum == gl->numStepsInLadder-1) { + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Min gain limit.\n", __func__); + return -2; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Deducting gain: currG=%d [%s] --> ", + __func__, gv->currGain, gv->currStep->stepName); + gv->targetGain = gv->currGain; + while (gv->targetGain <= gv->loTrig && + gv->currStepNum < (gl->numStepsInLadder - 1)) { + gv->targetGain -= 2 * + (gl->optStep[++(gv->currStepNum)].stepGain - gv->currStep->stepGain); + gv->currStep = &gl->optStep[gv->currStepNum]; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n", + gv->targetGain, gv->currStep->stepName); + return 2; + } + return 0; /* caller didn't call needAdjGain first */ +} + +/* + * Read rf register to determine if gainF needs correction + */ +static uint32_t +ar5212GetGainFCorrection(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t correction; + + HALASSERT(IS_RADX112_REV2(ah)); + + correction = 0; + if (ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0) == 1) { + const GAIN_VALUES *gv = &ahp->ah_gainValues; + uint32_t mixGain = gv->currStep->paramVal[0]; + uint32_t gainStep = + ar5212GetRfField(ar5212GetRfBank(ah, 7), 4, 32, 0); + switch (mixGain) { + case 0 : + correction = 0; + break; + case 1 : + correction = gainStep; + break; + case 2 : + correction = 2 * gainStep - 5; + break; + case 3 : + correction = 2 * gainStep; + break; + } + } + return correction; +} + +/* + * Exported call to check for a recent gain reading and return + * the current state of the thermal calibration gain engine. + */ +HAL_RFGAIN +ar5212GetRfgain(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + uint32_t rddata, probeType; + + /* NB: beware of touching the BB when PHY is powered down */ + if (!gv->active || !ahp->ah_phyPowerOn) + return HAL_RFGAIN_INACTIVE; + + if (ahp->ah_rfgainState == HAL_RFGAIN_READ_REQUESTED) { + /* Caller had asked to setup a new reading. Check it. */ + rddata = OS_REG_READ(ah, AR_PHY_PAPD_PROBE); + + if ((rddata & AR_PHY_PAPD_PROBE_NEXT_TX) == 0) { + /* bit got cleared, we have a new reading. */ + gv->currGain = rddata >> AR_PHY_PAPD_PROBE_GAINF_S; + probeType = MS(rddata, AR_PHY_PAPD_PROBE_TYPE); + if (probeType == AR_PHY_PAPD_PROBE_TYPE_CCK) { + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + HALASSERT(IS_RAD5112_ANY(ah)); + HALASSERT(ah->ah_magic == AR5212_MAGIC); + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) + gv->currGain += ee->ee_cckOfdmGainDelta; + else + gv->currGain += PHY_PROBE_CCK_CORRECTION; + } + if (IS_RADX112_REV2(ah)) { + uint32_t correct = ar5212GetGainFCorrection(ah); + if (gv->currGain >= correct) + gv->currGain -= correct; + else + gv->currGain = 0; + } + /* inactive by default */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + if (!ar5212InvalidGainReadback(ah, gv) && + ar5212IsGainAdjustNeeded(ah, gv) && + ar5212AdjustGain(ah, gv) > 0) { + /* + * Change needed. Copy ladder info + * into eeprom info. + */ + ahp->ah_rfgainState = HAL_RFGAIN_NEED_CHANGE; + /* for ap51 */ + ahp->ah_cwCalRequire = AH_TRUE; + /* Request IQ recalibration for temperature chang */ + ahp->ah_bIQCalibration = IQ_CAL_INACTIVE; + } + } + } + return ahp->ah_rfgainState; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212_xmit.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_xmit.c new file mode 100644 index 0000000..5aeefed --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212_xmit.c @@ -0,0 +1,1002 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212desc.h" +#include "ar5212/ar5212phy.h" +#ifdef AH_SUPPORT_5311 +#include "ar5212/ar5311reg.h" +#endif + +#ifdef AH_NEED_DESC_SWAP +static void ar5212SwapTxDesc(struct ath_desc *ds); +#endif + +/* + * Update Tx FIFO trigger level. + * + * Set bIncTrigLevel to TRUE to increase the trigger level. + * Set bIncTrigLevel to FALSE to decrease the trigger level. + * + * Returns TRUE if the trigger level was updated + */ +HAL_BOOL +ar5212UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t txcfg, curLevel, newLevel; + HAL_INT omask; + + if (ahp->ah_txTrigLev >= ahp->ah_maxTxTrigLev) + return AH_FALSE; + + /* + * Disable interrupts while futzing with the fifo level. + */ + omask = ath_hal_setInterrupts(ah, ahp->ah_maskReg &~ HAL_INT_GLOBAL); + + txcfg = OS_REG_READ(ah, AR_TXCFG); + curLevel = MS(txcfg, AR_FTRIG); + newLevel = curLevel; + if (bIncTrigLevel) { /* increase the trigger level */ + if (curLevel < ahp->ah_maxTxTrigLev) + newLevel++; + } else if (curLevel > MIN_TX_FIFO_THRESHOLD) + newLevel--; + if (newLevel != curLevel) + /* Update the trigger level */ + OS_REG_WRITE(ah, AR_TXCFG, + (txcfg &~ AR_FTRIG) | SM(newLevel, AR_FTRIG)); + + ahp->ah_txTrigLev = newLevel; + + /* re-enable chip interrupts */ + ath_hal_setInterrupts(ah, omask); + + return (newLevel != curLevel); +} + +/* + * Set the properties of the tx queue with the parameters + * from qInfo. + */ +HAL_BOOL +ar5212SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + if (q >= pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo); +} + +/* + * Return the properties for the specified tx queue. + */ +HAL_BOOL +ar5212GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + + if (q >= pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]); +} + +/* + * Allocate and initialize a tx DCU/QCU combination. + */ +int +ar5212SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_TX_QUEUE_INFO *qi; + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + int q, defqflags; + + /* by default enable OK+ERR+DESC+URN interrupts */ + defqflags = HAL_TXQ_TXOKINT_ENABLE + | HAL_TXQ_TXERRINT_ENABLE + | HAL_TXQ_TXDESCINT_ENABLE + | HAL_TXQ_TXURNINT_ENABLE; + /* XXX move queue assignment to driver */ + switch (type) { + case HAL_TX_QUEUE_BEACON: + q = pCap->halTotalQueues-1; /* highest priority */ + defqflags |= HAL_TXQ_DBA_GATED + | HAL_TXQ_CBR_DIS_QEMPTY + | HAL_TXQ_ARB_LOCKOUT_GLOBAL + | HAL_TXQ_BACKOFF_DISABLE; + break; + case HAL_TX_QUEUE_CAB: + q = pCap->halTotalQueues-2; /* next highest priority */ + defqflags |= HAL_TXQ_DBA_GATED + | HAL_TXQ_CBR_DIS_QEMPTY + | HAL_TXQ_CBR_DIS_BEMPTY + | HAL_TXQ_ARB_LOCKOUT_GLOBAL + | HAL_TXQ_BACKOFF_DISABLE; + break; + case HAL_TX_QUEUE_UAPSD: + q = pCap->halTotalQueues-3; /* nextest highest priority */ + if (ahp->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: no available UAPSD tx queue\n", __func__); + return -1; + } + break; + case HAL_TX_QUEUE_DATA: + for (q = 0; q < pCap->halTotalQueues; q++) + if (ahp->ah_txq[q].tqi_type == HAL_TX_QUEUE_INACTIVE) + break; + if (q == pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: no available tx queue\n", __func__); + return -1; + } + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: bad tx queue type %u\n", __func__, type); + return -1; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + + qi = &ahp->ah_txq[q]; + if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n", + __func__, q); + return -1; + } + OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); + qi->tqi_type = type; + if (qInfo == AH_NULL) { + qi->tqi_qflags = defqflags; + qi->tqi_aifs = INIT_AIFS; + qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ + qi->tqi_cwmax = INIT_CWMAX; + qi->tqi_shretry = INIT_SH_RETRY; + qi->tqi_lgretry = INIT_LG_RETRY; + qi->tqi_physCompBuf = 0; + } else { + qi->tqi_physCompBuf = qInfo->tqi_compBuf; + (void) ar5212SetTxQueueProps(ah, q, qInfo); + } + /* NB: must be followed by ar5212ResetTxQueue */ + return q; +} + +/* + * Update the h/w interrupt registers to reflect a tx q's configuration. + */ +static void +setTxQInterrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", __func__, + ahp->ah_txOkInterruptMask, ahp->ah_txErrInterruptMask, + ahp->ah_txDescInterruptMask, ahp->ah_txEolInterruptMask, + ahp->ah_txUrnInterruptMask); + + OS_REG_WRITE(ah, AR_IMR_S0, + SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK) + | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC) + ); + OS_REG_WRITE(ah, AR_IMR_S1, + SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR) + | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL) + ); + OS_REG_RMW_FIELD(ah, AR_IMR_S2, + AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask); +} + +/* + * Free a tx DCU/QCU combination. + */ +HAL_BOOL +ar5212ReleaseTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + HAL_TX_QUEUE_INFO *qi; + + if (q >= pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_FALSE; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q); + + qi->tqi_type = HAL_TX_QUEUE_INACTIVE; + ahp->ah_txOkInterruptMask &= ~(1 << q); + ahp->ah_txErrInterruptMask &= ~(1 << q); + ahp->ah_txDescInterruptMask &= ~(1 << q); + ahp->ah_txEolInterruptMask &= ~(1 << q); + ahp->ah_txUrnInterruptMask &= ~(1 << q); + setTxQInterrupts(ah, qi); + + return AH_TRUE; +} + +/* + * Set the retry, aifs, cwmin/max, readyTime regs for specified queue + * Assumes: + * phwChannel has been set to point to the current channel + */ +#define TU_TO_USEC(_tu) ((_tu) << 10) +HAL_BOOL +ar5212ResetTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + HAL_TX_QUEUE_INFO *qi; + uint32_t cwMin, chanCwMin, qmisc, dmisc; + + if (q >= pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_TRUE; /* XXX??? */ + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: reset queue %u\n", __func__, q); + + if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) { + /* + * Select cwmin according to channel type. + * NB: chan can be NULL during attach + */ + if (chan && IEEE80211_IS_CHAN_B(chan)) + chanCwMin = INIT_CWMIN_11B; + else + chanCwMin = INIT_CWMIN; + /* make sure that the CWmin is of the form (2^n - 1) */ + for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1) + ; + } else + cwMin = qi->tqi_cwmin; + + /* set cwMin/Max and AIFS values */ + OS_REG_WRITE(ah, AR_DLCL_IFS(q), + SM(cwMin, AR_D_LCL_IFS_CWMIN) + | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) + | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); + + /* Set retry limit values */ + OS_REG_WRITE(ah, AR_DRETRY_LIMIT(q), + SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) + | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) + | SM(qi->tqi_lgretry, AR_D_RETRY_LIMIT_FR_LG) + | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH) + ); + + /* NB: always enable early termination on the QCU */ + qmisc = AR_Q_MISC_DCU_EARLY_TERM_REQ + | SM(AR_Q_MISC_FSP_ASAP, AR_Q_MISC_FSP); + + /* NB: always enable DCU to wait for next fragment from QCU */ + dmisc = AR_D_MISC_FRAG_WAIT_EN; + +#ifdef AH_SUPPORT_5311 + if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) { + /* Configure DCU to use the global sequence count */ + dmisc |= AR5311_D_MISC_SEQ_NUM_CONTROL; + } +#endif + /* multiqueue support */ + if (qi->tqi_cbrPeriod) { + OS_REG_WRITE(ah, AR_QCBRCFG(q), + SM(qi->tqi_cbrPeriod,AR_Q_CBRCFG_CBR_INTERVAL) + | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_CBR_OVF_THRESH)); + qmisc = (qmisc &~ AR_Q_MISC_FSP) | AR_Q_MISC_FSP_CBR; + if (qi->tqi_cbrOverflowLimit) + qmisc |= AR_Q_MISC_CBR_EXP_CNTR_LIMIT; + } + if (qi->tqi_readyTime) { + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), + SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT) + | AR_Q_RDYTIMECFG_ENA); + } + + OS_REG_WRITE(ah, AR_DCHNTIME(q), + SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) + | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); + + if (qi->tqi_readyTime && + (qi->tqi_qflags & HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE)) + qmisc |= AR_Q_MISC_RDYTIME_EXP_POLICY; + if (qi->tqi_qflags & HAL_TXQ_DBA_GATED) + qmisc = (qmisc &~ AR_Q_MISC_FSP) | AR_Q_MISC_FSP_DBA_GATED; + if (MS(qmisc, AR_Q_MISC_FSP) != AR_Q_MISC_FSP_ASAP) { + /* + * These are meangingful only when not scheduled asap. + */ + if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_BEMPTY) + qmisc |= AR_Q_MISC_CBR_INCR_DIS0; + else + qmisc &= ~AR_Q_MISC_CBR_INCR_DIS0; + if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_QEMPTY) + qmisc |= AR_Q_MISC_CBR_INCR_DIS1; + else + qmisc &= ~AR_Q_MISC_CBR_INCR_DIS1; + } + + if (qi->tqi_qflags & HAL_TXQ_BACKOFF_DISABLE) + dmisc |= AR_D_MISC_POST_FR_BKOFF_DIS; + if (qi->tqi_qflags & HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE) + dmisc |= AR_D_MISC_FRAG_BKOFF_EN; + if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_GLOBAL) + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL); + else if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_INTRA) + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR, + AR_D_MISC_ARB_LOCKOUT_CNTRL); + if (qi->tqi_qflags & HAL_TXQ_IGNORE_VIRTCOL) + dmisc |= SM(AR_D_MISC_VIR_COL_HANDLING_IGNORE, + AR_D_MISC_VIR_COL_HANDLING); + if (qi->tqi_qflags & HAL_TXQ_SEQNUM_INC_DIS) + dmisc |= AR_D_MISC_SEQ_NUM_INCR_DIS; + + /* + * Fillin type-dependent bits. Most of this can be + * removed by specifying the queue parameters in the + * driver; it's here for backwards compatibility. + */ + switch (qi->tqi_type) { + case HAL_TX_QUEUE_BEACON: /* beacon frames */ + qmisc |= AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_BEACON_USE + | AR_Q_MISC_CBR_INCR_DIS1; + + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL) + | AR_D_MISC_BEACON_USE + | AR_D_MISC_POST_FR_BKOFF_DIS; + break; + case HAL_TX_QUEUE_CAB: /* CAB frames */ + /* + * No longer Enable AR_Q_MISC_RDYTIME_EXP_POLICY, + * There is an issue with the CAB Queue + * not properly refreshing the Tx descriptor if + * the TXE clear setting is used. + */ + qmisc |= AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_CBR_INCR_DIS1 + | AR_Q_MISC_CBR_INCR_DIS0; + + if (qi->tqi_readyTime) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: using tqi_readyTime\n", __func__); + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), + SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT) | + AR_Q_RDYTIMECFG_ENA); + } else { + int value; + /* + * NB: don't set default ready time if driver + * has explicitly specified something. This is + * here solely for backwards compatibility. + */ + /* + * XXX for now, hard-code a CAB interval of 70% + * XXX of the total beacon interval. + */ + + value = (ahp->ah_beaconInterval * 70 / 100) + - (ah->ah_config.ah_sw_beacon_response_time - + + ah->ah_config.ah_dma_beacon_response_time) + - ah->ah_config.ah_additional_swba_backoff; + /* + * XXX Ensure it isn't too low - nothing lower + * XXX than 10 TU + */ + if (value < 10) + value = 10; + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: defaulting to rdytime = %d uS\n", + __func__, value); + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), + SM(TU_TO_USEC(value), AR_Q_RDYTIMECFG_INT) | + AR_Q_RDYTIMECFG_ENA); + } + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL); + break; + default: /* NB: silence compiler */ + break; + } + + OS_REG_WRITE(ah, AR_QMISC(q), qmisc); + OS_REG_WRITE(ah, AR_DMISC(q), dmisc); + + /* Setup compression scratchpad buffer */ + /* + * XXX: calling this asynchronously to queue operation can + * cause unexpected behavior!!! + */ + if (qi->tqi_physCompBuf) { + HALASSERT(qi->tqi_type == HAL_TX_QUEUE_DATA || + qi->tqi_type == HAL_TX_QUEUE_UAPSD); + OS_REG_WRITE(ah, AR_Q_CBBS, (80 + 2*q)); + OS_REG_WRITE(ah, AR_Q_CBBA, qi->tqi_physCompBuf); + OS_REG_WRITE(ah, AR_Q_CBC, HAL_COMP_BUF_MAX_SIZE/1024); + OS_REG_WRITE(ah, AR_Q0_MISC + 4*q, + OS_REG_READ(ah, AR_Q0_MISC + 4*q) + | AR_Q_MISC_QCU_COMP_EN); + } + + /* + * Always update the secondary interrupt mask registers - this + * could be a new queue getting enabled in a running system or + * hw getting re-initialized during a reset! + * + * Since we don't differentiate between tx interrupts corresponding + * to individual queues - secondary tx mask regs are always unmasked; + * tx interrupts are enabled/disabled for all queues collectively + * using the primary mask reg + */ + if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) + ahp->ah_txOkInterruptMask |= 1 << q; + else + ahp->ah_txOkInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) + ahp->ah_txErrInterruptMask |= 1 << q; + else + ahp->ah_txErrInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE) + ahp->ah_txDescInterruptMask |= 1 << q; + else + ahp->ah_txDescInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) + ahp->ah_txEolInterruptMask |= 1 << q; + else + ahp->ah_txEolInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) + ahp->ah_txUrnInterruptMask |= 1 << q; + else + ahp->ah_txUrnInterruptMask &= ~(1 << q); + setTxQInterrupts(ah, qi); + + return AH_TRUE; +} +#undef TU_TO_USEC + +/* + * Get the TXDP for the specified queue + */ +uint32_t +ar5212GetTxDP(struct ath_hal *ah, u_int q) +{ + HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); + return OS_REG_READ(ah, AR_QTXDP(q)); +} + +/* + * Set the TxDP for the specified queue + */ +HAL_BOOL +ar5212SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp) +{ + HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); + HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + /* + * Make sure that TXE is deasserted before setting the TXDP. If TXE + * is still asserted, setting TXDP will have no effect. + */ + HALASSERT((OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) == 0); + + OS_REG_WRITE(ah, AR_QTXDP(q), txdp); + + return AH_TRUE; +} + +/* + * Set Transmit Enable bits for the specified queue + */ +HAL_BOOL +ar5212StartTxDma(struct ath_hal *ah, u_int q) +{ + HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); + + HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + + /* Check to be sure we're not enabling a q that has its TXD bit set. */ + HALASSERT((OS_REG_READ(ah, AR_Q_TXD) & (1 << q)) == 0); + + OS_REG_WRITE(ah, AR_Q_TXE, 1 << q); + return AH_TRUE; +} + +/* + * Return the number of pending frames or 0 if the specified + * queue is stopped. + */ +uint32_t +ar5212NumTxPending(struct ath_hal *ah, u_int q) +{ + uint32_t npend; + + HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); + HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + npend = OS_REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT; + if (npend == 0) { + /* + * Pending frame count (PFC) can momentarily go to zero + * while TXE remains asserted. In other words a PFC of + * zero is not sufficient to say that the queue has stopped. + */ + if (OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) + npend = 1; /* arbitrarily return 1 */ + } + return npend; +} + +/* + * Stop transmit on the specified queue + */ +HAL_BOOL +ar5212StopTxDma(struct ath_hal *ah, u_int q) +{ + u_int i; + u_int wait; + + HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); + + HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + OS_REG_WRITE(ah, AR_Q_TXD, 1 << q); + for (i = 1000; i != 0; i--) { + if (ar5212NumTxPending(ah, q) == 0) + break; + OS_DELAY(100); /* XXX get actual value */ + } +#ifdef AH_DEBUG + if (i == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: queue %u DMA did not stop in 100 msec\n", __func__, q); + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n", __func__, + OS_REG_READ(ah, AR_QSTS(q)), OS_REG_READ(ah, AR_Q_TXE), + OS_REG_READ(ah, AR_Q_TXD), OS_REG_READ(ah, AR_QCBRCFG(q))); + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n", + __func__, OS_REG_READ(ah, AR_QMISC(q)), + OS_REG_READ(ah, AR_QRDYTIMECFG(q)), + OS_REG_READ(ah, AR_Q_RDYTIMESHDN)); + } +#endif /* AH_DEBUG */ + + /* 2413+ and up can kill packets at the PCU level */ + if (ar5212NumTxPending(ah, q) && + (IS_2413(ah) || IS_5413(ah) || IS_2425(ah) || IS_2417(ah))) { + uint32_t tsfLow, j; + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: Num of pending TX Frames %d on Q %d\n", + __func__, ar5212NumTxPending(ah, q), q); + + /* Kill last PCU Tx Frame */ + /* TODO - save off and restore current values of Q1/Q2? */ + for (j = 0; j < 2; j++) { + tsfLow = OS_REG_READ(ah, AR_TSF_L32); + OS_REG_WRITE(ah, AR_QUIET2, SM(100, AR_QUIET2_QUIET_PER) | + SM(10, AR_QUIET2_QUIET_DUR)); + OS_REG_WRITE(ah, AR_QUIET1, AR_QUIET1_QUIET_ENABLE | + SM(tsfLow >> 10, AR_QUIET1_NEXT_QUIET)); + if ((OS_REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) { + break; + } + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: TSF moved while trying to set quiet time " + "TSF: 0x%08x\n", __func__, tsfLow); + HALASSERT(j < 1); /* TSF shouldn't count twice or reg access is taking forever */ + } + + OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE); + + /* Allow the quiet mechanism to do its work */ + OS_DELAY(200); + OS_REG_CLR_BIT(ah, AR_QUIET1, AR_QUIET1_QUIET_ENABLE); + + /* Give at least 1 millisec more to wait */ + wait = 100; + + /* Verify all transmit is dead */ + while (ar5212NumTxPending(ah, q)) { + if ((--wait) == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Failed to stop Tx DMA in %d msec after killing last frame\n", + __func__, wait); + break; + } + OS_DELAY(10); + } + + OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE); + } + + OS_REG_WRITE(ah, AR_Q_TXD, 0); + return (i != 0); +} + +/* + * Descriptor Access Functions + */ + +#define VALID_PKT_TYPES \ + ((1<ah_txPowerIndexOffset ); + if(txPower > 63) txPower=63; + + ads->ds_ctl0 = (pktLen & AR_FrameLen) + | (txPower << AR_XmitPower_S) + | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0) + | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0) + | SM(antMode, AR_AntModeXmit) + | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0) + ; + ads->ds_ctl1 = (type << AR_FrmType_S) + | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0) + | (comp << AR_CompProc_S) + | (compicvLen << AR_CompICVLen_S) + | (compivLen << AR_CompIVLen_S) + ; + ads->ds_ctl2 = SM(txTries0, AR_XmitDataTries0) + | (flags & HAL_TXDESC_DURENA ? AR_DurUpdateEna : 0) + ; + ads->ds_ctl3 = (txRate0 << AR_XmitRate0_S) + ; + if (keyIx != HAL_TXKEYIX_INVALID) { + /* XXX validate key index */ + ads->ds_ctl1 |= SM(keyIx, AR_DestIdx); + ads->ds_ctl0 |= AR_DestIdxValid; + } + if (flags & RTSCTS) { + if (!isValidTxRate(rtsctsRate)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid rts/cts rate 0x%x\n", + __func__, rtsctsRate); + return AH_FALSE; + } + /* XXX validate rtsctsDuration */ + ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0) + | (flags & HAL_TXDESC_RTSENA ? AR_RTSCTSEnable : 0) + ; + ads->ds_ctl2 |= SM(rtsctsDuration, AR_RTSCTSDuration); + ads->ds_ctl3 |= (rtsctsRate << AR_RTSCTSRate_S); + } + return AH_TRUE; +#undef RTSCTS +} + +HAL_BOOL +ar5212SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int txRate1, u_int txTries1, + u_int txRate2, u_int txTries2, + u_int txRate3, u_int txTries3) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + + if (txTries1) { + HALASSERT(isValidTxRate(txRate1)); + ads->ds_ctl2 |= SM(txTries1, AR_XmitDataTries1) + | AR_DurUpdateEna + ; + ads->ds_ctl3 |= (txRate1 << AR_XmitRate1_S); + } + if (txTries2) { + HALASSERT(isValidTxRate(txRate2)); + ads->ds_ctl2 |= SM(txTries2, AR_XmitDataTries2) + | AR_DurUpdateEna + ; + ads->ds_ctl3 |= (txRate2 << AR_XmitRate2_S); + } + if (txTries3) { + HALASSERT(isValidTxRate(txRate3)); + ads->ds_ctl2 |= SM(txTries3, AR_XmitDataTries3) + | AR_DurUpdateEna + ; + ads->ds_ctl3 |= (txRate3 << AR_XmitRate3_S); + } + return AH_TRUE; +} + +void +ar5212IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + +#ifdef AH_NEED_DESC_SWAP + ads->ds_ctl0 |= __bswap32(AR_TxInterReq); +#else + ads->ds_ctl0 |= AR_TxInterReq; +#endif +} + +HAL_BOOL +ar5212FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, + HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, u_int qcuId, + u_int descId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + uint32_t segLen = segLenList[0]; + + HALASSERT((segLen &~ AR_BufLen) == 0); + + ds->ds_data = bufAddrList[0]; + + if (firstSeg) { + /* + * First descriptor, don't clobber xmit control data + * setup by ar5212SetupTxDesc. + */ + ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More); + } else if (lastSeg) { /* !firstSeg && lastSeg */ + /* + * Last descriptor in a multi-descriptor frame, + * copy the multi-rate transmit parameters from + * the first frame for processing on completion. + */ + ads->ds_ctl1 = segLen; +#ifdef AH_NEED_DESC_SWAP + ads->ds_ctl0 = __bswap32(AR5212DESC_CONST(ds0)->ds_ctl0) + & AR_TxInterReq; + ads->ds_ctl2 = __bswap32(AR5212DESC_CONST(ds0)->ds_ctl2); + ads->ds_ctl3 = __bswap32(AR5212DESC_CONST(ds0)->ds_ctl3); +#else + ads->ds_ctl0 = AR5212DESC_CONST(ds0)->ds_ctl0 & AR_TxInterReq; + ads->ds_ctl2 = AR5212DESC_CONST(ds0)->ds_ctl2; + ads->ds_ctl3 = AR5212DESC_CONST(ds0)->ds_ctl3; +#endif + } else { /* !firstSeg && !lastSeg */ + /* + * Intermediate descriptor in a multi-descriptor frame. + */ +#ifdef AH_NEED_DESC_SWAP + ads->ds_ctl0 = __bswap32(AR5212DESC_CONST(ds0)->ds_ctl0) + & AR_TxInterReq; +#else + ads->ds_ctl0 = AR5212DESC_CONST(ds0)->ds_ctl0 & AR_TxInterReq; +#endif + ads->ds_ctl1 = segLen | AR_More; + ads->ds_ctl2 = 0; + ads->ds_ctl3 = 0; + } + ads->ds_txstatus0 = ads->ds_txstatus1 = 0; + return AH_TRUE; +} + +#ifdef AH_NEED_DESC_SWAP +/* Swap transmit descriptor */ +static __inline void +ar5212SwapTxDesc(struct ath_desc *ds) +{ + ds->ds_data = __bswap32(ds->ds_data); + ds->ds_ctl0 = __bswap32(ds->ds_ctl0); + ds->ds_ctl1 = __bswap32(ds->ds_ctl1); + ds->ds_hw[0] = __bswap32(ds->ds_hw[0]); + ds->ds_hw[1] = __bswap32(ds->ds_hw[1]); + ds->ds_hw[2] = __bswap32(ds->ds_hw[2]); + ds->ds_hw[3] = __bswap32(ds->ds_hw[3]); +} +#endif + +/* + * Processing of HW TX descriptor. + */ +HAL_STATUS +ar5212ProcTxDesc(struct ath_hal *ah, + struct ath_desc *ds, struct ath_tx_status *ts) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + +#ifdef AH_NEED_DESC_SWAP + if ((ads->ds_txstatus1 & __bswap32(AR_Done)) == 0) + return HAL_EINPROGRESS; + + ar5212SwapTxDesc(ds); +#else + if ((ads->ds_txstatus1 & AR_Done) == 0) + return HAL_EINPROGRESS; +#endif + + /* Update software copies of the HW status */ + ts->ts_seqnum = MS(ads->ds_txstatus1, AR_SeqNum); + ts->ts_tstamp = MS(ads->ds_txstatus0, AR_SendTimestamp); + ts->ts_status = 0; + if ((ads->ds_txstatus0 & AR_FrmXmitOK) == 0) { + if (ads->ds_txstatus0 & AR_ExcessiveRetries) + ts->ts_status |= HAL_TXERR_XRETRY; + if (ads->ds_txstatus0 & AR_Filtered) + ts->ts_status |= HAL_TXERR_FILT; + if (ads->ds_txstatus0 & AR_FIFOUnderrun) + ts->ts_status |= HAL_TXERR_FIFO; + } + /* + * Extract the transmit rate used and mark the rate as + * ``alternate'' if it wasn't the series 0 rate. + */ + ts->ts_finaltsi = MS(ads->ds_txstatus1, AR_FinalTSIndex); + switch (ts->ts_finaltsi) { + case 0: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate0); + break; + case 1: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate1); + break; + case 2: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate2); + break; + case 3: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate3); + break; + } + ts->ts_rssi = MS(ads->ds_txstatus1, AR_AckSigStrength); + ts->ts_shortretry = MS(ads->ds_txstatus0, AR_RTSFailCnt); + ts->ts_longretry = MS(ads->ds_txstatus0, AR_DataFailCnt); + /* + * The retry count has the number of un-acked tries for the + * final series used. When doing multi-rate retry we must + * fixup the retry count by adding in the try counts for + * each series that was fully-processed. Beware that this + * takes values from the try counts in the final descriptor. + * These are not required by the hardware. We assume they + * are placed there by the driver as otherwise we have no + * access and the driver can't do the calculation because it + * doesn't know the descriptor format. + */ + switch (ts->ts_finaltsi) { + case 3: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries2); + case 2: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries1); + case 1: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries0); + } + ts->ts_virtcol = MS(ads->ds_txstatus0, AR_VirtCollCnt); + ts->ts_antenna = (ads->ds_txstatus1 & AR_XmitAtenna ? 2 : 1); + + return HAL_OK; +} + +/* + * Determine which tx queues need interrupt servicing. + */ +void +ar5212GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + *txqs &= ahp->ah_intrTxqs; + ahp->ah_intrTxqs &= ~(*txqs); +} + +/* + * Retrieve the rate table from the given TX completion descriptor + */ +HAL_BOOL +ar5212GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries) +{ + const struct ar5212_desc *ads = AR5212DESC_CONST(ds0); + + rates[0] = MS(ads->ds_ctl3, AR_XmitRate0); + rates[1] = MS(ads->ds_ctl3, AR_XmitRate1); + rates[2] = MS(ads->ds_ctl3, AR_XmitRate2); + rates[3] = MS(ads->ds_ctl3, AR_XmitRate3); + + tries[0] = MS(ads->ds_ctl2, AR_XmitDataTries0); + tries[1] = MS(ads->ds_ctl2, AR_XmitDataTries1); + tries[2] = MS(ads->ds_ctl2, AR_XmitDataTries2); + tries[3] = MS(ads->ds_ctl2, AR_XmitDataTries3); + + return AH_TRUE; +} + +void +ar5212SetTxDescLink(struct ath_hal *ah, void *ds, uint32_t link) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + + ads->ds_link = link; +} + +void +ar5212GetTxDescLink(struct ath_hal *ah, void *ds, uint32_t *link) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + + *link = ads->ds_link; +} + +void +ar5212GetTxDescLinkPtr(struct ath_hal *ah, void *ds, uint32_t **linkptr) +{ + struct ar5212_desc *ads = AR5212DESC(ds); + + *linkptr = &ads->ds_link; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212desc.h b/sys/external/isc/atheros_hal/dist/ar5212/ar5212desc.h new file mode 100644 index 0000000..ce01dd2 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212desc.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AR5212_DESC_H_ +#define _ATH_AR5212_DESC_H_ + +/* + * Hardware-specific descriptor structures. + */ + +/* + * AR5212-specific tx/rx descriptor definition. + */ +struct ar5212_desc { + uint32_t ds_link; /* link pointer */ + uint32_t ds_data; /* data buffer pointer */ + uint32_t ds_ctl0; /* DMA control 0 */ + uint32_t ds_ctl1; /* DMA control 1 */ + union { + struct { /* xmit format */ + uint32_t ctl2; /* DMA control 2 */ + uint32_t ctl3; /* DMA control 3 */ + uint32_t status0;/* DMA status 0 */ + uint32_t status1;/* DMA status 1 */ + } tx; + struct { /* recv format */ + uint32_t status0;/* DMA status 0 */ + uint32_t status1;/* DMA status 1 */ + } rx; + } u; +} __packed; +#define AR5212DESC(_ds) ((struct ar5212_desc *)(_ds)) +#define AR5212DESC_CONST(_ds) ((const struct ar5212_desc *)(_ds)) + +#define ds_ctl2 u.tx.ctl2 +#define ds_ctl3 u.tx.ctl3 +#define ds_txstatus0 u.tx.status0 +#define ds_txstatus1 u.tx.status1 +#define ds_rxstatus0 u.rx.status0 +#define ds_rxstatus1 u.rx.status1 + +/* TX ds_ctl0 */ +#define AR_FrameLen 0x00000fff /* frame length */ +/* bits 12-15 are reserved */ +#define AR_XmitPower 0x003f0000 /* transmit power control */ +#define AR_XmitPower_S 16 +#define AR_RTSCTSEnable 0x00400000 /* RTS/CTS protocol enable */ +#define AR_VEOL 0x00800000 /* virtual end-of-list */ +#define AR_ClearDestMask 0x01000000 /* Clear destination mask bit */ +#define AR_AntModeXmit 0x1e000000 /* TX antenna seslection */ +#define AR_AntModeXmit_S 25 +#define AR_TxInterReq 0x20000000 /* TX interrupt request */ +#define AR_DestIdxValid 0x40000000 /* destination index valid */ +#define AR_CTSEnable 0x80000000 /* precede frame with CTS */ + +/* TX ds_ctl1 */ +#define AR_BufLen 0x00000fff /* data buffer length */ +#define AR_More 0x00001000 /* more desc in this frame */ +#define AR_DestIdx 0x000fe000 /* destination table index */ +#define AR_DestIdx_S 13 +#define AR_FrmType 0x00f00000 /* frame type indication */ +#define AR_FrmType_S 20 +#define AR_NoAck 0x01000000 /* No ACK flag */ +#define AR_CompProc 0x06000000 /* compression processing */ +#define AR_CompProc_S 25 +#define AR_CompIVLen 0x18000000 /* length of frame IV */ +#define AR_CompIVLen_S 27 +#define AR_CompICVLen 0x60000000 /* length of frame ICV */ +#define AR_CompICVLen_S 29 +/* bit 31 is reserved */ + +/* TX ds_ctl2 */ +#define AR_RTSCTSDuration 0x00007fff /* RTS/CTS duration */ +#define AR_RTSCTSDuration_S 0 +#define AR_DurUpdateEna 0x00008000 /* frame duration update ctl */ +#define AR_XmitDataTries0 0x000f0000 /* series 0 max attempts */ +#define AR_XmitDataTries0_S 16 +#define AR_XmitDataTries1 0x00f00000 /* series 1 max attempts */ +#define AR_XmitDataTries1_S 20 +#define AR_XmitDataTries2 0x0f000000 /* series 2 max attempts */ +#define AR_XmitDataTries2_S 24 +#define AR_XmitDataTries3 0xf0000000 /* series 3 max attempts */ +#define AR_XmitDataTries3_S 28 + +/* TX ds_ctl3 */ +#define AR_XmitRate0 0x0000001f /* series 0 tx rate */ +#define AR_XmitRate0_S 0 +#define AR_XmitRate1 0x000003e0 /* series 1 tx rate */ +#define AR_XmitRate1_S 5 +#define AR_XmitRate2 0x00007c00 /* series 2 tx rate */ +#define AR_XmitRate2_S 10 +#define AR_XmitRate3 0x000f8000 /* series 3 tx rate */ +#define AR_XmitRate3_S 15 +#define AR_RTSCTSRate 0x01f00000 /* RTS or CTS rate */ +#define AR_RTSCTSRate_S 20 +/* bits 25-31 are reserved */ + +/* RX ds_ctl1 */ +/* AR_BufLen 0x00000fff data buffer length */ +/* bit 12 is reserved */ +#define AR_RxInterReq 0x00002000 /* RX interrupt request */ +/* bits 14-31 are reserved */ + +/* TX ds_txstatus0 */ +#define AR_FrmXmitOK 0x00000001 /* TX success */ +#define AR_ExcessiveRetries 0x00000002 /* excessive retries */ +#define AR_FIFOUnderrun 0x00000004 /* TX FIFO underrun */ +#define AR_Filtered 0x00000008 /* TX filter indication */ +#define AR_RTSFailCnt 0x000000f0 /* RTS failure count */ +#define AR_RTSFailCnt_S 4 +#define AR_DataFailCnt 0x00000f00 /* Data failure count */ +#define AR_DataFailCnt_S 8 +#define AR_VirtCollCnt 0x0000f000 /* virtual collision count */ +#define AR_VirtCollCnt_S 12 +#define AR_SendTimestamp 0xffff0000 /* TX timestamp */ +#define AR_SendTimestamp_S 16 + +/* RX ds_rxstatus0 */ +#define AR_DataLen 0x00000fff /* RX data length */ +/* AR_More 0x00001000 more desc in this frame */ +#define AR_DecompCRCErr 0x00002000 /* decompression CRC error */ +/* bit 14 is reserved */ +#define AR_RcvRate 0x000f8000 /* reception rate */ +#define AR_RcvRate_S 15 +#define AR_RcvSigStrength 0x0ff00000 /* receive signal strength */ +#define AR_RcvSigStrength_S 20 +#define AR_RcvAntenna 0xf0000000 /* receive antenaa */ +#define AR_RcvAntenna_S 28 + +/* TX ds_txstatus1 */ +#define AR_Done 0x00000001 /* descripter complete */ +#define AR_SeqNum 0x00001ffe /* TX sequence number */ +#define AR_SeqNum_S 1 +#define AR_AckSigStrength 0x001fe000 /* strength of ACK */ +#define AR_AckSigStrength_S 13 +#define AR_FinalTSIndex 0x00600000 /* final TX attempt series ix */ +#define AR_FinalTSIndex_S 21 +#define AR_CompSuccess 0x00800000 /* compression status */ +#define AR_XmitAtenna 0x01000000 /* transmit antenna */ +/* bits 25-31 are reserved */ + +/* RX ds_rxstatus1 */ +/* AR_Done 0x00000001 descripter complete */ +#define AR_FrmRcvOK 0x00000002 /* frame reception success */ +#define AR_CRCErr 0x00000004 /* CRC error */ +#define AR_DecryptCRCErr 0x00000008 /* Decryption CRC fiailure */ +#define AR_PHYErr 0x00000010 /* PHY error */ +#define AR_MichaelErr 0x00000020 /* Michae MIC decrypt error */ +/* bits 6-7 are reserved */ +#define AR_KeyIdxValid 0x00000100 /* decryption key index valid */ +#define AR_KeyIdx 0x0000fe00 /* Decryption key index */ +#define AR_KeyIdx_S 9 +#define AR_RcvTimestamp 0x7fff0000 /* timestamp */ +#define AR_RcvTimestamp_S 16 +#define AR_KeyCacheMiss 0x80000000 /* key cache miss indication */ + +/* NB: phy error code overlays key index and valid fields */ +#define AR_PHYErrCode 0x0000ff00 /* PHY error code */ +#define AR_PHYErrCode_S 8 + +#endif /* _ATH_AR5212_DESC_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212phy.h b/sys/external/isc/atheros_hal/dist/ar5212/ar5212phy.h new file mode 100644 index 0000000..9e9bbbf --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212phy.h @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _DEV_ATH_AR5212PHY_H_ +#define _DEV_ATH_AR5212PHY_H_ + +/* PHY registers */ +#define AR_PHY_BASE 0x9800 /* base address of phy regs */ +#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) + +#define AR_PHY_TEST 0x9800 /* PHY test control */ +#define PHY_AGC_CLR 0x10000000 /* disable AGC to A2 */ + +#define AR_PHY_TESTCTRL 0x9808 /* PHY Test Control/Status */ +#define AR_PHY_TESTCTRL_TXHOLD 0x3800 /* Select Tx hold */ +#define AR_PHY_TESTCTRL_TXSRC_ALT 0x00000080 /* Select input to tsdac along with bit 1 */ +#define AR_PHY_TESTCTRL_TXSRC_ALT_S 7 +#define AR_PHY_TESTCTRL_TXSRC_SRC 0x00000002 /* Used with bit 7 */ +#define AR_PHY_TESTCTRL_TXSRC_SRC_S 1 + +#define AR_PHY_TURBO 0x9804 /* frame control register */ +#define AR_PHY_FC_TURBO_MODE 0x00000001 /* Set turbo mode bits */ +#define AR_PHY_FC_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode setting */ +#define AR_PHY_FC_TURBO_MIMO 0x00000004 /* Set turbo for mimo mode */ + +#define AR_PHY_TIMING3 0x9814 /* Timing control 3 */ +#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 +#define AR_PHY_TIMING3_DSC_MAN_S 17 +#define AR_PHY_TIMING3_DSC_EXP 0x0001E000 +#define AR_PHY_TIMING3_DSC_EXP_S 13 + +#define AR_PHY_CHIP_ID 0x9818 /* PHY chip revision ID */ +#define AR_PHY_CHIP_ID_REV_2 0x42 /* 5212 Rev 2 BB w. TPC fix */ +#define AR_PHY_CHIP_ID_REV_3 0x43 /* 5212 Rev 3 5213 */ +#define AR_PHY_CHIP_ID_REV_4 0x44 /* 5212 Rev 4 2313 and up */ + +#define AR_PHY_ACTIVE 0x981C /* activation register */ +#define AR_PHY_ACTIVE_EN 0x00000001 /* Activate PHY chips */ +#define AR_PHY_ACTIVE_DIS 0x00000000 /* Deactivate PHY chips */ + +#define AR_PHY_TX_CTL 0x9824 +#define AR_PHY_TX_FRAME_TO_TX_DATA_START 0x0000000f +#define AR_PHY_TX_FRAME_TO_TX_DATA_START_S 0 + +#define AR_PHY_ADC_CTL 0x982C +#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003 +#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0 +#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000 +#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000 /* BB Rev 4.2+ only */ +#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000 /* BB Rev 4.2+ only */ +#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000 +#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16 + +#define AR_PHY_BB_XP_PA_CTL 0x9838 +#define AR_PHY_BB_XPAA_ACTIVE_HIGH 0x00000001 +#define AR_PHY_BB_XPAB_ACTIVE_HIGH 0x00000002 +#define AR_PHY_BB_XPAB_ACTIVE_HIGH_S 1 + +#define AR_PHY_TSTDAC_CONST 0x983C +#define AR_PHY_TSTDAC_CONST_Q 0x0003FE00 +#define AR_PHY_TSTDAC_CONST_Q_S 9 +#define AR_PHY_TSTDAC_CONST_I 0x000001FF + + +#define AR_PHY_SETTLING 0x9844 +#define AR_PHY_SETTLING_AGC 0x0000007F +#define AR_PHY_SETTLING_AGC_S 0 +#define AR_PHY_SETTLING_SWITCH 0x00003F80 +#define AR_PHY_SETTLING_SWITCH_S 7 + +#define AR_PHY_RXGAIN 0x9848 +#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000 +#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12 +#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000 +#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18 + +#define AR_PHY_DESIRED_SZ 0x9850 +#define AR_PHY_DESIRED_SZ_ADC 0x000000FF +#define AR_PHY_DESIRED_SZ_ADC_S 0 +#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00 +#define AR_PHY_DESIRED_SZ_PGA_S 8 +#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000 +#define AR_PHY_DESIRED_SZ_TOT_DES_S 20 + +#define AR_PHY_FIND_SIG 0x9858 +#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000 +#define AR_PHY_FIND_SIG_FIRSTEP_S 12 +#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 +#define AR_PHY_FIND_SIG_FIRPWR_S 18 + +#define AR_PHY_AGC_CTL1 0x985C +#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80 +#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7 +#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000 +#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15 + +#define AR_PHY_AGC_CONTROL 0x9860 /* chip calibration and noise floor setting */ +#define AR_PHY_AGC_CONTROL_CAL 0x00000001 /* do internal calibration */ +#define AR_PHY_AGC_CONTROL_NF 0x00000002 /* do noise-floor calculation */ +#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 /* Enable noise floor calibration to happen */ +#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 /* Allow Filter calibration */ +#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 /* Don't update noise floor automatically */ + +#define AR_PHY_SFCORR_LOW 0x986C +#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21 + +#define AR_PHY_SFCORR 0x9868 +#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F +#define AR_PHY_SFCORR_M2COUNT_THR_S 0 +#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000 +#define AR_PHY_SFCORR_M1_THRESH_S 17 +#define AR_PHY_SFCORR_M2_THRESH 0x7F000000 +#define AR_PHY_SFCORR_M2_THRESH_S 24 + +#define AR_PHY_SLEEP_CTR_CONTROL 0x9870 +#define AR_PHY_SLEEP_CTR_LIMIT 0x9874 +#define AR_PHY_SLEEP_SCAL 0x9878 + +#define AR_PHY_PLL_CTL 0x987c /* PLL control register */ +#define AR_PHY_PLL_CTL_40 0xaa /* 40 MHz */ +#define AR_PHY_PLL_CTL_44 0xab /* 44 MHz for 11b, 11g */ +#define AR_PHY_PLL_CTL_44_5112 0xeb /* 44 MHz for 11b, 11g */ +#define AR_PHY_PLL_CTL_40_5112 0xea /* 40 MHz for 11a, turbos */ +#define AR_PHY_PLL_CTL_40_5413 0x04 /* 40 MHz for 11a, turbos with 5413 */ +#define AR_PHY_PLL_CTL_HALF 0x100 /* Half clock for 1/2 chan width */ +#define AR_PHY_PLL_CTL_QUARTER 0x200 /* Quarter clock for 1/4 chan width */ + +#define AR_PHY_BIN_MASK_1 0x9900 +#define AR_PHY_BIN_MASK_2 0x9904 +#define AR_PHY_BIN_MASK_3 0x9908 + +#define AR_PHY_MASK_CTL 0x990c /* What are these for?? */ +#define AR_PHY_MASK_CTL_MASK_4 0x00003FFF +#define AR_PHY_MASK_CTL_MASK_4_S 0 +#define AR_PHY_MASK_CTL_RATE 0xFF000000 +#define AR_PHY_MASK_CTL_RATE_S 24 + +#define AR_PHY_RX_DELAY 0x9914 /* analog pow-on time (100ns) */ +#define AR_PHY_RX_DELAY_DELAY 0x00003FFF /* delay from wakeup to rx ena */ + +#define AR_PHY_TIMING_CTRL4 0x9920 /* timing control */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F /* Mask for kcos_theta-1 for q correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0 /* shift for Q_COFF */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0 /* Mask for sin_theta for i correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 /* Shift for sin_theta for i correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800 /* enable IQ correction */ +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000 /* Mask for max number of samples (logarithmic) */ +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 /* Shift for max number of samples */ +#define AR_PHY_TIMING_CTRL4_DO_IQCAL 0x10000 /* perform IQ calibration */ +#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000 /* Enable spur filter */ +#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000 +#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000 + +#define AR_PHY_TIMING5 0x9924 +#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE +#define AR_PHY_TIMING5_CYCPWR_THR1_S 1 + +#define AR_PHY_PAPD_PROBE 0x9930 +#define AR_PHY_PAPD_PROBE_POWERTX 0x00007E00 +#define AR_PHY_PAPD_PROBE_POWERTX_S 9 +#define AR_PHY_PAPD_PROBE_NEXT_TX 0x00008000 /* command to take next reading */ +#define AR_PHY_PAPD_PROBE_TYPE 0x01800000 +#define AR_PHY_PAPD_PROBE_TYPE_S 23 +#define AR_PHY_PAPD_PROBE_TYPE_OFDM 0 +#define AR_PHY_PAPD_PROBE_TYPE_CCK 2 +#define AR_PHY_PAPD_PROBE_GAINF 0xFE000000 +#define AR_PHY_PAPD_PROBE_GAINF_S 25 + +#define AR_PHY_POWER_TX_RATE1 0x9934 +#define AR_PHY_POWER_TX_RATE2 0x9938 +#define AR_PHY_POWER_TX_RATE_MAX 0x993c +#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 + +#define AR_PHY_FRAME_CTL 0x9944 +#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038 +#define AR_PHY_FRAME_CTL_TX_CLIP_S 3 +#define AR_PHY_FRAME_CTL_ERR_SERV 0x20000000 +#define AR_PHY_FRAME_CTL_ERR_SERV_S 29 +#define AR_PHY_FRAME_CTL_EMU_M 0x80000000 +#define AR_PHY_FRAME_CTL_EMU_S 31 +#define AR_PHY_FRAME_CTL_WINLEN 0x00000003 +#define AR_PHY_FRAME_CTL_WINLEN_S 0 + +#define AR_PHY_TXPWRADJ 0x994C /* BB Rev 4.2+ only */ +#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0 +#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6 +#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000 +#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18 + +#define AR_PHY_RADAR_0 0x9954 /* radar detection settings */ +#define AR_PHY_RADAR_0_ENA 0x00000001 /* Enable radar detection */ +#define AR_PHY_RADAR_0_INBAND 0x0000003e /* Inband pulse threshold */ +#define AR_PHY_RADAR_0_INBAND_S 1 +#define AR_PHY_RADAR_0_PRSSI 0x00000FC0 /* Pulse rssi threshold */ +#define AR_PHY_RADAR_0_PRSSI_S 6 +#define AR_PHY_RADAR_0_HEIGHT 0x0003F000 /* Pulse height threshold */ +#define AR_PHY_RADAR_0_HEIGHT_S 12 +#define AR_PHY_RADAR_0_RRSSI 0x00FC0000 /* Radar rssi threshold */ +#define AR_PHY_RADAR_0_RRSSI_S 18 +#define AR_PHY_RADAR_0_FIRPWR 0x7F000000 /* Radar firpwr threshold */ +#define AR_PHY_RADAR_0_FIRPWR_S 24 + +/* ar5413 specific */ +#define AR_PHY_RADAR_2 0x9958 /* radar detection settings */ +#define AR_PHY_RADAR_2_ENRELSTEPCHK 0x00002000 /* Enable using max rssi */ +#define AR_PHY_RADAR_2_ENMAXRSSI 0x00004000 /* Enable using max rssi */ +#define AR_PHY_RADAR_2_BLOCKOFDMWEAK 0x00008000 /* En block OFDM weak sig as radar */ +#define AR_PHY_RADAR_2_USEFIR128 0x00400000 /* En measuring pwr over 128 cycles */ +#define AR_PHY_RADAR_2_ENRELPWRCHK 0x00800000 /* Enable using max rssi */ +#define AR_PHY_RADAR_2_MAXLEN 0x000000FF /* Max Pulse duration threshold */ +#define AR_PHY_RADAR_2_MAXLEN_S 0 +#define AR_PHY_RADAR_2_RELSTEP 0x00001F00 /* Pulse relative step threshold */ +#define AR_PHY_RADAR_2_RELSTEP_S 8 +#define AR_PHY_RADAR_2_RELPWR 0x003F0000 /* pulse relative power threshold */ +#define AR_PHY_RADAR_2_RELPWR_S 16 + +#define AR_PHY_SIGMA_DELTA 0x996C /* AR5312 only */ +#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 +#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0 +#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8 +#define AR_PHY_SIGMA_DELTA_FILT2_S 3 +#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00 +#define AR_PHY_SIGMA_DELTA_FILT1_S 8 +#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000 +#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13 + +#define AR_PHY_RESTART 0x9970 /* restart */ +#define AR_PHY_RESTART_DIV_GC 0x001C0000 /* bb_ant_fast_div_gc_limit */ +#define AR_PHY_RESTART_DIV_GC_S 18 + +#define AR_PHY_RFBUS_REQ 0x997C +#define AR_PHY_RFBUS_REQ_REQUEST 0x00000001 + +#define AR_PHY_TIMING7 0x9980 /* Spur mitigation masks */ +#define AR_PHY_TIMING8 0x9984 +#define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF +#define AR_PHY_TIMING8_PILOT_MASK_2_S 0 + +#define AR_PHY_BIN_MASK2_1 0x9988 +#define AR_PHY_BIN_MASK2_2 0x998c +#define AR_PHY_BIN_MASK2_3 0x9990 +#define AR_PHY_BIN_MASK2_4 0x9994 +#define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF +#define AR_PHY_BIN_MASK2_4_MASK_4_S 0 + +#define AR_PHY_TIMING9 0x9998 +#define AR_PHY_TIMING10 0x999c +#define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF +#define AR_PHY_TIMING10_PILOT_MASK_2_S 0 + +#define AR_PHY_TIMING11 0x99a0 /* Spur Mitigation control */ +#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF +#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0 +#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 +#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 +#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000 +#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000 + +#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 + +#define AR_PHY_M_SLEEP 0x99f0 /* sleep control registers */ +#define AR_PHY_REFCLKDLY 0x99f4 +#define AR_PHY_REFCLKPD 0x99f8 + +/* PHY IQ calibration results */ +#define AR_PHY_IQCAL_RES_PWR_MEAS_I 0x9c10 /* power measurement for I */ +#define AR_PHY_IQCAL_RES_PWR_MEAS_Q 0x9c14 /* power measurement for Q */ +#define AR_PHY_IQCAL_RES_IQ_CORR_MEAS 0x9c18 /* IQ correlation measurement */ + +#define AR_PHY_CURRENT_RSSI 0x9c1c /* rssi of current frame rx'd */ + +#define AR_PHY_RFBUS_GNT 0x9c20 +#define AR_PHY_RFBUS_GNT_GRANT 0x1 + +#define AR_PHY_PCDAC_TX_POWER_0 0xA180 +#define AR_PHY_PCDAC_TX_POWER(_n) (AR_PHY_PCDAC_TX_POWER_0 + ((_n)<<2)) + +#define AR_PHY_MODE 0xA200 /* Mode register */ +#define AR_PHY_MODE_QUARTER 0x40 /* Quarter Rate */ +#define AR_PHY_MODE_HALF 0x20 /* Half Rate */ +#define AR_PHY_MODE_AR5112 0x08 /* AR5112 */ +#define AR_PHY_MODE_AR5111 0x00 /* AR5111/AR2111 */ +#define AR_PHY_MODE_DYNAMIC 0x04 /* dynamic CCK/OFDM mode */ +#define AR_PHY_MODE_RF2GHZ 0x02 /* 2.4 GHz */ +#define AR_PHY_MODE_RF5GHZ 0x00 /* 5 GHz */ +#define AR_PHY_MODE_CCK 0x01 /* CCK */ +#define AR_PHY_MODE_OFDM 0x00 /* OFDM */ +#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100 /* Disable dynamic CCK detection */ + +#define AR_PHY_CCK_TX_CTRL 0xA204 +#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 + +#define AR_PHY_CCK_DETECT 0xA208 +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0 +#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 + +#define AR_PHY_GAIN_2GHZ 0xA20C +#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000 +#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18 + +#define AR_PHY_CCK_RXCTRL4 0xA21C +#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000 +#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19 + +#define AR_PHY_DAG_CTRLCCK 0xA228 +#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200 /* BB Rev 4.2+ only */ +#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00 /* BB Rev 4.2+ only */ +#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10 /* BB Rev 4.2+ only */ + +#define AR_PHY_POWER_TX_RATE3 0xA234 +#define AR_PHY_POWER_TX_RATE4 0xA238 + +#define AR_PHY_FAST_ADC 0xA24C +#define AR_PHY_BLUETOOTH 0xA254 + +#define AR_PHY_TPCRG1 0xA258 /* ar2413 power control */ +#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000 +#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14 +#define AR_PHY_TPCRG1_PDGAIN_SETTING1 0x00030000 +#define AR_PHY_TPCRG1_PDGAIN_SETTING1_S 16 +#define AR_PHY_TPCRG1_PDGAIN_SETTING2 0x000c0000 +#define AR_PHY_TPCRG1_PDGAIN_SETTING2_S 18 +#define AR_PHY_TPCRG1_PDGAIN_SETTING3 0x00300000 +#define AR_PHY_TPCRG1_PDGAIN_SETTING3_S 20 + +#define AR_PHY_TPCRG5 0xA26C /* ar2413 power control */ +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22 + +#endif /* _DEV_ATH_AR5212PHY_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5212reg.h b/sys/external/isc/atheros_hal/dist/ar5212/ar5212reg.h new file mode 100644 index 0000000..96dfa9d --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5212reg.h @@ -0,0 +1,1006 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _DEV_ATH_AR5212REG_H_ +#define _DEV_ATH_AR5212REG_H_ + +/* + * Definitions for the Atheros 5212 chipset. + */ + +/* DMA Control and Interrupt Registers */ +#define AR_CR 0x0008 /* MAC control register */ +#define AR_RXDP 0x000C /* MAC receive queue descriptor pointer */ +#define AR_CFG 0x0014 /* MAC configuration and status register */ +#define AR_IER 0x0024 /* MAC Interrupt enable register */ +/* 0x28 is RTSD0 on the 5211 */ +/* 0x2c is RTSD1 on the 5211 */ +#define AR_TXCFG 0x0030 /* MAC tx DMA size config register */ +#define AR_RXCFG 0x0034 /* MAC rx DMA size config register */ +/* 0x38 is the jumbo descriptor address on the 5211 */ +#define AR_MIBC 0x0040 /* MAC MIB control register */ +#define AR_TOPS 0x0044 /* MAC timeout prescale count */ +#define AR_RXNPTO 0x0048 /* MAC no frame received timeout */ +#define AR_TXNPTO 0x004C /* MAC no frame trasmitted timeout */ +#define AR_RPGTO 0x0050 /* MAC receive frame gap timeout */ +#define AR_RPCNT 0x0054 /* MAC receive frame count limit */ +#define AR_MACMISC 0x0058 /* MAC miscellaneous control/status register */ +#define AR_SPC_0 0x005c /* MAC sleep performance (awake cycles) */ +#define AR_SPC_1 0x0060 /* MAC sleep performance (asleep cycles) */ +/* 0x5c is for QCU/DCU clock gating control on 5311 */ +#define AR_ISR 0x0080 /* MAC Primary interrupt status register */ +#define AR_ISR_S0 0x0084 /* MAC Secondary interrupt status register 0 */ +#define AR_ISR_S1 0x0088 /* MAC Secondary interrupt status register 1 */ +#define AR_ISR_S2 0x008c /* MAC Secondary interrupt status register 2 */ +#define AR_ISR_S3 0x0090 /* MAC Secondary interrupt status register 3 */ +#define AR_ISR_S4 0x0094 /* MAC Secondary interrupt status register 4 */ +#define AR_IMR 0x00a0 /* MAC Primary interrupt mask register */ +#define AR_IMR_S0 0x00a4 /* MAC Secondary interrupt mask register 0 */ +#define AR_IMR_S1 0x00a8 /* MAC Secondary interrupt mask register 1 */ +#define AR_IMR_S2 0x00ac /* MAC Secondary interrupt mask register 2 */ +#define AR_IMR_S3 0x00b0 /* MAC Secondary interrupt mask register 3 */ +#define AR_IMR_S4 0x00b4 /* MAC Secondary interrupt mask register 4 */ +#define AR_ISR_RAC 0x00c0 /* ISR read-and-clear access */ +/* Shadow copies with read-and-clear access */ +#define AR_ISR_S0_S 0x00c4 /* ISR_S0 shadow copy */ +#define AR_ISR_S1_S 0x00c8 /* ISR_S1 shadow copy */ +#define AR_ISR_S2_S 0x00cc /* ISR_S2 shadow copy */ +#define AR_ISR_S3_S 0x00d0 /* ISR_S3 shadow copy */ +#define AR_ISR_S4_S 0x00d4 /* ISR_S4 shadow copy */ +#define AR_DMADBG_0 0x00e0 /* DMA debug 0 */ +#define AR_DMADBG_1 0x00e4 /* DMA debug 1 */ +#define AR_DMADBG_2 0x00e8 /* DMA debug 2 */ +#define AR_DMADBG_3 0x00ec /* DMA debug 3 */ +#define AR_DMADBG_4 0x00f0 /* DMA debug 4 */ +#define AR_DMADBG_5 0x00f4 /* DMA debug 5 */ +#define AR_DMADBG_6 0x00f8 /* DMA debug 6 */ +#define AR_DMADBG_7 0x00fc /* DMA debug 7 */ +#define AR_DCM_A 0x0400 /* Decompression mask address */ +#define AR_DCM_D 0x0404 /* Decompression mask data */ +#define AR_DCCFG 0x0420 /* Decompression configuration */ +#define AR_CCFG 0x0600 /* Compression configuration */ +#define AR_CCUCFG 0x0604 /* Compression catchup configuration */ +#define AR_CPC_0 0x0610 /* Compression performance counter 0 */ +#define AR_CPC_1 0x0614 /* Compression performance counter 1 */ +#define AR_CPC_2 0x0618 /* Compression performance counter 2 */ +#define AR_CPC_3 0x061c /* Compression performance counter 3 */ +#define AR_CPCOVF 0x0620 /* Compression performance overflow status */ + +#define AR_Q0_TXDP 0x0800 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q1_TXDP 0x0804 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q2_TXDP 0x0808 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q3_TXDP 0x080c /* MAC Transmit Queue descriptor pointer */ +#define AR_Q4_TXDP 0x0810 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q5_TXDP 0x0814 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q6_TXDP 0x0818 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q7_TXDP 0x081c /* MAC Transmit Queue descriptor pointer */ +#define AR_Q8_TXDP 0x0820 /* MAC Transmit Queue descriptor pointer */ +#define AR_Q9_TXDP 0x0824 /* MAC Transmit Queue descriptor pointer */ +#define AR_QTXDP(_i) (AR_Q0_TXDP + ((_i)<<2)) + +#define AR_Q_TXE 0x0840 /* MAC Transmit Queue enable */ +#define AR_Q_TXE_M 0x000003FF /* Mask for TXE (QCU 0-9) */ +#define AR_Q_TXD 0x0880 /* MAC Transmit Queue disable */ +#define AR_Q_TXD_M 0x000003FF /* Mask for TXD (QCU 0-9) */ + +#define AR_Q0_CBRCFG 0x08c0 /* MAC CBR configuration */ +#define AR_Q1_CBRCFG 0x08c4 /* MAC CBR configuration */ +#define AR_Q2_CBRCFG 0x08c8 /* MAC CBR configuration */ +#define AR_Q3_CBRCFG 0x08cc /* MAC CBR configuration */ +#define AR_Q4_CBRCFG 0x08d0 /* MAC CBR configuration */ +#define AR_Q5_CBRCFG 0x08d4 /* MAC CBR configuration */ +#define AR_Q6_CBRCFG 0x08d8 /* MAC CBR configuration */ +#define AR_Q7_CBRCFG 0x08dc /* MAC CBR configuration */ +#define AR_Q8_CBRCFG 0x08e0 /* MAC CBR configuration */ +#define AR_Q9_CBRCFG 0x08e4 /* MAC CBR configuration */ +#define AR_QCBRCFG(_i) (AR_Q0_CBRCFG + ((_i)<<2)) + +#define AR_Q0_RDYTIMECFG 0x0900 /* MAC ReadyTime configuration */ +#define AR_Q1_RDYTIMECFG 0x0904 /* MAC ReadyTime configuration */ +#define AR_Q2_RDYTIMECFG 0x0908 /* MAC ReadyTime configuration */ +#define AR_Q3_RDYTIMECFG 0x090c /* MAC ReadyTime configuration */ +#define AR_Q4_RDYTIMECFG 0x0910 /* MAC ReadyTime configuration */ +#define AR_Q5_RDYTIMECFG 0x0914 /* MAC ReadyTime configuration */ +#define AR_Q6_RDYTIMECFG 0x0918 /* MAC ReadyTime configuration */ +#define AR_Q7_RDYTIMECFG 0x091c /* MAC ReadyTime configuration */ +#define AR_Q8_RDYTIMECFG 0x0920 /* MAC ReadyTime configuration */ +#define AR_Q9_RDYTIMECFG 0x0924 /* MAC ReadyTime configuration */ +#define AR_QRDYTIMECFG(_i) (AR_Q0_RDYTIMECFG + ((_i)<<2)) + +#define AR_Q_ONESHOTARM_SC 0x0940 /* MAC OneShotArm set control */ +#define AR_Q_ONESHOTARM_CC 0x0980 /* MAC OneShotArm clear control */ + +#define AR_Q0_MISC 0x09c0 /* MAC Miscellaneous QCU settings */ +#define AR_Q1_MISC 0x09c4 /* MAC Miscellaneous QCU settings */ +#define AR_Q2_MISC 0x09c8 /* MAC Miscellaneous QCU settings */ +#define AR_Q3_MISC 0x09cc /* MAC Miscellaneous QCU settings */ +#define AR_Q4_MISC 0x09d0 /* MAC Miscellaneous QCU settings */ +#define AR_Q5_MISC 0x09d4 /* MAC Miscellaneous QCU settings */ +#define AR_Q6_MISC 0x09d8 /* MAC Miscellaneous QCU settings */ +#define AR_Q7_MISC 0x09dc /* MAC Miscellaneous QCU settings */ +#define AR_Q8_MISC 0x09e0 /* MAC Miscellaneous QCU settings */ +#define AR_Q9_MISC 0x09e4 /* MAC Miscellaneous QCU settings */ +#define AR_QMISC(_i) (AR_Q0_MISC + ((_i)<<2)) + +#define AR_Q0_STS 0x0a00 /* MAC Miscellaneous QCU status */ +#define AR_Q1_STS 0x0a04 /* MAC Miscellaneous QCU status */ +#define AR_Q2_STS 0x0a08 /* MAC Miscellaneous QCU status */ +#define AR_Q3_STS 0x0a0c /* MAC Miscellaneous QCU status */ +#define AR_Q4_STS 0x0a10 /* MAC Miscellaneous QCU status */ +#define AR_Q5_STS 0x0a14 /* MAC Miscellaneous QCU status */ +#define AR_Q6_STS 0x0a18 /* MAC Miscellaneous QCU status */ +#define AR_Q7_STS 0x0a1c /* MAC Miscellaneous QCU status */ +#define AR_Q8_STS 0x0a20 /* MAC Miscellaneous QCU status */ +#define AR_Q9_STS 0x0a24 /* MAC Miscellaneous QCU status */ +#define AR_QSTS(_i) (AR_Q0_STS + ((_i)<<2)) + +#define AR_Q_RDYTIMESHDN 0x0a40 /* MAC ReadyTimeShutdown status */ +#define AR_Q_CBBS 0xb00 /* Compression buffer base select */ +#define AR_Q_CBBA 0xb04 /* Compression buffer base access */ +#define AR_Q_CBC 0xb08 /* Compression buffer configuration */ + +#define AR_D0_QCUMASK 0x1000 /* MAC QCU Mask */ +#define AR_D1_QCUMASK 0x1004 /* MAC QCU Mask */ +#define AR_D2_QCUMASK 0x1008 /* MAC QCU Mask */ +#define AR_D3_QCUMASK 0x100c /* MAC QCU Mask */ +#define AR_D4_QCUMASK 0x1010 /* MAC QCU Mask */ +#define AR_D5_QCUMASK 0x1014 /* MAC QCU Mask */ +#define AR_D6_QCUMASK 0x1018 /* MAC QCU Mask */ +#define AR_D7_QCUMASK 0x101c /* MAC QCU Mask */ +#define AR_D8_QCUMASK 0x1020 /* MAC QCU Mask */ +#define AR_D9_QCUMASK 0x1024 /* MAC QCU Mask */ +#define AR_DQCUMASK(_i) (AR_D0_QCUMASK + ((_i)<<2)) + +#define AR_D0_LCL_IFS 0x1040 /* MAC DCU-specific IFS settings */ +#define AR_D1_LCL_IFS 0x1044 /* MAC DCU-specific IFS settings */ +#define AR_D2_LCL_IFS 0x1048 /* MAC DCU-specific IFS settings */ +#define AR_D3_LCL_IFS 0x104c /* MAC DCU-specific IFS settings */ +#define AR_D4_LCL_IFS 0x1050 /* MAC DCU-specific IFS settings */ +#define AR_D5_LCL_IFS 0x1054 /* MAC DCU-specific IFS settings */ +#define AR_D6_LCL_IFS 0x1058 /* MAC DCU-specific IFS settings */ +#define AR_D7_LCL_IFS 0x105c /* MAC DCU-specific IFS settings */ +#define AR_D8_LCL_IFS 0x1060 /* MAC DCU-specific IFS settings */ +#define AR_D9_LCL_IFS 0x1064 /* MAC DCU-specific IFS settings */ +#define AR_DLCL_IFS(_i) (AR_D0_LCL_IFS + ((_i)<<2)) + +#define AR_D0_RETRY_LIMIT 0x1080 /* MAC Retry limits */ +#define AR_D1_RETRY_LIMIT 0x1084 /* MAC Retry limits */ +#define AR_D2_RETRY_LIMIT 0x1088 /* MAC Retry limits */ +#define AR_D3_RETRY_LIMIT 0x108c /* MAC Retry limits */ +#define AR_D4_RETRY_LIMIT 0x1090 /* MAC Retry limits */ +#define AR_D5_RETRY_LIMIT 0x1094 /* MAC Retry limits */ +#define AR_D6_RETRY_LIMIT 0x1098 /* MAC Retry limits */ +#define AR_D7_RETRY_LIMIT 0x109c /* MAC Retry limits */ +#define AR_D8_RETRY_LIMIT 0x10a0 /* MAC Retry limits */ +#define AR_D9_RETRY_LIMIT 0x10a4 /* MAC Retry limits */ +#define AR_DRETRY_LIMIT(_i) (AR_D0_RETRY_LIMIT + ((_i)<<2)) + +#define AR_D0_CHNTIME 0x10c0 /* MAC ChannelTime settings */ +#define AR_D1_CHNTIME 0x10c4 /* MAC ChannelTime settings */ +#define AR_D2_CHNTIME 0x10c8 /* MAC ChannelTime settings */ +#define AR_D3_CHNTIME 0x10cc /* MAC ChannelTime settings */ +#define AR_D4_CHNTIME 0x10d0 /* MAC ChannelTime settings */ +#define AR_D5_CHNTIME 0x10d4 /* MAC ChannelTime settings */ +#define AR_D6_CHNTIME 0x10d8 /* MAC ChannelTime settings */ +#define AR_D7_CHNTIME 0x10dc /* MAC ChannelTime settings */ +#define AR_D8_CHNTIME 0x10e0 /* MAC ChannelTime settings */ +#define AR_D9_CHNTIME 0x10e4 /* MAC ChannelTime settings */ +#define AR_DCHNTIME(_i) (AR_D0_CHNTIME + ((_i)<<2)) + +#define AR_D0_MISC 0x1100 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D1_MISC 0x1104 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D2_MISC 0x1108 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D3_MISC 0x110c /* MAC Miscellaneous DCU-specific settings */ +#define AR_D4_MISC 0x1110 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D5_MISC 0x1114 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D6_MISC 0x1118 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D7_MISC 0x111c /* MAC Miscellaneous DCU-specific settings */ +#define AR_D8_MISC 0x1120 /* MAC Miscellaneous DCU-specific settings */ +#define AR_D9_MISC 0x1124 /* MAC Miscellaneous DCU-specific settings */ +#define AR_DMISC(_i) (AR_D0_MISC + ((_i)<<2)) + +#define AR_D_SEQNUM 0x1140 /* MAC Frame sequence number */ + +/* MAC DCU-global IFS settings */ +#define AR_D_GBL_IFS_SIFS 0x1030 /* DCU global SIFS settings */ +#define AR_D_GBL_IFS_SLOT 0x1070 /* DC global slot interval */ +#define AR_D_GBL_IFS_EIFS 0x10b0 /* DCU global EIFS setting */ +#define AR_D_GBL_IFS_MISC 0x10f0 /* DCU global misc. IFS settings */ +#define AR_D_FPCTL 0x1230 /* DCU frame prefetch settings */ +#define AR_D_TXPSE 0x1270 /* DCU transmit pause control/status */ +#define AR_D_TXBLK_CMD 0x1038 /* DCU transmit filter cmd (w/only) */ +#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i)) /* DCU transmit filter data */ +#define AR_D_TXBLK_CLR 0x143c /* DCU clear tx filter (w/only) */ +#define AR_D_TXBLK_SET 0x147c /* DCU set tx filter (w/only) */ + +#define AR_RC 0x4000 /* Warm reset control register */ +#define AR_SCR 0x4004 /* Sleep control register */ +#define AR_INTPEND 0x4008 /* Interrupt Pending register */ +#define AR_SFR 0x400C /* Sleep force register */ +#define AR_PCICFG 0x4010 /* PCI configuration register */ +#define AR_GPIOCR 0x4014 /* GPIO control register */ +#define AR_GPIODO 0x4018 /* GPIO data output access register */ +#define AR_GPIODI 0x401C /* GPIO data input access register */ +#define AR_SREV 0x4020 /* Silicon Revision register */ +#define AR_TXEPOST 0x4028 /* TXE write posting resgister */ +#define AR_QSM 0x402C /* QCU sleep mask */ + +#define AR_PCIE_PMC 0x4068 /* PCIe power mgt config and status register */ +#define AR_PCIE_SERDES 0x4080 /* PCIe Serdes register */ +#define AR_PCIE_SERDES2 0x4084 /* PCIe Serdes register */ + +#define AR_EEPROM_ADDR 0x6000 /* EEPROM address register (10 bit) */ +#define AR_EEPROM_DATA 0x6004 /* EEPROM data register (16 bit) */ +#define AR_EEPROM_CMD 0x6008 /* EEPROM command register */ +#define AR_EEPROM_STS 0x600c /* EEPROM status register */ +#define AR_EEPROM_CFG 0x6010 /* EEPROM configuration register */ + +#define AR_STA_ID0 0x8000 /* MAC station ID0 register - low 32 bits */ +#define AR_STA_ID1 0x8004 /* MAC station ID1 register - upper 16 bits */ +#define AR_BSS_ID0 0x8008 /* MAC BSSID low 32 bits */ +#define AR_BSS_ID1 0x800C /* MAC BSSID upper 16 bits / AID */ +#define AR_SLOT_TIME 0x8010 /* MAC Time-out after a collision */ +#define AR_TIME_OUT 0x8014 /* MAC ACK & CTS time-out */ +#define AR_RSSI_THR 0x8018 /* MAC RSSI warning & missed beacon threshold */ +#define AR_USEC 0x801c /* MAC transmit latency register */ +#define AR_BEACON 0x8020 /* MAC beacon control value/mode bits */ +#define AR_CFP_PERIOD 0x8024 /* MAC CFP Interval (TU/msec) */ +#define AR_TIMER0 0x8028 /* MAC Next beacon time (TU/msec) */ +#define AR_TIMER1 0x802c /* MAC DMA beacon alert time (1/8 TU) */ +#define AR_TIMER2 0x8030 /* MAC Software beacon alert (1/8 TU) */ +#define AR_TIMER3 0x8034 /* MAC ATIM window time */ +#define AR_CFP_DUR 0x8038 /* MAC maximum CFP duration in TU */ +#define AR_RX_FILTER 0x803C /* MAC receive filter register */ +#define AR_MCAST_FIL0 0x8040 /* MAC multicast filter lower 32 bits */ +#define AR_MCAST_FIL1 0x8044 /* MAC multicast filter upper 32 bits */ +#define AR_DIAG_SW 0x8048 /* MAC PCU control register */ +#define AR_TSF_L32 0x804c /* MAC local clock lower 32 bits */ +#define AR_TSF_U32 0x8050 /* MAC local clock upper 32 bits */ +#define AR_TST_ADDAC 0x8054 /* ADDAC test register */ +#define AR_DEF_ANTENNA 0x8058 /* default antenna register */ +#define AR_QOS_MASK 0x805c /* MAC AES mute mask: QoS field */ +#define AR_SEQ_MASK 0x8060 /* MAC AES mute mask: seqnum field */ +#define AR_OBSERV_2 0x8068 /* Observation bus 2 */ +#define AR_OBSERV_1 0x806c /* Observation bus 1 */ + +#define AR_LAST_TSTP 0x8080 /* MAC Time stamp of the last beacon received */ +#define AR_NAV 0x8084 /* MAC current NAV value */ +#define AR_RTS_OK 0x8088 /* MAC RTS exchange success counter */ +#define AR_RTS_FAIL 0x808c /* MAC RTS exchange failure counter */ +#define AR_ACK_FAIL 0x8090 /* MAC ACK failure counter */ +#define AR_FCS_FAIL 0x8094 /* FCS check failure counter */ +#define AR_BEACON_CNT 0x8098 /* Valid beacon counter */ + +#define AR_SLEEP1 0x80d4 /* Enhanced sleep control 1 */ +#define AR_SLEEP2 0x80d8 /* Enhanced sleep control 2 */ +#define AR_SLEEP3 0x80dc /* Enhanced sleep control 3 */ +#define AR_BSSMSKL 0x80e0 /* BSSID mask lower 32 bits */ +#define AR_BSSMSKU 0x80e4 /* BSSID mask upper 16 bits */ +#define AR_TPC 0x80e8 /* Transmit power control for self gen frames */ +#define AR_TFCNT 0x80ec /* Profile count, transmit frames */ +#define AR_RFCNT 0x80f0 /* Profile count, receive frames */ +#define AR_RCCNT 0x80f4 /* Profile count, receive clear */ +#define AR_CCCNT 0x80f8 /* Profile count, cycle counter */ + +#define AR_QUIET1 0x80fc /* Quiet time programming for TGh */ +#define AR_QUIET1_NEXT_QUIET_S 0 /* TSF of next quiet period (TU) */ +#define AR_QUIET1_NEXT_QUIET 0xffff +#define AR_QUIET1_QUIET_ENABLE 0x10000 /* Enable Quiet time operation */ +#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x20000 /* Do we ack/cts during quiet period */ +#define AR_QUIET1_QUIET_ACK_CTS_ENABLE_S 17 + +#define AR_QUIET2 0x8100 /* More Quiet time programming */ +#define AR_QUIET2_QUIET_PER_S 0 /* Periodicity of quiet period (TU) */ +#define AR_QUIET2_QUIET_PER 0xffff +#define AR_QUIET2_QUIET_DUR_S 16 /* Duration of quiet period (TU) */ +#define AR_QUIET2_QUIET_DUR 0xffff0000 + +#define AR_TSF_PARM 0x8104 /* TSF parameters */ +#define AR_NOACK 0x8108 /* No ack policy in QoS Control Field */ +#define AR_PHY_ERR 0x810c /* Phy error filter */ + +#define AR_QOS_CONTROL 0x8118 /* Control TKIP MIC for QoS */ +#define AR_QOS_SELECT 0x811c /* MIC QoS select */ +#define AR_MISC_MODE 0x8120 /* PCU Misc. mode control */ + +/* Hainan MIB counter registers */ +#define AR_FILTOFDM 0x8124 /* Count of filtered OFDM frames */ +#define AR_FILTCCK 0x8128 /* Count of filtered CCK frames */ +#define AR_PHYCNT1 0x812c /* Phy Error 1 counter */ +#define AR_PHYCNTMASK1 0x8130 /* Phy Error 1 counter mask */ +#define AR_PHYCNT2 0x8134 /* Phy Error 2 counter */ +#define AR_PHYCNTMASK2 0x8138 /* Phy Error 2 counter mask */ +#define AR_PHY_COUNTMAX (3 << 22) /* Max value in counter before intr */ +#define AR_MIBCNT_INTRMASK (3<<22) /* Mask for top two bits of counters */ + +#define AR_RATE_DURATION_0 0x8700 /* base of multi-rate retry */ +#define AR_RATE_DURATION(_n) (AR_RATE_DURATION_0 + ((_n)<<2)) + +#define AR_KEYTABLE_0 0x8800 /* MAC Key Cache */ +#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) + +#define AR_CFP_MASK 0x0000ffff /* Mask for next beacon time */ + +#define AR_CR_RXE 0x00000004 /* Receive enable */ +#define AR_CR_RXD 0x00000020 /* Receive disable */ +#define AR_CR_SWI 0x00000040 /* One-shot software interrupt */ + +#define AR_CFG_SWTD 0x00000001 /* byteswap tx descriptor words */ +#define AR_CFG_SWTB 0x00000002 /* byteswap tx data buffer words */ +#define AR_CFG_SWRD 0x00000004 /* byteswap rx descriptor words */ +#define AR_CFG_SWRB 0x00000008 /* byteswap rx data buffer words */ +#define AR_CFG_SWRG 0x00000010 /* byteswap register access data words */ +#define AR_CFG_AP_ADHOC_INDICATION 0x00000020 /* AP/adhoc indication (0-AP, 1-Adhoc) */ +#define AR_CFG_PHOK 0x00000100 /* PHY OK status */ +#define AR_CFG_EEBS 0x00000200 /* EEPROM busy */ +#define AR_5211_CFG_CLK_GATE_DIS 0x00000400 /* Clock gating disable (Oahu only) */ +#define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000 /* Mask of PCI core master request queue full threshold */ +#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 /* Shift for PCI core master request queue full threshold */ + +#define AR_IER_ENABLE 0x00000001 /* Global interrupt enable */ +#define AR_IER_DISABLE 0x00000000 /* Global interrupt disable */ + +#define AR_DMASIZE_4B 0x00000000 /* DMA size 4 bytes (TXCFG + RXCFG) */ +#define AR_DMASIZE_8B 0x00000001 /* DMA size 8 bytes */ +#define AR_DMASIZE_16B 0x00000002 /* DMA size 16 bytes */ +#define AR_DMASIZE_32B 0x00000003 /* DMA size 32 bytes */ +#define AR_DMASIZE_64B 0x00000004 /* DMA size 64 bytes */ +#define AR_DMASIZE_128B 0x00000005 /* DMA size 128 bytes */ +#define AR_DMASIZE_256B 0x00000006 /* DMA size 256 bytes */ +#define AR_DMASIZE_512B 0x00000007 /* DMA size 512 bytes */ + +#define AR_FTRIG 0x000003F0 /* Mask for Frame trigger level */ +#define AR_FTRIG_S 4 /* Shift for Frame trigger level */ +#define AR_FTRIG_IMMED 0x00000000 /* bytes in PCU TX FIFO before air */ +#define AR_FTRIG_64B 0x00000010 /* default */ +#define AR_FTRIG_128B 0x00000020 +#define AR_FTRIG_192B 0x00000030 +#define AR_FTRIG_256B 0x00000040 /* 5 bits total */ + +#define AR_RXCFG_ZLFDMA 0x00000010 /* Enable DMA of zero-length frame */ + +#define AR_MIBC_COW 0x00000001 /* counter overflow warning */ +#define AR_MIBC_FMC 0x00000002 /* freeze MIB counters */ +#define AR_MIBC_CMC 0x00000004 /* clear MIB counters */ +#define AR_MIBC_MCS 0x00000008 /* MIB counter strobe, increment all */ + +#define AR_TOPS_MASK 0x0000FFFF /* Mask for timeout prescale */ + +#define AR_RXNPTO_MASK 0x000003FF /* Mask for no frame received timeout */ + +#define AR_TXNPTO_MASK 0x000003FF /* Mask for no frame transmitted timeout */ +#define AR_TXNPTO_QCU_MASK 0x000FFC00 /* Mask indicating the set of QCUs */ + /* for which frame completions will cause */ + /* a reset of the no frame xmit'd timeout */ + +#define AR_RPGTO_MASK 0x000003FF /* Mask for receive frame gap timeout */ + +#define AR_RPCNT_MASK 0x0000001F /* Mask for receive frame count limit */ + +#define AR_MACMISC_DMA_OBS 0x000001E0 /* Mask for DMA observation bus mux select */ +#define AR_MACMISC_DMA_OBS_S 5 /* Shift for DMA observation bus mux select */ +#define AR_MACMISC_MISC_OBS 0x00000E00 /* Mask for MISC observation bus mux select */ +#define AR_MACMISC_MISC_OBS_S 9 /* Shift for MISC observation bus mux select */ +#define AR_MACMISC_MAC_OBS_BUS_LSB 0x00007000 /* Mask for MAC observation bus mux select (lsb) */ +#define AR_MACMISC_MAC_OBS_BUS_LSB_S 12 /* Shift for MAC observation bus mux select (lsb) */ +#define AR_MACMISC_MAC_OBS_BUS_MSB 0x00038000 /* Mask for MAC observation bus mux select (msb) */ +#define AR_MACMISC_MAC_OBS_BUS_MSB_S 15 /* Shift for MAC observation bus mux select (msb) */ + +/* + * Interrupt Status Registers + * + * Only the bits in the ISR_P register and the IMR_P registers + * control whether the MAC's INTA# output is asserted. The bits in + * the secondary interrupt status/mask registers control what bits + * are set in the primary interrupt status register; however the + * IMR_S* registers DO NOT determine whether INTA# is asserted. + * That is INTA# is asserted only when the logical AND of ISR_P + * and IMR_P is non-zero. The secondary interrupt mask/status + * registers affect what bits are set in ISR_P but they do not + * directly affect whether INTA# is asserted. + */ +#define AR_ISR_RXOK 0x00000001 /* At least one frame received sans errors */ +#define AR_ISR_RXDESC 0x00000002 /* Receive interrupt request */ +#define AR_ISR_RXERR 0x00000004 /* Receive error interrupt */ +#define AR_ISR_RXNOPKT 0x00000008 /* No frame received within timeout clock */ +#define AR_ISR_RXEOL 0x00000010 /* Received descriptor empty interrupt */ +#define AR_ISR_RXORN 0x00000020 /* Receive FIFO overrun interrupt */ +#define AR_ISR_TXOK 0x00000040 /* Transmit okay interrupt */ +#define AR_ISR_TXDESC 0x00000080 /* Transmit interrupt request */ +#define AR_ISR_TXERR 0x00000100 /* Transmit error interrupt */ +#define AR_ISR_TXNOPKT 0x00000200 /* No frame transmitted interrupt */ +#define AR_ISR_TXEOL 0x00000400 /* Transmit descriptor empty interrupt */ +#define AR_ISR_TXURN 0x00000800 /* Transmit FIFO underrun interrupt */ +#define AR_ISR_MIB 0x00001000 /* MIB interrupt - see MIBC */ +#define AR_ISR_SWI 0x00002000 /* Software interrupt */ +#define AR_ISR_RXPHY 0x00004000 /* PHY receive error interrupt */ +#define AR_ISR_RXKCM 0x00008000 /* Key-cache miss interrupt */ +#define AR_ISR_SWBA 0x00010000 /* Software beacon alert interrupt */ +#define AR_ISR_BRSSI 0x00020000 /* Beacon threshold interrupt */ +#define AR_ISR_BMISS 0x00040000 /* Beacon missed interrupt */ +#define AR_ISR_HIUERR 0x00080000 /* An unexpected bus error has occurred */ +#define AR_ISR_BNR 0x00100000 /* Beacon not ready interrupt */ +#define AR_ISR_RXCHIRP 0x00200000 /* Phy received a 'chirp' */ +#define AR_ISR_RXDOPPL 0x00400000 /* Phy received a 'doppler chirp' */ +#define AR_ISR_BCNMISC 0x00800000 /* 'or' of TIM, CABEND, DTIMSYNC, BCNTO, + CABTO, DTIM bits from ISR_S2 */ +#define AR_ISR_TIM 0x00800000 /* TIM interrupt */ +#define AR_ISR_GPIO 0x01000000 /* GPIO Interrupt */ +#define AR_ISR_QCBROVF 0x02000000 /* QCU CBR overflow interrupt */ +#define AR_ISR_QCBRURN 0x04000000 /* QCU CBR underrun interrupt */ +#define AR_ISR_QTRIG 0x08000000 /* QCU scheduling trigger interrupt */ +#define AR_ISR_RESV0 0xF0000000 /* Reserved */ + +#define AR_ISR_S0_QCU_TXOK 0x000003FF /* Mask for TXOK (QCU 0-9) */ +#define AR_ISR_S0_QCU_TXOK_S 0 +#define AR_ISR_S0_QCU_TXDESC 0x03FF0000 /* Mask for TXDESC (QCU 0-9) */ +#define AR_ISR_S0_QCU_TXDESC_S 16 + +#define AR_ISR_S1_QCU_TXERR 0x000003FF /* Mask for TXERR (QCU 0-9) */ +#define AR_ISR_S1_QCU_TXERR_S 0 +#define AR_ISR_S1_QCU_TXEOL 0x03FF0000 /* Mask for TXEOL (QCU 0-9) */ +#define AR_ISR_S1_QCU_TXEOL_S 16 + +#define AR_ISR_S2_QCU_TXURN 0x000003FF /* Mask for TXURN (QCU 0-9) */ +#define AR_ISR_S2_MCABT 0x00010000 /* Master cycle abort interrupt */ +#define AR_ISR_S2_SSERR 0x00020000 /* SERR interrupt */ +#define AR_ISR_S2_DPERR 0x00040000 /* PCI bus parity error */ +#define AR_ISR_S2_TIM 0x01000000 /* TIM */ +#define AR_ISR_S2_CABEND 0x02000000 /* CABEND */ +#define AR_ISR_S2_DTIMSYNC 0x04000000 /* DTIMSYNC */ +#define AR_ISR_S2_BCNTO 0x08000000 /* BCNTO */ +#define AR_ISR_S2_CABTO 0x10000000 /* CABTO */ +#define AR_ISR_S2_DTIM 0x20000000 /* DTIM */ +#define AR_ISR_S2_TSFOOR 0x40000000 /* TSF OOR */ +#define AR_ISR_S2_TBTT 0x80000000 /* TBTT timer */ + +#define AR_ISR_S3_QCU_QCBROVF 0x000003FF /* Mask for QCBROVF (QCU 0-9) */ +#define AR_ISR_S3_QCU_QCBRURN 0x03FF0000 /* Mask for QCBRURN (QCU 0-9) */ + +#define AR_ISR_S4_QCU_QTRIG 0x000003FF /* Mask for QTRIG (QCU 0-9) */ +#define AR_ISR_S4_RESV0 0xFFFFFC00 /* Reserved */ + +/* + * Interrupt Mask Registers + * + * Only the bits in the IMR control whether the MAC's INTA# + * output will be asserted. The bits in the secondary interrupt + * mask registers control what bits get set in the primary + * interrupt status register; however the IMR_S* registers + * DO NOT determine whether INTA# is asserted. + */ +#define AR_IMR_RXOK 0x00000001 /* At least one frame received sans errors */ +#define AR_IMR_RXDESC 0x00000002 /* Receive interrupt request */ +#define AR_IMR_RXERR 0x00000004 /* Receive error interrupt */ +#define AR_IMR_RXNOPKT 0x00000008 /* No frame received within timeout clock */ +#define AR_IMR_RXEOL 0x00000010 /* Received descriptor empty interrupt */ +#define AR_IMR_RXORN 0x00000020 /* Receive FIFO overrun interrupt */ +#define AR_IMR_TXOK 0x00000040 /* Transmit okay interrupt */ +#define AR_IMR_TXDESC 0x00000080 /* Transmit interrupt request */ +#define AR_IMR_TXERR 0x00000100 /* Transmit error interrupt */ +#define AR_IMR_TXNOPKT 0x00000200 /* No frame transmitted interrupt */ +#define AR_IMR_TXEOL 0x00000400 /* Transmit descriptor empty interrupt */ +#define AR_IMR_TXURN 0x00000800 /* Transmit FIFO underrun interrupt */ +#define AR_IMR_MIB 0x00001000 /* MIB interrupt - see MIBC */ +#define AR_IMR_SWI 0x00002000 /* Software interrupt */ +#define AR_IMR_RXPHY 0x00004000 /* PHY receive error interrupt */ +#define AR_IMR_RXKCM 0x00008000 /* Key-cache miss interrupt */ +#define AR_IMR_SWBA 0x00010000 /* Software beacon alert interrupt */ +#define AR_IMR_BRSSI 0x00020000 /* Beacon threshold interrupt */ +#define AR_IMR_BMISS 0x00040000 /* Beacon missed interrupt */ +#define AR_IMR_HIUERR 0x00080000 /* An unexpected bus error has occurred */ +#define AR_IMR_BNR 0x00100000 /* BNR interrupt */ +#define AR_IMR_RXCHIRP 0x00200000 /* RXCHIRP interrupt */ +#define AR_IMR_BCNMISC 0x00800000 /* Venice: BCNMISC */ +#define AR_IMR_TIM 0x00800000 /* TIM interrupt */ +#define AR_IMR_GPIO 0x01000000 /* GPIO Interrupt */ +#define AR_IMR_QCBROVF 0x02000000 /* QCU CBR overflow interrupt */ +#define AR_IMR_QCBRURN 0x04000000 /* QCU CBR underrun interrupt */ +#define AR_IMR_QTRIG 0x08000000 /* QCU scheduling trigger interrupt */ +#define AR_IMR_RESV0 0xF0000000 /* Reserved */ + +#define AR_IMR_S0_QCU_TXOK 0x000003FF /* TXOK (QCU 0-9) */ +#define AR_IMR_S0_QCU_TXOK_S 0 +#define AR_IMR_S0_QCU_TXDESC 0x03FF0000 /* TXDESC (QCU 0-9) */ +#define AR_IMR_S0_QCU_TXDESC_S 16 + +#define AR_IMR_S1_QCU_TXERR 0x000003FF /* TXERR (QCU 0-9) */ +#define AR_IMR_S1_QCU_TXERR_S 0 +#define AR_IMR_S1_QCU_TXEOL 0x03FF0000 /* TXEOL (QCU 0-9) */ +#define AR_IMR_S1_QCU_TXEOL_S 16 + +#define AR_IMR_S2_QCU_TXURN 0x000003FF /* Mask for TXURN (QCU 0-9) */ +#define AR_IMR_S2_QCU_TXURN_S 0 +#define AR_IMR_S2_MCABT 0x00010000 /* Master cycle abort interrupt */ +#define AR_IMR_S2_SSERR 0x00020000 /* SERR interrupt */ +#define AR_IMR_S2_DPERR 0x00040000 /* PCI bus parity error */ +#define AR_IMR_S2_TIM 0x01000000 /* TIM */ +#define AR_IMR_S2_CABEND 0x02000000 /* CABEND */ +#define AR_IMR_S2_DTIMSYNC 0x04000000 /* DTIMSYNC */ +#define AR_IMR_S2_BCNTO 0x08000000 /* BCNTO */ +#define AR_IMR_S2_CABTO 0x10000000 /* CABTO */ +#define AR_IMR_S2_DTIM 0x20000000 /* DTIM */ +#define AR_IMR_S2_TSFOOR 0x40000000 /* TSF OOR */ +#define AR_IMR_S2_TBTT 0x80000000 /* TBTT timer */ + +/* AR_IMR_SR2 bits that correspond to AR_IMR_BCNMISC */ +#define AR_IMR_SR2_BCNMISC \ + (AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | \ + AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | AR_IMR_S2_TSFOOR | \ + AR_IMR_S2_TBTT) + +#define AR_IMR_S3_QCU_QCBROVF 0x000003FF /* Mask for QCBROVF (QCU 0-9) */ +#define AR_IMR_S3_QCU_QCBRURN 0x03FF0000 /* Mask for QCBRURN (QCU 0-9) */ +#define AR_IMR_S3_QCU_QCBRURN_S 16 /* Shift for QCBRURN (QCU 0-9) */ + +#define AR_IMR_S4_QCU_QTRIG 0x000003FF /* Mask for QTRIG (QCU 0-9) */ +#define AR_IMR_S4_RESV0 0xFFFFFC00 /* Reserved */ + +/* QCU registers */ +#define AR_NUM_QCU 10 /* Only use QCU 0-9 for forward QCU compatibility */ +#define AR_QCU_0 0x0001 +#define AR_QCU_1 0x0002 +#define AR_QCU_2 0x0004 +#define AR_QCU_3 0x0008 +#define AR_QCU_4 0x0010 +#define AR_QCU_5 0x0020 +#define AR_QCU_6 0x0040 +#define AR_QCU_7 0x0080 +#define AR_QCU_8 0x0100 +#define AR_QCU_9 0x0200 + +#define AR_Q_CBRCFG_CBR_INTERVAL 0x00FFFFFF /* Mask for CBR interval (us) */ +#define AR_Q_CBRCFG_CBR_INTERVAL_S 0 /* Shift for CBR interval */ +#define AR_Q_CBRCFG_CBR_OVF_THRESH 0xFF000000 /* Mask for CBR overflow threshold */ +#define AR_Q_CBRCFG_CBR_OVF_THRESH_S 24 /* Shift for CBR overflow thresh */ + +#define AR_Q_RDYTIMECFG_INT 0x00FFFFFF /* CBR interval (us) */ +#define AR_Q_RDYTIMECFG_INT_S 0 // Shift for ReadyTime Interval (us) */ +#define AR_Q_RDYTIMECFG_ENA 0x01000000 /* CBR enable */ +/* bits 25-31 are reserved */ + +#define AR_Q_MISC_FSP 0x0000000F /* Frame Scheduling Policy mask */ +#define AR_Q_MISC_FSP_ASAP 0 /* ASAP */ +#define AR_Q_MISC_FSP_CBR 1 /* CBR */ +#define AR_Q_MISC_FSP_DBA_GATED 2 /* DMA Beacon Alert gated */ +#define AR_Q_MISC_FSP_TIM_GATED 3 /* TIM gated */ +#define AR_Q_MISC_FSP_BEACON_SENT_GATED 4 /* Beacon-sent-gated */ +#define AR_Q_MISC_FSP_S 0 +#define AR_Q_MISC_ONE_SHOT_EN 0x00000010 /* OneShot enable */ +#define AR_Q_MISC_CBR_INCR_DIS1 0x00000020 /* Disable CBR expired counter incr + (empty q) */ +#define AR_Q_MISC_CBR_INCR_DIS0 0x00000040 /* Disable CBR expired counter incr + (empty beacon q) */ +#define AR_Q_MISC_BEACON_USE 0x00000080 /* Beacon use indication */ +#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT 0x00000100 /* CBR expired counter limit enable */ +#define AR_Q_MISC_RDYTIME_EXP_POLICY 0x00000200 /* Enable TXE cleared on ReadyTime expired or VEOL */ +#define AR_Q_MISC_RESET_CBR_EXP_CTR 0x00000400 /* Reset CBR expired counter */ +#define AR_Q_MISC_DCU_EARLY_TERM_REQ 0x00000800 /* DCU frame early termination request control */ +#define AR_Q_MISC_QCU_COMP_EN 0x00001000 /* QCU frame compression enable */ +#define AR_Q_MISC_RESV0 0xFFFFF000 /* Reserved */ + +#define AR_Q_STS_PEND_FR_CNT 0x00000003 /* Mask for Pending Frame Count */ +#define AR_Q_STS_RESV0 0x000000FC /* Reserved */ +#define AR_Q_STS_CBR_EXP_CNT 0x0000FF00 /* Mask for CBR expired counter */ +#define AR_Q_STS_RESV1 0xFFFF0000 /* Reserved */ + +/* DCU registers */ +#define AR_NUM_DCU 10 /* Only use 10 DCU's for forward QCU/DCU compatibility */ +#define AR_DCU_0 0x0001 +#define AR_DCU_1 0x0002 +#define AR_DCU_2 0x0004 +#define AR_DCU_3 0x0008 +#define AR_DCU_4 0x0010 +#define AR_DCU_5 0x0020 +#define AR_DCU_6 0x0040 +#define AR_DCU_7 0x0080 +#define AR_DCU_8 0x0100 +#define AR_DCU_9 0x0200 + +#define AR_D_QCUMASK 0x000003FF /* Mask for QCU Mask (QCU 0-9) */ +#define AR_D_QCUMASK_RESV0 0xFFFFFC00 /* Reserved */ + +#define AR_D_LCL_IFS_CWMIN 0x000003FF /* Mask for CW_MIN */ +#define AR_D_LCL_IFS_CWMIN_S 0 +#define AR_D_LCL_IFS_CWMAX 0x000FFC00 /* Mask for CW_MAX */ +#define AR_D_LCL_IFS_CWMAX_S 10 +#define AR_D_LCL_IFS_AIFS 0x0FF00000 /* Mask for AIFS */ +#define AR_D_LCL_IFS_AIFS_S 20 +/* + * Note: even though this field is 8 bits wide the + * maximum supported AIFS value is 0xfc. Setting the AIFS value + * to 0xfd 0xfe, or 0xff will not work correctly and will cause + * the DCU to hang. + */ +#define AR_D_LCL_IFS_RESV0 0xF0000000 /* Reserved */ + +#define AR_D_RETRY_LIMIT_FR_SH 0x0000000F /* frame short retry limit */ +#define AR_D_RETRY_LIMIT_FR_SH_S 0 +#define AR_D_RETRY_LIMIT_FR_LG 0x000000F0 /* frame long retry limit */ +#define AR_D_RETRY_LIMIT_FR_LG_S 4 +#define AR_D_RETRY_LIMIT_STA_SH 0x00003F00 /* station short retry limit */ +#define AR_D_RETRY_LIMIT_STA_SH_S 8 +#define AR_D_RETRY_LIMIT_STA_LG 0x000FC000 /* station short retry limit */ +#define AR_D_RETRY_LIMIT_STA_LG_S 14 +#define AR_D_RETRY_LIMIT_RESV0 0xFFF00000 /* Reserved */ + +#define AR_D_CHNTIME_DUR 0x000FFFFF /* ChannelTime duration (us) */ +#define AR_D_CHNTIME_DUR_S 0 /* Shift for ChannelTime duration */ +#define AR_D_CHNTIME_EN 0x00100000 /* ChannelTime enable */ +#define AR_D_CHNTIME_RESV0 0xFFE00000 /* Reserved */ + +#define AR_D_MISC_BKOFF_THRESH 0x0000003F /* Backoff threshold */ +#define AR_D_MISC_ETS_RTS 0x00000040 /* End of transmission series + station RTS/data failure + count reset policy */ +#define AR_D_MISC_ETS_CW 0x00000080 /* End of transmission series + CW reset policy */ +#define AR_D_MISC_FRAG_WAIT_EN 0x00000100 /* Wait for next fragment */ +#define AR_D_MISC_FRAG_BKOFF_EN 0x00000200 /* Backoff during a frag burst */ +#define AR_D_MISC_HCF_POLL_EN 0x00000800 /* HFC poll enable */ +#define AR_D_MISC_BKOFF_PERSISTENCE 0x00001000 /* Backoff persistence factor + setting */ +#define AR_D_MISC_FR_PREFETCH_EN 0x00002000 /* Frame prefetch enable */ +#define AR_D_MISC_VIR_COL_HANDLING 0x0000C000 /* Mask for Virtual collision + handling policy */ +#define AR_D_MISC_VIR_COL_HANDLING_S 14 +/* FOO redefined for venice CW increment policy */ +#define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0 /* Normal */ +#define AR_D_MISC_VIR_COL_HANDLING_IGNORE 1 /* Ignore */ +#define AR_D_MISC_BEACON_USE 0x00010000 /* Beacon use indication */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL 0x00060000 /* DCU arbiter lockout ctl */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17 /* DCU arbiter lockout ctl */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE 0 /* No lockout */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1 /* Intra-frame */ +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL 2 /* Global */ +#define AR_D_MISC_ARB_LOCKOUT_IGNORE 0x00080000 /* DCU arbiter lockout ignore control */ +#define AR_D_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Sequence number increment disable */ +#define AR_D_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Post-frame backoff disable */ +#define AR_D_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual coll. handling policy */ +#define AR_D_MISC_BLOWN_IFS_POLICY 0x00800000 /* Blown IFS handling policy */ +#define AR_D_MISC_RESV0 0xFE000000 /* Reserved */ + +#define AR_D_SEQNUM_RESV0 0xFFFFF000 /* Reserved */ + +#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 /* LFSR slice select */ +#define AR_D_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode indication */ +#define AR_D_GBL_IFS_MISC_SIFS_DURATION_USEC 0x000003F0 /* SIFS duration (us) */ +#define AR_D_GBL_IFS_MISC_USEC_DURATION 0x000FFC00 /* microsecond duration */ +#define AR_D_GBL_IFS_MISC_USEC_DURATION_S 10 +#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY 0x00300000 /* DCU arbiter delay */ +#define AR_D_GBL_IFS_MISC_RESV0 0xFFC00000 /* Reserved */ + +/* DMA & PCI Registers in PCI space (usable during sleep) */ +#define AR_RC_MAC 0x00000001 /* MAC reset */ +#define AR_RC_BB 0x00000002 /* Baseband reset */ +#define AR_RC_RESV0 0x00000004 /* Reserved */ +#define AR_RC_RESV1 0x00000008 /* Reserved */ +#define AR_RC_PCI 0x00000010 /* PCI-core reset */ + +#define AR_SCR_SLDUR 0x0000ffff /* sleep duration, units of 128us */ +#define AR_SCR_SLDUR_S 0 +#define AR_SCR_SLE 0x00030000 /* sleep enable */ +#define AR_SCR_SLE_S 16 +#define AR_SCR_SLE_WAKE 0 /* force wake */ +#define AR_SCR_SLE_SLP 1 /* force sleep */ +#define AR_SCR_SLE_NORM 2 /* sleep logic normal operation */ +#define AR_SCR_SLDTP 0x00040000 /* sleep duration timing policy */ +#define AR_SCR_SLDWP 0x00080000 /* sleep duration write policy */ +#define AR_SCR_SLEPOL 0x00100000 /* sleep policy mode */ +#define AR_SCR_MIBIE 0x00200000 /* sleep perf cntrs MIB intr ena */ +#define AR_SCR_UNKNOWN 0x00400000 + +#define AR_INTPEND_TRUE 0x00000001 /* interrupt pending */ + +#define AR_SFR_SLEEP 0x00000001 /* force sleep */ + +#define AR_PCICFG_SCLK_SEL 0x00000002 /* sleep clock select */ +#define AR_PCICFG_SCLK_SEL_S 1 +#define AR_PCICFG_CLKRUNEN 0x00000004 /* enable PCI CLKRUN function */ +#define AR_PCICFG_EEPROM_SIZE 0x00000018 /* Mask for EEPROM size */ +#define AR_PCICFG_EEPROM_SIZE_4 0 /* EEPROM size 4 Kbit */ +#define AR_PCICFG_EEPROM_SIZE_8K 1 /* EEPROM size 8 Kbit */ +#define AR_PCICFG_EEPROM_SIZE_16K 2 /* EEPROM size 16 Kbit */ +#define AR_PCICFG_EEPROM_SIZE_FAILED 3 /* Failure */ +#define AR_PCICFG_EEPROM_SIZE_S 3 +#define AR_PCICFG_LEDCTL 0x00000060 /* LED control Status */ +#define AR_PCICFG_LEDCTL_NONE 0 /* STA is not associated or trying */ +#define AR_PCICFG_LEDCTL_PEND 1 /* STA is trying to associate */ +#define AR_PCICFG_LEDCTL_ASSOC 2 /* STA is associated */ +#define AR_PCICFG_LEDCTL_S 5 +#define AR_PCICFG_PCI_BUS_SEL 0x00000380 /* PCI observation bus mux select */ +#define AR_PCICFG_DIS_CBE_FIX 0x00000400 /* Disable fix for bad PCI CBE# generation */ +#define AR_PCICFG_SL_INTEN 0x00000800 /* enable interrupt line assertion when asleep */ +#define AR_PCICFG_RETRYFIXEN 0x00001000 /* Enable PCI core retry fix */ +#define AR_PCICFG_SL_INPEN 0x00002000 /* Force asleep when an interrupt is pending */ +#define AR_PCICFG_RESV1 0x0000C000 /* Reserved */ +#define AR_PCICFG_SPWR_DN 0x00010000 /* mask for sleep/awake indication */ +#define AR_PCICFG_LEDMODE 0x000E0000 /* LED mode */ +#define AR_PCICFG_LEDMODE_PROP 0 /* Blink prop to filtered tx/rx */ +#define AR_PCICFG_LEDMODE_RPROP 1 /* Blink prop to unfiltered tx/rx */ +#define AR_PCICFG_LEDMODE_SPLIT 2 /* Blink power for tx/net for rx */ +#define AR_PCICFG_LEDMODE_RAND 3 /* Blink randomly */ +/* NB: s/w led control present in Hainan 1.1 and above */ +#define AR_PCICFG_LEDMODE_OFF 4 /* s/w control + both led's off */ +#define AR_PCICFG_LEDMODE_POWON 5 /* s/w control + power led on */ +#define AR_PCICFG_LEDMODE_NETON 6 /* s/w control + network led on */ +#define AR_PCICFG_LEDMODE_S 17 +#define AR_PCICFG_LEDBLINK 0x00700000 /* LED blink threshold select */ +#define AR_PCICFG_LEDBLINK_S 20 +#define AR_PCICFG_LEDSLOW 0x00800000 /* LED slowest blink rate mode */ +#define AR_PCICFG_LEDSLOW_S 23 +#define AR_PCICFG_SCLK_RATE_IND 0x03000000 /* Sleep clock rate */ +#define AR_PCICFG_SCLK_RATE_IND_S 24 +#define AR_PCICFG_RESV2 0xFC000000 /* Reserved */ + +#define AR_GPIOCR_CR_SHIFT 2 /* Each CR is 2 bits */ +#define AR_GPIOCR_CR_N(_g) (0 << (AR_GPIOCR_CR_SHIFT * (_g))) +#define AR_GPIOCR_CR_0(_g) (1 << (AR_GPIOCR_CR_SHIFT * (_g))) +#define AR_GPIOCR_CR_1(_g) (2 << (AR_GPIOCR_CR_SHIFT * (_g))) +#define AR_GPIOCR_CR_A(_g) (3 << (AR_GPIOCR_CR_SHIFT * (_g))) +#define AR_GPIOCR_INT_SHIFT 12 /* Interrupt select field shifter */ +#define AR_GPIOCR_INT(_g) ((_g) << AR_GPIOCR_INT_SHIFT) +#define AR_GPIOCR_INT_MASK 0x00007000 /* Interrupt select field mask */ +#define AR_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO Interrupt */ +#define AR_GPIOCR_INT_SELL 0x00000000 /* Generate int if pin is low */ +#define AR_GPIOCR_INT_SELH 0x00010000 /* Generate int if pin is high */ +#define AR_GPIOCR_INT_SEL AR_GPIOCR_INT_SELH + +#define AR_SREV_ID 0x000000FF /* Mask to read SREV info */ +#define AR_SREV_ID_S 4 /* Mask to shift Major Rev Info */ +#define AR_SREV_REVISION 0x0000000F /* Mask for Chip revision level */ +#define AR_SREV_REVISION_MIN 0 /* lowest revision level */ +#define AR_SREV_REVISION_MAX 0xF /* highest revision level */ +#define AR_SREV_FPGA 1 +#define AR_SREV_D2PLUS 2 +#define AR_SREV_D2PLUS_MS 3 /* metal spin */ +#define AR_SREV_CRETE 4 +#define AR_SREV_CRETE_MS 5 /* FCS metal spin */ +#define AR_SREV_CRETE_MS23 7 /* 2.3 metal spin (6 skipped) */ +#define AR_SREV_CRETE_23 8 /* 2.3 full tape out */ +#define AR_SREV_GRIFFIN_LITE 8 +#define AR_SREV_HAINAN 9 +#define AR_SREV_CONDOR 11 +#define AR_SREV_VERSION 0x000000F0 /* Mask for Chip version */ +#define AR_SREV_VERSION_CRETE 0 +#define AR_SREV_VERSION_MAUI_1 1 +#define AR_SREV_VERSION_MAUI_2 2 +#define AR_SREV_VERSION_SPIRIT 3 +#define AR_SREV_VERSION_OAHU 4 +#define AR_SREV_VERSION_VENICE 5 +#define AR_SREV_VERSION_GRIFFIN 7 +#define AR_SREV_VERSION_CONDOR 9 +#define AR_SREV_VERSION_EAGLE 10 +#define AR_SREV_VERSION_COBRA 11 +#define AR_SREV_2413 AR_SREV_VERSION_GRIFFIN +#define AR_SREV_5413 AR_SREV_VERSION_EAGLE +#define AR_SREV_2415 AR_SREV_VERSION_COBRA +#define AR_SREV_5424 AR_SREV_VERSION_CONDOR +#define AR_SREV_2425 14 /* SWAN */ +#define AR_SREV_2417 15 /* Nala */ +#define AR_SREV_OAHU_ES 0 /* Engineering Sample */ +#define AR_SREV_OAHU_PROD 2 /* Production */ + +#define AR_PHYREV_HAINAN 0x43 +#define AR_ANALOG5REV_HAINAN 0x46 + +#define AR_RADIO_SREV_MAJOR 0xF0 +#define AR_RADIO_SREV_MINOR 0x0F +#define AR_RAD5111_SREV_MAJOR 0x10 /* All current supported ar5211 5 GHz + radios are rev 0x10 */ +#define AR_RAD5111_SREV_PROD 0x15 /* Current production level radios */ +#define AR_RAD2111_SREV_MAJOR 0x20 /* All current supported ar5211 2 GHz + radios are rev 0x10 */ +#define AR_RAD5112_SREV_MAJOR 0x30 /* 5112 Major Rev */ +#define AR_RAD5112_SREV_2_0 0x35 /* AR5112 Revision 2.0 */ +#define AR_RAD5112_SREV_2_1 0x36 /* AR5112 Revision 2.1 */ +#define AR_RAD2112_SREV_MAJOR 0x40 /* 2112 Major Rev */ +#define AR_RAD2112_SREV_2_0 0x45 /* AR2112 Revision 2.0 */ +#define AR_RAD2112_SREV_2_1 0x46 /* AR2112 Revision 2.1 */ +#define AR_RAD2413_SREV_MAJOR 0x50 /* 2413 Major Rev */ +#define AR_RAD5413_SREV_MAJOR 0x60 /* 5413 Major Rev */ +#define AR_RAD2316_SREV_MAJOR 0x70 /* 2316 Major Rev */ +#define AR_RAD2317_SREV_MAJOR 0x80 /* 2317 Major Rev */ +#define AR_RAD5424_SREV_MAJOR 0xa0 /* Mostly same as 5413 Major Rev */ + +#define AR_PCIE_PMC_ENA_L1 0x01 /* enable PCIe core enter L1 when + d2_sleep_en is asserted */ +#define AR_PCIE_PMC_ENA_RESET 0x08 /* enable reset on link going down */ + +/* EEPROM Registers in the MAC */ +#define AR_EEPROM_CMD_READ 0x00000001 +#define AR_EEPROM_CMD_WRITE 0x00000002 +#define AR_EEPROM_CMD_RESET 0x00000004 + +#define AR_EEPROM_STS_READ_ERROR 0x00000001 +#define AR_EEPROM_STS_READ_COMPLETE 0x00000002 +#define AR_EEPROM_STS_WRITE_ERROR 0x00000004 +#define AR_EEPROM_STS_WRITE_COMPLETE 0x00000008 + +#define AR_EEPROM_CFG_SIZE 0x00000003 /* size determination override */ +#define AR_EEPROM_CFG_SIZE_AUTO 0 +#define AR_EEPROM_CFG_SIZE_4KBIT 1 +#define AR_EEPROM_CFG_SIZE_8KBIT 2 +#define AR_EEPROM_CFG_SIZE_16KBIT 3 +#define AR_EEPROM_CFG_DIS_WWRCL 0x00000004 /* Disable wait for write completion */ +#define AR_EEPROM_CFG_CLOCK 0x00000018 /* clock rate control */ +#define AR_EEPROM_CFG_CLOCK_S 3 /* clock rate control */ +#define AR_EEPROM_CFG_CLOCK_156KHZ 0 +#define AR_EEPROM_CFG_CLOCK_312KHZ 1 +#define AR_EEPROM_CFG_CLOCK_625KHZ 2 +#define AR_EEPROM_CFG_RESV0 0x000000E0 /* Reserved */ +#define AR_EEPROM_CFG_PKEY 0x00FFFF00 /* protection key */ +#define AR_EEPROM_CFG_PKEY_S 8 +#define AR_EEPROM_CFG_EN_L 0x01000000 /* EPRM_EN_L setting */ + +/* MAC PCU Registers */ + +#define AR_STA_ID1_SADH_MASK 0x0000FFFF /* upper 16 bits of MAC addr */ +#define AR_STA_ID1_STA_AP 0x00010000 /* Device is AP */ +#define AR_STA_ID1_ADHOC 0x00020000 /* Device is ad-hoc */ +#define AR_STA_ID1_PWR_SAV 0x00040000 /* Power save reporting in + self-generated frames */ +#define AR_STA_ID1_KSRCHDIS 0x00080000 /* Key search disable */ +#define AR_STA_ID1_PCF 0x00100000 /* Observe PCF */ +#define AR_STA_ID1_USE_DEFANT 0x00200000 /* Use default antenna */ +#define AR_STA_ID1_UPD_DEFANT 0x00400000 /* Update default antenna w/ + TX antenna */ +#define AR_STA_ID1_RTS_USE_DEF 0x00800000 /* Use default antenna to send RTS */ +#define AR_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mb/s rate for ACK & CTS */ +#define AR_STA_ID1_BASE_RATE_11B 0x02000000/* Use 11b base rate for ACK & CTS */ +#define AR_STA_ID1_USE_DA_SG 0x04000000 /* Use default antenna for + self-generated frames */ +#define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000 /* Enable Michael */ +#define AR_STA_ID1_KSRCH_MODE 0x10000000 /* Look-up key when keyID != 0 */ +#define AR_STA_ID1_PRE_SEQNUM 0x20000000 /* Preserve s/w sequence number */ +#define AR_STA_ID1_CBCIV_ENDIAN 0x40000000 +#define AR_STA_ID1_MCAST_KSRCH 0x80000000 /* Do keycache search for mcast */ + +#define AR_BSS_ID1_U16 0x0000FFFF /* Upper 16 bits of BSSID */ +#define AR_BSS_ID1_AID 0xFFFF0000 /* Association ID */ +#define AR_BSS_ID1_AID_S 16 + +#define AR_SLOT_TIME_MASK 0x000007FF /* Slot time mask */ + +#define AR_TIME_OUT_ACK 0x00003FFF /* ACK time-out */ +#define AR_TIME_OUT_ACK_S 0 +#define AR_TIME_OUT_CTS 0x3FFF0000 /* CTS time-out */ +#define AR_TIME_OUT_CTS_S 16 + +#define AR_RSSI_THR_MASK 0x000000FF /* Beacon RSSI warning threshold */ +#define AR_RSSI_THR_BM_THR 0x0000FF00 /* Missed beacon threshold */ +#define AR_RSSI_THR_BM_THR_S 8 + +#define AR_USEC_USEC 0x0000007F /* clock cycles in 1 usec */ +#define AR_USEC_USEC_S 0 +#define AR_USEC_USEC32 0x00003F80 /* 32MHz clock cycles in 1 usec */ +#define AR_USEC_USEC32_S 7 + +#define AR5212_USEC_TX_LAT_M 0x007FC000 /* Tx latency */ +#define AR5212_USEC_TX_LAT_S 14 +#define AR5212_USEC_RX_LAT_M 0x1F800000 /* Rx latency */ +#define AR5212_USEC_RX_LAT_S 23 + +#define AR_BEACON_PERIOD 0x0000FFFF /* Beacon period mask in TU/msec */ +#define AR_BEACON_PERIOD_S 0 +#define AR_BEACON_TIM 0x007F0000 /* byte offset of TIM start */ +#define AR_BEACON_TIM_S 16 +#define AR_BEACON_EN 0x00800000 /* Beacon enable */ +#define AR_BEACON_RESET_TSF 0x01000000 /* Clear TSF to 0 */ + +#define AR_RX_NONE 0x00000000 /* Disallow all frames */ +#define AR_RX_UCAST 0x00000001 /* Allow unicast frames */ +#define AR_RX_MCAST 0x00000002 /* Allow multicast frames */ +#define AR_RX_BCAST 0x00000004 /* Allow broadcast frames */ +#define AR_RX_CONTROL 0x00000008 /* Allow control frames */ +#define AR_RX_BEACON 0x00000010 /* Allow beacon frames */ +#define AR_RX_PROM 0x00000020 /* Promiscuous mode, all packets */ +#define AR_RX_PROBE_REQ 0x00000080 /* Allow probe request frames */ + +#define AR_DIAG_CACHE_ACK 0x00000001 /* No ACK if no valid key found */ +#define AR_DIAG_ACK_DIS 0x00000002 /* Disable ACK generation */ +#define AR_DIAG_CTS_DIS 0x00000004 /* Disable CTS generation */ +#define AR_DIAG_ENCRYPT_DIS 0x00000008 /* Disable encryption */ +#define AR_DIAG_DECRYPT_DIS 0x00000010 /* Disable decryption */ +#define AR_DIAG_RX_DIS 0x00000020 /* Disable receive */ +#define AR_DIAG_CORR_FCS 0x00000080 /* Corrupt FCS */ +#define AR_DIAG_CHAN_INFO 0x00000100 /* Dump channel info */ +#define AR_DIAG_EN_SCRAMSD 0x00000200 /* Enable fixed scrambler seed */ +#define AR_DIAG_SCRAM_SEED 0x0001FC00 /* Fixed scrambler seed */ +#define AR_DIAG_SCRAM_SEED_S 10 +#define AR_DIAG_FRAME_NV0 0x00020000 /* Accept frames of non-zero + protocol version */ +#define AR_DIAG_OBS_PT_SEL 0x000C0000 /* Observation point select */ +#define AR_DIAG_OBS_PT_SEL_S 18 +#define AR_DIAG_RX_CLR_HI 0x00100000 /* Force rx_clear high */ +#define AR_DIAG_IGNORE_CS 0x00200000 /* Force virtual carrier sense */ +#define AR_DIAG_CHAN_IDLE 0x00400000 /* Force channel idle high */ +#define AR_DIAG_PHEAR_ME 0x00800000 /* Uses framed and wait_wep in the pherr_enable_eifs if set to 0 */ + +#define AR_SLEEP1_NEXT_DTIM 0x0007ffff /* Abs. time(1/8TU) for next DTIM */ +#define AR_SLEEP1_NEXT_DTIM_S 0 +#define AR_SLEEP1_ASSUME_DTIM 0x00080000 /* Assume DTIM present on missent beacon */ +#define AR_SLEEP1_ENH_SLEEP_ENA 0x00100000 /* Enable enhanced sleep logic */ +#define AR_SLEEP1_CAB_TIMEOUT 0xff000000 /* CAB timeout(TU) */ +#define AR_SLEEP1_CAB_TIMEOUT_S 24 + +#define AR_SLEEP2_NEXT_TIM 0x0007ffff /* Abs. time(1/8TU) for next DTIM */ +#define AR_SLEEP2_NEXT_TIM_S 0 +#define AR_SLEEP2_BEACON_TIMEOUT 0xff000000 /* Beacon timeout(TU) */ +#define AR_SLEEP2_BEACON_TIMEOUT_S 24 + +#define AR_SLEEP3_TIM_PERIOD 0x0000ffff /* Tim/Beacon period (TU) */ +#define AR_SLEEP3_TIM_PERIOD_S 0 +#define AR_SLEEP3_DTIM_PERIOD 0xffff0000 /* DTIM period (TU) */ +#define AR_SLEEP3_DTIM_PERIOD_S 16 + +#define AR_TPC_ACK 0x0000003f /* ack frames */ +#define AR_TPC_ACK_S 0 +#define AR_TPC_CTS 0x00003f00 /* cts frames */ +#define AR_TPC_CTS_S 8 +#define AR_TPC_CHIRP 0x003f0000 /* chirp frames */ +#define AR_TPC_CHIRP_S 16 +#define AR_TPC_DOPPLER 0x0f000000 /* doppler chirp span */ +#define AR_TPC_DOPPLER_S 24 + +#define AR_PHY_ERR_RADAR 0x00000020 /* Radar signal */ +#define AR_PHY_ERR_OFDM_TIMING 0x00020000 /* False detect for OFDM */ +#define AR_PHY_ERR_CCK_TIMING 0x02000000 /* False detect for CCK */ + +#define AR_TSF_PARM_INCREMENT 0x000000ff +#define AR_TSF_PARM_INCREMENT_S 0 + +#define AR_NOACK_2BIT_VALUE 0x0000000f +#define AR_NOACK_2BIT_VALUE_S 0 +#define AR_NOACK_BIT_OFFSET 0x00000070 +#define AR_NOACK_BIT_OFFSET_S 4 +#define AR_NOACK_BYTE_OFFSET 0x00000180 +#define AR_NOACK_BYTE_OFFSET_S 7 + +#define AR_MISC_MODE_BSSID_MATCH_FORCE 0x1 /* Force BSSID match */ +#define AR_MISC_MODE_ACKSIFS_MEMORY 0x2 /* ACKSIFS use contents of Rate */ +#define AR_MISC_MODE_MIC_NEW_LOC_ENABLE 0x4 /* Xmit Michael Key same as Rcv */ +#define AR_MISC_MODE_TX_ADD_TSF 0x8 /* Beacon/Probe-Rsp timestamp add (not replace) */ + +#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0) /* key bit 0-31 */ +#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4) /* key bit 32-47 */ +#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8) /* key bit 48-79 */ +#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12) /* key bit 80-95 */ +#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16) /* key bit 96-127 */ +#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20) /* key type */ +#define AR_KEYTABLE_TYPE_40 0x00000000 /* WEP 40 bit key */ +#define AR_KEYTABLE_TYPE_104 0x00000001 /* WEP 104 bit key */ +#define AR_KEYTABLE_TYPE_128 0x00000003 /* WEP 128 bit key */ +#define AR_KEYTABLE_TYPE_TKIP 0x00000004 /* TKIP and Michael */ +#define AR_KEYTABLE_TYPE_AES 0x00000005 /* AES/OCB 128 bit key */ +#define AR_KEYTABLE_TYPE_CCM 0x00000006 /* AES/CCM 128 bit key */ +#define AR_KEYTABLE_TYPE_CLR 0x00000007 /* no encryption */ +#define AR_KEYTABLE_ANT 0x00000008 /* previous transmit antenna */ +#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24) /* MAC address 1-32 */ +#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28) /* MAC address 33-47 */ +#define AR_KEYTABLE_VALID 0x00008000 /* key and MAC address valid */ + +/* Compress settings */ +#define AR_CCFG_WIN_M 0x00000007 /* mask for AR_CCFG_WIN size */ +#define AR_CCFG_MIB_INT_EN 0x00000008 /* compression performance MIB counter int enable */ +#define AR_CCUCFG_RESET_VAL 0x00100200 /* the should be reset value */ +#define AR_CCUCFG_CATCHUP_EN 0x00000001 /* Compression catchup enable */ +#define AR_DCM_D_EN 0x00000001 /* all direct frames to be decompressed */ +#define AR_COMPRESSION_WINDOW_SIZE 4096 /* default comp. window size */ + +#endif /* _DEV_AR5212REG_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5311reg.h b/sys/external/isc/atheros_hal/dist/ar5212/ar5311reg.h new file mode 100644 index 0000000..b79370e --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5311reg.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _DEV_ATH_AR5311REG_H_ +#define _DEV_ATH_AR5311REG_H_ + +/* + * Definitions for the Atheros 5311 chipset. + */ +#define AR5311_QDCLKGATE 0x005c /* MAC QCU/DCU clock gating control */ +#define AR5311_QDCLKGATE_QCU_M 0x0000FFFF /* QCU clock disable */ +#define AR5311_QDCLKGATE_DCU_M 0x07FF0000 /* DCU clock disable */ + +#define AR5311_RXCFG_DEF_RX_ANTENNA 0x00000008 /* Default Receive Antenna */ + +/* + * NOTE: MAC_5211/MAC_5311 difference + * On Oahu the TX latency field has increased from 6 bits to 9 bits. + * The RX latency field is unchanged but is shifted over 3 bits. + */ +#define AR5311_USEC_TX_LAT_M 0x000FC000 /* tx latency (usec) */ +#define AR5311_USEC_TX_LAT_S 14 +#define AR5311_USEC_RX_LAT_M 0x03F00000 /* rx latency (usec) */ +#define AR5311_USEC_RX_LAT_S 20 + +/* + * NOTE: MAC_5211/MAC_5311 difference + * On Maui2/Spirit the frame sequence number is controlled per DCU. + * On Oahu the frame sequence number is global across all DCUs and + * is controlled + */ +#define AR5311_D_MISC_SEQ_NUM_CONTROL 0x01000000 /* seq num local or global */ +#define AR5311_DIAG_USE_ECO 0x00000400 /* "super secret" enable ECO */ + +#endif /* _DEV_ATH_AR5311REG_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5212/ar5413.c b/sys/external/isc/atheros_hal/dist/ar5212/ar5413.c new file mode 100644 index 0000000..ab6cc65 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5212/ar5413.c @@ -0,0 +1,802 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v3.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#define AH_5212_5413 +#include "ar5212/ar5212.ini" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar5413State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[PWR_TABLE_SIZE_2413]; + + uint32_t Bank1Data[N(ar5212Bank1_5413)]; + uint32_t Bank2Data[N(ar5212Bank2_5413)]; + uint32_t Bank3Data[N(ar5212Bank3_5413)]; + uint32_t Bank6Data[N(ar5212Bank6_5413)]; + uint32_t Bank7Data[N(ar5212Bank7_5413)]; + + /* + * Private state for reduced stack usage. + */ + /* filled out Vpd table for all pdGains (chanL) */ + uint16_t vpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (chanR) */ + uint16_t vpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; + /* filled out Vpd table for all pdGains (interpolated) */ + uint16_t vpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL] + [MAX_PWR_RANGE_IN_HALF_DB]; +}; +#define AR5413(ah) ((struct ar5413State *) AH5212(ah)->ah_rfHal) + +extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar5413WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + HAL_INI_WRITE_ARRAY(ah, ar5212Modes_5413, modesIndex, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212Common_5413, 1, writes); + HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_5413, freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar5413SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + + OS_MARK(ah, AH_MARK_SETCHANNEL, freq); + + if (freq < 4800) { + uint32_t txctl; + + if (((freq - 2192) % 5) == 0) { + channelSel = ((freq - 672) * 2 - 3040)/10; + bModeSynth = 0; + } else if (((freq - 2224) % 5) == 0) { + channelSel = ((freq - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u MHz\n", + __func__, freq); + return AH_FALSE; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else if (((freq % 5) == 2) && (freq <= 5435)) { + freq = freq - 2; /* Align to even 5MHz raster */ + channelSel = ath_hal_reverseBits( + (uint32_t)(((freq - 4800)*10)/25 + 1), 8); + aModeRefSel = ath_hal_reverseBits(0, 2); + } else if ((freq % 20) == 0 && freq >= 5120) { + channelSel = ath_hal_reverseBits( + ((freq - 4800) / 20 << 2), 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else if ((freq % 10) == 0) { + channelSel = ath_hal_reverseBits( + ((freq - 4800) / 10 << 1), 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else if ((freq % 5) == 0) { + channelSel = ath_hal_reverseBits( + (freq - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", + __func__, freq); + return AH_FALSE; + } + + reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 12) | 0x1; + OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); + + reg32 >>= 8; + OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar5413SetRfRegs(struct ath_hal *ah, + const struct ieee80211_channel *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ +#define RF_BANK_SETUP(_priv, _ix, _col) do { \ + int i; \ + for (i = 0; i < N(ar5212Bank##_ix##_5413); i++) \ + (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_5413[i][_col];\ +} while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + uint16_t freq = ath_hal_gethwchannel(ah, chan); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + uint16_t ob5GHz = 0, db5GHz = 0; + uint16_t ob2GHz = 0, db2GHz = 0; + struct ar5413State *priv = AR5413(ah); + int regWrites = 0; + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan %u/0x%x modesIndex %u\n", + __func__, chan->ic_freq, chan->ic_flags, modesIndex); + + HALASSERT(priv != AH_NULL); + + /* Setup rf parameters */ + switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) { + case IEEE80211_CHAN_A: + if (freq > 4000 && freq < 5260) { + ob5GHz = ee->ee_ob1; + db5GHz = ee->ee_db1; + } else if (freq >= 5260 && freq < 5500) { + ob5GHz = ee->ee_ob2; + db5GHz = ee->ee_db2; + } else if (freq >= 5500 && freq < 5725) { + ob5GHz = ee->ee_ob3; + db5GHz = ee->ee_db3; + } else if (freq >= 5725) { + ob5GHz = ee->ee_ob4; + db5GHz = ee->ee_db4; + } else { + /* XXX else */ + } + break; + case IEEE80211_CHAN_B: + ob2GHz = ee->ee_obFor24; + db2GHz = ee->ee_dbFor24; + break; + case IEEE80211_CHAN_G: + case IEEE80211_CHAN_PUREG: /* NB: really 108G */ + ob2GHz = ee->ee_obFor24g; + db2GHz = ee->ee_dbFor24g; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->ic_flags); + return AH_FALSE; + } + + /* Bank 1 Write */ + RF_BANK_SETUP(priv, 1, 1); + + /* Bank 2 Write */ + RF_BANK_SETUP(priv, 2, modesIndex); + + /* Bank 3 Write */ + RF_BANK_SETUP(priv, 3, modesIndex); + + /* Bank 6 Write */ + RF_BANK_SETUP(priv, 6, modesIndex); + + /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 241, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 238, 0); + + /* TODO - only for Eagle 1.0 2GHz - remove for production */ + /* XXX: but without this bit G doesn't work. */ + ar5212ModifyRfBuffer(priv->Bank6Data, 1 , 1, 291, 2); + + /* Optimum value for rf_pwd_iclobuf2G for PCIe chips only */ + if (AH_PRIVATE(ah)->ah_ispcie) { + ar5212ModifyRfBuffer(priv->Bank6Data, ath_hal_reverseBits(6, 3), + 3, 131, 3); + } + } else { + ar5212ModifyRfBuffer(priv->Bank6Data, ob5GHz, 3, 247, 0); + ar5212ModifyRfBuffer(priv->Bank6Data, db5GHz, 3, 244, 0); + + } + + /* Bank 7 Setup */ + RF_BANK_SETUP(priv, 7, modesIndex); + + /* Write Analog registers */ + HAL_INI_WRITE_BANK(ah, ar5212Bank1_5413, priv->Bank1Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank2_5413, priv->Bank2Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank3_5413, priv->Bank3Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank6_5413, priv->Bank6Data, regWrites); + HAL_INI_WRITE_BANK(ah, ar5212Bank7_5413, priv->Bank7Data, regWrites); + + /* Now that we have reprogrammed rfgain value, clear the flag. */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar5413GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar5413State *priv = AR5413(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Return indices surrounding the value in sorted integer lists. + * + * NB: the input list is assumed to be sorted in ascending order + */ +static void +GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize, + uint32_t *vlo, uint32_t *vhi) +{ + int16_t target = v; + const uint16_t *ep = lp+listSize; + const uint16_t *tp; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < lp[0]) { + *vlo = *vhi = 0; + return; + } + if (target >= ep[-1]) { + *vlo = *vhi = listSize - 1; + return; + } + + /* look for value being near or between 2 values in list */ + for (tp = lp; tp < ep; tp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (*tp == target) { + *vlo = *vhi = tp - (const uint16_t *) lp; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < tp[1]) { + *vlo = tp - (const uint16_t *) lp; + *vhi = *vlo + 1; + return; + } + } +} + +/* + * Fill the Vpdlist for indices Pmax-Pmin + */ +static HAL_BOOL +ar5413FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t Pmax, + const int16_t *pwrList, const uint16_t *VpdList, + uint16_t numIntercepts, + uint16_t retVpdList[][64]) +{ + uint16_t ii, jj, kk; + int16_t currPwr = (int16_t)(2*Pmin); + /* since Pmin is pwr*2 and pwrList is 4*pwr */ + uint32_t idxL, idxR; + + ii = 0; + jj = 0; + + if (numIntercepts < 2) + return AH_FALSE; + + while (ii <= (uint16_t)(Pmax - Pmin)) { + GetLowerUpperIndex(currPwr, (const uint16_t *) pwrList, + numIntercepts, &(idxL), &(idxR)); + if (idxR < 1) + idxR = 1; /* extrapolate below */ + if (idxL == (uint32_t)(numIntercepts - 1)) + idxL = numIntercepts - 2; /* extrapolate above */ + if (pwrList[idxL] == pwrList[idxR]) + kk = VpdList[idxL]; + else + kk = (uint16_t) + (((currPwr - pwrList[idxL])*VpdList[idxR]+ + (pwrList[idxR] - currPwr)*VpdList[idxL])/ + (pwrList[idxR] - pwrList[idxL])); + retVpdList[pdGainIdx][ii] = kk; + ii++; + currPwr += 2; /* half dB steps */ + } + + return AH_TRUE; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static int16_t +interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, + int16_t targetLeft, int16_t targetRight) +{ + int16_t rv; + + if (srcRight != srcLeft) { + rv = ((target - srcLeft)*targetRight + + (srcRight - target)*targetLeft) / (srcRight - srcLeft); + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Uses the data points read from EEPROM to reconstruct the pdadc power table + * Called by ar5413SetPowerTable() + */ +static int +ar5413getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel, + const RAW_DATA_STRUCT_2413 *pRawDataset, + uint16_t pdGainOverlap_t2, + int16_t *pMinCalPower, uint16_t pPdGainBoundaries[], + uint16_t pPdGainValues[], uint16_t pPDADCValues[]) +{ + struct ar5413State *priv = AR5413(ah); +#define VpdTable_L priv->vpdTable_L +#define VpdTable_R priv->vpdTable_R +#define VpdTable_I priv->vpdTable_I + uint32_t ii, jj, kk; + int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */ + uint32_t idxL, idxR; + uint32_t numPdGainsUsed = 0; + /* + * If desired to support -ve power levels in future, just + * change pwr_I_0 to signed 5-bits. + */ + int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on. */ + int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; + /* to accomodate -ve power levels later on */ + uint16_t numVpd = 0; + uint16_t Vpd_step; + int16_t tmpVal ; + uint32_t sizeCurrVpdTable, maxIndex, tgtIndex; + + /* Get upper lower index */ + GetLowerUpperIndex(channel, pRawDataset->pChannels, + pRawDataset->numChannels, &(idxL), &(idxR)); + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain; + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]; + if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) { + Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]; + } + Pmin_t2[numPdGainsUsed] = (int16_t) + (Pmin_t2[numPdGainsUsed] / 2); + Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]) + Pmax_t2[numPdGainsUsed] = + pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]; + Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2); + ar5413FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L + ); + ar5413FillVpdTable( + numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]), + &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R + ); + for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) { + VpdTable_I[numPdGainsUsed][kk] = + interpolate_signed( + channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR], + (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]); + } + /* fill VpdTable_I for this pdGain */ + numPdGainsUsed++; + } + /* if this pdGain is used */ + } + + *pMinCalPower = Pmin_t2[0]; + kk = 0; /* index for the final table */ + for (ii = 0; ii < numPdGainsUsed; ii++) { + if (ii == (numPdGainsUsed - 1)) + pPdGainBoundaries[ii] = Pmax_t2[ii] + + PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB; + else + pPdGainBoundaries[ii] = (uint16_t) + ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 ); + if (pPdGainBoundaries[ii] > 63) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: clamp pPdGainBoundaries[%d] %d\n", + __func__, ii, pPdGainBoundaries[ii]);/*XXX*/ + pPdGainBoundaries[ii] = 63; + } + + /* Find starting index for this pdGain */ + if (ii == 0) + ss = 0; /* for the first pdGain, start from index 0 */ + else + ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) - + pdGainOverlap_t2; + Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + *-ve ss indicates need to extrapolate data below for this pdGain + */ + while (ss < 0) { + tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step); + pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii]; + tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii]; + maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; + + while (ss < (int16_t)maxIndex) + pPDADCValues[kk++] = VpdTable_I[ii][ss++]; + + Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] - + VpdTable_I[ii][sizeCurrVpdTable-2]); + Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); + /* + * for last gain, pdGainBoundary == Pmax_t2, so will + * have to extrapolate + */ + if (tgtIndex > maxIndex) { /* need to extrapolate above */ + while(ss < (int16_t)tgtIndex) { + tmpVal = (uint16_t) + (VpdTable_I[ii][sizeCurrVpdTable-1] + + (ss-maxIndex)*Vpd_step); + pPDADCValues[kk++] = (tmpVal > 127) ? + 127 : tmpVal; + ss++; + } + } /* extrapolated above */ + } /* for all pdGainUsed */ + + while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) { + pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1]; + ii++; + } + while (kk < 128) { + pPDADCValues[kk] = pPDADCValues[kk-1]; + kk++; + } + + return numPdGainsUsed; +#undef VpdTable_L +#undef VpdTable_R +#undef VpdTable_I +} + +static HAL_BOOL +ar5413SetPowerTable(struct ath_hal *ah, + int16_t *minPower, int16_t *maxPower, + const struct ieee80211_channel *chan, + uint16_t *rfXpdGain) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint16_t freq = ath_hal_gethwchannel(ah, chan); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; + uint16_t pdGainOverlap_t2; + int16_t minCalPower5413_t2; + uint16_t *pdadcValues = ahp->ah_pcdacTable; + uint16_t gainBoundaries[4]; + uint32_t reg32, regoffset; + int i, numPdGainsUsed; +#ifndef AH_USE_INIPDGAIN + uint32_t tpcrg1; +#endif + + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", + __func__, chan->ic_freq, chan->ic_flags); + + if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IEEE80211_IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else { + HALASSERT(IEEE80211_IS_CHAN_5GHZ(chan)); + pRawDataset = &ee->ee_rawDataset2413[headerInfo11A]; + } + + pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP); + + numPdGainsUsed = ar5413getGainBoundariesAndPdadcsForPowers(ah, + freq, pRawDataset, pdGainOverlap_t2, + &minCalPower5413_t2,gainBoundaries, rfXpdGain, pdadcValues); + HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); + +#ifdef AH_USE_INIPDGAIN + /* + * Use pd_gains curve from eeprom; Atheros always uses + * the default curve from the ini file but some vendors + * (e.g. Zcomax) want to override this curve and not + * honoring their settings results in tx power 5dBm low. + */ + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (pRawDataset->pDataPerChannel[0].numPdGains - 1)); +#else + tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); + tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) + | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); + switch (numPdGainsUsed) { + case 3: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3; + tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3); + /* fall thru... */ + case 2: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2; + tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2); + /* fall thru... */ + case 1: + tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1; + tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1); + break; + } +#ifdef AH_DEBUG + if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1)) + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default " + "pd_gains (default 0x%x, calculated 0x%x)\n", + __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); +#endif + OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); +#endif + + /* + * Note the pdadc table may not start at 0 dBm power, could be + * negative or greater than 0. Need to offset the power + * values by the amount of minPower for griffin + */ + if (minCalPower5413_t2 != 0) + ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower5413_t2); + else + ahp->ah_txPowerIndexOffset = 0; + + /* Finally, write the power values into the baseband power table */ + regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */ + for (i = 0; i < 32; i++) { + reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0) | + ((pdadcValues[4*i + 1] & 0xFF) << 8) | + ((pdadcValues[4*i + 2] & 0xFF) << 16) | + ((pdadcValues[4*i + 3] & 0xFF) << 24) ; + OS_REG_WRITE(ah, regoffset, reg32); + regoffset += 4; + } + + OS_REG_WRITE(ah, AR_PHY_TPCRG5, + SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + + return AH_TRUE; +} + +static int16_t +ar5413GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) +{ + uint32_t ii,jj; + uint16_t Pmin=0,numVpd; + + for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; + /* work backwards 'cause highest pdGain for lowest power */ + numVpd = data->pDataPerPDGain[jj].numVpd; + if (numVpd > 0) { + Pmin = data->pDataPerPDGain[jj].pwr_t4[0]; + return(Pmin); + } + } + return(Pmin); +} + +static int16_t +ar5413GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) +{ + uint32_t ii; + uint16_t Pmax=0,numVpd; + + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { + /* work forwards cuase lowest pdGain for highest power */ + numVpd = data->pDataPerPDGain[ii].numVpd; + if (numVpd > 0) { + Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1]; + return(Pmax); + } + } + return(Pmax); +} + +static HAL_BOOL +ar5413GetChannelMaxMinPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *maxPow, int16_t *minPow) +{ + uint16_t freq = chan->ic_freq; /* NB: never mapped */ + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; + const RAW_DATA_PER_CHANNEL_2413 *data=AH_NULL; + uint16_t numChannels; + int totalD,totalF, totalMin,last, i; + + *maxPow = 0; + + if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; + else if (IEEE80211_IS_CHAN_B(chan)) + pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; + else { + HALASSERT(IEEE80211_IS_CHAN_5GHZ(chan)); + pRawDataset = &ee->ee_rawDataset2413[headerInfo11A]; + } + + numChannels = pRawDataset->numChannels; + data = pRawDataset->pDataPerChannel; + + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if (numChannels < 1) + return(AH_FALSE); + + if ((freq < data[0].channelValue) || + (freq > data[numChannels-1].channelValue)) { + if (freq < data[0].channelValue) { + *maxPow = ar5413GetMaxPower(ah, &data[0]); + *minPow = ar5413GetMinPower(ah, &data[0]); + return(AH_TRUE); + } else { + *maxPow = ar5413GetMaxPower(ah, &data[numChannels - 1]); + *minPow = ar5413GetMinPower(ah, &data[numChannels - 1]); + return(AH_TRUE); + } + } + + /* Linearly interpolate the power value now */ + for (last=0,i=0; (i data[i].channelValue); + last = i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = ar5413GetMaxPower(ah, &data[i]) - ar5413GetMaxPower(ah, &data[last]); + *maxPow = (int8_t) ((totalF*(freq-data[last].channelValue) + + ar5413GetMaxPower(ah, &data[last])*totalD)/totalD); + totalMin = ar5413GetMinPower(ah, &data[i]) - ar5413GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(freq-data[last].channelValue) + + ar5413GetMinPower(ah, &data[last])*totalD)/totalD); + return(AH_TRUE); + } else { + if (freq == data[i].channelValue) { + *maxPow = ar5413GetMaxPower(ah, &data[i]); + *minPow = ar5413GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar5413RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +static HAL_BOOL +ar5413RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5413State *priv; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar5413State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar5413RfDetach; + priv->base.writeRegs = ar5413WriteRegs; + priv->base.getRfBank = ar5413GetRfBank; + priv->base.setChannel = ar5413SetChannel; + priv->base.setRfRegs = ar5413SetRfRegs; + priv->base.setPowerTable = ar5413SetPowerTable; + priv->base.getChannelMaxMinPower = ar5413GetChannelMaxMinPower; + priv->base.getNfAdjust = ar5212GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + + return AH_TRUE; +} + +static HAL_BOOL +ar5413Probe(struct ath_hal *ah) +{ + return IS_5413(ah); +} +AH_RF(RF5413, ar5413Probe, ar5413RfAttach); diff --git a/sys/external/isc/atheros_hal/dist/ar5312/ar5312.h b/sys/external/isc/atheros_hal/dist/ar5312/ar5312.h new file mode 100644 index 0000000..d729356 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5312/ar5312.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AR5312_H_ +#define _ATH_AR5312_H_ + +#include "ah_soc.h" +#include "ar5212/ar5212.h" + +#define AR5312_UNIT(_ah) \ + (((const struct ar531x_config *)((_ah)->ah_st))->unit) +#define AR5312_BOARDCONFIG(_ah) \ + (((const struct ar531x_config *)((_ah)->ah_st))->board) +#define AR5312_RADIOCONFIG(_ah) \ + (((const struct ar531x_config *)((_ah)->ah_st))->radio) + +#define IS_5312_2_X(ah) \ + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && \ + (AH_PRIVATE(ah)->ah_macRev == 2 || AH_PRIVATE(ah)->ah_macRev == 7)) +#define IS_5315(ah) \ + (AH_PRIVATE(ah)->ah_devid == AR5212_AR2315_REV6 || \ + AH_PRIVATE(ah)->ah_devid == AR5212_AR2315_REV7 || \ + AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV1 || \ + AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV2) + +extern HAL_BOOL ar5312IsInterruptPending(struct ath_hal *ah); + +/* AR5312 */ +extern HAL_BOOL ar5312GpioCfgOutput(struct ath_hal *, uint32_t gpio, + HAL_GPIO_MUX_TYPE); +extern HAL_BOOL ar5312GpioCfgInput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5312GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val); +extern uint32_t ar5312GpioGet(struct ath_hal *ah, uint32_t gpio); +extern void ar5312GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel); + +/* AR2315+ */ +extern HAL_BOOL ar5315GpioCfgOutput(struct ath_hal *, uint32_t gpio, + HAL_GPIO_MUX_TYPE); +extern HAL_BOOL ar5315GpioCfgInput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5315GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val); +extern uint32_t ar5315GpioGet(struct ath_hal *ah, uint32_t gpio); +extern void ar5315GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel); + +extern void ar5312SetLedState(struct ath_hal *ah, HAL_LED_STATE state); +extern HAL_BOOL ar5312DetectCardPresent(struct ath_hal *ah); +extern void ar5312SetupClock(struct ath_hal *ah, HAL_OPMODE opmode); +extern void ar5312RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode); +extern void ar5312DumpState(struct ath_hal *ah); +extern HAL_BOOL ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode, + struct ieee80211_channel *chan, + HAL_BOOL bChannelChange, + HAL_RESET_TYPE resetType, + HAL_STATUS *status); +extern HAL_BOOL ar5312ChipReset(struct ath_hal *ah, + struct ieee80211_channel *chan); +extern HAL_BOOL ar5312SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, + int setChip); +extern HAL_BOOL ar5312PhyDisable(struct ath_hal *ah); +extern HAL_BOOL ar5312Disable(struct ath_hal *ah); +extern HAL_BOOL ar5312MacReset(struct ath_hal *ah, unsigned int RCMask); +extern uint32_t ar5312GetPowerMode(struct ath_hal *ah); +extern HAL_BOOL ar5312GetPowerStatus(struct ath_hal *ah); + +/* BSP functions */ +extern HAL_BOOL ar5312EepromRead(struct ath_hal *, u_int off, uint16_t *data); +extern HAL_BOOL ar5312EepromWrite(struct ath_hal *, u_int off, uint16_t data); + +#endif /* _ATH_AR3212_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5312/ar5312_attach.c b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_attach.c new file mode 100644 index 0000000..5c84eb8 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_attach.c @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5312/ar5312phy.h" + +/* Add static register initialization vectors */ +#define AH_5212_COMMON +#include "ar5212/ar5212.ini" + +static HAL_BOOL ar5312GetMacAddr(struct ath_hal *ah); + +static void +ar5312AniSetup(struct ath_hal *ah) +{ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -41, -41, -48, -48, -48 }, + .coarseHigh = { -18, -18, -16, -14, -12 }, + .coarseLow = { -56, -56, -60, -60, -60 }, + .firpwr = { -72, -72, -75, -78, -80 }, + .maxSpurImmunityLevel = 2, + .cycPwrThr1 = { 2, 4, 6 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE); +} + +/* + * Attach for an AR5312 part. + */ +static struct ath_hal * +ar5312Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH_NULL; + struct ath_hal *ah; + struct ath_hal_rf *rf; + uint32_t val; + uint16_t eeval; + HAL_STATUS ecode; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp = ath_hal_malloc(sizeof (struct ath_hal_5212)); + if (ahp == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ar5212InitState(ahp, devid, sc, st, sh, status); + ah = &ahp->ah_priv.h; + + /* override 5212 methods for our needs */ + ah->ah_reset = ar5312Reset; + ah->ah_phyDisable = ar5312PhyDisable; + ah->ah_setLedState = ar5312SetLedState; + ah->ah_detectCardPresent = ar5312DetectCardPresent; + ah->ah_setPowerMode = ar5312SetPowerMode; + ah->ah_getPowerMode = ar5312GetPowerMode; + ah->ah_isInterruptPending = ar5312IsInterruptPending; + + ahp->ah_priv.ah_eepromRead = ar5312EepromRead; +#ifdef AH_SUPPORT_WRITE_EEPROM + ahp->ah_priv.ah_eepromWrite = ar5312EepromWrite; +#endif +#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317) + if (IS_5315(ah)) { + ahp->ah_priv.ah_gpioCfgOutput = ar5315GpioCfgOutput; + ahp->ah_priv.ah_gpioCfgInput = ar5315GpioCfgInput; + ahp->ah_priv.ah_gpioGet = ar5315GpioGet; + ahp->ah_priv.ah_gpioSet = ar5315GpioSet; + ahp->ah_priv.ah_gpioSetIntr = ar5315GpioSetIntr; + } else +#endif + { + ahp->ah_priv.ah_gpioCfgOutput = ar5312GpioCfgOutput; + ahp->ah_priv.ah_gpioCfgInput = ar5312GpioCfgInput; + ahp->ah_priv.ah_gpioGet = ar5312GpioGet; + ahp->ah_priv.ah_gpioSet = ar5312GpioSet; + ahp->ah_priv.ah_gpioSetIntr = ar5312GpioSetIntr; + } + + ah->ah_gpioCfgInput = ahp->ah_priv.ah_gpioCfgInput; + ah->ah_gpioCfgOutput = ahp->ah_priv.ah_gpioCfgOutput; + ah->ah_gpioGet = ahp->ah_priv.ah_gpioGet; + ah->ah_gpioSet = ahp->ah_priv.ah_gpioSet; + ah->ah_gpioSetIntr = ahp->ah_priv.ah_gpioSetIntr; + + /* setup common ini data; rf backends handle remainder */ + HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2); + + if (!ar5312ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + ecode = HAL_EIO; + goto bad; + } + +#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317) + if ((devid == AR5212_AR2315_REV6) || + (devid == AR5212_AR2315_REV7) || + (devid == AR5212_AR2317_REV1) || + (devid == AR5212_AR2317_REV2) ) { + val = ((OS_REG_READ(ah, (AR5315_RSTIMER_BASE -((uint32_t) sh)) + AR5315_WREV)) >> AR5315_WREV_S) + & AR5315_WREV_ID; + AH_PRIVATE(ah)->ah_macVersion = val >> AR5315_WREV_ID_S; + AH_PRIVATE(ah)->ah_macRev = val & AR5315_WREV_REVISION; + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: Mac Chip Rev 0x%02x.%x\n" , __func__, + AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev); + } else +#endif + { + val = OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + 0x0020); + val = OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + 0x0080); + /* Read Revisions from Chips */ + val = ((OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + AR5312_WREV)) >> AR5312_WREV_S) & AR5312_WREV_ID; + AH_PRIVATE(ah)->ah_macVersion = val >> AR5312_WREV_ID_S; + AH_PRIVATE(ah)->ah_macRev = val & AR5312_WREV_REVISION; + } + /* XXX - THIS IS WRONG. NEEDS TO BE FIXED */ + if (((AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_VENICE && + AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_VENICE) || + AH_PRIVATE(ah)->ah_macRev < AR_SREV_D2PLUS) && + AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_COBRA) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: Mac Chip Rev 0x%02x.%x is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_macVersion, + AH_PRIVATE(ah)->ah_macRev); +#endif + ecode = HAL_ENOTSUPP; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah); + + rf = ath_hal_rfprobe(ah, &ecode); + if (rf == AH_NULL) + goto bad; + if (IS_RAD5112(ah) && !IS_RADX112_REV2(ah)) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: 5112 Rev 1 is not supported by this " + "driver (analog5GhzRev 0x%x)\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); +#endif + ecode = HAL_ENOTSUPP; + goto bad; + } + + ecode = ath_hal_legacyEepromAttach(ah); + if (ecode != HAL_OK) { + goto bad; + } + + /* + * If Bmode and AR5212, verify 2.4 analog exists + */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) && + (AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD5111_SREV_MAJOR) { + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00004007); + OS_DELAY(2000); + AH_PRIVATE(ah)->ah_analog2GhzRev = ar5212GetRadioRev(ah); + + /* Set baseband for 5GHz chip */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + OS_DELAY(2000); + if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != AR_RAD2111_SREV_MAJOR) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: 2G Radio Chip Rev 0x%02X is not " + "supported by this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog2GhzRev); +#endif + ecode = HAL_ENOTSUPP; + goto bad; + } + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read regulatory domain from EEPROM\n", + __func__); + goto bad; + } + AH_PRIVATE(ah)->ah_currentRD = eeval; + /* XXX record serial number */ + + /* XXX other capabilities */ + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar5212FillCapabilityInfo(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: failed ar5212FillCapabilityInfo\n", __func__); + ecode = HAL_EEREAD; + goto bad; + } + + if (!rf->attach(ah, &ecode)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + /* arrange a direct call instead of thunking */ + AH_PRIVATE(ah)->ah_getNfAdjust = ahp->ah_rfHal->getNfAdjust; + + /* Initialize gain ladder thermal calibration structure */ + ar5212InitializeGainValues(ah); + + /* BSP specific call for MAC address of this WMAC device */ + if (!ar5312GetMacAddr(ah)) { + ecode = HAL_EEBADMAC; + goto bad; + } + + ar5312AniSetup(ah); + ar5212InitNfCalHistBuffer(ah); + + /* XXX EAR stuff goes here */ + return ah; + +bad: + if (ahp) + ar5212Detach((struct ath_hal *) ahp); + if (status) + *status = ecode; + return AH_NULL; +} + +static HAL_BOOL +ar5312GetMacAddr(struct ath_hal *ah) +{ + const struct ar531x_boarddata *board = AR5312_BOARDCONFIG(ah); + int wlanNum = AR5312_UNIT(ah); + const uint8_t *macAddr; + + switch (wlanNum) { + case 0: + macAddr = board->wlan0Mac; + break; + case 1: + macAddr = board->wlan1Mac; + break; + default: +#ifdef AH_DEBUG + ath_hal_printf(ah, "Invalid WLAN wmac index (%d)\n", + wlanNum); +#endif + return AH_FALSE; + } + OS_MEMCPY(AH5212(ah)->ah_macaddr, macAddr, 6); + return AH_TRUE; +} + +static const char* +ar5312Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID) { + switch (devid) { + case AR5212_AR5312_REV2: + case AR5212_AR5312_REV7: + return "Atheros 5312 WiSoC"; + case AR5212_AR2313_REV8: + return "Atheros 2313 WiSoC"; + case AR5212_AR2315_REV6: + case AR5212_AR2315_REV7: + return "Atheros 2315 WiSoC"; + case AR5212_AR2317_REV1: + case AR5212_AR2317_REV2: + return "Atheros 2317 WiSoC"; + case AR5212_AR2413: + return "Atheros 2413"; + case AR5212_AR2417: + return "Atheros 2417"; + } + } + return AH_NULL; +} +AH_CHIP(AR5312, ar5312Probe, ar5312Attach); diff --git a/sys/external/isc/atheros_hal/dist/ar5312/ar5312_eeprom.c b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_eeprom.c new file mode 100644 index 0000000..7a84232 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_eeprom.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + + +#ifdef AH_SUPPORT_AR5312 + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5212/ar5212desc.h" + +/* + * Read 16 bits of data from offset into *data + */ +HAL_BOOL +ar5312EepromRead(struct ath_hal *ah, u_int off, uint16_t *dataIn) +{ + int i,offset; + const char *eepromAddr = AR5312_RADIOCONFIG(ah); + uint8_t *data; + + data = (uint8_t *) dataIn; + for (i=0,offset=2*off; i<2; i++,offset++) { + data[i] = eepromAddr[offset]; + } + return AH_TRUE; +} +#endif /* AH_SUPPORT_AR5312 */ diff --git a/sys/external/isc/atheros_hal/dist/ar5312/ar5312_gpio.c b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_gpio.c new file mode 100644 index 0000000..20a575d --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_gpio.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5312 + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5312/ar5312phy.h" + +#define AR_NUM_GPIO 6 /* 6 GPIO pins */ +#define AR5312_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */ + +/* + * Configure GPIO Output lines + */ +HAL_BOOL +ar5312GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) +{ + uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, gpioOffset+AR5312_GPIOCR, + (OS_REG_READ(ah, gpioOffset+AR5312_GPIOCR) &~ AR_GPIOCR_CR_A(gpio)) + | AR_GPIOCR_CR_A(gpio)); + + return AH_TRUE; +} + +/* + * Configure GPIO Input lines + */ +HAL_BOOL +ar5312GpioCfgInput(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, gpioOffset+AR5312_GPIOCR, + (OS_REG_READ(ah, gpioOffset+AR5312_GPIOCR) &~ AR_GPIOCR_CR_A(gpio)) + | AR_GPIOCR_CR_N(gpio)); + + return AH_TRUE; +} + +/* + * Once configured for I/O - set output lines + */ +HAL_BOOL +ar5312GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) +{ + uint32_t reg; + uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, gpioOffset+AR5312_GPIODO); + reg &= ~(1 << gpio); + reg |= (val&1) << gpio; + + OS_REG_WRITE(ah, gpioOffset+AR5312_GPIODO, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - get input lines + */ +uint32_t +ar5312GpioGet(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + if (gpio < AR_NUM_GPIO) { + uint32_t val = OS_REG_READ(ah, gpioOffset+AR5312_GPIODI); + val = ((val & AR5312_GPIOD_MASK) >> gpio) & 0x1; + return val; + } else { + return 0xffffffff; + } +} + +/* + * Set the GPIO Interrupt + */ +void +ar5312GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) +{ + uint32_t val; + uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + /* XXX bounds check gpio */ + val = OS_REG_READ(ah, gpioOffset+AR5312_GPIOCR); + val &= ~(AR_GPIOCR_CR_A(gpio) | + AR_GPIOCR_INT_MASK | AR_GPIOCR_INT_ENA | AR_GPIOCR_INT_SEL); + val |= AR_GPIOCR_CR_N(gpio) | AR_GPIOCR_INT(gpio) | AR_GPIOCR_INT_ENA; + if (ilevel) + val |= AR_GPIOCR_INT_SELH; /* interrupt on pin high */ + else + val |= AR_GPIOCR_INT_SELL; /* interrupt on pin low */ + + /* Don't need to change anything for low level interrupt. */ + OS_REG_WRITE(ah, gpioOffset+AR5312_GPIOCR, val); + + /* Change the interrupt mask. */ + (void) ar5212SetInterrupts(ah, AH5212(ah)->ah_maskReg | HAL_INT_GPIO); +} + + +#endif /* AH_SUPPORT_AR5312 */ diff --git a/sys/external/isc/atheros_hal/dist/ar5312/ar5312_interrupts.c b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_interrupts.c new file mode 100644 index 0000000..0a1545c --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_interrupts.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5312 + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5312/ar5312phy.h" + + +/* + * Checks to see if an interrupt is pending on our NIC + * + * Returns: TRUE if an interrupt is pending + * FALSE if not + */ +HAL_BOOL +ar5312IsInterruptPending(struct ath_hal *ah) +{ + /* + * Some platforms trigger our ISR before applying power to + * the card. For the 5312, this is always true. + */ + + return(AH_TRUE); +} +#endif /* AH_SUPPORT_AR5312 */ diff --git a/sys/external/isc/atheros_hal/dist/ar5312/ar5312_misc.c b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_misc.c new file mode 100644 index 0000000..3d85ece --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_misc.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5312 + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5312/ar5312phy.h" + +#define AR_NUM_GPIO 6 /* 6 GPIO pins */ +#define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */ + +/* + * Change the LED blinking pattern to correspond to the connectivity + */ +void +ar5312SetLedState(struct ath_hal *ah, HAL_LED_STATE state) +{ + uint32_t val; + uint32_t resOffset = (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)); + if(IS_2316(ah)) return; /* not yet */ + val = SM(AR5312_PCICFG_LEDSEL0, AR5312_PCICFG_LEDSEL) | + SM(AR5312_PCICFG_LEDMOD0, AR5312_PCICFG_LEDMODE) | + 2; + OS_REG_WRITE(ah, resOffset+AR5312_PCICFG, + (OS_REG_READ(ah, AR5312_PCICFG) &~ + (AR5312_PCICFG_LEDSEL | AR5312_PCICFG_LEDMODE | + AR5312_PCICFG_LEDSBR)) + | val); +} + +/* + * Detect if our wireless mac is present. + */ +HAL_BOOL +ar5312DetectCardPresent(struct ath_hal *ah) +{ + uint16_t macVersion, macRev; + uint32_t v; + + /* + * Read the Silicon Revision register and compare that + * to what we read at attach time. If the same, we say + * a card/device is present. + */ +#if (AH_SUPPORT_2316 || AH_SUPPORT_2317) + if(IS_5315(ah)) + { + v = (OS_REG_READ(ah, + (AR5315_RSTIMER_BASE-((uint32_t) ah->ah_sh)) + AR5315_WREV)) + & AR_SREV_ID; + macVersion = v >> AR_SREV_ID_S; + macRev = v & AR_SREV_REVISION; + return (AH_PRIVATE(ah)->ah_macVersion == macVersion && + AH_PRIVATE(ah)->ah_macRev == macRev); + } + else +#endif + { + v = (OS_REG_READ(ah, + (AR5312_RSTIMER_BASE-((uint32_t) ah->ah_sh)) + AR5312_WREV)) + & AR_SREV_ID; + macVersion = v >> AR_SREV_ID_S; + macRev = v & AR_SREV_REVISION; + return (AH_PRIVATE(ah)->ah_macVersion == macVersion && + AH_PRIVATE(ah)->ah_macRev == macRev); + } +} + +/* + * If 32KHz clock exists, use it to lower power consumption during sleep + * + * Note: If clock is set to 32 KHz, delays on accessing certain + * baseband registers (27-31, 124-127) are required. + */ +void +ar5312SetupClock(struct ath_hal *ah, HAL_OPMODE opmode) +{ + if (ar5212Use32KHzclock(ah, opmode)) { + /* + * Enable clocks to be turned OFF in BB during sleep + * and also enable turning OFF 32MHz/40MHz Refclk + * from A2. + */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x0d); + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0c); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x03); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x05); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) ? 0x14 : 0x18); + + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1); + OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */ + + } else { + OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, + IS_RAD5112_ANY(ah) ? 39 : 31); + + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); + + if (IS_5312_2_X(ah)) { + /* Set ADC/DAC select values */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04); + } else { + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) ? 0x14 : 0x18); + } + } +} + +/* + * If 32KHz clock exists, turn it off and turn back on the 32Mhz + */ +void +ar5312RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode) +{ + if (ar5212Use32KHzclock(ah, opmode)) { + /* # Set sleep clock rate back to 32 MHz. */ + OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, + IS_RAD5112_ANY(ah) ? 39 : 31); + + /* + * Restore BB registers to power-on defaults + */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); + OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); + if (IS_5312_2_X(ah)) { + /* Set ADC/DAC select values */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04); + } else { + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); + OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); + OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) ? 0x14 : 0x18); + } + } +} + +#endif /* AH_SUPPORT_AR5312 */ diff --git a/sys/external/isc/atheros_hal/dist/ar5312/ar5312_power.c b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_power.c new file mode 100644 index 0000000..7db6d80 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_power.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5312 + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5212/ar5212desc.h" + +/* + * Notify Power Mgt is enabled in self-generated frames. + * If requested, force chip awake. + * + * Returns A_OK if chip is awake or successfully forced awake. + * + * WARNING WARNING WARNING + * There is a problem with the chip where sometimes it will not wake up. + */ +static HAL_BOOL +ar5312SetPowerModeAwake(struct ath_hal *ah, int setChip) +{ + /* No need for this at the moment for APs */ + return AH_TRUE; +} + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, force chip to sleep. + */ +static void +ar5312SetPowerModeSleep(struct ath_hal *ah, int setChip) +{ + /* No need for this at the moment for APs */ +} + +/* + * Notify Power Management is enabled in self-generating + * fames. If request, set power mode of chip to + * auto/normal. Duration in units of 128us (1/8 TU). + */ +static void +ar5312SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) +{ + /* No need for this at the moment for APs */ +} + +/* + * Set power mgt to the requested mode, and conditionally set + * the chip as well + */ +HAL_BOOL +ar5312SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) +{ +#ifdef AH_DEBUG + static const char* modes[] = { + "AWAKE", + "FULL-SLEEP", + "NETWORK SLEEP", + "UNDEFINED" + }; +#endif + int status = AH_TRUE; + + HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, + modes[ah->ah_powerMode], modes[mode], + setChip ? "set chip " : ""); + switch (mode) { + case HAL_PM_AWAKE: + status = ar5312SetPowerModeAwake(ah, setChip); + break; + case HAL_PM_FULL_SLEEP: + ar5312SetPowerModeSleep(ah, setChip); + break; + case HAL_PM_NETWORK_SLEEP: + ar5312SetPowerModeNetworkSleep(ah, setChip); + break; + default: + HALDEBUG(ah, HAL_DEBUG_POWER, "%s: unknown power mode %u\n", + __func__, mode); + return AH_FALSE; + } + ah->ah_powerMode = mode; + return status; +} + +/* + * Return the current sleep mode of the chip + */ +uint32_t +ar5312GetPowerMode(struct ath_hal *ah) +{ + return HAL_PM_AWAKE; +} + +/* + * Return the current sleep state of the chip + * TRUE = sleeping + */ +HAL_BOOL +ar5312GetPowerStatus(struct ath_hal *ah) +{ + return 0; /* Currently, 5312 is never in sleep mode. */ +} +#endif /* AH_SUPPORT_AR5312 */ diff --git a/sys/external/isc/atheros_hal/dist/ar5312/ar5312_reset.c b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_reset.c new file mode 100644 index 0000000..1f1f6cf --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5312/ar5312_reset.c @@ -0,0 +1,888 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5312 + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5312/ar5312phy.h" + +#include "ah_eeprom_v3.h" + +/* Additional Time delay to wait after activiting the Base band */ +#define BASE_ACTIVATE_DELAY 100 /* 100 usec */ +#define PLL_SETTLE_DELAY 300 /* 300 usec */ + +extern int16_t ar5212GetNf(struct ath_hal *, const struct ieee80211_channel *); +extern void ar5212SetRateDurationTable(struct ath_hal *, + const struct ieee80211_channel *); +extern HAL_BOOL ar5212SetTransmitPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain); +extern void ar5212SetDeltaSlope(struct ath_hal *, + const struct ieee80211_channel *); +extern HAL_BOOL ar5212SetBoardValues(struct ath_hal *, + const struct ieee80211_channel *); +extern void ar5212SetIFSTiming(struct ath_hal *, + const struct ieee80211_channel *); +extern HAL_BOOL ar5212IsSpurChannel(struct ath_hal *, + const struct ieee80211_channel *); +extern HAL_BOOL ar5212ChannelChange(struct ath_hal *, + const struct ieee80211_channel *); + +static HAL_BOOL ar5312SetResetReg(struct ath_hal *, uint32_t resetMask); + +static int +write_common(struct ath_hal *ah, const HAL_INI_ARRAY *ia, + HAL_BOOL bChannelChange, int writes) +{ +#define IS_NO_RESET_TIMER_ADDR(x) \ + ( (((x) >= AR_BEACON) && ((x) <= AR_CFP_DUR)) || \ + (((x) >= AR_SLEEP1) && ((x) <= AR_SLEEP3))) +#define V(r, c) (ia)->data[((r)*(ia)->cols) + (c)] + int i; + + /* Write Common Array Parameters */ + for (i = 0; i < ia->rows; i++) { + uint32_t reg = V(i, 0); + /* XXX timer/beacon setup registers? */ + /* On channel change, don't reset the PCU registers */ + if (!(bChannelChange && IS_NO_RESET_TIMER_ADDR(reg))) { + OS_REG_WRITE(ah, reg, V(i, 1)); + DMA_YIELD(writes); + } + } + return writes; +#undef IS_NO_RESET_TIMER_ADDR +#undef V +} + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + * + * bChannelChange is used to preserve DMA/PCU registers across + * a HW Reset during channel change. + */ +HAL_BOOL +ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode, + struct ieee80211_channel *chan, + HAL_BOOL bChannelChange, + HAL_RESET_TYPE resetType, + HAL_STATUS *status) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) +#define FAIL(_code) do { ecode = _code; goto bad; } while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *ichan; + const HAL_EEPROM *ee; + uint32_t saveFrameSeqCount, saveDefAntenna; + uint32_t macStaId1, synthDelay, txFrm2TxDStart; + uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL]; + int16_t cckOfdmPwrDelta = 0; + u_int modesIndex, freqIndex; + HAL_STATUS ecode; + int i, regWrites = 0; + uint32_t testReg; + uint32_t saveLedState = 0; + + HALASSERT(ah->ah_magic == AR5212_MAGIC); + ee = AH_PRIVATE(ah)->ah_eeprom; + + OS_MARK(ah, AH_MARK_RESET, bChannelChange); + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->ic_freq, chan->ic_flags); + FAIL(HAL_EINVAL); + } + switch (opmode) { + case HAL_M_STA: + case HAL_M_IBSS: + case HAL_M_HOSTAP: + case HAL_M_MONITOR: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n", + __func__, opmode); + FAIL(HAL_EINVAL); + break; + } + HALASSERT(ahp->ah_eeversion >= AR_EEPROM_VER3); + + /* Preserve certain DMA hardware registers on a channel change */ + if (bChannelChange) { + /* + * On Venice, the TSF is almost preserved across a reset; + * it requires the doubling writes to the RESET_TSF + * bit in the AR_BEACON register; it also has the quirk + * of the TSF going back in time on the station (station + * latches onto the last beacon's tsf during a reset 50% + * of the times); the latter is not a problem for adhoc + * stations since as long as the TSF is behind, it will + * get resynchronized on receiving the next beacon; the + * TSF going backwards in time could be a problem for the + * sleep operation (supported on infrastructure stations + * only) - the best and most general fix for this situation + * is to resynchronize the various sleep/beacon timers on + * the receipt of the next beacon i.e. when the TSF itself + * gets resynchronized to the AP's TSF - power save is + * needed to be temporarily disabled until that time + * + * Need to save the sequence number to restore it after + * the reset! + */ + saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM); + } else + saveFrameSeqCount = 0; /* NB: silence compiler */ + + /* If the channel change is across the same mode - perform a fast channel change */ + if ((IS_2413(ah) || IS_5413(ah))) { + /* + * Channel change can only be used when: + * -channel change requested - so it's not the initial reset. + * -it's not a change to the current channel - often called when switching modes + * on a channel + * -the modes of the previous and requested channel are the same - some ugly code for XR + */ + if (bChannelChange && + AH_PRIVATE(ah)->ah_curchan != AH_NULL && + (chan->ic_freq != AH_PRIVATE(ah)->ah_curchan->ic_freq) && + ((chan->ic_flags & IEEE80211_CHAN_ALLTURBO) == + (AH_PRIVATE(ah)->ah_curchan->ic_flags & IEEE80211_CHAN_ALLTURBO))) { + if (ar5212ChannelChange(ah, chan)) + /* If ChannelChange completed - skip the rest of reset */ + return AH_TRUE; + } + } + + /* + * Preserve the antenna on a channel change + */ + saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA); + if (saveDefAntenna == 0) /* XXX magic constants */ + saveDefAntenna = 1; + + /* Save hardware flag before chip reset clears the register */ + macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & + (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT); + + /* Save led state from pci config register */ + if (!IS_5315(ah)) + saveLedState = OS_REG_READ(ah, AR5312_PCICFG) & + (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK | + AR_PCICFG_LEDSLOW); + + ar5312RestoreClock(ah, opmode); /* move to refclk operation */ + + /* + * Adjust gain parameters before reset if + * there's an outstanding gain updated. + */ + (void) ar5212GetRfgain(ah); + + if (!ar5312ChipReset(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + FAIL(HAL_EIO); + } + + /* Setup the indices for the next set of register array writes */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + freqIndex = 2; + modesIndex = IEEE80211_IS_CHAN_108G(chan) ? 5 : + IEEE80211_IS_CHAN_G(chan) ? 4 : 3; + } else { + freqIndex = 1; + modesIndex = IEEE80211_IS_CHAN_ST(chan) ? 2 : 1; + } + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + /* Set correct Baseband to analog shift setting to access analog chips. */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0); + regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange, + regWrites); + ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan)) + ar5212SetIFSTiming(ah, chan); + + /* Overwrite INI values for revised chipsets */ + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) { + /* ADC_CTL */ + OS_REG_WRITE(ah, AR_PHY_ADC_CTL, + SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) | + SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) | + AR_PHY_ADC_CTL_OFF_PWDDAC | + AR_PHY_ADC_CTL_OFF_PWDADC); + + /* TX_PWR_ADJ */ + if (chan->channel == 2484) { + cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta - ee->ee_scaledCh14FilterCckDelta); + } else { + cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta); + } + + if (IEEE80211_IS_CHAN_G(chan)) { + OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, + SM((ee->ee_cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) | + SM((cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX)); + } else { + OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0); + } + + /* Add barker RSSI thresh enable as disabled */ + OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK, + AR_PHY_DAG_CTRLCCK_EN_RSSI_THR); + OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK, + AR_PHY_DAG_CTRLCCK_RSSI_THR, 2); + + /* Set the mute mask to the correct default */ + OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F); + } + + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) { + /* Clear reg to alllow RX_CLEAR line debug */ + OS_REG_WRITE(ah, AR_PHY_BLUETOOTH, 0); + } + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) { +#ifdef notyet + /* Enable burst prefetch for the data queues */ + OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... ); + /* Enable double-buffering */ + OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS); +#endif + } + + if (IS_5312_2_X(ah)) { + /* ADC_CTRL */ + OS_REG_WRITE(ah, AR_PHY_SIGMA_DELTA, + SM(2, AR_PHY_SIGMA_DELTA_ADC_SEL) | + SM(4, AR_PHY_SIGMA_DELTA_FILT2) | + SM(0x16, AR_PHY_SIGMA_DELTA_FILT1) | + SM(0, AR_PHY_SIGMA_DELTA_ADC_CLIP)); + + if (IEEE80211_IS_CHAN_2GHZ(chan)) + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, AR_PHY_RXGAIN_TXRX_RF_MAX, 0x0F); + + /* CCK Short parameter adjustment in 11B mode */ + if (IEEE80211_IS_CHAN_B(chan)) + OS_REG_RMW_FIELD(ah, AR_PHY_CCK_RXCTRL4, AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT, 12); + + /* Set ADC/DAC select values */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04); + + /* Increase 11A AGC Settling */ + if (IEEE80211_IS_CHAN_A(chan)) + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_AGC, 32); + } else { + /* Set ADC/DAC select values */ + OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); + } + + /* Setup the transmit power values. */ + if (!ar5212SetTransmitPower(ah, chan, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + FAIL(HAL_EIO); + } + + /* Write the analog registers */ + if (!ahp->ah_rfHal->setRfRegs(ah, chan, modesIndex, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n", + __func__); + FAIL(HAL_EIO); + } + + /* Write delta slope for OFDM enabled modes (A, G, Turbo) */ + if (IEEE80211_IS_CHAN_OFDM(chan)) { + if (IS_5413(ah) || + AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3) + ar5212SetSpurMitigation(ah, chan); + ar5212SetDeltaSlope(ah, chan); + } + + /* Setup board specific options for EEPROM version 3 */ + if (!ar5212SetBoardValues(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error setting board options\n", __func__); + FAIL(HAL_EIO); + } + + /* Restore certain DMA hardware registers on a channel change */ + if (bChannelChange) + OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); + OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4) + | macStaId1 + | AR_STA_ID1_RTS_USE_DEF + | ahp->ah_staId1Defaults + ); + ar5212SetOperatingMode(ah, opmode); + + /* Set Venice BSSID mask according to current state */ + OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); + OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); + + /* Restore previous led state */ + if (!IS_5315(ah)) + OS_REG_WRITE(ah, AR5312_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState); + + /* Restore previous antenna */ + OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); + + /* then our BSSID */ + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4)); + + /* Restore bmiss rssi & count thresholds */ + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + + OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */ + + if (!ar5212SetChannel(ah, chan)) + FAIL(HAL_EIO); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1); + + ar5212SetRateDurationTable(ah, chan); + + /* Set Tx frame start to tx data start delay */ + if (IS_RAD5112_ANY(ah) && + (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))) { + txFrm2TxDStart = + IEEE80211_IS_CHAN_HALF(chan) ? + TX_FRAME_D_START_HALF_RATE: + TX_FRAME_D_START_QUARTER_RATE; + OS_REG_RMW_FIELD(ah, AR_PHY_TX_CTL, + AR_PHY_TX_FRAME_TO_TX_DATA_START, txFrm2TxDStart); + } + + /* + * Setup fast diversity. + * Fast diversity can be enabled or disabled via regadd.txt. + * Default is enabled. + * For reference, + * Disable: reg val + * 0x00009860 0x00009d18 (if 11a / 11g, else no change) + * 0x00009970 0x192bb514 + * 0x0000a208 0xd03e4648 + * + * Enable: 0x00009860 0x00009d10 (if 11a / 11g, else no change) + * 0x00009970 0x192fb514 + * 0x0000a208 0xd03e6788 + */ + + /* XXX Setup pre PHY ENABLE EAR additions */ + + /* flush SCAL reg */ + if (IS_5312_2_X(ah)) { + (void) OS_REG_READ(ah, AR_PHY_SLEEP_SCAL); + } + + /* + * Wait for the frequency synth to settle (synth goes on + * via AR_PHY_ACTIVE_EN). Read the phy active delay register. + * Value is in 100ns increments. + */ + synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IEEE80211_IS_CHAN_B(chan)) { + synthDelay = (4 * synthDelay) / 22; + } else { + synthDelay /= 10; + } + + /* Activate the PHY (includes baseband activate and synthesizer on) */ + OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + + /* + * There is an issue if the AP starts the calibration before + * the base band timeout completes. This could result in the + * rx_clear false triggering. As a workaround we add delay an + * extra BASE_ACTIVATE_DELAY usecs to ensure this condition + * does not happen. + */ + if (IEEE80211_IS_CHAN_HALF(chan)) { + OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY); + } else if (IEEE80211_IS_CHAN_QUARTER(chan)) { + OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY); + } else { + OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY); + } + + /* + * The udelay method is not reliable with notebooks. + * Need to check to see if the baseband is ready + */ + testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL); + /* Selects the Tx hold */ + OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD); + i = 0; + while ((i++ < 20) && + (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */ OS_DELAY(200); + OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg); + + /* Calibrate the AGC and start a NF calculation */ + OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, + OS_REG_READ(ah, AR_PHY_AGC_CONTROL) + | AR_PHY_AGC_CONTROL_CAL + | AR_PHY_AGC_CONTROL_NF); + + if (!IEEE80211_IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) { + /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */ + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, + INIT_IQCAL_LOG_COUNT_MAX); + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_DO_IQCAL); + ahp->ah_bIQCalibration = IQ_CAL_RUNNING; + } else + ahp->ah_bIQCalibration = IQ_CAL_INACTIVE; + + /* Setup compression registers */ + ar5212SetCompRegs(ah); + + /* Set 1:1 QCU to DCU mapping for all queues */ + for (i = 0; i < AR_NUM_DCU; i++) + OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); + + ahp->ah_intrTxqs = 0; + for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++) + ar5212ResetTxQueue(ah, i); + + /* + * Setup interrupt handling. Note that ar5212ResetTxQueue + * manipulates the secondary IMR's as queues are enabled + * and disabled. This is done with RMW ops to insure the + * settings we make here are preserved. + */ + ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN + | AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN + | AR_IMR_HIUERR + ; + if (opmode == HAL_M_HOSTAP) + ahp->ah_maskReg |= AR_IMR_MIB; + OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg); + /* Enable bus errors that are OR'd to set the HIUERR bit */ + OS_REG_WRITE(ah, AR_IMR_S2, + OS_REG_READ(ah, AR_IMR_S2) + | AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR); + + if (AH_PRIVATE(ah)->ah_rfkillEnabled) + ar5212EnableRfKill(ah); + + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: offset calibration failed to complete in 1ms;" + " noisy environment?\n", __func__); + } + + /* + * Set clocks back to 32kHz if they had been using refClk, then + * use an external 32kHz crystal when sleeping, if one exists. + */ + ar5312SetupClock(ah, opmode); + + /* + * Writing to AR_BEACON will start timers. Hence it should + * be the last register to be written. Do not reset tsf, do + * not enable beacons at this point, but preserve other values + * like beaconInterval. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF))); + + /* XXX Setup post reset EAR additions */ + + /* QoS support */ + if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE || + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && + AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) { + OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa); /* XXX magic */ + OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210); /* XXX magic */ + } + + /* Turn on NOACK Support for QoS packets */ + OS_REG_WRITE(ah, AR_NOACK, + SM(2, AR_NOACK_2BIT_VALUE) | + SM(5, AR_NOACK_BIT_OFFSET) | + SM(0, AR_NOACK_BYTE_OFFSET)); + + /* Restore user-specified settings */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + if (ahp->ah_slottime != (u_int) -1) + ar5212SetSlotTime(ah, ahp->ah_slottime); + if (ahp->ah_acktimeout != (u_int) -1) + ar5212SetAckTimeout(ah, ahp->ah_acktimeout); + if (ahp->ah_ctstimeout != (u_int) -1) + ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout); + if (ahp->ah_sifstime != (u_int) -1) + ar5212SetSifsTime(ah, ahp->ah_sifstime); + if (AH_PRIVATE(ah)->ah_diagreg != 0) + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); + + AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ + + if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan)) + chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT; + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); + + OS_MARK(ah, AH_MARK_RESET_DONE, 0); + + return AH_TRUE; +bad: + OS_MARK(ah, AH_MARK_RESET_DONE, ecode); + if (status != AH_NULL) + *status = ecode; + return AH_FALSE; +#undef FAIL +#undef N +} + +/* + * Places the PHY and Radio chips into reset. A full reset + * must be called to leave this state. The PCI/MAC/PCU are + * not placed into reset as we must receive interrupt to + * re-enable the hardware. + */ +HAL_BOOL +ar5312PhyDisable(struct ath_hal *ah) +{ + return ar5312SetResetReg(ah, AR_RC_BB); +} + +/* + * Places all of hardware into reset + */ +HAL_BOOL +ar5312Disable(struct ath_hal *ah) +{ + if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + /* + * Reset the HW - PCI must be reset after the rest of the + * device has been reset. + */ + return ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB); +} + +/* + * Places the hardware into reset and then pulls it out of reset + * + * TODO: Only write the PLL if we're changing to or from CCK mode + * + * WARNING: The order of the PLL and mode registers must be correct. + */ +HAL_BOOL +ar5312ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + + OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0); + + /* + * Reset the HW + */ + if (!ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n", + __func__); + return AH_FALSE; + } + + /* Bring out of sleep mode (AGAIN) */ + if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetPowerMode failed\n", + __func__); + return AH_FALSE; + } + + /* Clear warm reset register */ + if (!ar5312SetResetReg(ah, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n", + __func__); + return AH_FALSE; + } + + /* + * Perform warm reset before the mode/PLL/turbo registers + * are changed in order to deactivate the radio. Mode changes + * with an active radio can result in corrupted shifts to the + * radio device. + */ + + /* + * Set CCK and Turbo modes correctly. + */ + if (chan != AH_NULL) { /* NB: can be null during attach */ + uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo; + + if (IS_RAD5112_ANY(ah)) { + rfMode = AR_PHY_MODE_AR5112; + if (!IS_5315(ah)) { + if (IEEE80211_IS_CHAN_CCK(chan)) { + phyPLL = AR_PHY_PLL_CTL_44_5312; + } else { + if (IEEE80211_IS_CHAN_HALF(chan)) { + phyPLL = AR_PHY_PLL_CTL_40_5312_HALF; + } else if (IEEE80211_IS_CHAN_QUARTER(chan)) { + phyPLL = AR_PHY_PLL_CTL_40_5312_QUARTER; + } else { + phyPLL = AR_PHY_PLL_CTL_40_5312; + } + } + } else { + if (IEEE80211_IS_CHAN_CCK(chan)) + phyPLL = AR_PHY_PLL_CTL_44_5112; + else + phyPLL = AR_PHY_PLL_CTL_40_5112; + if (IEEE80211_IS_CHAN_HALF(chan)) + phyPLL |= AR_PHY_PLL_CTL_HALF; + else if (IEEE80211_IS_CHAN_QUARTER(chan)) + phyPLL |= AR_PHY_PLL_CTL_QUARTER; + } + } else { + rfMode = AR_PHY_MODE_AR5111; + if (IEEE80211_IS_CHAN_CCK(chan)) + phyPLL = AR_PHY_PLL_CTL_44; + else + phyPLL = AR_PHY_PLL_CTL_40; + if (IEEE80211_IS_CHAN_HALF(chan)) + phyPLL = AR_PHY_PLL_CTL_HALF; + else if (IEEE80211_IS_CHAN_QUARTER(chan)) + phyPLL = AR_PHY_PLL_CTL_QUARTER; + } + if (IEEE80211_IS_CHAN_G(chan)) + rfMode |= AR_PHY_MODE_DYNAMIC; + else if (IEEE80211_IS_CHAN_OFDM(chan)) + rfMode |= AR_PHY_MODE_OFDM; + else + rfMode |= AR_PHY_MODE_CCK; + if (IEEE80211_IS_CHAN_5GHZ(chan)) + rfMode |= AR_PHY_MODE_RF5GHZ; + else + rfMode |= AR_PHY_MODE_RF2GHZ; + turbo = IEEE80211_IS_CHAN_TURBO(chan) ? + (AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0; + curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL); + /* + * PLL, Mode, and Turbo values must be written in the correct + * order to ensure: + * - The PLL cannot be set to 44 unless the CCK or DYNAMIC + * mode bit is set + * - Turbo cannot be set at the same time as CCK or DYNAMIC + */ + if (IEEE80211_IS_CHAN_CCK(chan)) { + OS_REG_WRITE(ah, AR_PHY_TURBO, turbo); + OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); + if (curPhyPLL != phyPLL) { + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, phyPLL); + /* Wait for the PLL to settle */ + OS_DELAY(PLL_SETTLE_DELAY); + } + } else { + if (curPhyPLL != phyPLL) { + OS_REG_WRITE(ah, AR_PHY_PLL_CTL, phyPLL); + /* Wait for the PLL to settle */ + OS_DELAY(PLL_SETTLE_DELAY); + } + OS_REG_WRITE(ah, AR_PHY_TURBO, turbo); + OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); + } + } + return AH_TRUE; +} + +/* + * Write the given reset bit mask into the reset register + */ +static HAL_BOOL +ar5312SetResetReg(struct ath_hal *ah, uint32_t resetMask) +{ + uint32_t mask = resetMask ? resetMask : ~0; + HAL_BOOL rt; + + if ((rt = ar5312MacReset(ah, mask)) == AH_FALSE) { + return rt; + } + if ((resetMask & AR_RC_MAC) == 0) { + if (isBigEndian()) { + /* + * Set CFG, little-endian for descriptor accesses. + */ +#ifdef AH_NEED_DESC_SWAP + mask = INIT_CONFIG_STATUS | AR_CFG_SWRD; +#else + mask = INIT_CONFIG_STATUS | + AR_CFG_SWTD | AR_CFG_SWRD; +#endif + OS_REG_WRITE(ah, AR_CFG, mask); + } else + OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS); + } + return rt; +} + +/* + * ar5312MacReset resets (and then un-resets) the specified + * wireless components. + * Note: The RCMask cannot be zero on entering from ar5312SetResetReg. + */ + +HAL_BOOL +ar5312MacReset(struct ath_hal *ah, unsigned int RCMask) +{ + int wlanNum = AR5312_UNIT(ah); + uint32_t resetBB, resetBits, regMask; + uint32_t reg; + + if (RCMask == 0) + return(AH_FALSE); +#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317 ) + if (IS_5315(ah)) { + switch(wlanNum) { + case 0: + resetBB = AR5315_RC_BB0_CRES | AR5315_RC_WBB0_RES; + /* Warm and cold reset bits for wbb */ + resetBits = AR5315_RC_WMAC0_RES; + break; + case 1: + resetBB = AR5315_RC_BB1_CRES | AR5315_RC_WBB1_RES; + /* Warm and cold reset bits for wbb */ + resetBits = AR5315_RC_WMAC1_RES; + break; + default: + return(AH_FALSE); + } + regMask = ~(resetBB | resetBits); + + /* read before */ + reg = OS_REG_READ(ah, + (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5315_RESET)); + + if (RCMask == AR_RC_BB) { + /* Put baseband in reset */ + reg |= resetBB; /* Cold and warm reset the baseband bits */ + } else { + /* + * Reset the MAC and baseband. This is a bit different than + * the PCI version, but holding in reset causes problems. + */ + reg &= regMask; + reg |= (resetBits | resetBB) ; + } + OS_REG_WRITE(ah, + (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET), + reg); + /* read after */ + OS_REG_READ(ah, + (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5315_RESET)); + OS_DELAY(100); + + /* Bring MAC and baseband out of reset */ + reg &= regMask; + /* read before */ + OS_REG_READ(ah, + (AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET)); + OS_REG_WRITE(ah, + (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET), + reg); + /* read after */ + OS_REG_READ(ah, + (AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET)); + + + } + else +#endif + { + + switch(wlanNum) { + case 0: + resetBB = AR5312_RC_BB0_CRES | AR5312_RC_WBB0_RES; + /* Warm and cold reset bits for wbb */ + resetBits = AR5312_RC_WMAC0_RES; + break; + case 1: + resetBB = AR5312_RC_BB1_CRES | AR5312_RC_WBB1_RES; + /* Warm and cold reset bits for wbb */ + resetBits = AR5312_RC_WMAC1_RES; + break; + default: + return(AH_FALSE); + } + regMask = ~(resetBB | resetBits); + + /* read before */ + reg = OS_REG_READ(ah, + (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5312_RESET)); + + if (RCMask == AR_RC_BB) { + /* Put baseband in reset */ + reg |= resetBB; /* Cold and warm reset the baseband bits */ + } else { + /* + * Reset the MAC and baseband. This is a bit different than + * the PCI version, but holding in reset causes problems. + */ + reg &= regMask; + reg |= (resetBits | resetBB) ; + } + OS_REG_WRITE(ah, + (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET), + reg); + /* read after */ + OS_REG_READ(ah, + (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5312_RESET)); + OS_DELAY(100); + + /* Bring MAC and baseband out of reset */ + reg &= regMask; + /* read before */ + OS_REG_READ(ah, + (AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET)); + OS_REG_WRITE(ah, + (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET), + reg); + /* read after */ + OS_REG_READ(ah, + (AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET)); + } + return(AH_TRUE); +} + +#endif /* AH_SUPPORT_AR5312 */ diff --git a/sys/external/isc/atheros_hal/dist/ar5312/ar5312phy.h b/sys/external/isc/atheros_hal/dist/ar5312/ar5312phy.h new file mode 100644 index 0000000..fcb8564 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5312/ar5312phy.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _DEV_ATH_AR5312PHY_H_ +#define _DEV_ATH_AR5312PHY_H_ + +#include "ar5212/ar5212phy.h" + +/* PHY registers */ + +#define AR_PHY_PLL_CTL_44_5312 0x14d6 /* 44 MHz for 11b, 11g */ +#define AR_PHY_PLL_CTL_40_5312 0x14d4 /* 40 MHz for 11a, turbos */ +#define AR_PHY_PLL_CTL_40_5312_HALF 0x15d4 /* 40 MHz for 11a, turbos (Half)*/ +#define AR_PHY_PLL_CTL_40_5312_QUARTER 0x16d4 /* 40 MHz for 11a, turbos (Quarter)*/ + +#endif /* _DEV_ATH_AR5312PHY_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5312/ar5312reg.h b/sys/external/isc/atheros_hal/dist/ar5312/ar5312reg.h new file mode 100644 index 0000000..bdfeffa --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5312/ar5312reg.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _DEV_ATH_AR5312REG_H_ +#define _DEV_ATH_AR5312REG_H_ + +#include "ar5212/ar5212reg.h" +/* + * Definitions for the Atheros 5312 chipset. + */ + +/* Register base addresses for modules which are not wmac modules */ +/* 531X has a fixed memory map */ + + +#define REG_WRITE(_reg,_val) *((volatile uint32_t *)(_reg)) = (_val); +#define REG_READ(_reg) *((volatile uint32_t *)(_reg)) +/* + * PCI-MAC Configuration registers (AR2315+) + */ +#define AR5315_RSTIMER_BASE 0xb1000000 /* Address for reset/timer registers */ +#define AR5315_GPIO_BASE 0xb1000000 /* Address for GPIO registers */ +#define AR5315_WLAN0 0xb0000000 + +#define AR5315_RESET 0x0004 /* Offset of reset control register */ +#define AR5315_SREV 0x0014 /* Offset of reset control register */ +#define AR5315_ENDIAN_CTL 0x000c /* offset of the endian control register */ +#define AR5315_CONFIG_WLAN 0x00000002 /* WLAN byteswap */ + +#define AR5315_REV_MAJ 0x00f0 +#define AR5315_REV_MIN 0x000f + +#define AR5315_GPIODIR 0x0098 /* GPIO direction register */ +#define AR5315_GPIODO 0x0090 /* GPIO data output access reg */ +#define AR5315_GPIODI 0x0088 /* GPIO data input access reg*/ +#define AR5315_GPIOINT 0x00a0 /* GPIO interrupt control */ + +#define AR5315_GPIODIR_M(x) (1 << (x)) /* mask for i/o */ +#define AR5315_GPIODIR_O(x) (1 << (x)) /* output */ +#define AR5315_GPIODIR_I(x) 0 /* input */ + +#define AR5315_GPIOINT_S 0 +#define AR5315_GPIOINT_M 0x3F +#define AR5315_GPIOINTLVL_S 6 +#define AR5315_GPIOINTLVL_M (3 << AR5315_GPIOINTLVL_S) + +#define AR5315_WREV (-0xefbfe0) /* Revision ID register offset */ +#define AR5315_WREV_S 0 /* Shift for WMAC revision info */ +#define AR5315_WREV_ID 0x000000FF /* Mask for WMAC revision info */ +#define AR5315_WREV_ID_S 4 /* Shift for WMAC Rev ID */ +#define AR5315_WREV_REVISION 0x0000000F /* Mask for WMAN Revsion version */ + +#define AR5315_RC_BB0_CRES 0x00000002 /* Cold reset to WMAC0 & WBB0 */ +#define AR5315_RC_BB1_CRES 0x00000200 /* Cold reset to WMAC1 & WBB1n */ +#define AR5315_RC_WMAC0_RES 0x00000001 /* Warm reset to WMAC 0 */ +#define AR5315_RC_WBB0_RES 0x00000002 /* Warm reset to WBB0 */ +#define AR5315_RC_WMAC1_RES 0x00020000 /* Warm reset to WMAC1 */ +#define AR5315_RC_WBB1_RES 0x00040000 /* Warm reset to WBB */ + +/* + * PCI-MAC Configuration registers (AR5312) + */ +#define AR5312_RSTIMER_BASE 0xbc003000 /* Address for reset/timer registers */ +#define AR5312_GPIO_BASE 0xbc002000 /* Address for GPIO registers */ +#define AR5312_WLAN0 0xb8000000 +#define AR5312_WLAN1 0xb8500000 + +#define AR5312_RESET 0x0020 /* Offset of reset control register */ +#define AR5312_PCICFG 0x00B0 /* MAC/PCI configuration reg (LEDs) */ + +#define AR5312_PCICFG_LEDMODE 0x0000001c /* LED Mode mask */ +#define AR5312_PCICFG_LEDMODE_S 2 /* LED Mode shift */ +#define AR5312_PCICFG_LEDMOD0 0 /* Blnk prop to Tx and filtered Rx */ +#define AR5312_PCICFG_LEDMOD1 1 /* Blnk prop to all Tx and Rx */ +#define AR5312_PCICFG_LEDMOD2 2 /* DEBG flash */ +#define AR5312_PCICFG_LEDMOD3 3 /* BLNK Randomly */ + +#define AR5312_PCICFG_LEDSEL 0x000000e0 /* LED Throughput select */ +#define AR5312_PCICFG_LEDSEL_S 5 +#define AR5312_PCICFG_LEDSEL0 0 /* See blink rate table on p. 143 */ +#define AR5312_PCICFG_LEDSEL1 1 /* of AR5212 data sheet */ +#define AR5312_PCICFG_LEDSEL2 2 +#define AR5312_PCICFG_LEDSEL3 3 +#define AR5312_PCICFG_LEDSEL4 4 +#define AR5312_PCICFG_LEDSEL5 5 +#define AR5312_PCICFG_LEDSEL6 6 +#define AR5312_PCICFG_LEDSEL7 7 + +#define AR5312_PCICFG_LEDSBR 0x00000100 /* Slow blink rate if no + activity. 0 = blink @ lowest + rate */ + +#undef AR_GPIOCR +#undef AR_GPIODO /* Undefine the 5212 defs */ +#undef AR_GPIODI + +#define AR5312_GPIOCR 0x0008 /* GPIO Control register */ +#define AR5312_GPIODO 0x0000 /* GPIO data output access reg */ +#define AR5312_GPIODI 0x0004 /* GPIO data input access reg*/ +/* NB: AR5312 uses AR5212 defines for GPIOCR definitions */ + +#define AR5312_WREV 0x0090 /* Revision ID register offset */ +#define AR5312_WREV_S 8 /* Shift for WMAC revision info */ +#define AR5312_WREV_ID 0x000000FF /* Mask for WMAC revision info */ +#define AR5312_WREV_ID_S 4 /* Shift for WMAC Rev ID */ +#define AR5312_WREV_REVISION 0x0000000F /* Mask for WMAN Revsion version */ + +#define AR5312_RC_BB0_CRES 0x00000004 /* Cold reset to WMAC0 & WBB0 */ +#define AR5312_RC_BB1_CRES 0x00000200 /* Cold reset to WMAC1 & WBB1n */ +#define AR5312_RC_WMAC0_RES 0x00002000 /* Warm reset to WMAC 0 */ +#define AR5312_RC_WBB0_RES 0x00004000 /* Warm reset to WBB0 */ +#define AR5312_RC_WMAC1_RES 0x00020000 /* Warm reset to WMAC1 */ +#define AR5312_RC_WBB1_RES 0x00040000 /* Warm reset to WBB */ + + +#define AR_RAD2112_SREV_MAJOR 0x40 /* 2112 Major Rev */ + +enum AR5312PowerMode { + AR5312_POWER_MODE_FORCE_SLEEP = 0, + AR5312_POWER_MODE_FORCE_WAKE = 1, + AR5312_POWER_MODE_NORMAL = 2, +}; + +#endif /* _DEV_AR5312REG_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5312/ar5315_gpio.c b/sys/external/isc/atheros_hal/dist/ar5312/ar5315_gpio.c new file mode 100644 index 0000000..4c04c86 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5312/ar5315_gpio.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#if (AH_SUPPORT_2316 || AH_SUPPORT_2317) + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5312/ar5312.h" +#include "ar5312/ar5312reg.h" +#include "ar5312/ar5312phy.h" + +#define AR_NUM_GPIO 7 /* 6 GPIO pins */ +#define AR5315_GPIOD_MASK 0x0000007F /* GPIO data reg r/w mask */ + +/* + * Configure GPIO Output lines + */ +HAL_BOOL +ar5315GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) +{ + uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, gpioOffset+AR5315_GPIODIR, + (OS_REG_READ(ah, gpioOffset+AR5315_GPIODIR) &~ AR5315_GPIODIR_M(gpio)) + | AR5315_GPIODIR_O(gpio)); + + return AH_TRUE; +} + +/* + * Configure GPIO Input lines + */ +HAL_BOOL +ar5315GpioCfgInput(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + HALASSERT(gpio < AR_NUM_GPIO); + + OS_REG_WRITE(ah, gpioOffset+AR5315_GPIODIR, + (OS_REG_READ(ah, gpioOffset+AR5315_GPIODIR) &~ AR5315_GPIODIR_M(gpio)) + | AR5315_GPIODIR_I(gpio)); + + return AH_TRUE; +} + +/* + * Once configured for I/O - set output lines + */ +HAL_BOOL +ar5315GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) +{ + uint32_t reg; + uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + HALASSERT(gpio < AR_NUM_GPIO); + + reg = OS_REG_READ(ah, gpioOffset+AR5315_GPIODO); + reg &= ~(1 << gpio); + reg |= (val&1) << gpio; + + OS_REG_WRITE(ah, gpioOffset+AR5315_GPIODO, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - get input lines + */ +uint32_t +ar5315GpioGet(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + if (gpio < AR_NUM_GPIO) { + uint32_t val = OS_REG_READ(ah, gpioOffset+AR5315_GPIODI); + val = ((val & AR5315_GPIOD_MASK) >> gpio) & 0x1; + return val; + } else { + return 0xffffffff; + } +} + +/* + * Set the GPIO Interrupt + */ +void +ar5315GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) +{ + uint32_t val; + uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh)); + + /* XXX bounds check gpio */ + val = OS_REG_READ(ah, gpioOffset+AR5315_GPIOINT); + val &= ~(AR5315_GPIOINT_M | AR5315_GPIOINTLVL_M); + val |= gpio << AR5315_GPIOINT_S; + if (ilevel) + val |= 2 << AR5315_GPIOINTLVL_S; /* interrupt on pin high */ + else + val |= 1 << AR5315_GPIOINTLVL_S; /* interrupt on pin low */ + + /* Don't need to change anything for low level interrupt. */ + OS_REG_WRITE(ah, gpioOffset+AR5315_GPIOINT, val); + + /* Change the interrupt mask. */ + (void) ar5212SetInterrupts(ah, AH5212(ah)->ah_maskReg | HAL_INT_GPIO); +} + + +#endif /* AH_SUPPORT_2316 || AH_SUPPORT_2317 */ diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar2133.c b/sys/external/isc/atheros_hal/dist/ar5416/ar2133.c new file mode 100644 index 0000000..457a7c3 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar2133.c @@ -0,0 +1,587 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v14.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar2133State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[1]; + + uint32_t *Bank0Data; + uint32_t *Bank1Data; + uint32_t *Bank2Data; + uint32_t *Bank3Data; + uint32_t *Bank6Data; + uint32_t *Bank7Data; + + /* NB: Bank*Data storage follows */ +}; +#define AR2133(ah) ((struct ar2133State *) AH5212(ah)->ah_rfHal) + +#define ar5416ModifyRfBuffer ar5212ModifyRfBuffer /*XXX*/ + +void ar5416ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); + +static void +ar2133WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + (void) ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_bb_rfgain, + freqIndex, writes); +} + +/* + * Fix on 2.4 GHz band for orientation sensitivity issue by increasing + * rf_pwd_icsyndiv. + * + * Theoretical Rules: + * if 2 GHz band + * if forceBiasAuto + * if synth_freq < 2412 + * bias = 0 + * else if 2412 <= synth_freq <= 2422 + * bias = 1 + * else // synth_freq > 2422 + * bias = 2 + * else if forceBias > 0 + * bias = forceBias & 7 + * else + * no change, use value from ini file + * else + * no change, invalid band + * + * 1st Mod: + * 2422 also uses value of 2 + * + * + * 2nd Mod: + * Less than 2412 uses value of 0, 2412 and above uses value of 2 + */ +static void +ar2133ForceBias(struct ath_hal *ah, uint16_t synth_freq) +{ + uint32_t tmp_reg; + int reg_writes = 0; + uint32_t new_bias = 0; + struct ar2133State *priv = AR2133(ah); + + /* XXX this is a bit of a silly check for 2.4ghz channels -adrian */ + if (synth_freq >= 3000) + return; + + if (synth_freq < 2412) + new_bias = 0; + else if (synth_freq < 2422) + new_bias = 1; + else + new_bias = 2; + + /* pre-reverse this field */ + tmp_reg = ath_hal_reverseBits(new_bias, 3); + + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Force rf_pwd_icsyndiv to %1d on %4d\n", + __func__, new_bias, synth_freq); + + /* swizzle rf_pwd_icsyndiv */ + ar5416ModifyRfBuffer(priv->Bank6Data, tmp_reg, 3, 181, 3); + + /* write Bank 6 with new params */ + ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank6, priv->Bank6Data, reg_writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + */ +static HAL_BOOL +ar2133SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t channelSel = 0; + uint32_t bModeSynth = 0; + uint32_t aModeRefSel = 0; + uint32_t reg32 = 0; + uint16_t freq; + CHAN_CENTERS centers; + + OS_MARK(ah, AH_MARK_SETCHANNEL, chan->ic_freq); + + ar5416GetChannelCenters(ah, chan, ¢ers); + freq = centers.synth_center; + + if (freq < 4800) { + uint32_t txctl; + + if (((freq - 2192) % 5) == 0) { + channelSel = ((freq - 672) * 2 - 3040)/10; + bModeSynth = 0; + } else if (((freq - 2224) % 5) == 0) { + channelSel = ((freq - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u MHz\n", __func__, freq); + return AH_FALSE; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath_hal_reverseBits(channelSel, 8); + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + /* + * Handle programming the RF synth for odd frequencies in the + * 4.9->5GHz range. This matches the programming from the + * later model 802.11abg RF synths. + * + * This interoperates on the quarter rate channels with the + * AR5112 and later RF synths. Please note that the synthesiser + * isn't able to completely accurately represent these frequencies + * (as the resolution in this reference is 2.5MHz) and thus it will + * be slightly "off centre." This matches the same slightly + * incorrect * centre frequency behaviour that the AR5112 and later + * channel selection code has. + * + * This is disabled because it hasn't been tested for regulatory + * compliance and neither have the NICs which would use it. + * So if you enable this code, you must first ensure that you've + * re-certified the NICs in question beforehand or you will be + * violating your local regulatory rules and breaking the law. + */ +#if 0 + } else if (((freq % 5) == 2) && (freq <= 5435)) { + freq = freq - 2; + channelSel = ath_hal_reverseBits( + (uint32_t) (((freq - 4800) * 10) / 25 + 1), 8); + /* XXX what about for Howl/Sowl? */ + aModeRefSel = ath_hal_reverseBits(0, 2); +#endif + } else if ((freq % 20) == 0 && freq >= 5120) { + channelSel = ath_hal_reverseBits(((freq - 4800) / 20 << 2), 8); + if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah)) + aModeRefSel = ath_hal_reverseBits(3, 2); + else + aModeRefSel = ath_hal_reverseBits(1, 2); + } else if ((freq % 10) == 0) { + channelSel = ath_hal_reverseBits(((freq - 4800) / 10 << 1), 8); + if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah)) + aModeRefSel = ath_hal_reverseBits(2, 2); + else + aModeRefSel = ath_hal_reverseBits(1, 2); + } else if ((freq % 5) == 0) { + channelSel = ath_hal_reverseBits((freq - 4800) / 5, 8); + aModeRefSel = ath_hal_reverseBits(1, 2); + } else { + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, + "%s: invalid channel %u MHz\n", + __func__, freq); + return AH_FALSE; + } + + /* Workaround for hw bug - AR5416 specific */ + if (AR_SREV_OWL(ah) && ah->ah_config.ah_ar5416_biasadj) + ar2133ForceBias(ah, freq); + + reg32 = (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 5) | 0x1; + + OS_REG_WRITE(ah, AR_PHY(0x37), reg32); + + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; + +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar2133GetRfBank(struct ath_hal *ah, int bank) +{ + struct ar2133State *priv = AR2133(ah); + + HALASSERT(priv != AH_NULL); + switch (bank) { + case 1: return priv->Bank1Data; + case 2: return priv->Bank2Data; + case 3: return priv->Bank3Data; + case 6: return priv->Bank6Data; + case 7: return priv->Bank7Data; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + * + * REQUIRES: Access to the analog rf device + */ +static HAL_BOOL +ar2133SetRfRegs(struct ath_hal *ah, const struct ieee80211_channel *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ + struct ar2133State *priv = AR2133(ah); + int writes; + + HALASSERT(priv); + + /* Setup Bank 0 Write */ + ath_hal_ini_bank_setup(priv->Bank0Data, &AH5416(ah)->ah_ini_bank0, 1); + + /* Setup Bank 1 Write */ + ath_hal_ini_bank_setup(priv->Bank1Data, &AH5416(ah)->ah_ini_bank1, 1); + + /* Setup Bank 2 Write */ + ath_hal_ini_bank_setup(priv->Bank2Data, &AH5416(ah)->ah_ini_bank2, 1); + + /* Setup Bank 3 Write */ + ath_hal_ini_bank_setup(priv->Bank3Data, &AH5416(ah)->ah_ini_bank3, modesIndex); + + /* Setup Bank 6 Write */ + ath_hal_ini_bank_setup(priv->Bank6Data, &AH5416(ah)->ah_ini_bank6, modesIndex); + + /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: 2ghz: OB_2:%d, DB_2:%d\n", + __func__, + ath_hal_eepromGet(ah, AR_EEP_OB_2, AH_NULL), + ath_hal_eepromGet(ah, AR_EEP_DB_2, AH_NULL)); + ar5416ModifyRfBuffer(priv->Bank6Data, + ath_hal_eepromGet(ah, AR_EEP_OB_2, AH_NULL), 3, 197, 0); + ar5416ModifyRfBuffer(priv->Bank6Data, + ath_hal_eepromGet(ah, AR_EEP_DB_2, AH_NULL), 3, 194, 0); + } else { + HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: 5ghz: OB_5:%d, DB_5:%d\n", + __func__, + ath_hal_eepromGet(ah, AR_EEP_OB_5, AH_NULL), + ath_hal_eepromGet(ah, AR_EEP_DB_5, AH_NULL)); + ar5416ModifyRfBuffer(priv->Bank6Data, + ath_hal_eepromGet(ah, AR_EEP_OB_5, AH_NULL), 3, 203, 0); + ar5416ModifyRfBuffer(priv->Bank6Data, + ath_hal_eepromGet(ah, AR_EEP_DB_5, AH_NULL), 3, 200, 0); + } + /* Setup Bank 7 Setup */ + ath_hal_ini_bank_setup(priv->Bank7Data, &AH5416(ah)->ah_ini_bank7, 1); + + /* Write Analog registers */ + writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank0, + priv->Bank0Data, 0); + writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank1, + priv->Bank1Data, writes); + writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank2, + priv->Bank2Data, writes); + writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank3, + priv->Bank3Data, writes); + writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank6, + priv->Bank6Data, writes); + (void) ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank7, + priv->Bank7Data, writes); + + return AH_TRUE; +#undef RF_BANK_SETUP +} + +/* + * Read the transmit power levels from the structures taken from EEPROM + * Interpolate read transmit power values for this channel + * Organize the transmit power values into a table for writing into the hardware + */ + +static HAL_BOOL +ar2133SetPowerTable(struct ath_hal *ah, int16_t *pPowerMin, int16_t *pPowerMax, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain) +{ + return AH_TRUE; +} + +#if 0 +static int16_t +ar2133GetMinPower(struct ath_hal *ah, EXPN_DATA_PER_CHANNEL_5112 *data) +{ + int i, minIndex; + int16_t minGain,minPwr,minPcdac,retVal; + + /* Assume NUM_POINTS_XPD0 > 0 */ + minGain = data->pDataPerXPD[0].xpd_gain; + for (minIndex=0,i=1; ipDataPerXPD[i].xpd_gain < minGain) { + minIndex = i; + minGain = data->pDataPerXPD[i].xpd_gain; + } + } + minPwr = data->pDataPerXPD[minIndex].pwr_t4[0]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[0]; + for (i=1; ipDataPerXPD[minIndex].pwr_t4[i] < minPwr) { + minPwr = data->pDataPerXPD[minIndex].pwr_t4[i]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[i]; + } + } + retVal = minPwr - (minPcdac*2); + return(retVal); +} +#endif + +static HAL_BOOL +ar2133GetChannelMaxMinPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *maxPow, int16_t *minPow) +{ +#if 0 + struct ath_hal_5212 *ahp = AH5212(ah); + int numChannels=0,i,last; + int totalD, totalF,totalMin; + EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL; + EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL; + + *maxPow = 0; + if (IS_CHAN_A(chan)) { + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11A].pDataPerChannel; + numChannels = powerArray[headerInfo11A].numChannels; + } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) { + /* XXX - is this correct? Should we also use the same power for turbo G? */ + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11G].pDataPerChannel; + numChannels = powerArray[headerInfo11G].numChannels; + } else if (IS_CHAN_B(chan)) { + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11B].pDataPerChannel; + numChannels = powerArray[headerInfo11B].numChannels; + } else { + return (AH_TRUE); + } + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if ((numChannels < 1) || + (chan->channel < data[0].channelValue) || + (chan->channel > data[numChannels-1].channelValue)) + return(AH_FALSE); + + /* Linearly interpolate the power value now */ + for (last=0,i=0; + (ichannel > data[i].channelValue); + last=i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = data[i].maxPower_t4 - data[last].maxPower_t4; + *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD); + + totalMin = ar2133GetMinPower(ah,&data[i]) - ar2133GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar2133GetMinPower(ah, &data[last])*totalD)/totalD); + return (AH_TRUE); + } else { + if (chan->channel == data[i].channelValue) { + *maxPow = data[i].maxPower_t4; + *minPow = ar2133GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +#else + *maxPow = *minPow = 0; + return AH_FALSE; +#endif +} + +/* + * The ordering of nfarray is thus: + * + * nfarray[0]: Chain 0 ctl + * nfarray[1]: Chain 1 ctl + * nfarray[2]: Chain 2 ctl + * nfarray[3]: Chain 0 ext + * nfarray[4]: Chain 1 ext + * nfarray[5]: Chain 2 ext + */ +static void +ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + int16_t nf; + + /* + * Blank nf array - some chips may only + * have one or two RX chainmasks enabled. + */ + nfarray[0] = nfarray[1] = nfarray[2] = 0; + nfarray[3] = nfarray[4] = nfarray[5] = 0; + + switch (ahp->ah_rx_chainmask) { + case 0x7: + nf = MS(OS_REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 2] is %d\n", nf); + nfarray[2] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 2] is %d\n", nf); + nfarray[5] = nf; + /* fall thru... */ + case 0x3: + case 0x5: + nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 1] is %d\n", nf); + nfarray[1] = nf; + + + nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 1] is %d\n", nf); + nfarray[4] = nf; + /* fall thru... */ + case 0x1: + nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 0] is %d\n", nf); + nfarray[0] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 0] is %d\n", nf); + nfarray[3] = nf; + + break; + } +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + * Stubbed:Not used by Fowl + */ +static int16_t +ar2133GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + return 0; +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar2133RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +/* + * Allocate memory for analog bank scratch buffers + * Scratch Buffer will be reinitialized every reset so no need to zero now + */ +HAL_BOOL +ar2133RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar2133State *priv; + uint32_t *bankData; + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: attach AR2133 radio\n", __func__); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar2133State) + + AH5416(ah)->ah_ini_bank0.rows * sizeof(uint32_t) + + AH5416(ah)->ah_ini_bank1.rows * sizeof(uint32_t) + + AH5416(ah)->ah_ini_bank2.rows * sizeof(uint32_t) + + AH5416(ah)->ah_ini_bank3.rows * sizeof(uint32_t) + + AH5416(ah)->ah_ini_bank6.rows * sizeof(uint32_t) + + AH5416(ah)->ah_ini_bank7.rows * sizeof(uint32_t) + ); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar2133RfDetach; + priv->base.writeRegs = ar2133WriteRegs; + priv->base.getRfBank = ar2133GetRfBank; + priv->base.setChannel = ar2133SetChannel; + priv->base.setRfRegs = ar2133SetRfRegs; + priv->base.setPowerTable = ar2133SetPowerTable; + priv->base.getChannelMaxMinPower = ar2133GetChannelMaxMinPower; + priv->base.getNfAdjust = ar2133GetNfAdjust; + + bankData = (uint32_t *) &priv[1]; + priv->Bank0Data = bankData, bankData += AH5416(ah)->ah_ini_bank0.rows; + priv->Bank1Data = bankData, bankData += AH5416(ah)->ah_ini_bank1.rows; + priv->Bank2Data = bankData, bankData += AH5416(ah)->ah_ini_bank2.rows; + priv->Bank3Data = bankData, bankData += AH5416(ah)->ah_ini_bank3.rows; + priv->Bank6Data = bankData, bankData += AH5416(ah)->ah_ini_bank6.rows; + priv->Bank7Data = bankData, bankData += AH5416(ah)->ah_ini_bank7.rows; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + /* + * Set noise floor adjust method; we arrange a + * direct call instead of thunking. + */ + AH_PRIVATE(ah)->ah_getNfAdjust = priv->base.getNfAdjust; + AH_PRIVATE(ah)->ah_getNoiseFloor = ar2133GetNoiseFloor; + + return AH_TRUE; +} + +static HAL_BOOL +ar2133Probe(struct ath_hal *ah) +{ + return (AR_SREV_OWL(ah) || AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)); +} + +AH_RF(RF2133, ar2133Probe, ar2133RfAttach); diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416.h b/sys/external/isc/atheros_hal/dist/ar5416/ar5416.h new file mode 100644 index 0000000..d7d0579 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416.h @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AR5416_H_ +#define _ATH_AR5416_H_ + +#include "ar5212/ar5212.h" +#include "ar5416_cal.h" +#include "ah_eeprom_v14.h" /* for CAL_TARGET_POWER_* */ + +#define AR5416_MAGIC 0x20065416 + +enum { + HAL_RESET_POWER_ON, + HAL_RESET_WARM, + HAL_RESET_COLD, +}; + +typedef struct { + uint16_t synth_center; + uint16_t ctl_center; + uint16_t ext_center; +} CHAN_CENTERS; + +typedef enum Ar5416_Rates { + rate6mb, rate9mb, rate12mb, rate18mb, + rate24mb, rate36mb, rate48mb, rate54mb, + rate1l, rate2l, rate2s, rate5_5l, + rate5_5s, rate11l, rate11s, rateXr, + rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3, + rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7, + rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3, + rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7, + rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm, + Ar5416RateSize +} AR5416_RATES; + +#define AR5416_DEFAULT_RXCHAINMASK 7 +#define AR5416_DEFAULT_TXCHAINMASK 1 +#define AR5416_MAX_RATE_POWER 63 +#define AR5416_KEYTABLE_SIZE 128 + +#define AR5416_CCA_MAX_GOOD_VALUE -85 +#define AR5416_CCA_MAX_HIGH_VALUE -62 +#define AR5416_CCA_MIN_BAD_VALUE -140 +#define AR9285_CCA_MAX_GOOD_VALUE -118 + +#define AR5416_SPUR_RSSI_THRESH 40 + +struct ar5416NfLimits { + int16_t max; + int16_t min; + int16_t nominal; +}; + +struct ath_hal_5416 { + struct ath_hal_5212 ah_5212; + + /* NB: RF data setup at attach */ + HAL_INI_ARRAY ah_ini_bb_rfgain; + HAL_INI_ARRAY ah_ini_bank0; + HAL_INI_ARRAY ah_ini_bank1; + HAL_INI_ARRAY ah_ini_bank2; + HAL_INI_ARRAY ah_ini_bank3; + HAL_INI_ARRAY ah_ini_bank6; + HAL_INI_ARRAY ah_ini_bank7; + HAL_INI_ARRAY ah_ini_addac; + HAL_INI_ARRAY ah_ini_pcieserdes; + + void (*ah_writeIni)(struct ath_hal *, + const struct ieee80211_channel *); + void (*ah_spurMitigate)(struct ath_hal *, + const struct ieee80211_channel *); + + /* calibration ops */ + HAL_BOOL (*ah_cal_initcal)(struct ath_hal *, + const struct ieee80211_channel *); + void (*ah_cal_pacal)(struct ath_hal *, + HAL_BOOL is_reset); + + /* optional open-loop tx power control related methods */ + void (*ah_olcInit)(struct ath_hal *); + void (*ah_olcTempCompensation)(struct ath_hal *); + + /* tx power control */ + HAL_BOOL (*ah_setPowerCalTable) (struct ath_hal *ah, + struct ar5416eeprom *pEepData, + const struct ieee80211_channel *chan, + int16_t *pTxPowerIndexOffset); + + /* baseband operations */ + void (*ah_initPLL) (struct ath_hal *ah, + const struct ieee80211_channel *chan); + + /* bluetooth coexistence operations */ + void (*ah_btCoexSetDiversity)(struct ath_hal *ah); + + u_int ah_globaltxtimeout; /* global tx timeout */ + u_int ah_gpioMask; + int ah_hangs; /* h/w hangs state */ + uint8_t ah_keytype[AR5416_KEYTABLE_SIZE]; + /* + * Primary/Extension Channel Tx, Rx, Rx Clear State + */ + uint32_t ah_cycleCount; + uint32_t ah_ctlBusy; + uint32_t ah_extBusy; + uint32_t ah_rxBusy; + uint32_t ah_txBusy; + uint32_t ah_rx_chainmask; + uint32_t ah_tx_chainmask; + + HAL_ANI_CMD ah_ani_function; + + struct ar5416PerCal ah_cal; /* periodic calibration state */ + + struct ar5416NfLimits nf_2g; + struct ar5416NfLimits nf_5g; + + /* + * TX power configuration related structures + */ + int initPDADC; + int ah_ht40PowerIncForPdadc; + int16_t ah_ratesArray[Ar5416RateSize]; + + int ah_need_an_top2_fixup; /* merlin or later chips that may need this workaround */ + + /* + * Bluetooth coexistence static setup according to the registry + */ + HAL_BT_MODULE ah_btModule; /* Bluetooth module identifier */ + uint8_t ah_btCoexConfigType; /* BT coex configuration */ + uint8_t ah_btActiveGpioSelect; /* GPIO pin for BT_ACTIVE */ + uint8_t ah_btPriorityGpioSelect; /* GPIO pin for BT_PRIORITY */ + uint8_t ah_wlanActiveGpioSelect; /* GPIO pin for WLAN_ACTIVE */ + uint8_t ah_btActivePolarity; /* Polarity of BT_ACTIVE */ + HAL_BOOL ah_btCoexSingleAnt; /* Single or dual antenna configuration */ + uint8_t ah_btWlanIsolation; /* Isolation between BT and WLAN in dB */ + + /* + * Bluetooth coexistence runtime settings + */ + HAL_BOOL ah_btCoexEnabled; /* If Bluetooth coexistence is enabled */ + uint32_t ah_btCoexMode; /* Register setting for AR_BT_COEX_MODE */ + uint32_t ah_btCoexBTWeight; /* Register setting for AR_BT_COEX_WEIGHT */ + uint32_t ah_btCoexWLANWeight; /* Register setting for AR_BT_COEX_WEIGHT */ + uint32_t ah_btCoexMode2; /* Register setting for AR_BT_COEX_MODE2 */ + uint32_t ah_btCoexFlag; /* Special tuning flags for BT coex */ +}; +#define AH5416(_ah) ((struct ath_hal_5416 *)(_ah)) + +#define IS_5416_PCI(ah) ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_VERSION_OWL_PCI) +#define IS_5416_PCIE(ah) ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_VERSION_OWL_PCIE) +#undef IS_PCIE +#define IS_PCIE(ah) (IS_5416_PCIE(ah)) + +extern HAL_BOOL ar2133RfAttach(struct ath_hal *, HAL_STATUS *); + +struct ath_hal; + +extern uint32_t ar5416GetRadioRev(struct ath_hal *ah); +extern void ar5416InitState(struct ath_hal_5416 *, uint16_t devid, + HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, + HAL_STATUS *status); +extern void ar5416Detach(struct ath_hal *ah); +extern void ar5416AttachPCIE(struct ath_hal *ah); +extern HAL_BOOL ar5416FillCapabilityInfo(struct ath_hal *ah); + +extern void ar5416AniAttach(struct ath_hal *, const struct ar5212AniParams *, + const struct ar5212AniParams *, HAL_BOOL ena); +extern void ar5416AniDetach(struct ath_hal *); +extern HAL_BOOL ar5416AniControl(struct ath_hal *, HAL_ANI_CMD cmd, int param); +extern HAL_BOOL ar5416AniSetParams(struct ath_hal *, + const struct ar5212AniParams *, const struct ar5212AniParams *); +extern void ar5416ProcessMibIntr(struct ath_hal *, const HAL_NODE_STATS *); +extern void ar5416RxMonitor(struct ath_hal *, const HAL_NODE_STATS *, + const struct ieee80211_channel *); +extern void ar5416AniPoll(struct ath_hal *, const struct ieee80211_channel *); +extern void ar5416AniReset(struct ath_hal *, const struct ieee80211_channel *, + HAL_OPMODE, int); + +extern void ar5416SetBeaconTimers(struct ath_hal *, const HAL_BEACON_TIMERS *); +extern void ar5416BeaconInit(struct ath_hal *ah, + uint32_t next_beacon, uint32_t beacon_period); +extern void ar5416ResetStaBeaconTimers(struct ath_hal *ah); +extern void ar5416SetStaBeaconTimers(struct ath_hal *ah, + const HAL_BEACON_STATE *); +extern uint64_t ar5416GetNextTBTT(struct ath_hal *); + +/* ar5416_btcoex.c */ +extern void ar5416SetBTCoexInfo(struct ath_hal *ah, + HAL_BT_COEX_INFO *btinfo); +extern void ar5416BTCoexConfig(struct ath_hal *ah, + HAL_BT_COEX_CONFIG *btconf); +extern void ar5416BTCoexAntennaDiversity(struct ath_hal *ah); +extern void ar5416BTCoexSetQcuThresh(struct ath_hal *ah, int qnum); +extern void ar5416BTCoexSetWeights(struct ath_hal *ah, uint32_t stompType); +extern void ar5416BTCoexSetupBmissThresh(struct ath_hal *ah, + uint32_t thresh); +extern void ar5416BTCoexSetParameter(struct ath_hal *ah, uint32_t type, + uint32_t value); +extern void ar5416BTCoexDisable(struct ath_hal *ah); +extern int ar5416BTCoexEnable(struct ath_hal *ah); +extern void ar5416InitBTCoex(struct ath_hal *ah); + +extern HAL_BOOL ar5416EepromRead(struct ath_hal *, u_int off, uint16_t *data); +extern HAL_BOOL ar5416EepromWrite(struct ath_hal *, u_int off, uint16_t data); + +extern HAL_BOOL ar5416IsInterruptPending(struct ath_hal *ah); +extern HAL_BOOL ar5416GetPendingInterrupts(struct ath_hal *, HAL_INT *masked); +extern HAL_INT ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints); + +extern HAL_BOOL ar5416GpioCfgOutput(struct ath_hal *, uint32_t gpio, + HAL_GPIO_MUX_TYPE); +extern HAL_BOOL ar5416GpioCfgInput(struct ath_hal *, uint32_t gpio); +extern HAL_BOOL ar5416GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val); +extern uint32_t ar5416GpioGet(struct ath_hal *ah, uint32_t gpio); +extern void ar5416GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel); + +extern u_int ar5416GetWirelessModes(struct ath_hal *ah); +extern void ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state); +extern uint64_t ar5416GetTsf64(struct ath_hal *ah); +extern void ar5416SetTsf64(struct ath_hal *ah, uint64_t tsf64); +extern void ar5416ResetTsf(struct ath_hal *ah); +extern uint32_t ar5416GetCurRssi(struct ath_hal *ah); +extern HAL_BOOL ar5416SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); +extern HAL_BOOL ar5416SetDecompMask(struct ath_hal *, uint16_t, int); +extern void ar5416SetCoverageClass(struct ath_hal *, uint8_t, int); +extern HAL_BOOL ar5416GetMibCycleCounts(struct ath_hal *ah, + HAL_SURVEY_SAMPLE *hsample); +extern void ar5416SetChainMasks(struct ath_hal *ah, uint32_t, uint32_t); +extern uint32_t ar5416Get11nExtBusy(struct ath_hal *ah); +extern void ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode); +extern HAL_HT_RXCLEAR ar5416Get11nRxClear(struct ath_hal *ah); +extern void ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear); +extern HAL_STATUS ar5416SetQuiet(struct ath_hal *ah, uint32_t period, + uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag); +extern HAL_STATUS ar5416GetCapability(struct ath_hal *ah, + HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result); +extern HAL_BOOL ar5416SetCapability(struct ath_hal *ah, + HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t val, + HAL_STATUS *status); +extern HAL_BOOL ar5416GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize); +extern HAL_BOOL ar5416SetRifsDelay(struct ath_hal *ah, + const struct ieee80211_channel *chan, HAL_BOOL enable); + +extern void ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); +extern HAL_BOOL ar5416GetDfsDefaultThresh(struct ath_hal *ah, + HAL_PHYERR_PARAM *pe); +extern void ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); +extern HAL_BOOL ar5416ProcessRadarEvent(struct ath_hal *ah, + struct ath_rx_status *rxs, uint64_t fulltsf, const char *buf, + HAL_DFS_EVENT *event); +extern HAL_BOOL ar5416IsFastClockEnabled(struct ath_hal *ah); + +/* ar9280_spectral.c */ +extern void ar5416ConfigureSpectralScan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss); +extern void ar5416GetSpectralParams(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss); +extern HAL_BOOL ar5416IsSpectralActive(struct ath_hal *ah); +extern HAL_BOOL ar5416IsSpectralEnabled(struct ath_hal *ah); +extern void ar5416StartSpectralScan(struct ath_hal *ah); +extern void ar5416StopSpectralScan(struct ath_hal *ah); +extern uint32_t ar5416GetSpectralConfig(struct ath_hal *ah); +extern void ar5416RestoreSpectralConfig(struct ath_hal *ah, uint32_t restoreval); + +extern HAL_BOOL ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, + int setChip); +extern HAL_POWER_MODE ar5416GetPowerMode(struct ath_hal *ah); +extern HAL_BOOL ar5416GetPowerStatus(struct ath_hal *ah); + +extern HAL_BOOL ar5416ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry); +extern HAL_BOOL ar5416SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, + const HAL_KEYVAL *k, const uint8_t *mac, int xorKey); + +extern uint32_t ar5416GetRxFilter(struct ath_hal *ah); +extern void ar5416SetRxFilter(struct ath_hal *ah, uint32_t bits); +extern HAL_BOOL ar5416StopDmaReceive(struct ath_hal *ah); +extern void ar5416StartPcuReceive(struct ath_hal *ah); +extern void ar5416StopPcuReceive(struct ath_hal *ah); +extern HAL_BOOL ar5416SetupRxDesc(struct ath_hal *, + struct ath_desc *, uint32_t size, u_int flags); +extern HAL_STATUS ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *, + uint32_t, struct ath_desc *, uint64_t, + struct ath_rx_status *); + +extern HAL_BOOL ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, + struct ieee80211_channel *chan, + HAL_BOOL bChannelChange, + HAL_RESET_TYPE, + HAL_STATUS *status); +extern HAL_BOOL ar5416PhyDisable(struct ath_hal *ah); +extern HAL_RFGAIN ar5416GetRfgain(struct ath_hal *ah); +extern HAL_BOOL ar5416Disable(struct ath_hal *ah); +extern HAL_BOOL ar5416ChipReset(struct ath_hal *ah, + const struct ieee80211_channel *); +extern int ar5416GetRegChainOffset(struct ath_hal *ah, int i); +extern HAL_BOOL ar5416SetBoardValues(struct ath_hal *, + const struct ieee80211_channel *); +extern HAL_BOOL ar5416SetResetReg(struct ath_hal *, uint32_t type); +extern HAL_BOOL ar5416SetTxPowerLimit(struct ath_hal *ah, uint32_t limit); +extern HAL_BOOL ar5416SetTransmitPower(struct ath_hal *, + const struct ieee80211_channel *, uint16_t *); +extern HAL_BOOL ar5416GetChipPowerLimits(struct ath_hal *ah, + struct ieee80211_channel *chan); +extern void ar5416GetChannelCenters(struct ath_hal *, + const struct ieee80211_channel *chan, CHAN_CENTERS *centers); +extern void ar5416SetRatesArrayFromTargetPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *ratesArray, + const CAL_TARGET_POWER_LEG *targetPowerCck, + const CAL_TARGET_POWER_LEG *targetPowerCckExt, + const CAL_TARGET_POWER_LEG *targetPowerOfdm, + const CAL_TARGET_POWER_LEG *targetPowerOfdmExt, + const CAL_TARGET_POWER_HT *targetPowerHt20, + const CAL_TARGET_POWER_HT *targetPowerHt40); +extern void ar5416GetTargetPowers(struct ath_hal *ah, + const struct ieee80211_channel *chan, + CAL_TARGET_POWER_HT *powInfo, + uint16_t numChannels, CAL_TARGET_POWER_HT *pNewPower, + uint16_t numRates, HAL_BOOL isHt40Target); +extern void ar5416GetTargetPowersLeg(struct ath_hal *ah, + const struct ieee80211_channel *chan, + CAL_TARGET_POWER_LEG *powInfo, + uint16_t numChannels, CAL_TARGET_POWER_LEG *pNewPower, + uint16_t numRates, HAL_BOOL isExtTarget); +extern void ar5416InitChainMasks(struct ath_hal *ah); +extern void ar5416RestoreChainMask(struct ath_hal *ah); +extern void ar5416EepromSetAddac(struct ath_hal *ah, + const struct ieee80211_channel *chan); +extern uint16_t ar5416GetMaxEdgePower(uint16_t freq, + CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz); +extern void ar5416InitPLL(struct ath_hal *ah, + const struct ieee80211_channel *chan); + +/* TX power setup related routines in ar5416_reset.c */ +extern void ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, + const struct ieee80211_channel *chan, CAL_DATA_PER_FREQ *pRawDataSet, + uint8_t * bChans, uint16_t availPiers, + uint16_t tPdGainOverlap, int16_t *pMinCalPower, + uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues, + uint16_t numXpdGains); +extern void ar5416SetGainBoundariesClosedLoop(struct ath_hal *ah, + int i, uint16_t pdGainOverlap_t2, + uint16_t gainBoundaries[]); +extern uint16_t ar5416GetXpdGainValues(struct ath_hal *ah, uint16_t xpdMask, + uint16_t xpdGainValues[]); +extern void ar5416WriteDetectorGainBiases(struct ath_hal *ah, + uint16_t numXpdGain, uint16_t xpdGainValues[]); +extern void ar5416WritePdadcValues(struct ath_hal *ah, int i, + uint8_t pdadcValues[]); +extern HAL_BOOL ar5416SetPowerCalTable(struct ath_hal *ah, + struct ar5416eeprom *pEepData, const struct ieee80211_channel *chan, + int16_t *pTxPowerIndexOffset); +extern void ar5416WriteTxPowerRateRegisters(struct ath_hal *ah, + const struct ieee80211_channel *chan, const int16_t ratesArray[]); + +extern HAL_BOOL ar5416StopTxDma(struct ath_hal *ah, u_int q); +extern HAL_BOOL ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, + u_int txRate0, u_int txTries0, + u_int keyIx, u_int antMode, u_int flags, + u_int rtsctsRate, u_int rtsctsDuration, + u_int compicvLen, u_int compivLen, u_int comp); +extern HAL_BOOL ar5416SetupXTxDesc(struct ath_hal *, struct ath_desc *, + u_int txRate1, u_int txRetries1, + u_int txRate2, u_int txRetries2, + u_int txRate3, u_int txRetries3); +extern HAL_BOOL ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, + HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, + u_int descId, u_int qcuId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0); +extern HAL_STATUS ar5416ProcTxDesc(struct ath_hal *ah, + struct ath_desc *, struct ath_tx_status *); +extern HAL_BOOL ar5416GetTxCompletionRates(struct ath_hal *ah, + const struct ath_desc *ds0, int *rates, int *tries); + +extern HAL_BOOL ar5416ResetTxQueue(struct ath_hal *ah, u_int q); +extern int ar5416SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo); + +extern HAL_BOOL ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds, + HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, + u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int keyIx, + HAL_CIPHER cipher, uint8_t delims, + HAL_BOOL firstSeg, HAL_BOOL lastSeg, HAL_BOOL lastAggr); +extern HAL_BOOL ar5416SetupFirstTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int aggrLen, u_int flags, u_int txPower, u_int txRate0, u_int txTries0, + u_int antMode, u_int rtsctsRate, u_int rtsctsDuration); +extern HAL_BOOL ar5416SetupLastTxDesc(struct ath_hal *ah, struct ath_desc *ds, + const struct ath_desc *ds0); +extern HAL_BOOL ar5416SetGlobalTxTimeout(struct ath_hal *ah, u_int tu); +extern u_int ar5416GetGlobalTxTimeout(struct ath_hal *ah); +extern void ar5416Set11nRateScenario(struct ath_hal *ah, struct ath_desc *ds, + u_int durUpdateEn, u_int rtsctsRate, HAL_11N_RATE_SERIES series[], + u_int nseries, u_int flags); + +extern void ar5416Set11nAggrFirst(struct ath_hal *ah, struct ath_desc *ds, + u_int aggrLen, u_int numDelims); +extern void ar5416Set11nAggrMiddle(struct ath_hal *ah, struct ath_desc *ds, u_int numDelims); +extern void ar5416Set11nAggrLast(struct ath_hal *ah, struct ath_desc *ds); +extern void ar5416Clr11nAggr(struct ath_hal *ah, struct ath_desc *ds); +extern void ar5416Set11nVirtualMoreFrag(struct ath_hal *ah, + struct ath_desc *ds, u_int vmf); + +extern void ar5416Set11nBurstDuration(struct ath_hal *ah, struct ath_desc *ds, u_int burstDuration); + +extern const HAL_RATE_TABLE *ar5416GetRateTable(struct ath_hal *, u_int mode); +#endif /* _ATH_AR5416_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416.ini b/sys/external/isc/atheros_hal/dist/ar5416/ar5416.ini new file mode 100644 index 0000000..7f8c793 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416.ini @@ -0,0 +1,705 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008-2009 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +/* Auto Generated PCI Register Writes. Created: 09/20/06 */ + +static const uint32_t ar5416Modes[][6] = { + /* Register A A-20/40 G-20/40 G G-Turbo */ + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, + { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, + { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, + { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, + { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, + { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 }, + { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b }, + { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, +#ifdef TB243 + { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, + { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, + { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 }, +#else + { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, + { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, + { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, +#ifdef __LINUX_ARM_ARCH__ + { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, +#else + { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, +#endif +#endif + { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, + { 0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, + { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, + { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, + { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, + { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, + { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, + { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, + { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, + { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, + { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const uint32_t ar5416Common[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, +#ifdef AR9100 + { 0x00020010, 0x00000000 }, +#else + { 0x00007010, 0x00000000 }, +#endif + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0xa8000010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00070000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a002e }, + { 0x0000984c, 0x1284233c }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x05100000 }, + { 0x0000a920, 0x05100000 }, + { 0x0000b920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280b212 }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5d50e188 }, + { 0x00009958, 0x00081fff }, + { 0x0000c95c, 0x004b6a8e }, + { 0x0000c968, 0x000003ce }, + { 0x00009970, 0x190fb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x001fff00 }, + { 0x000099ac, 0x00000000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000200 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099fc, 0x00001042 }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, + { 0x0000a210, 0x40806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x00000bb5 }, + { 0x0000a22c, 0x00000011 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0e79e5c6 }, + { 0x0000b26c, 0x0e79e5c6 }, + { 0x0000c26c, 0x0e79e5c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x08000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, +}; + +static const uint32_t ar5416Bank0[][2] = { + { 0x000098b0, 0x1e5795e5 }, + { 0x000098e0, 0x02008020 }, +}; + +static const uint32_t ar5416BB_RfGain[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000141 }, + { 0x00009a10, 0x000001e1, 0x00000181 }, + { 0x00009a14, 0x00000021, 0x000001c1 }, + { 0x00009a18, 0x00000061, 0x00000001 }, + { 0x00009a1c, 0x00000168, 0x00000041 }, + { 0x00009a20, 0x000001a8, 0x000001a8 }, + { 0x00009a24, 0x000001e8, 0x000001e8 }, + { 0x00009a28, 0x00000028, 0x00000028 }, + { 0x00009a2c, 0x00000068, 0x00000068 }, + { 0x00009a30, 0x00000189, 0x000000a8 }, + { 0x00009a34, 0x000001c9, 0x00000169 }, + { 0x00009a38, 0x00000009, 0x000001a9 }, + { 0x00009a3c, 0x00000049, 0x000001e9 }, + { 0x00009a40, 0x00000089, 0x00000029 }, + { 0x00009a44, 0x00000170, 0x00000069 }, + { 0x00009a48, 0x000001b0, 0x00000190 }, + { 0x00009a4c, 0x000001f0, 0x000001d0 }, + { 0x00009a50, 0x00000030, 0x00000010 }, + { 0x00009a54, 0x00000070, 0x00000050 }, + { 0x00009a58, 0x00000191, 0x00000090 }, + { 0x00009a5c, 0x000001d1, 0x00000151 }, + { 0x00009a60, 0x00000011, 0x00000191 }, + { 0x00009a64, 0x00000051, 0x000001d1 }, + { 0x00009a68, 0x00000091, 0x00000011 }, + { 0x00009a6c, 0x000001b8, 0x00000051 }, + { 0x00009a70, 0x000001f8, 0x00000198 }, + { 0x00009a74, 0x00000038, 0x000001d8 }, + { 0x00009a78, 0x00000078, 0x00000018 }, + { 0x00009a7c, 0x00000199, 0x00000058 }, + { 0x00009a80, 0x000001d9, 0x00000098 }, + { 0x00009a84, 0x00000019, 0x00000159 }, + { 0x00009a88, 0x00000059, 0x00000199 }, + { 0x00009a8c, 0x00000099, 0x000001d9 }, + { 0x00009a90, 0x000000d9, 0x00000019 }, + { 0x00009a94, 0x000000f9, 0x00000059 }, + { 0x00009a98, 0x000000f9, 0x00000099 }, + { 0x00009a9c, 0x000000f9, 0x000000d9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const uint32_t ar5416Bank1[][2] = { + { 0x000098b0, 0x02108421 }, + { 0x000098ec, 0x00000008 }, +}; + +static const uint32_t ar5416Bank2[][2] = { + { 0x000098b0, 0x0e73ff17 }, + { 0x000098e0, 0x00000420 }, +}; + +static const uint32_t ar5416Bank3[][3] = { + { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +#ifdef USE_NONTPC_BANK +static const uint32_t ar5416Bank6[][3] = { +/* Reg A G */ + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x004210a2, 0x004210a2 }, + { 0x0000989c, 0x0014008f, 0x0014008f }, + { 0x0000989c, 0x00c40003, 0x00c40003 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000f1, 0x000000f1 }, + { 0x0000989c, 0x00002081, 0x00002081 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +#else +/* TPC bank */ +static const uint32_t ar5416Bank6[][3] = { +/* Reg A G */ + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x00423022, 0x00423022 }, + { 0x0000989c, 0x201400df, 0x201400df }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000e1, 0x000000e1 }, + { 0x0000989c, 0x00007081, 0x00007081 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +#endif + +static const uint32_t ar5416Bank7[][2] = { + { 0x0000989c, 0x00000500 }, + { 0x0000989c, 0x00000800 }, + { 0x000098cc, 0x0000000e }, +}; + +static const uint32_t ar5416Addac[][2] = { + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000003 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x0000000c }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000030 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000060 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000058 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x000098c4, 0x00000000 }, +}; + +/* hand-crafted from code that does explicit register writes */ +static const uint32_t ar5416PciePhy[][2] = { + { AR_PCIE_SERDES, 0x9248fc00 }, + { AR_PCIE_SERDES, 0x24924924 }, + { AR_PCIE_SERDES, 0x28000039 }, + { AR_PCIE_SERDES, 0x53160824 }, + { AR_PCIE_SERDES, 0xe5980579 }, + { AR_PCIE_SERDES, 0x001defff }, + { AR_PCIE_SERDES, 0x1aaabe40 }, + { AR_PCIE_SERDES, 0xbe105554 }, + { AR_PCIE_SERDES, 0x000e3007 }, + { AR_PCIE_SERDES2, 0x00000000 }, +}; diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_ani.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_ani.c new file mode 100644 index 0000000..fadd5ad --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_ani.c @@ -0,0 +1,991 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +/* + * XXX this is virtually the same code as for 5212; we reuse + * storage in the 5212 state block; need to refactor. + */ +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* + * Anti noise immunity support. We track phy errors and react + * to excessive errors by adjusting the noise immunity parameters. + */ + +#define HAL_EP_RND(x, mul) \ + ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) +#define BEACON_RSSI(ahp) \ + HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgbrssi, \ + HAL_RSSI_EP_MULTIPLIER) + +/* + * ANI processing tunes radio parameters according to PHY errors + * and related information. This is done for for noise and spur + * immunity in all operating modes if the device indicates it's + * capable at attach time. In addition, when there is a reference + * rssi value (e.g. beacon frames from an ap in station mode) + * further tuning is done. + * + * ANI_ENA indicates whether any ANI processing should be done; + * this is specified at attach time. + * + * ANI_ENA_RSSI indicates whether rssi-based processing should + * done, this is enabled based on operating mode and is meaningful + * only if ANI_ENA is true. + * + * ANI parameters are typically controlled only by the hal. The + * AniControl interface however permits manual tuning through the + * diagnostic api. + */ +#define ANI_ENA(ah) \ + (AH5212(ah)->ah_procPhyErr & HAL_ANI_ENA) +#define ANI_ENA_RSSI(ah) \ + (AH5212(ah)->ah_procPhyErr & HAL_RSSI_ANI_ENA) + +#define ah_mibStats ah_stats.ast_mibstats + +static void +enableAniMIBCounters(struct ath_hal *ah, const struct ar5212AniParams *params) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: Enable mib counters: " + "OfdmPhyErrBase 0x%x cckPhyErrBase 0x%x\n", + __func__, params->ofdmPhyErrBase, params->cckPhyErrBase); + + OS_REG_WRITE(ah, AR_FILTOFDM, 0); + OS_REG_WRITE(ah, AR_FILTCCK, 0); + + OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase); + OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); + + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save+clear counters*/ + ar5212EnableMibCounters(ah); /* enable everything */ +} + +static void +disableAniMIBCounters(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_ANI, "Disable MIB counters\n"); + + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save stats */ + ar5212DisableMibCounters(ah); /* disable everything */ + + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, 0); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, 0); +} + +static void +setPhyErrBase(struct ath_hal *ah, struct ar5212AniParams *params) +{ + if (params->ofdmTrigHigh >= AR_PHY_COUNTMAX) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "OFDM Trigger %d is too high for hw counters, using max\n", + params->ofdmTrigHigh); + params->ofdmPhyErrBase = 0; + } else + params->ofdmPhyErrBase = AR_PHY_COUNTMAX - params->ofdmTrigHigh; + if (params->cckTrigHigh >= AR_PHY_COUNTMAX) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "CCK Trigger %d is too high for hw counters, using max\n", + params->cckTrigHigh); + params->cckPhyErrBase = 0; + } else + params->cckPhyErrBase = AR_PHY_COUNTMAX - params->cckTrigHigh; +} + +/* + * Setup ANI handling. Sets all thresholds and reset the + * channel statistics. Note that ar5416AniReset should be + * called by ar5416Reset before anything else happens and + * that's where we force initial settings. + */ +void +ar5416AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24, + const struct ar5212AniParams *params5, HAL_BOOL enable) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (params24 != AH_NULL) { + OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24)); + setPhyErrBase(ah, &ahp->ah_aniParams24); + } + if (params5 != AH_NULL) { + OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5)); + setPhyErrBase(ah, &ahp->ah_aniParams5); + } + + OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani)); + /* Enable MIB Counters */ + enableAniMIBCounters(ah, &ahp->ah_aniParams24 /*XXX*/); + + if (enable) { /* Enable ani now */ + HALASSERT(params24 != AH_NULL && params5 != AH_NULL); + ahp->ah_procPhyErr |= HAL_ANI_ENA; + } else { + ahp->ah_procPhyErr &= ~HAL_ANI_ENA; + } +} + +/* + * Cleanup any ANI state setup. + * + * This doesn't restore registers to their default settings! + */ +void +ar5416AniDetach(struct ath_hal *ah) +{ + HALDEBUG(ah, HAL_DEBUG_ANI, "Detaching Ani\n"); + disableAniMIBCounters(ah); +} + +/* + * Control Adaptive Noise Immunity Parameters + */ +HAL_BOOL +ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) +{ + typedef int TABLE[]; + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState = ahp->ah_curani; + const struct ar5212AniParams *params = AH_NULL; + + /* + * This function may be called before there's a current + * channel (eg to disable ANI.) + */ + if (aniState != AH_NULL) + params = aniState->params; + + OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd); + + /* These commands can't be disabled */ + if (cmd == HAL_ANI_PRESENT) + return AH_TRUE; + + if (cmd == HAL_ANI_MODE) { + if (param == 0) { + ahp->ah_procPhyErr &= ~HAL_ANI_ENA; + /* Turn off HW counters if we have them */ + ar5416AniDetach(ah); + } else { /* normal/auto mode */ + /* don't mess with state if already enabled */ + if (! (ahp->ah_procPhyErr & HAL_ANI_ENA)) { + /* Enable MIB Counters */ + /* + * XXX use 2.4ghz params if no channel is + * available + */ + enableAniMIBCounters(ah, + ahp->ah_curani != AH_NULL ? + ahp->ah_curani->params: + &ahp->ah_aniParams24); + ahp->ah_procPhyErr |= HAL_ANI_ENA; + } + } + return AH_TRUE; + } + + /* Check whether the particular function is enabled */ + if (((1 << cmd) & AH5416(ah)->ah_ani_function) == 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: command %d disabled\n", + __func__, cmd); + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: cmd %d; mask %x\n", __func__, cmd, AH5416(ah)->ah_ani_function); + return AH_FALSE; + } + + + switch (cmd) { + case HAL_ANI_NOISE_IMMUNITY_LEVEL: { + u_int level = param; + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_NOISE_IMMUNITY_LEVEL: set level = %d\n", __func__, level); + if (level > params->maxNoiseImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: immunity level out of range (%u > %u)\n", + __func__, level, params->maxNoiseImmunityLevel); + return AH_FALSE; + } + + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_TOT_DES, params->totalSizeDesired[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_LOW, params->coarseLow[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_HIGH, params->coarseHigh[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRPWR, params->firpwr[level]); + + if (level > aniState->noiseImmunityLevel) + ahp->ah_stats.ast_ani_niup++; + else if (level < aniState->noiseImmunityLevel) + ahp->ah_stats.ast_ani_nidown++; + aniState->noiseImmunityLevel = level; + break; + } + case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: { + static const TABLE m1ThreshLow = { 127, 50 }; + static const TABLE m2ThreshLow = { 127, 40 }; + static const TABLE m1Thresh = { 127, 0x4d }; + static const TABLE m2Thresh = { 127, 0x40 }; + static const TABLE m2CountThr = { 31, 16 }; + static const TABLE m2CountThrLow = { 63, 48 }; + u_int on = param ? 1 : 0; + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: %s\n", __func__, on ? "enabled" : "disabled"); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]); + + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]); + + if (on) { + OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + } else { + OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + } + if (on) + ahp->ah_stats.ast_ani_ofdmon++; + else + ahp->ah_stats.ast_ani_ofdmoff++; + aniState->ofdmWeakSigDetectOff = !on; + break; + } + case HAL_ANI_CCK_WEAK_SIGNAL_THR: { + static const TABLE weakSigThrCck = { 8, 6 }; + u_int high = param ? 1 : 0; + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_CCK_WEAK_SIGNAL_THR: %s\n", __func__, high ? "high" : "low"); + OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, + AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, weakSigThrCck[high]); + if (high) + ahp->ah_stats.ast_ani_cckhigh++; + else + ahp->ah_stats.ast_ani_ccklow++; + aniState->cckWeakSigThreshold = high; + break; + } + case HAL_ANI_FIRSTEP_LEVEL: { + u_int level = param; + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_FIRSTEP_LEVEL: level = %d\n", __func__, level); + if (level > params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: firstep level out of range (%u > %u)\n", + __func__, level, params->maxFirstepLevel); + return AH_FALSE; + } + OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRSTEP, params->firstep[level]); + if (level > aniState->firstepLevel) + ahp->ah_stats.ast_ani_stepup++; + else if (level < aniState->firstepLevel) + ahp->ah_stats.ast_ani_stepdown++; + aniState->firstepLevel = level; + break; + } + case HAL_ANI_SPUR_IMMUNITY_LEVEL: { + u_int level = param; + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_SPUR_IMMUNITY_LEVEL: level = %d\n", __func__, level); + if (level > params->maxSpurImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: spur immunity level out of range (%u > %u)\n", + __func__, level, params->maxSpurImmunityLevel); + return AH_FALSE; + } + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5, + AR_PHY_TIMING5_CYCPWR_THR1, params->cycPwrThr1[level]); + + if (level > aniState->spurImmunityLevel) + ahp->ah_stats.ast_ani_spurup++; + else if (level < aniState->spurImmunityLevel) + ahp->ah_stats.ast_ani_spurdown++; + aniState->spurImmunityLevel = level; + break; + } +#ifdef AH_PRIVATE_DIAG + case HAL_ANI_PHYERR_RESET: + ahp->ah_stats.ast_ani_ofdmerrs = 0; + ahp->ah_stats.ast_ani_cckerrs = 0; + break; +#endif /* AH_PRIVATE_DIAG */ + default: + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: invalid cmd %u\n", + __func__, cmd); + return AH_FALSE; + } + return AH_TRUE; +} + +static void +ar5416AniOfdmErrTrigger(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(chan != AH_NULL); + + if (!ANI_ENA(ah)) + return; + + aniState = ahp->ah_curani; + params = aniState->params; + /* First, raise noise immunity level, up to max */ + if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) { + if (ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel + 1)) + return; + } + /* then, raise spur immunity level, up to max */ + if (aniState->spurImmunityLevel+1 < params->maxSpurImmunityLevel) { + if (ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel + 1)) + return; + } + + /* + * In the case of AP mode operation, we cannot bucketize beacons + * according to RSSI. Instead, raise Firstep level, up to max, and + * simply return. + */ + if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) { + if (aniState->firstepLevel < params->maxFirstepLevel) { + if (ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1)) + return; + } + } + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrHigh) { + /* + * Beacon rssi is high, can turn off ofdm + * weak sig detect. + */ + if (!aniState->ofdmWeakSigDetectOff) { + ar5416AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_FALSE); + ar5416AniControl(ah, + HAL_ANI_SPUR_IMMUNITY_LEVEL, 0); + return; + } + /* + * If weak sig detect is already off, as last resort, + * raise firstep level + */ + if (aniState->firstepLevel < params->maxFirstepLevel) { + if (ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1)) + return; + } + } else if (rssi > params->rssiThrLow) { + /* + * Beacon rssi in mid range, need ofdm weak signal + * detect, but we can raise firststepLevel. + */ + if (aniState->ofdmWeakSigDetectOff) + ar5416AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE); + if (aniState->firstepLevel < params->maxFirstepLevel) + if (ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1)) + return; + } else { + /* + * Beacon rssi is low, if in 11b/g mode, turn off ofdm + * weak signal detection and zero firstepLevel to + * maximize CCK sensitivity + */ + if (IEEE80211_IS_CHAN_CCK(chan)) { + if (!aniState->ofdmWeakSigDetectOff) + ar5416AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_FALSE); + if (aniState->firstepLevel > 0) + if (ar5416AniControl(ah, + HAL_ANI_FIRSTEP_LEVEL, 0)) + return; + } + } + } +} + +static void +ar5416AniCckErrTrigger(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(chan != AH_NULL); + + if (!ANI_ENA(ah)) + return; + + /* first, raise noise immunity level, up to max */ + aniState = ahp->ah_curani; + params = aniState->params; + if ((AH5416(ah)->ah_ani_function & (1 << HAL_ANI_NOISE_IMMUNITY_LEVEL) && + aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel)) { + ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel + 1); + return; + } + + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrLow) { + /* + * Beacon signal in mid and high range, + * raise firstep level. + */ + if (aniState->firstepLevel < params->maxFirstepLevel) + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + } else { + /* + * Beacon rssi is low, zero firstep level to maximize + * CCK sensitivity in 11b/g mode. + */ + if (IEEE80211_IS_CHAN_CCK(chan)) { + if (aniState->firstepLevel > 0) + ar5416AniControl(ah, + HAL_ANI_FIRSTEP_LEVEL, 0); + } + } + } +} + +static void +ar5416AniRestart(struct ath_hal *ah, struct ar5212AniState *aniState) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const struct ar5212AniParams *params = aniState->params; + + aniState->listenTime = 0; + /* + * NB: these are written on reset based on the + * ini so we must re-write them! + */ + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: Writing ofdmbase=%u cckbase=%u\n", __func__, + params->ofdmPhyErrBase, params->cckPhyErrBase); + OS_REG_WRITE(ah, AR_PHY_ERR_1, params->ofdmPhyErrBase); + OS_REG_WRITE(ah, AR_PHY_ERR_2, params->cckPhyErrBase); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + aniState->ofdmPhyErrCount = 0; + aniState->cckPhyErrCount = 0; +} + +/* + * Restore/reset the ANI parameters and reset the statistics. + * This routine must be called for every channel change. + * + * NOTE: This is where ah_curani is set; other ani code assumes + * it is setup to reflect the current channel. + */ +void +ar5416AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan, + HAL_OPMODE opmode, int restore) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); + /* XXX bounds check ic_devdata */ + struct ar5212AniState *aniState = &ahp->ah_ani[chan->ic_devdata]; + uint32_t rxfilter; + + if ((ichan->privFlags & CHANNEL_ANI_INIT) == 0) { + OS_MEMZERO(aniState, sizeof(*aniState)); + if (IEEE80211_IS_CHAN_2GHZ(chan)) + aniState->params = &ahp->ah_aniParams24; + else + aniState->params = &ahp->ah_aniParams5; + ichan->privFlags |= CHANNEL_ANI_INIT; + HALASSERT((ichan->privFlags & CHANNEL_ANI_SETUP) == 0); + } + ahp->ah_curani = aniState; +#if 0 + ath_hal_printf(ah,"%s: chan %u/0x%x restore %d opmode %u%s\n", + __func__, chan->ic_freq, chan->ic_flags, restore, opmode, + ichan->privFlags & CHANNEL_ANI_SETUP ? " setup" : ""); +#else + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: chan %u/0x%x restore %d opmode %u%s\n", + __func__, chan->ic_freq, chan->ic_flags, restore, opmode, + ichan->privFlags & CHANNEL_ANI_SETUP ? " setup" : ""); +#endif + OS_MARK(ah, AH_MARK_ANI_RESET, opmode); + + /* + * Turn off PHY error frame delivery while we futz with settings. + */ + rxfilter = ah->ah_getRxFilter(ah); + ah->ah_setRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR); + + /* + * If ANI is disabled at this point, don't set the default + * ANI parameter settings - leave the HAL settings there. + * This is (currently) needed for reliable radar detection. + */ + if (! ANI_ENA(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ANI disabled\n", + __func__); + goto finish; + } + + /* + * Use a restrictive set of ANI parameters for hostap mode. + */ + if (opmode == HAL_M_HOSTAP) { + if (IEEE80211_IS_CHAN_2GHZ(chan)) + AH5416(ah)->ah_ani_function = + HAL_ANI_SPUR_IMMUNITY_LEVEL | HAL_ANI_FIRSTEP_LEVEL; + else + AH5416(ah)->ah_ani_function = 0; + } + + /* + * Automatic processing is done only in station mode right now. + */ + if (opmode == HAL_M_STA) + ahp->ah_procPhyErr |= HAL_RSSI_ANI_ENA; + else + ahp->ah_procPhyErr &= ~HAL_RSSI_ANI_ENA; + /* + * Set all ani parameters. We either set them to initial + * values or restore the previous ones for the channel. + * XXX if ANI follows hardware, we don't care what mode we're + * XXX in, we should keep the ani parameters + */ + if (restore && (ichan->privFlags & CHANNEL_ANI_SETUP)) { + ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel); + ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel); + ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + !aniState->ofdmWeakSigDetectOff); + ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, + aniState->cckWeakSigThreshold); + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel); + } else { + ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0); + ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0); + ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_FALSE); + ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE); + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); + ichan->privFlags |= CHANNEL_ANI_SETUP; + } + + /* + * In case the counters haven't yet been setup; set them up. + */ + enableAniMIBCounters(ah, aniState->params); + ar5416AniRestart(ah, aniState); + +finish: + /* restore RX filter mask */ + ah->ah_setRxFilter(ah, rxfilter); +} + +/* + * Process a MIB interrupt. We may potentially be invoked because + * any of the MIB counters overflow/trigger so don't assume we're + * here because a PHY error counter triggered. + */ +void +ar5416ProcessMibIntr(struct ath_hal *ah, const HAL_NODE_STATS *stats) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t phyCnt1, phyCnt2; + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: mibc 0x%x phyCnt1 0x%x phyCnt2 0x%x " + "filtofdm 0x%x filtcck 0x%x\n", + __func__, OS_REG_READ(ah, AR_MIBC), + OS_REG_READ(ah, AR_PHYCNT1), OS_REG_READ(ah, AR_PHYCNT2), + OS_REG_READ(ah, AR_FILTOFDM), OS_REG_READ(ah, AR_FILTCCK)); + + /* + * First order of business is to clear whatever caused + * the interrupt so we don't keep getting interrupted. + * We have the usual mib counters that are reset-on-read + * and the additional counters that appeared starting in + * Hainan. We collect the mib counters and explicitly + * zero additional counters we are not using. Anything + * else is reset only if it caused the interrupt. + */ + /* NB: these are not reset-on-read */ + phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1); + phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2); + /* not used, always reset them in case they are the cause */ + OS_REG_WRITE(ah, AR_FILTOFDM, 0); + OS_REG_WRITE(ah, AR_FILTCCK, 0); + if ((OS_REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING) == 0) + OS_REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + ahp->ah_stats.ast_nodestats = *stats; + + /* + * Check for an ani stat hitting the trigger threshold. + * When this happens we get a MIB interrupt and the top + * 2 bits of the counter register will be 0b11, hence + * the mask check of phyCnt?. + */ + if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || + ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { + struct ar5212AniState *aniState = ahp->ah_curani; + const struct ar5212AniParams *params = aniState->params; + uint32_t ofdmPhyErrCnt, cckPhyErrCnt; + + ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase; + ahp->ah_stats.ast_ani_ofdmerrs += + ofdmPhyErrCnt - aniState->ofdmPhyErrCount; + aniState->ofdmPhyErrCount = ofdmPhyErrCnt; + + cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase; + ahp->ah_stats.ast_ani_cckerrs += + cckPhyErrCnt - aniState->cckPhyErrCount; + aniState->cckPhyErrCount = cckPhyErrCnt; + + /* + * NB: figure out which counter triggered. If both + * trigger we'll only deal with one as the processing + * clobbers the error counter so the trigger threshold + * check will never be true. + */ + if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh) + ar5416AniOfdmErrTrigger(ah); + if (aniState->cckPhyErrCount > params->cckTrigHigh) + ar5416AniCckErrTrigger(ah); + /* NB: always restart to insure the h/w counters are reset */ + ar5416AniRestart(ah, aniState); + } +} + +static void +ar5416AniLowerImmunity(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(ANI_ENA(ah)); + + aniState = ahp->ah_curani; + params = aniState->params; + + /* + * In the case of AP mode operation, we cannot bucketize beacons + * according to RSSI. Instead, lower Firstep level, down to min, and + * simply return. + */ + if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) { + if (aniState->firstepLevel > 0) { + if (ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1)) + return; + } + } + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrHigh) { + /* + * Beacon signal is high, leave ofdm weak signal + * detection off or it may oscillate. Let it fall + * through. + */ + } else if (rssi > params->rssiThrLow) { + /* + * Beacon rssi in mid range, turn on ofdm weak signal + * detection or lower firstep level. + */ + if (aniState->ofdmWeakSigDetectOff) { + if (ar5416AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE)) + return; + } + if (aniState->firstepLevel > 0) { + if (ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1)) + return; + } + } else { + /* + * Beacon rssi is low, reduce firstep level. + */ + if (aniState->firstepLevel > 0) { + if (ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1)) + return; + } + } + } + /* then lower spur immunity level, down to zero */ + if (aniState->spurImmunityLevel > 0) { + if (ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel - 1)) + return; + } + /* + * if all else fails, lower noise immunity level down to a min value + * zero for now + */ + if (aniState->noiseImmunityLevel > 0) { + if (ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel - 1)) + return; + } +} + +#define CLOCK_RATE 44000 /* XXX use mac_usec or similar */ +/* convert HW counter values to ms using 11g clock rate, goo9d enough + for 11a and Turbo */ + +/* + * Return an approximation of the time spent ``listening'' by + * deducting the cycles spent tx'ing and rx'ing from the total + * cycle count since our last call. A return value <0 indicates + * an invalid/inconsistent time. + * + * This may be called with ANI disabled; in which case simply keep + * the statistics and don't write to the aniState pointer. + * + * XXX TODO: Make this cleaner! + */ +static int32_t +ar5416AniGetListenTime(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState = NULL; + int32_t listenTime = 0; + int good; + HAL_SURVEY_SAMPLE hs; + + /* + * We shouldn't see ah_curchan be NULL, but just in case.. + */ + if (AH_PRIVATE(ah)->ah_curchan == AH_NULL) { + ath_hal_printf(ah, "%s: ah_curchan = NULL?\n", __func__); + return (0); + } + + /* + * Fetch the current statistics, squirrel away the current + * sample. + */ + OS_MEMZERO(&hs, sizeof(hs)); + good = ar5416GetMibCycleCounts(ah, &hs); + ath_hal_survey_add_sample(ah, &hs); + + if (ANI_ENA(ah)) + aniState = ahp->ah_curani; + + if (good == AH_FALSE) { + /* + * Cycle counter wrap (or initial call); it's not possible + * to accurately calculate a value because the registers + * right shift rather than wrap--so punt and return 0. + */ + listenTime = 0; + ahp->ah_stats.ast_ani_lzero++; + } else if (ANI_ENA(ah)) { + /* + * Only calculate and update the cycle count if we have + * an ANI state. + */ + int32_t ccdelta = + AH5416(ah)->ah_cycleCount - aniState->cycleCount; + int32_t rfdelta = + AH5416(ah)->ah_rxBusy - aniState->rxFrameCount; + int32_t tfdelta = + AH5416(ah)->ah_txBusy - aniState->txFrameCount; + listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE; + } + + /* + * Again, only update ANI state if we have it. + */ + if (ANI_ENA(ah)) { + aniState->cycleCount = AH5416(ah)->ah_cycleCount; + aniState->rxFrameCount = AH5416(ah)->ah_rxBusy; + aniState->txFrameCount = AH5416(ah)->ah_txBusy; + } + + return listenTime; +} + +/* + * Update ani stats in preparation for listen time processing. + */ +static void +updateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const struct ar5212AniParams *params = aniState->params; + uint32_t phyCnt1, phyCnt2; + int32_t ofdmPhyErrCnt, cckPhyErrCnt; + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + + /* NB: these are not reset-on-read */ + phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1); + phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2); + + /* NB: these are spec'd to never roll-over */ + ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase; + if (ofdmPhyErrCnt < 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "OFDM phyErrCnt %d phyCnt1 0x%x\n", + ofdmPhyErrCnt, phyCnt1); + ofdmPhyErrCnt = AR_PHY_COUNTMAX; + } + ahp->ah_stats.ast_ani_ofdmerrs += + ofdmPhyErrCnt - aniState->ofdmPhyErrCount; + aniState->ofdmPhyErrCount = ofdmPhyErrCnt; + + cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase; + if (cckPhyErrCnt < 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "CCK phyErrCnt %d phyCnt2 0x%x\n", + cckPhyErrCnt, phyCnt2); + cckPhyErrCnt = AR_PHY_COUNTMAX; + } + ahp->ah_stats.ast_ani_cckerrs += + cckPhyErrCnt - aniState->cckPhyErrCount; + aniState->cckPhyErrCount = cckPhyErrCnt; +} + +void +ar5416RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats, + const struct ieee80211_channel *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi; +} + +/* + * Do periodic processing. This routine is called from the + * driver's rx interrupt handler after processing frames. + */ +void +ar5416AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState = ahp->ah_curani; + const struct ar5212AniParams *params; + int32_t listenTime; + + /* Always update from the MIB, for statistics gathering */ + listenTime = ar5416AniGetListenTime(ah); + + /* XXX can aniState be null? */ + if (aniState == AH_NULL) + return; + + if (!ANI_ENA(ah)) + return; + + if (listenTime < 0) { + ahp->ah_stats.ast_ani_lneg++; + /* restart ANI period if listenTime is invalid */ + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: invalid listenTime\n", + __func__); + ar5416AniRestart(ah, aniState); + } + /* XXX beware of overflow? */ + aniState->listenTime += listenTime; + + OS_MARK(ah, AH_MARK_ANI_POLL, aniState->listenTime); + + params = aniState->params; + if (aniState->listenTime > 5*params->period) { + /* + * Check to see if need to lower immunity if + * 5 aniPeriods have passed + */ + updateMIBStats(ah, aniState); + if (aniState->ofdmPhyErrCount <= aniState->listenTime * + params->ofdmTrigLow/1000 && + aniState->cckPhyErrCount <= aniState->listenTime * + params->cckTrigLow/1000) + ar5416AniLowerImmunity(ah); + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: lower immunity\n", + __func__); + ar5416AniRestart(ah, aniState); + } else if (aniState->listenTime > params->period) { + updateMIBStats(ah, aniState); + /* check to see if need to raise immunity */ + if (aniState->ofdmPhyErrCount > aniState->listenTime * + params->ofdmTrigHigh / 1000) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: OFDM err %u listenTime %u\n", __func__, + aniState->ofdmPhyErrCount, aniState->listenTime); + ar5416AniOfdmErrTrigger(ah); + ar5416AniRestart(ah, aniState); + } else if (aniState->cckPhyErrCount > aniState->listenTime * + params->cckTrigHigh / 1000) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: CCK err %u listenTime %u\n", __func__, + aniState->cckPhyErrCount, aniState->listenTime); + ar5416AniCckErrTrigger(ah); + ar5416AniRestart(ah, aniState); + } + } +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_attach.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_attach.c new file mode 100644 index 0000000..4b9ebda --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_attach.c @@ -0,0 +1,1075 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ar5416/ar5416.ini" + +static void ar5416ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, + HAL_BOOL power_off); +static void ar5416DisablePCIE(struct ath_hal *ah); +static void ar5416WriteIni(struct ath_hal *ah, + const struct ieee80211_channel *chan); +static void ar5416SpurMitigate(struct ath_hal *ah, + const struct ieee80211_channel *chan); + +static void +ar5416AniSetup(struct ath_hal *ah) +{ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -55, -55, -55, -55, -62 }, + .coarseHigh = { -14, -14, -14, -14, -12 }, + .coarseLow = { -64, -64, -64, -64, -70 }, + .firpwr = { -78, -78, -78, -78, -80 }, + .maxSpurImmunityLevel = 7, + .cycPwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + /* NB: disable ANI noise immmunity for reliable RIFS rx */ + AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL); + ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE); +} + +/* + * AR5416 doesn't do OLC or temperature compensation. + */ +static void +ar5416olcInit(struct ath_hal *ah) +{ +} + +static void +ar5416olcTempCompensation(struct ath_hal *ah) +{ +} + +/* + * Attach for an AR5416 part. + */ +void +ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + + ahp = &ahp5416->ah_5212; + ar5212InitState(ahp, devid, sc, st, sh, status); + ah = &ahp->ah_priv.h; + + /* override 5212 methods for our needs */ + ah->ah_magic = AR5416_MAGIC; + ah->ah_getRateTable = ar5416GetRateTable; + ah->ah_detach = ar5416Detach; + + /* Reset functions */ + ah->ah_reset = ar5416Reset; + ah->ah_phyDisable = ar5416PhyDisable; + ah->ah_disable = ar5416Disable; + ah->ah_configPCIE = ar5416ConfigPCIE; + ah->ah_disablePCIE = ar5416DisablePCIE; + ah->ah_perCalibration = ar5416PerCalibration; + ah->ah_perCalibrationN = ar5416PerCalibrationN, + ah->ah_resetCalValid = ar5416ResetCalValid, + ah->ah_setTxPowerLimit = ar5416SetTxPowerLimit; + ah->ah_setTxPower = ar5416SetTransmitPower; + ah->ah_setBoardValues = ar5416SetBoardValues; + + /* Transmit functions */ + ah->ah_stopTxDma = ar5416StopTxDma; + ah->ah_setupTxDesc = ar5416SetupTxDesc; + ah->ah_setupXTxDesc = ar5416SetupXTxDesc; + ah->ah_fillTxDesc = ar5416FillTxDesc; + ah->ah_procTxDesc = ar5416ProcTxDesc; + ah->ah_getTxCompletionRates = ar5416GetTxCompletionRates; + ah->ah_setupTxQueue = ar5416SetupTxQueue; + ah->ah_resetTxQueue = ar5416ResetTxQueue; + + /* Receive Functions */ + ah->ah_getRxFilter = ar5416GetRxFilter; + ah->ah_setRxFilter = ar5416SetRxFilter; + ah->ah_stopDmaReceive = ar5416StopDmaReceive; + ah->ah_startPcuReceive = ar5416StartPcuReceive; + ah->ah_stopPcuReceive = ar5416StopPcuReceive; + ah->ah_setupRxDesc = ar5416SetupRxDesc; + ah->ah_procRxDesc = ar5416ProcRxDesc; + ah->ah_rxMonitor = ar5416RxMonitor; + ah->ah_aniPoll = ar5416AniPoll; + ah->ah_procMibEvent = ar5416ProcessMibIntr; + + /* Misc Functions */ + ah->ah_getCapability = ar5416GetCapability; + ah->ah_setCapability = ar5416SetCapability; + ah->ah_getDiagState = ar5416GetDiagState; + ah->ah_setLedState = ar5416SetLedState; + ah->ah_gpioCfgOutput = ar5416GpioCfgOutput; + ah->ah_gpioCfgInput = ar5416GpioCfgInput; + ah->ah_gpioGet = ar5416GpioGet; + ah->ah_gpioSet = ar5416GpioSet; + ah->ah_gpioSetIntr = ar5416GpioSetIntr; + ah->ah_getTsf64 = ar5416GetTsf64; + ah->ah_setTsf64 = ar5416SetTsf64; + ah->ah_resetTsf = ar5416ResetTsf; + ah->ah_getRfGain = ar5416GetRfgain; + ah->ah_setAntennaSwitch = ar5416SetAntennaSwitch; + ah->ah_setDecompMask = ar5416SetDecompMask; + ah->ah_setCoverageClass = ar5416SetCoverageClass; + ah->ah_setQuiet = ar5416SetQuiet; + ah->ah_getMibCycleCounts = ar5416GetMibCycleCounts; + ah->ah_setChainMasks = ar5416SetChainMasks; + + ah->ah_resetKeyCacheEntry = ar5416ResetKeyCacheEntry; + ah->ah_setKeyCacheEntry = ar5416SetKeyCacheEntry; + + /* DFS Functions */ + ah->ah_enableDfs = ar5416EnableDfs; + ah->ah_getDfsThresh = ar5416GetDfsThresh; + ah->ah_getDfsDefaultThresh = ar5416GetDfsDefaultThresh; + ah->ah_procRadarEvent = ar5416ProcessRadarEvent; + ah->ah_isFastClockEnabled = ar5416IsFastClockEnabled; + + /* Spectral Scan Functions */ + ah->ah_spectralConfigure = ar5416ConfigureSpectralScan; + ah->ah_spectralGetConfig = ar5416GetSpectralParams; + ah->ah_spectralStart = ar5416StartSpectralScan; + ah->ah_spectralStop = ar5416StopSpectralScan; + ah->ah_spectralIsEnabled = ar5416IsSpectralEnabled; + ah->ah_spectralIsActive = ar5416IsSpectralActive; + + /* Power Management Functions */ + ah->ah_setPowerMode = ar5416SetPowerMode; + + /* Beacon Management Functions */ + ah->ah_setBeaconTimers = ar5416SetBeaconTimers; + ah->ah_beaconInit = ar5416BeaconInit; + ah->ah_setStationBeaconTimers = ar5416SetStaBeaconTimers; + ah->ah_resetStationBeaconTimers = ar5416ResetStaBeaconTimers; + ah->ah_getNextTBTT = ar5416GetNextTBTT; + + /* 802.11n Functions */ + ah->ah_chainTxDesc = ar5416ChainTxDesc; + ah->ah_setupFirstTxDesc = ar5416SetupFirstTxDesc; + ah->ah_setupLastTxDesc = ar5416SetupLastTxDesc; + ah->ah_set11nRateScenario = ar5416Set11nRateScenario; + ah->ah_set11nAggrFirst = ar5416Set11nAggrFirst; + ah->ah_set11nAggrMiddle = ar5416Set11nAggrMiddle; + ah->ah_set11nAggrLast = ar5416Set11nAggrLast; + ah->ah_clr11nAggr = ar5416Clr11nAggr; + ah->ah_set11nBurstDuration = ar5416Set11nBurstDuration; + ah->ah_get11nExtBusy = ar5416Get11nExtBusy; + ah->ah_set11nMac2040 = ar5416Set11nMac2040; + ah->ah_get11nRxClear = ar5416Get11nRxClear; + ah->ah_set11nRxClear = ar5416Set11nRxClear; + ah->ah_set11nVirtMoreFrag = ar5416Set11nVirtualMoreFrag; + + /* Interrupt functions */ + ah->ah_isInterruptPending = ar5416IsInterruptPending; + ah->ah_getPendingInterrupts = ar5416GetPendingInterrupts; + ah->ah_setInterrupts = ar5416SetInterrupts; + + /* Bluetooth Coexistence functions */ + ah->ah_btCoexSetInfo = ar5416SetBTCoexInfo; + ah->ah_btCoexSetConfig = ar5416BTCoexConfig; + ah->ah_btCoexSetQcuThresh = ar5416BTCoexSetQcuThresh; + ah->ah_btCoexSetWeights = ar5416BTCoexSetWeights; + ah->ah_btCoexSetBmissThresh = ar5416BTCoexSetupBmissThresh; + ah->ah_btCoexSetParameter = ar5416BTCoexSetParameter; + ah->ah_btCoexDisable = ar5416BTCoexDisable; + ah->ah_btCoexEnable = ar5416BTCoexEnable; + AH5416(ah)->ah_btCoexSetDiversity = ar5416BTCoexAntennaDiversity; + + ahp->ah_priv.ah_getWirelessModes= ar5416GetWirelessModes; + ahp->ah_priv.ah_eepromRead = ar5416EepromRead; +#ifdef AH_SUPPORT_WRITE_EEPROM + ahp->ah_priv.ah_eepromWrite = ar5416EepromWrite; +#endif + ahp->ah_priv.ah_getChipPowerLimits = ar5416GetChipPowerLimits; + + /* Internal ops */ + AH5416(ah)->ah_writeIni = ar5416WriteIni; + AH5416(ah)->ah_spurMitigate = ar5416SpurMitigate; + + /* Internal baseband ops */ + AH5416(ah)->ah_initPLL = ar5416InitPLL; + + /* Internal calibration ops */ + AH5416(ah)->ah_cal_initcal = ar5416InitCalHardware; + + /* Internal TX power control related operations */ + AH5416(ah)->ah_olcInit = ar5416olcInit; + AH5416(ah)->ah_olcTempCompensation = ar5416olcTempCompensation; + AH5416(ah)->ah_setPowerCalTable = ar5416SetPowerCalTable; + + /* + * Start by setting all Owl devices to 2x2 + */ + AH5416(ah)->ah_rx_chainmask = AR5416_DEFAULT_RXCHAINMASK; + AH5416(ah)->ah_tx_chainmask = AR5416_DEFAULT_TXCHAINMASK; + + /* Enable all ANI functions to begin with */ + AH5416(ah)->ah_ani_function = 0xffffffff; + + /* Set overridable ANI methods */ + AH5212(ah)->ah_aniControl = ar5416AniControl; + + /* + * Default FIFO Trigger levels + * + * These define how filled the TX FIFO needs to be before + * the baseband begins to be given some data. + * + * To be paranoid, we ensure that the TX trigger level always + * has at least enough space for two TX DMA to occur. + * The TX DMA size is currently hard-coded to AR_TXCFG_DMASZ_128B. + * That means we need to leave at least 256 bytes available in + * the TX DMA FIFO. + */ +#define AR_FTRIG_512B 0x00000080 // 5 bits total + /* + * AR9285/AR9271 have half the size TX FIFO compared to + * other devices + */ + if (AR_SREV_KITE(ah) || AR_SREV_9271(ah)) { + AH5212(ah)->ah_txTrigLev = (AR_FTRIG_256B >> AR_FTRIG_S); + AH5212(ah)->ah_maxTxTrigLev = ((2048 / 64) - 1); + } else { + AH5212(ah)->ah_txTrigLev = (AR_FTRIG_512B >> AR_FTRIG_S); + AH5212(ah)->ah_maxTxTrigLev = ((4096 / 64) - 1); + } +#undef AR_FTRIG_512B + + /* And now leave some headspace - 256 bytes */ + AH5212(ah)->ah_maxTxTrigLev -= 4; +} + +uint32_t +ar5416GetRadioRev(struct ath_hal *ah) +{ + uint32_t val; + int i; + + /* Read Radio Chip Rev Extract */ + OS_REG_WRITE(ah, AR_PHY(0x36), 0x00007058); + for (i = 0; i < 8; i++) + OS_REG_WRITE(ah, AR_PHY(0x20), 0x00010000); + val = (OS_REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; + val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); + return ath_hal_reverseBits(val, 8); +} + +/* + * Attach for an AR5416 part. + */ +static struct ath_hal * +ar5416Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) +{ + struct ath_hal_5416 *ahp5416; + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + uint32_t val; + HAL_STATUS ecode; + HAL_BOOL rfStatus; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416) + + /* extra space for Owl 2.1/2.2 WAR */ + sizeof(ar5416Addac) + ); + if (ahp5416 == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ar5416InitState(ahp5416, devid, sc, st, sh, status); + ahp = &ahp5416->ah_5212; + ah = &ahp->ah_priv.h; + + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { + /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", __func__); + ecode = HAL_EIO; + goto bad; + } + + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", __func__); + ecode = HAL_EIO; + goto bad; + } + /* Read Revisions from Chips before taking out of reset */ + val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID; + AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S; + AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION; + AH_PRIVATE(ah)->ah_ispcie = (devid == AR5416_DEVID_PCIE); + + /* setup common ini data; rf backends handle remainder */ + HAL_INI_INIT(&ahp->ah_ini_modes, ar5416Modes, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar5416Common, 2); + + HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar5416BB_RfGain, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar5416Bank0, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar5416Bank1, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar5416Bank2, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar5416Bank3, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar5416Bank6, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar5416Bank7, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar5416Addac, 2); + + if (! IS_5416V2_2(ah)) { /* Owl 2.1/2.0 */ + ath_hal_printf(ah, "[ath] Enabling CLKDRV workaround for AR5416 < v2.2\n"); + struct ini { + uint32_t *data; /* NB: !const */ + int rows, cols; + }; + /* override CLKDRV value */ + OS_MEMCPY(&AH5416(ah)[1], ar5416Addac, sizeof(ar5416Addac)); + AH5416(ah)->ah_ini_addac.data = (uint32_t *) &AH5416(ah)[1]; + HAL_INI_VAL((struct ini *)&AH5416(ah)->ah_ini_addac, 31, 1) = 0; + } + + HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, ar5416PciePhy, 2); + ar5416AttachPCIE(ah); + + ecode = ath_hal_v14EepromAttach(ah); + if (ecode != HAL_OK) + goto bad; + + if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); + switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { + case AR_RAD5122_SREV_MAJOR: /* Fowl: 5G/2x2 */ + case AR_RAD2122_SREV_MAJOR: /* Fowl: 2+5G/2x2 */ + case AR_RAD2133_SREV_MAJOR: /* Fowl: 2G/3x3 */ + case AR_RAD5133_SREV_MAJOR: /* Fowl: 2+5G/3x3 */ + break; + default: + if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { + /* + * When RF_Silen is used the analog chip is reset. + * So when the system boots with radio switch off + * the RF chip rev reads back as zero and we need + * to use the mac+phy revs to set the radio rev. + */ + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5133_SREV_MAJOR; + break; + } + /* NB: silently accept anything in release code per Atheros */ +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; +#endif + } + + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar5416FillCapabilityInfo(ah)) { + ecode = HAL_EEREAD; + goto bad; + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + /* XXX How about the serial number ? */ + /* Read Reg Domain */ + AH_PRIVATE(ah)->ah_currentRD = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + AH_PRIVATE(ah)->ah_currentRDext = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL); + + /* + * ah_miscMode is populated by ar5416FillCapabilityInfo() + * starting from griffin. Set here to make sure that + * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is + * placed into hardware. + */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); + + rfStatus = ar2133RfAttach(ah, &ecode); + if (!rfStatus) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + + ar5416AniSetup(ah); /* Anti Noise Immunity */ + + AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ; + AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ; + AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ; + AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ; + AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ; + AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; + + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +bad: + if (ahp) + ar5416Detach((struct ath_hal *) ahp); + if (status) + *status = ecode; + return AH_NULL; +} + +void +ar5416Detach(struct ath_hal *ah) +{ + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); + + HALASSERT(ah != AH_NULL); + HALASSERT(ah->ah_magic == AR5416_MAGIC); + + /* Make sure that chip is awake before writing to it */ + if (! ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, + "%s: failed to wake up chip\n", + __func__); + + ar5416AniDetach(ah); + ar5212RfDetach(ah); + ah->ah_disable(ah); + ar5416SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE); + ath_hal_eepromDetach(ah); + ath_hal_free(ah); +} + +void +ar5416AttachPCIE(struct ath_hal *ah) +{ + if (AH_PRIVATE(ah)->ah_ispcie) + ath_hal_configPCIE(ah, AH_FALSE, AH_FALSE); + else + ath_hal_disablePCIE(ah); +} + +static void +ar5416ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) +{ + + /* This is only applicable for AR5418 (AR5416 PCIe) */ + if (! AH_PRIVATE(ah)->ah_ispcie) + return; + + if (! restore) { + ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0); + OS_DELAY(1000); + } + + if (power_off) { /* Power-off */ + /* clear bit 19 to disable L1 */ + OS_REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + } else { /* Power-on */ + /* Set default WAR values for Owl */ + OS_REG_WRITE(ah, AR_WA, AR_WA_DEFAULT); + + /* set bit 19 to allow forcing of pcie core into L1 state */ + OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + } +} + +/* + * Disable PCIe PHY if PCIe isn't used. + */ +static void +ar5416DisablePCIE(struct ath_hal *ah) +{ + + /* PCIe? Don't */ + if (AH_PRIVATE(ah)->ah_ispcie) + return; + + /* .. Only applicable for AR5416v2 or later */ + if (! (AR_SREV_OWL(ah) && AR_SREV_OWL_20_OR_LATER(ah))) + return; + + OS_REG_WRITE_BUFFER_ENABLE(ah); + + /* + * Disable the PCIe PHY. + */ + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); + OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007); + + /* Load the new settings */ + OS_REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); + + OS_REG_WRITE_BUFFER_FLUSH(ah); + OS_REG_WRITE_BUFFER_DISABLE(ah); +} + +static void +ar5416WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + u_int modesIndex, freqIndex; + int regWrites = 0; + + /* Setup the indices for the next set of register array writes */ + /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + freqIndex = 2; + if (IEEE80211_IS_CHAN_HT40(chan)) + modesIndex = 3; + else if (IEEE80211_IS_CHAN_108G(chan)) + modesIndex = 5; + else + modesIndex = 4; + } else { + freqIndex = 1; + if (IEEE80211_IS_CHAN_HT40(chan) || + IEEE80211_IS_CHAN_TURBO(chan)) + modesIndex = 2; + else + modesIndex = 1; + } + + /* Set correct Baseband to analog shift setting to access analog chips. */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* + * Write addac shifts + */ + OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); + + /* NB: only required for Sowl */ + if (AR_SREV_SOWL(ah)) + ar5416EepromSetAddac(ah, chan); + + regWrites = ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_addac, 1, + regWrites); + OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); + + regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, + modesIndex, regWrites); + regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, + 1, regWrites); + + /* XXX updated regWrites? */ + AH5212(ah)->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites); +} + +/* + * Convert to baseband spur frequency given input channel frequency + * and compute register settings below. + */ + +static void +ar5416SpurMitigate(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 }; + static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 }; + static const int inc[4] = { 0, 100, 0, 0 }; + + int bb_spur = AR_NO_SPUR; + int bin, cur_bin; + int spur_freq_sd; + int spur_delta_phase; + int denominator; + int upper, lower, cur_vit_mask; + int tmp, new; + int i; + + int8_t mask_m[123]; + int8_t mask_p[123]; + int8_t mask_amt; + int tmp_mask; + int cur_bb_spur; + HAL_BOOL is2GHz = IEEE80211_IS_CHAN_2GHZ(chan); + + OS_MEMZERO(mask_m, sizeof(mask_m)); + OS_MEMZERO(mask_p, sizeof(mask_p)); + + /* + * Need to verify range +/- 9.5 for static ht20, otherwise spur + * is out-of-band and can be ignored. + */ + /* XXX ath9k changes */ + for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { + cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz); + if (AR_NO_SPUR == cur_bb_spur) + break; + cur_bb_spur = cur_bb_spur - (freq * 10); + if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { + bb_spur = cur_bb_spur; + break; + } + } + if (AR_NO_SPUR == bb_spur) + return; + + bin = bb_spur * 32; + + tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0)); + new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | + AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + + OS_REG_WRITE_BUFFER_ENABLE(ah); + + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), new); + + new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | + AR_PHY_SPUR_REG_ENABLE_MASK_PPM | + AR_PHY_SPUR_REG_MASK_RATE_SELECT | + AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | + SM(AR5416_SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); + OS_REG_WRITE(ah, AR_PHY_SPUR_REG, new); + /* + * Should offset bb_spur by +/- 10 MHz for dynamic 2040 MHz + * config, no offset for HT20. + * spur_delta_phase = bb_spur/40 * 2**21 for static ht20, + * /80 for dyn2040. + */ + spur_delta_phase = ((bb_spur * 524288) / 100) & + AR_PHY_TIMING11_SPUR_DELTA_PHASE; + /* + * in 11A mode the denominator of spur_freq_sd should be 40 and + * it should be 44 in 11G + */ + denominator = IEEE80211_IS_CHAN_2GHZ(chan) ? 440 : 400; + spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; + + new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + OS_REG_WRITE(ah, AR_PHY_TIMING11, new); + + + /* + * ============================================ + * pilot mask 1 [31:0] = +6..-26, no 0 bin + * pilot mask 2 [19:0] = +26..+7 + * + * channel mask 1 [31:0] = +6..-26, no 0 bin + * channel mask 2 [19:0] = +26..+7 + */ + //cur_bin = -26; + cur_bin = -6000; + upper = bin + 100; + lower = bin - 100; + + for (i = 0; i < 4; i++) { + int pilot_mask = 0; + int chan_mask = 0; + int bp = 0; + for (bp = 0; bp < 30; bp++) { + if ((cur_bin > lower) && (cur_bin < upper)) { + pilot_mask = pilot_mask | 0x1 << bp; + chan_mask = chan_mask | 0x1 << bp; + } + cur_bin += 100; + } + cur_bin += inc[i]; + OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); + OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask); + } + + /* ================================================= + * viterbi mask 1 based on channel magnitude + * four levels 0-3 + * - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c) + * [1 2 2 1] for -9.6 or [1 2 1] for +16 + * - enable_mask_ppm, all bins move with freq + * + * - mask_select, 8 bits for rates (reg 67,0x990c) + * - mask_rate_cntl, 8 bits for rates (reg 67,0x990c) + * choose which mask to use mask or mask2 + */ + + /* + * viterbi mask 2 2nd set for per data rate puncturing + * four levels 0-3 + * - mask_select, 8 bits for rates (reg 67) + * - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994) + * [1 2 2 1] for -9.6 or [1 2 1] for +16 + */ + cur_vit_mask = 6100; + upper = bin + 120; + lower = bin - 120; + + for (i = 0; i < 123; i++) { + if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + if ((abs(cur_vit_mask - bin)) < 75) { + mask_amt = 1; + } else { + mask_amt = 0; + } + if (cur_vit_mask < 0) { + mask_m[abs(cur_vit_mask / 100)] = mask_amt; + } else { + mask_p[cur_vit_mask / 100] = mask_amt; + } + } + cur_vit_mask -= 100; + } + + tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) + | (mask_m[48] << 26) | (mask_m[49] << 24) + | (mask_m[50] << 22) | (mask_m[51] << 20) + | (mask_m[52] << 18) | (mask_m[53] << 16) + | (mask_m[54] << 14) | (mask_m[55] << 12) + | (mask_m[56] << 10) | (mask_m[57] << 8) + | (mask_m[58] << 6) | (mask_m[59] << 4) + | (mask_m[60] << 2) | (mask_m[61] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + + tmp_mask = (mask_m[31] << 28) + | (mask_m[32] << 26) | (mask_m[33] << 24) + | (mask_m[34] << 22) | (mask_m[35] << 20) + | (mask_m[36] << 18) | (mask_m[37] << 16) + | (mask_m[48] << 14) | (mask_m[39] << 12) + | (mask_m[40] << 10) | (mask_m[41] << 8) + | (mask_m[42] << 6) | (mask_m[43] << 4) + | (mask_m[44] << 2) | (mask_m[45] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + + tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) + | (mask_m[18] << 26) | (mask_m[18] << 24) + | (mask_m[20] << 22) | (mask_m[20] << 20) + | (mask_m[22] << 18) | (mask_m[22] << 16) + | (mask_m[24] << 14) | (mask_m[24] << 12) + | (mask_m[25] << 10) | (mask_m[26] << 8) + | (mask_m[27] << 6) | (mask_m[28] << 4) + | (mask_m[29] << 2) | (mask_m[30] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + + tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28) + | (mask_m[ 2] << 26) | (mask_m[ 3] << 24) + | (mask_m[ 4] << 22) | (mask_m[ 5] << 20) + | (mask_m[ 6] << 18) | (mask_m[ 7] << 16) + | (mask_m[ 8] << 14) | (mask_m[ 9] << 12) + | (mask_m[10] << 10) | (mask_m[11] << 8) + | (mask_m[12] << 6) | (mask_m[13] << 4) + | (mask_m[14] << 2) | (mask_m[15] << 0); + OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + + tmp_mask = (mask_p[15] << 28) + | (mask_p[14] << 26) | (mask_p[13] << 24) + | (mask_p[12] << 22) | (mask_p[11] << 20) + | (mask_p[10] << 18) | (mask_p[ 9] << 16) + | (mask_p[ 8] << 14) | (mask_p[ 7] << 12) + | (mask_p[ 6] << 10) | (mask_p[ 5] << 8) + | (mask_p[ 4] << 6) | (mask_p[ 3] << 4) + | (mask_p[ 2] << 2) | (mask_p[ 1] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + + tmp_mask = (mask_p[30] << 28) + | (mask_p[29] << 26) | (mask_p[28] << 24) + | (mask_p[27] << 22) | (mask_p[26] << 20) + | (mask_p[25] << 18) | (mask_p[24] << 16) + | (mask_p[23] << 14) | (mask_p[22] << 12) + | (mask_p[21] << 10) | (mask_p[20] << 8) + | (mask_p[19] << 6) | (mask_p[18] << 4) + | (mask_p[17] << 2) | (mask_p[16] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + + tmp_mask = (mask_p[45] << 28) + | (mask_p[44] << 26) | (mask_p[43] << 24) + | (mask_p[42] << 22) | (mask_p[41] << 20) + | (mask_p[40] << 18) | (mask_p[39] << 16) + | (mask_p[38] << 14) | (mask_p[37] << 12) + | (mask_p[36] << 10) | (mask_p[35] << 8) + | (mask_p[34] << 6) | (mask_p[33] << 4) + | (mask_p[32] << 2) | (mask_p[31] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + + tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) + | (mask_p[59] << 26) | (mask_p[58] << 24) + | (mask_p[57] << 22) | (mask_p[56] << 20) + | (mask_p[55] << 18) | (mask_p[54] << 16) + | (mask_p[53] << 14) | (mask_p[52] << 12) + | (mask_p[51] << 10) | (mask_p[50] << 8) + | (mask_p[49] << 6) | (mask_p[48] << 4) + | (mask_p[47] << 2) | (mask_p[46] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); + + OS_REG_WRITE_BUFFER_FLUSH(ah); + OS_REG_WRITE_BUFFER_DISABLE(ah); +} + +/* + * Fill all software cached or static hardware state information. + * Return failure if capabilities are to come from EEPROM and + * cannot be read. + */ +HAL_BOOL +ar5416FillCapabilityInfo(struct ath_hal *ah) +{ + struct ath_hal_private *ahpriv = AH_PRIVATE(ah); + HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; + uint16_t val; + + /* Construct wireless mode from EEPROM */ + pCap->halWirelessModes = 0; + if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { + pCap->halWirelessModes |= HAL_MODE_11A + | HAL_MODE_11NA_HT20 + | HAL_MODE_11NA_HT40PLUS + | HAL_MODE_11NA_HT40MINUS + ; + } + if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE)) { + pCap->halWirelessModes |= HAL_MODE_11G + | HAL_MODE_11NG_HT20 + | HAL_MODE_11NG_HT40PLUS + | HAL_MODE_11NG_HT40MINUS + ; + pCap->halWirelessModes |= HAL_MODE_11A + | HAL_MODE_11NA_HT20 + | HAL_MODE_11NA_HT40PLUS + | HAL_MODE_11NA_HT40MINUS + ; + } + + pCap->halLow2GhzChan = 2312; + pCap->halHigh2GhzChan = 2732; + + pCap->halLow5GhzChan = 4915; + pCap->halHigh5GhzChan = 6100; + + pCap->halCipherCkipSupport = AH_FALSE; + pCap->halCipherTkipSupport = AH_TRUE; + pCap->halCipherAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES); + + pCap->halMicCkipSupport = AH_FALSE; + pCap->halMicTkipSupport = AH_TRUE; + pCap->halMicAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES); + /* + * Starting with Griffin TX+RX mic keys can be combined + * in one key cache slot. + */ + pCap->halTkipMicTxRxKeySupport = AH_TRUE; + pCap->halChanSpreadSupport = AH_TRUE; + pCap->halSleepAfterBeaconBroken = AH_TRUE; + + pCap->halCompressSupport = AH_FALSE; + pCap->halBurstSupport = AH_TRUE; + pCap->halFastFramesSupport = AH_TRUE; + pCap->halChapTuningSupport = AH_TRUE; + pCap->halTurboPrimeSupport = AH_TRUE; + + pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G; + + pCap->halPSPollBroken = AH_TRUE; /* XXX fixed in later revs? */ + pCap->halNumMRRetries = 4; /* Hardware supports 4 MRR */ + pCap->halNumTxMaps = 1; /* Single TX ptr per descr */ + pCap->halVEOLSupport = AH_TRUE; + pCap->halBssIdMaskSupport = AH_TRUE; + pCap->halMcastKeySrchSupport = AH_TRUE; /* Works on AR5416 and later */ + pCap->halTsfAddSupport = AH_TRUE; + pCap->hal4AddrAggrSupport = AH_FALSE; /* Broken in Owl */ + pCap->halSpectralScanSupport = AH_FALSE; /* AR9280 and later */ + + if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK) + pCap->halTotalQueues = val; + else + pCap->halTotalQueues = HAL_NUM_TX_QUEUES; + + if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK) + pCap->halKeyCacheSize = val; + else + pCap->halKeyCacheSize = AR5416_KEYTABLE_SIZE; + + /* XXX Which chips? */ + pCap->halChanHalfRate = AH_TRUE; + pCap->halChanQuarterRate = AH_TRUE; + + pCap->halTstampPrecision = 32; + pCap->halHwPhyCounterSupport = AH_TRUE; + pCap->halIntrMask = HAL_INT_COMMON + | HAL_INT_RX + | HAL_INT_TX + | HAL_INT_FATAL + | HAL_INT_BNR + | HAL_INT_BMISC + | HAL_INT_DTIMSYNC + | HAL_INT_TSFOOR + | HAL_INT_CST + | HAL_INT_GTT + ; + + pCap->halFastCCSupport = AH_TRUE; + pCap->halNumGpioPins = 14; + pCap->halWowSupport = AH_FALSE; + pCap->halWowMatchPatternExact = AH_FALSE; + pCap->halBtCoexSupport = AH_FALSE; /* XXX need support */ + pCap->halAutoSleepSupport = AH_FALSE; + pCap->hal4kbSplitTransSupport = AH_TRUE; + /* Disable this so Block-ACK works correctly */ + pCap->halHasRxSelfLinkedTail = AH_FALSE; +#if 0 /* XXX not yet */ + pCap->halNumAntCfg2GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_2GHZ); + pCap->halNumAntCfg5GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_5GHZ); +#endif + pCap->halHTSupport = AH_TRUE; + pCap->halTxChainMask = ath_hal_eepromGet(ah, AR_EEP_TXMASK, AH_NULL); + /* XXX CB71 uses GPIO 0 to indicate 3 rx chains */ + pCap->halRxChainMask = ath_hal_eepromGet(ah, AR_EEP_RXMASK, AH_NULL); + /* AR5416 may have 3 antennas but is a 2x2 stream device */ + pCap->halTxStreams = 2; + pCap->halRxStreams = 2; + + /* + * If the TX or RX chainmask has less than 2 chains active, + * mark it as a 1-stream device for the relevant stream. + */ + if (owl_get_ntxchains(pCap->halTxChainMask) == 1) + pCap->halTxStreams = 1; + /* XXX Eww */ + if (owl_get_ntxchains(pCap->halRxChainMask) == 1) + pCap->halRxStreams = 1; + pCap->halRtsAggrLimit = 8*1024; /* Owl 2.0 limit */ + pCap->halMbssidAggrSupport = AH_FALSE; /* Broken on Owl */ + pCap->halForcePpmSupport = AH_TRUE; + pCap->halEnhancedPmSupport = AH_TRUE; + pCap->halBssidMatchSupport = AH_TRUE; + pCap->halGTTSupport = AH_TRUE; + pCap->halCSTSupport = AH_TRUE; + pCap->halEnhancedDfsSupport = AH_FALSE; + /* Hardware supports 32 bit TSF values in the RX descriptor */ + pCap->halHasLongRxDescTsf = AH_TRUE; + /* + * BB Read WAR: this is only for AR5008/AR9001 NICs + * It is also set individually in the AR91xx attach functions. + */ + if (AR_SREV_OWL(ah)) + pCap->halHasBBReadWar = AH_TRUE; + + if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) && + ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) { + /* NB: enabled by default */ + ahpriv->ah_rfkillEnabled = AH_TRUE; + pCap->halRfSilentSupport = AH_TRUE; + } + + /* + * The MAC will mark frames as RXed if there's a descriptor + * to write them to. So if it hits a self-linked final descriptor, + * it'll keep ACKing frames even though they're being silently + * dropped. Thus, this particular feature of the driver can't + * be used for 802.11n devices. + */ + ahpriv->ah_rxornIsFatal = AH_FALSE; + + /* + * If it's a PCI NIC, ask the HAL OS layer to serialise + * register access, or SMP machines may cause the hardware + * to hang. This is applicable to AR5416 and AR9220; I'm not + * sure about AR9160 or AR9227. + */ + if (! AH_PRIVATE(ah)->ah_ispcie) + pCap->halSerialiseRegWar = 1; + + /* + * AR5416 and later NICs support MYBEACON filtering. + */ + pCap->halRxDoMyBeacon = AH_TRUE; + + return AH_TRUE; +} + +static const char* +ar5416Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID) { + if (devid == AR5416_DEVID_PCI) + return "Atheros 5416"; + if (devid == AR5416_DEVID_PCIE) + return "Atheros 5418"; + } + return AH_NULL; +} +AH_CHIP(AR5416, ar5416Probe, ar5416Attach); diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_beacon.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_beacon.c new file mode 100644 index 0000000..6691c11 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_beacon.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#define TU_TO_USEC(_tu) ((_tu) << 10) +#define ONE_EIGHTH_TU_TO_USEC(_tu8) ((_tu8) << 7) + +/* + * Return the hardware NextTBTT in TSF + */ +uint64_t +ar5416GetNextTBTT(struct ath_hal *ah) +{ + return OS_REG_READ(ah, AR_NEXT_TBTT); +} + +/* + * Initialize all of the hardware registers used to + * send beacons. Note that for station operation the + * driver calls ar5416SetStaBeaconTimers instead. + */ +void +ar5416SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt) +{ + uint32_t bperiod; + struct ath_hal_5212 *ahp = AH5212(ah); + + OS_REG_WRITE(ah, AR_NEXT_TBTT, TU_TO_USEC(bt->bt_nexttbtt)); + OS_REG_WRITE(ah, AR_NEXT_DBA, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextdba)); + OS_REG_WRITE(ah, AR_NEXT_SWBA, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextswba)); + OS_REG_WRITE(ah, AR_NEXT_NDP, TU_TO_USEC(bt->bt_nextatim)); + + bperiod = TU_TO_USEC(bt->bt_intval & HAL_BEACON_PERIOD); + ahp->ah_beaconInterval = bt->bt_intval & HAL_BEACON_PERIOD; + OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, bperiod); + OS_REG_WRITE(ah, AR_DBA_PERIOD, bperiod); + OS_REG_WRITE(ah, AR_SWBA_PERIOD, bperiod); + OS_REG_WRITE(ah, AR_NDP_PERIOD, bperiod); + + /* + * Reset TSF if required. + */ + if (bt->bt_intval & AR_BEACON_RESET_TSF) + ar5416ResetTsf(ah); + + /* enable timers */ + /* NB: flags == 0 handled specially for backwards compatibility */ + OS_REG_SET_BIT(ah, AR_TIMER_MODE, + bt->bt_flags != 0 ? bt->bt_flags : + AR_TIMER_MODE_TBTT | AR_TIMER_MODE_DBA | AR_TIMER_MODE_SWBA); +} + +/* + * Initializes all of the hardware registers used to + * send beacons. Note that for station operation the + * driver calls ar5212SetStaBeaconTimers instead. + */ +void +ar5416BeaconInit(struct ath_hal *ah, + uint32_t next_beacon, uint32_t beacon_period) +{ + HAL_BEACON_TIMERS bt; + + bt.bt_nexttbtt = next_beacon; + /* + * TIMER1: in AP/adhoc mode this controls the DMA beacon + * alert timer; otherwise it controls the next wakeup time. + * TIMER2: in AP mode, it controls the SBA beacon alert + * interrupt; otherwise it sets the start of the next CFP. + */ + bt.bt_flags = 0; + switch (AH_PRIVATE(ah)->ah_opmode) { + case HAL_M_STA: + case HAL_M_MONITOR: + bt.bt_nextdba = 0xffff; + bt.bt_nextswba = 0x7ffff; + bt.bt_flags |= AR_TIMER_MODE_TBTT; + break; + case HAL_M_IBSS: + OS_REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ATIM_TXPOLICY); + bt.bt_flags |= AR_TIMER_MODE_NDP; + /* fall thru... */ + case HAL_M_HOSTAP: + bt.bt_nextdba = (next_beacon - + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ + bt.bt_nextswba = (next_beacon - + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ + bt.bt_flags |= AR_TIMER_MODE_TBTT + | AR_TIMER_MODE_DBA + | AR_TIMER_MODE_SWBA; + break; + } + /* + * Set the ATIM window + * Our hardware does not support an ATIM window of 0 + * (beacons will not work). If the ATIM windows is 0, + * force it to 1. + */ + bt.bt_nextatim = next_beacon + 1; + bt.bt_intval = beacon_period & + (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN); + ar5416SetBeaconTimers(ah, &bt); +} + +#define AR_BEACON_PERIOD_MAX 0xffff + +void +ar5416ResetStaBeaconTimers(struct ath_hal *ah) +{ + uint32_t val; + + OS_REG_WRITE(ah, AR_NEXT_TBTT, 0); /* no beacons */ + val = OS_REG_READ(ah, AR_STA_ID1); + val |= AR_STA_ID1_PWR_SAV; /* XXX */ + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + val & ~(AR_STA_ID1_USE_DEFANT | AR_STA_ID1_PCF)); + OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, AR_BEACON_PERIOD_MAX); + OS_REG_WRITE(ah, AR_DBA_PERIOD, AR_BEACON_PERIOD_MAX); +} + +/* + * Set all the beacon related bits on the h/w for stations + * i.e. initializes the corresponding h/w timers; + * also tells the h/w whether to anticipate PCF beacons + */ +void +ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) +{ + uint32_t nextTbtt, nextdtim,beaconintval, dtimperiod; + + HALASSERT(bs->bs_intval != 0); + + /* NB: no cfp setting since h/w automatically takes care */ + + OS_REG_WRITE(ah, AR_NEXT_TBTT, TU_TO_USEC(bs->bs_nexttbtt)); + + /* + * Start the beacon timers by setting the BEACON register + * to the beacon interval; no need to write tim offset since + * h/w parses IEs. + */ + OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, + TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD)); + OS_REG_WRITE(ah, AR_DBA_PERIOD, + TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD)); + + /* + * Configure the BMISS interrupt. Note that we + * assume the caller blocks interrupts while enabling + * the threshold. + */ + HALASSERT(bs->bs_bmissthreshold <= + (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S)); + OS_REG_RMW_FIELD(ah, AR_RSSI_THR, + AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); + + /* + * Program the sleep registers to correlate with the beacon setup. + */ + + /* + * Oahu beacons timers on the station were used for power + * save operation (waking up in anticipation of a beacon) + * and any CFP function; Venice does sleep/power-save timers + * differently - so this is the right place to set them up; + * don't think the beacon timers are used by venice sta hw + * for any useful purpose anymore + * Setup venice's sleep related timers + * Current implementation assumes sw processing of beacons - + * assuming an interrupt is generated every beacon which + * causes the hardware to become awake until the sw tells + * it to go to sleep again; beacon timeout is to allow for + * beacon jitter; cab timeout is max time to wait for cab + * after seeing the last DTIM or MORE CAB bit + */ + +/* + * I've bumped these to 30TU for now. + * + * Some APs (AR933x/AR934x?) in 2GHz especially seem to not always + * transmit beacon frames at exactly the right times and with it set + * to 10TU, the NIC starts not waking up at the right times to hear + * these slightly-larger-jitering beacons. It also never recovers + * from that (it doesn't resync? I'm not sure.) + * + * So for now bump this to 30TU. Ideally we'd cap this based on + * the beacon interval so the sum of CAB+BEACON timeouts never + * exceeded the beacon interval. + * + * Now, since we're doing all the math in the ath(4) driver in TU + * rather than TSF, we may be seeing the result of dumb rounding + * errors causing the jitter to actually be a much bigger problem. + * I'll have to investigate that with a fine tooth comb. + */ +#define CAB_TIMEOUT_VAL 10 /* in TU */ +#define BEACON_TIMEOUT_VAL 10 /* in TU */ +#define SLEEP_SLOP 3 /* in TU */ + + /* + * For max powersave mode we may want to sleep for longer than a + * beacon period and not want to receive all beacons; modify the + * timers accordingly; make sure to align the next TIM to the + * next DTIM if we decide to wake for DTIMs only + */ + beaconintval = bs->bs_intval & HAL_BEACON_PERIOD; + HALASSERT(beaconintval != 0); + if (bs->bs_sleepduration > beaconintval) { + HALASSERT(roundup(bs->bs_sleepduration, beaconintval) == + bs->bs_sleepduration); + beaconintval = bs->bs_sleepduration; + } + dtimperiod = bs->bs_dtimperiod; + if (bs->bs_sleepduration > dtimperiod) { + HALASSERT(dtimperiod == 0 || + roundup(bs->bs_sleepduration, dtimperiod) == + bs->bs_sleepduration); + dtimperiod = bs->bs_sleepduration; + } + HALASSERT(beaconintval <= dtimperiod); + if (beaconintval == dtimperiod) + nextTbtt = bs->bs_nextdtim; + else + nextTbtt = bs->bs_nexttbtt; + nextdtim = bs->bs_nextdtim; + + OS_REG_WRITE(ah, AR_NEXT_DTIM, + TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); + OS_REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP)); + + /* cab timeout is now in 1/8 TU */ + OS_REG_WRITE(ah, AR5416_SLEEP1, + SM((CAB_TIMEOUT_VAL << 3), AR5416_SLEEP1_CAB_TIMEOUT) + | AR5416_SLEEP1_ASSUME_DTIM); + + /* XXX autosleep? Use min beacon timeout; check ath9k -adrian */ + /* beacon timeout is now in 1/8 TU */ + OS_REG_WRITE(ah, AR5416_SLEEP2, + SM((BEACON_TIMEOUT_VAL << 3), AR5416_SLEEP2_BEACON_TIMEOUT)); + + /* TIM_PERIOD and DTIM_PERIOD are now in uS. */ + OS_REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval)); + OS_REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); + + OS_REG_SET_BIT(ah, AR_TIMER_MODE, + AR_TIMER_MODE_TBTT | AR_TIMER_MODE_TIM | AR_TIMER_MODE_DTIM); + +#define HAL_TSFOOR_THRESHOLD 0x00004240 /* TSF OOR threshold (16k us) */ + + /* TSF out of range threshold */ +// OS_REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold); + OS_REG_WRITE(ah, AR_TSFOOR_THRESHOLD, HAL_TSFOOR_THRESHOLD); + + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n", + __func__, bs->bs_nextdtim); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next beacon %d\n", + __func__, nextTbtt); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: beacon period %d\n", + __func__, beaconintval); + HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: DTIM period %d\n", + __func__, dtimperiod); +#undef CAB_TIMEOUT_VAL +#undef BEACON_TIMEOUT_VAL +#undef SLEEP_SLOP +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_btcoex.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_btcoex.c new file mode 100644 index 0000000..c73b0ee --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_btcoex.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2005 Atheros Communications, Inc. + * Copyright (c) 2008-2010, Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#ifdef AH_DEBUG +#include "ah_desc.h" /* NB: for HAL_PHYERR* */ +#endif + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar5416/ar5416desc.h" /* AR5416_CONTTXMODE */ +#include "ar5416/ar5416_btcoex.h" + +void +ar5416SetBTCoexInfo(struct ath_hal *ah, HAL_BT_COEX_INFO *btinfo) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + ahp->ah_btModule = btinfo->bt_module; + ahp->ah_btCoexConfigType = btinfo->bt_coex_config; + ahp->ah_btActiveGpioSelect = btinfo->bt_gpio_bt_active; + ahp->ah_btPriorityGpioSelect = btinfo->bt_gpio_bt_priority; + ahp->ah_wlanActiveGpioSelect = btinfo->bt_gpio_wlan_active; + ahp->ah_btActivePolarity = btinfo->bt_active_polarity; + ahp->ah_btCoexSingleAnt = btinfo->bt_single_ant; + ahp->ah_btWlanIsolation = btinfo->bt_isolation; +} + +void +ar5416BTCoexConfig(struct ath_hal *ah, HAL_BT_COEX_CONFIG *btconf) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + HAL_BOOL rxClearPolarity = btconf->bt_rxclear_polarity; + + /* + * For Kiwi and Osprey, the polarity of rx_clear is active high. + * The bt_rxclear_polarity flag from ath(4) needs to be inverted. + */ + if (AR_SREV_KIWI(ah)) { + rxClearPolarity = !btconf->bt_rxclear_polarity; + } + + ahp->ah_btCoexMode = (ahp->ah_btCoexMode & AR_BT_QCU_THRESH) | + SM(btconf->bt_time_extend, AR_BT_TIME_EXTEND) | + SM(btconf->bt_txstate_extend, AR_BT_TXSTATE_EXTEND) | + SM(btconf->bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | + SM(btconf->bt_mode, AR_BT_MODE) | + SM(btconf->bt_quiet_collision, AR_BT_QUIET) | + SM(rxClearPolarity, AR_BT_RX_CLEAR_POLARITY) | + SM(btconf->bt_priority_time, AR_BT_PRIORITY_TIME) | + SM(btconf->bt_first_slot_time, AR_BT_FIRST_SLOT_TIME); + + ahp->ah_btCoexMode2 |= SM(btconf->bt_hold_rxclear, + AR_BT_HOLD_RX_CLEAR); + + if (ahp->ah_btCoexSingleAnt == AH_FALSE) { + /* Enable ACK to go out even though BT has higher priority. */ + ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT; + } +} + +void +ar5416BTCoexSetQcuThresh(struct ath_hal *ah, int qnum) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + ahp->ah_btCoexMode |= SM(qnum, AR_BT_QCU_THRESH); +} + +void +ar5416BTCoexSetWeights(struct ath_hal *ah, u_int32_t stompType) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + if (AR_SREV_KIWI_10_OR_LATER(ah)) { + /* TODO: TX RX seperate is not enabled. */ + switch (stompType) { + case HAL_BT_COEX_STOMP_ALL: + ahp->ah_btCoexBTWeight = AR5416_BT_WGHT; + ahp->ah_btCoexWLANWeight = AR5416_STOMP_ALL_WLAN_WGHT; + break; + case HAL_BT_COEX_STOMP_LOW: + ahp->ah_btCoexBTWeight = AR5416_BT_WGHT; + ahp->ah_btCoexWLANWeight = AR5416_STOMP_LOW_WLAN_WGHT; + break; + case HAL_BT_COEX_STOMP_ALL_FORCE: + ahp->ah_btCoexBTWeight = AR5416_BT_WGHT; + ahp->ah_btCoexWLANWeight = + AR5416_STOMP_ALL_FORCE_WLAN_WGHT; + break; + case HAL_BT_COEX_STOMP_LOW_FORCE: + ahp->ah_btCoexBTWeight = AR5416_BT_WGHT; + ahp->ah_btCoexWLANWeight = + AR5416_STOMP_LOW_FORCE_WLAN_WGHT; + break; + case HAL_BT_COEX_STOMP_NONE: + case HAL_BT_COEX_NO_STOMP: + ahp->ah_btCoexBTWeight = AR5416_BT_WGHT; + ahp->ah_btCoexWLANWeight = AR5416_STOMP_NONE_WLAN_WGHT; + break; + default: + /* There is a forceWeight from registry */ + ahp->ah_btCoexBTWeight = stompType & 0xffff; + ahp->ah_btCoexWLANWeight = stompType >> 16; + break; + } + } else { + switch (stompType) { + case HAL_BT_COEX_STOMP_ALL: + ahp->ah_btCoexBTWeight = AR5416_BT_WGHT; + ahp->ah_btCoexWLANWeight = AR5416_STOMP_ALL_WLAN_WGHT; + break; + case HAL_BT_COEX_STOMP_LOW: + ahp->ah_btCoexBTWeight = AR5416_BT_WGHT; + ahp->ah_btCoexWLANWeight = AR5416_STOMP_LOW_WLAN_WGHT; + break; + case HAL_BT_COEX_STOMP_ALL_FORCE: + ahp->ah_btCoexBTWeight = AR5416_BT_WGHT; + ahp->ah_btCoexWLANWeight = + AR5416_STOMP_ALL_FORCE_WLAN_WGHT; + break; + case HAL_BT_COEX_STOMP_LOW_FORCE: + ahp->ah_btCoexBTWeight = AR5416_BT_WGHT; + ahp->ah_btCoexWLANWeight = + AR5416_STOMP_LOW_FORCE_WLAN_WGHT; + break; + case HAL_BT_COEX_STOMP_NONE: + case HAL_BT_COEX_NO_STOMP: + ahp->ah_btCoexBTWeight = AR5416_BT_WGHT; + ahp->ah_btCoexWLANWeight = AR5416_STOMP_NONE_WLAN_WGHT; + break; + default: + /* There is a forceWeight from registry */ + ahp->ah_btCoexBTWeight = stompType & 0xffff; + ahp->ah_btCoexWLANWeight = stompType >> 16; + break; + } + } +} + +void +ar5416BTCoexSetupBmissThresh(struct ath_hal *ah, u_int32_t thresh) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + ahp->ah_btCoexMode2 |= SM(thresh, AR_BT_BCN_MISS_THRESH); +} + +/* + * There is no antenna diversity for Owl, Kiwi, etc. + * + * Kite will override this particular method. + */ +void +ar5416BTCoexAntennaDiversity(struct ath_hal *ah) +{ +} + +void +ar5416BTCoexSetParameter(struct ath_hal *ah, u_int32_t type, u_int32_t value) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + switch (type) { + case HAL_BT_COEX_SET_ACK_PWR: + if (value) { + ahp->ah_btCoexFlag |= HAL_BT_COEX_FLAG_LOW_ACK_PWR; + OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_LOW_ACK_POWER); + } else { + ahp->ah_btCoexFlag &= ~HAL_BT_COEX_FLAG_LOW_ACK_PWR; + OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_HIGH_ACK_POWER); + } + break; + case HAL_BT_COEX_ANTENNA_DIVERSITY: + /* This is overridden for Kite */ + break; +#if 0 + case HAL_BT_COEX_LOWER_TX_PWR: + if (value) { + if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) == 0) { + ahp->ah_btCoexFlag |= HAL_BT_COEX_FLAG_LOWER_TX_PWR; + AH_PRIVATE(ah)->ah_config.ath_hal_desc_tpc = 1; + ar5416SetTxPowerLimit(ah, AH_PRIVATE(ah)->ah_power_limit, AH_PRIVATE(ah)->ah_extra_txpow, 0); + } + } + else { + if (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) { + ahp->ah_btCoexFlag &= ~HAL_BT_COEX_FLAG_LOWER_TX_PWR; + AH_PRIVATE(ah)->ah_config.ath_hal_desc_tpc = 0; + ar5416SetTxPowerLimit(ah, AH_PRIVATE(ah)->ah_power_limit, AH_PRIVATE(ah)->ah_extra_txpow, 0); + } + } + break; +#endif + default: + break; + } +} + +void +ar5416BTCoexDisable(struct ath_hal *ah) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + /* Always drive rx_clear_external output as 0 */ + ar5416GpioSet(ah, ahp->ah_wlanActiveGpioSelect, 0); + ar5416GpioCfgOutput(ah, ahp->ah_wlanActiveGpioSelect, + HAL_GPIO_OUTPUT_MUX_AS_OUTPUT); + + if (AR_SREV_9271(ah)) { + /* + * Set wlanActiveGpio to input when disabling BT-COEX to + * reduce power consumption + */ + ar5416GpioCfgInput(ah, ahp->ah_wlanActiveGpioSelect); + } + + if (ahp->ah_btCoexSingleAnt == AH_TRUE) { + OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, + 1); + OS_REG_RMW_FIELD(ah, AR_MISC_MODE, AR_PCU_BT_ANT_PREVENT_RX, + 0); + } + + OS_REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); + OS_REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); + if (AR_SREV_KIWI_10_OR_LATER(ah)) + OS_REG_WRITE(ah, AR_BT_COEX_WEIGHT2, 0); + OS_REG_WRITE(ah, AR_BT_COEX_MODE2, 0); + + ahp->ah_btCoexEnabled = AH_FALSE; +} + +int +ar5416BTCoexEnable(struct ath_hal *ah) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + /* Program coex mode and weight registers to actually enable coex */ + OS_REG_WRITE(ah, AR_BT_COEX_MODE, ahp->ah_btCoexMode); + OS_REG_WRITE(ah, AR_BT_COEX_WEIGHT, + SM(ahp->ah_btCoexWLANWeight & 0xFFFF, AR_BT_WL_WGHT) | + SM(ahp->ah_btCoexBTWeight & 0xFFFF, AR_BT_BT_WGHT)); + if (AR_SREV_KIWI_10_OR_LATER(ah)) { + OS_REG_WRITE(ah, AR_BT_COEX_WEIGHT2, + SM(ahp->ah_btCoexWLANWeight >> 16, AR_BT_WL_WGHT)); + } + OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); + + /* Added Select GPIO5~8 instaed SPI */ + if (AR_SREV_9271(ah)) { + uint32_t val; + + val = OS_REG_READ(ah, AR9271_CLOCK_CONTROL); + val &= 0xFFFFFEFF; + OS_REG_WRITE(ah, AR9271_CLOCK_CONTROL, val); + } + + if (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_LOW_ACK_PWR) + OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_LOW_ACK_POWER); + else + OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_HIGH_ACK_POWER); + + if (ahp->ah_btCoexSingleAnt == AH_TRUE) { + OS_REG_RMW_FIELD(ah, AR_QUIET1, + AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); + /* XXX should update miscMode? */ + OS_REG_RMW_FIELD(ah, AR_MISC_MODE, + AR_PCU_BT_ANT_PREVENT_RX, 1); + } else { + OS_REG_RMW_FIELD(ah, AR_QUIET1, + AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); + /* XXX should update miscMode? */ + OS_REG_RMW_FIELD(ah, AR_MISC_MODE, + AR_PCU_BT_ANT_PREVENT_RX, 0); + } + + if (ahp->ah_btCoexConfigType == HAL_BT_COEX_CFG_3WIRE) { + /* For 3-wire, configure the desired GPIO port for rx_clear */ + ar5416GpioCfgOutput(ah, ahp->ah_wlanActiveGpioSelect, + HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE); + } else { + /* + * For 2-wire, configure the desired GPIO port + * for TX_FRAME output + */ + ar5416GpioCfgOutput(ah, ahp->ah_wlanActiveGpioSelect, + HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME); + } + + /* + * Enable a weak pull down on BT_ACTIVE. + * When BT device is disabled, BT_ACTIVE might be floating. + */ + OS_REG_RMW(ah, AR_GPIO_PDPU, + (0x2 << (ahp->ah_btActiveGpioSelect * 2)), + (0x3 << (ahp->ah_btActiveGpioSelect * 2))); + + ahp->ah_btCoexEnabled = AH_TRUE; + + return (0); +} + +void +ar5416InitBTCoex(struct ath_hal *ah) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + HALDEBUG(ah, HAL_DEBUG_BT_COEX, + "%s: called; configType=%d\n", + __func__, + ahp->ah_btCoexConfigType); + + if (ahp->ah_btCoexConfigType == HAL_BT_COEX_CFG_3WIRE) { + OS_REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, + (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB | + AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB)); + + /* + * Set input mux for bt_prority_async and + * bt_active_async to GPIO pins + */ + OS_REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, + AR_GPIO_INPUT_MUX1_BT_ACTIVE, + ahp->ah_btActiveGpioSelect); + OS_REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, + AR_GPIO_INPUT_MUX1_BT_PRIORITY, + ahp->ah_btPriorityGpioSelect); + + /* + * Configure the desired GPIO ports for input + */ + ar5416GpioCfgInput(ah, ahp->ah_btActiveGpioSelect); + ar5416GpioCfgInput(ah, ahp->ah_btPriorityGpioSelect); + + /* + * Configure the antenna diversity setup. + * It's a no-op for AR9287; AR9285 overrides this + * as required. + */ + AH5416(ah)->ah_btCoexSetDiversity(ah); + + if (ahp->ah_btCoexEnabled) + ar5416BTCoexEnable(ah); + else + ar5416BTCoexDisable(ah); + } else if (ahp->ah_btCoexConfigType != HAL_BT_COEX_CFG_NONE) { + /* 2-wire */ + if (ahp->ah_btCoexEnabled) { + /* Connect bt_active_async to baseband */ + OS_REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL, + (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF | + AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF)); + OS_REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, + AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); + + /* + * Set input mux for bt_prority_async and + * bt_active_async to GPIO pins + */ + OS_REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, + AR_GPIO_INPUT_MUX1_BT_ACTIVE, + ahp->ah_btActiveGpioSelect); + + /* Configure the desired GPIO ports for input */ + ar5416GpioCfgInput(ah, ahp->ah_btActiveGpioSelect); + + /* Enable coexistence on initialization */ + ar5416BTCoexEnable(ah); + } + } +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_btcoex.h b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_btcoex.h new file mode 100644 index 0000000..0d3e316 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_btcoex.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __ATH_AR5416_BTCOEX_H__ +#define __ATH_AR5416_BTCOEX_H__ +/* + * Weight table configurations. + */ +#define AR5416_BT_WGHT 0xff55 +#define AR5416_STOMP_ALL_WLAN_WGHT 0xfcfc +#define AR5416_STOMP_LOW_WLAN_WGHT 0xa8a8 +#define AR5416_STOMP_NONE_WLAN_WGHT 0x0000 +#define AR5416_STOMP_ALL_FORCE_WLAN_WGHT 0xffff // Stomp BT even when WLAN is idle +#define AR5416_STOMP_LOW_FORCE_WLAN_WGHT 0xaaaa // Stomp BT even when WLAN is idle + +#endif /* __ATH_AR5416_BTCOEX_H__ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal.c new file mode 100644 index 0000000..35bb8d4 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal.c @@ -0,0 +1,832 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" + +#include "ar5212/ar5212.h" /* for NF cal related declarations */ + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* Owl specific stuff */ +#define NUM_NOISEFLOOR_READINGS 6 /* 3 chains * (ctl + ext) */ + +static void ar5416StartNFCal(struct ath_hal *ah); +static void ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *); +static int16_t ar5416GetNf(struct ath_hal *, struct ieee80211_channel *); + +static uint16_t ar5416GetDefaultNF(struct ath_hal *ah, const struct ieee80211_channel *chan); +static void ar5416SanitizeNF(struct ath_hal *ah, int16_t *nf); + +/* + * Determine if calibration is supported by device and channel flags + */ + +/* + * ADC GAIN/DC offset calibration is for calibrating two ADCs that + * are acting as one by interleaving incoming symbols. This isn't + * relevant for 2.4GHz 20MHz wide modes because, as far as I can tell, + * the secondary ADC is never enabled. It is enabled however for + * 5GHz modes. + * + * It hasn't been confirmed whether doing this calibration is needed + * at all in the above modes and/or whether it's actually harmful. + * So for now, let's leave it enabled and just remember to get + * confirmation that it needs to be clarified. + * + * See US Patent No: US 7,541,952 B1: + * " Method and Apparatus for Offset and Gain Compensation for + * Analog-to-Digital Converters." + */ +static OS_INLINE HAL_BOOL +ar5416IsCalSupp(struct ath_hal *ah, const struct ieee80211_channel *chan, + HAL_CAL_TYPE calType) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + + switch (calType & cal->suppCals) { + case IQ_MISMATCH_CAL: + /* Run IQ Mismatch for non-CCK only */ + return !IEEE80211_IS_CHAN_B(chan); + case ADC_GAIN_CAL: + case ADC_DC_CAL: + /* + * Run ADC Gain Cal for either 5ghz any or 2ghz HT40. + * + * Don't run ADC calibrations for 5ghz fast clock mode + * in HT20 - only one ADC is used. + */ + if (IEEE80211_IS_CHAN_HT20(chan) && + (IS_5GHZ_FAST_CLOCK_EN(ah, chan))) + return AH_FALSE; + if (IEEE80211_IS_CHAN_5GHZ(chan)) + return AH_TRUE; + if (IEEE80211_IS_CHAN_HT40(chan)) + return AH_TRUE; + return AH_FALSE; + } + return AH_FALSE; +} + +/* + * Setup HW to collect samples used for current cal + */ +static void +ar5416SetupMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal) +{ + /* Start calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */ + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, + currCal->calData->calCountMax); + + /* Select calibration to run */ + switch (currCal->calData->calType) { + case IQ_MISMATCH_CAL: + OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: start IQ Mismatch calibration\n", __func__); + break; + case ADC_GAIN_CAL: + OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: start ADC Gain calibration\n", __func__); + break; + case ADC_DC_CAL: + OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: start ADC DC calibration\n", __func__); + break; + case ADC_DC_INIT_CAL: + OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: start Init ADC DC calibration\n", __func__); + break; + } + /* Kick-off cal */ + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL); +} + +/* + * Initialize shared data structures and prepare a cal to be run. + */ +static void +ar5416ResetMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + + /* Reset data structures shared between different calibrations */ + OS_MEMZERO(cal->caldata, sizeof(cal->caldata)); + cal->calSamples = 0; + + /* Setup HW for new calibration */ + ar5416SetupMeasurement(ah, currCal); + + /* Change SW state to RUNNING for this calibration */ + currCal->calState = CAL_RUNNING; +} + +#if 0 +/* + * Run non-periodic calibrations. + */ +static HAL_BOOL +ar5416RunInitCals(struct ath_hal *ah, int init_cal_count) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CHANNEL_INTERNAL ichan; /* XXX bogus */ + HAL_CAL_LIST *curCal = ahp->ah_cal_curr; + HAL_BOOL isCalDone; + int i; + + if (curCal == AH_NULL) + return AH_FALSE; + + ichan.calValid = 0; + for (i = 0; i < init_cal_count; i++) { + /* Reset this Cal */ + ar5416ResetMeasurement(ah, curCal); + /* Poll for offset calibration complete */ + if (!ath_hal_wait(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Cal %d failed to finish in 100ms.\n", + __func__, curCal->calData->calType); + /* Re-initialize list pointers for periodic cals */ + cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL; + return AH_FALSE; + } + /* Run this cal */ + ar5416DoCalibration(ah, &ichan, ahp->ah_rxchainmask, + curCal, &isCalDone); + if (!isCalDone) + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: init cal %d did not complete.\n", + __func__, curCal->calData->calType); + if (curCal->calNext != AH_NULL) + curCal = curCal->calNext; + } + + /* Re-initialize list pointers for periodic cals */ + cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL; + return AH_TRUE; +} +#endif + + +/* + * AGC calibration for the AR5416, AR9130, AR9160, AR9280. + */ +HAL_BOOL +ar5416InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + /* Disable ADC */ + OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, + AR_PHY_ADC_CTL_OFF_PWDADC); + + /* Enable Rx Filter Cal */ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_FLTR_CAL); + } + + /* Calibrate the AGC */ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); + + /* Poll for offset calibration complete */ + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: offset calibration did not complete in 1ms; " + "noisy environment?\n", __func__); + return AH_FALSE; + } + + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + /* Enable ADC */ + OS_REG_SET_BIT(ah, AR_PHY_ADC_CTL, + AR_PHY_ADC_CTL_OFF_PWDADC); + + /* Disable Rx Filter Cal */ + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_FLTR_CAL); + } + + return AH_TRUE; +} + +/* + * Initialize Calibration infrastructure. + */ +#define MAX_CAL_CHECK 32 +HAL_BOOL +ar5416InitCal(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CHANNEL_INTERNAL *ichan; + + ichan = ath_hal_checkchannel(ah, chan); + HALASSERT(ichan != AH_NULL); + + /* Do initial chipset-specific calibration */ + if (! AH5416(ah)->ah_cal_initcal(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: initial chipset calibration did " + "not complete in time; noisy environment?\n", __func__); + return AH_FALSE; + } + + /* If there's PA Cal, do it */ + if (AH5416(ah)->ah_cal_pacal) + AH5416(ah)->ah_cal_pacal(ah, AH_TRUE); + + /* + * Do NF calibration after DC offset and other CALs. + * Per system engineers, noise floor value can sometimes be 20 dB + * higher than normal value if DC offset and noise floor cal are + * triggered at the same time. + */ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + + /* + * This may take a while to run; make sure subsequent + * calibration routines check that this has completed + * before reading the value and triggering a subsequent + * calibration. + */ + + /* Initialize list pointers */ + cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL; + + /* + * Enable IQ, ADC Gain, ADC DC Offset Cals + */ + if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah)) { + /* Setup all non-periodic, init time only calibrations */ + /* XXX: Init DC Offset not working yet */ +#if 0 + if (ar5416IsCalSupp(ah, chan, ADC_DC_INIT_CAL)) { + INIT_CAL(&cal->adcDcCalInitData); + INSERT_CAL(cal, &cal->adcDcCalInitData); + } + /* Initialize current pointer to first element in list */ + cal->cal_curr = cal->cal_list; + + if (cal->ah_cal_curr != AH_NULL && !ar5416RunInitCals(ah, 0)) + return AH_FALSE; +#endif + } + + /* If Cals are supported, add them to list via INIT/INSERT_CAL */ + if (ar5416IsCalSupp(ah, chan, ADC_GAIN_CAL)) { + INIT_CAL(&cal->adcGainCalData); + INSERT_CAL(cal, &cal->adcGainCalData); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: enable ADC Gain Calibration.\n", __func__); + } + if (ar5416IsCalSupp(ah, chan, ADC_DC_CAL)) { + INIT_CAL(&cal->adcDcCalData); + INSERT_CAL(cal, &cal->adcDcCalData); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: enable ADC DC Calibration.\n", __func__); + } + if (ar5416IsCalSupp(ah, chan, IQ_MISMATCH_CAL)) { + INIT_CAL(&cal->iqCalData); + INSERT_CAL(cal, &cal->iqCalData); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: enable IQ Calibration.\n", __func__); + } + /* Initialize current pointer to first element in list */ + cal->cal_curr = cal->cal_list; + + /* Kick off measurements for the first cal */ + if (cal->cal_curr != AH_NULL) + ar5416ResetMeasurement(ah, cal->cal_curr); + + /* Mark all calibrations on this channel as being invalid */ + ichan->calValid = 0; + + return AH_TRUE; +#undef MAX_CAL_CHECK +} + +/* + * Entry point for upper layers to restart current cal. + * Reset the calibration valid bit in channel. + */ +HAL_BOOL +ar5416ResetCalValid(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); + HAL_CAL_LIST *currCal = cal->cal_curr; + + if (!AR_SREV_SOWL_10_OR_LATER(ah)) + return AH_FALSE; + if (currCal == AH_NULL) + return AH_FALSE; + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->ic_freq, chan->ic_flags); + return AH_FALSE; + } + /* + * Expected that this calibration has run before, post-reset. + * Current state should be done + */ + if (currCal->calState != CAL_DONE) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Calibration state incorrect, %d\n", + __func__, currCal->calState); + return AH_FALSE; + } + + /* Verify Cal is supported on this channel */ + if (!ar5416IsCalSupp(ah, chan, currCal->calData->calType)) + return AH_FALSE; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: Resetting Cal %d state for channel %u/0x%x\n", + __func__, currCal->calData->calType, chan->ic_freq, + chan->ic_flags); + + /* Disable cal validity in channel */ + ichan->calValid &= ~currCal->calData->calType; + currCal->calState = CAL_WAITING; + + return AH_TRUE; +} + +/* + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +static void +ar5416DoCalibration(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan, + uint8_t rxchainmask, HAL_CAL_LIST *currCal, HAL_BOOL *isCalDone) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + + /* Cal is assumed not done until explicitly set below */ + *isCalDone = AH_FALSE; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: %s Calibration, state %d, calValid 0x%x\n", + __func__, currCal->calData->calName, currCal->calState, + ichan->calValid); + + /* Calibration in progress. */ + if (currCal->calState == CAL_RUNNING) { + /* Check to see if it has finished. */ + if (!(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_CAL)) { + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: sample %d of %d finished\n", + __func__, cal->calSamples, + currCal->calData->calNumSamples); + /* + * Collect measurements for active chains. + */ + currCal->calData->calCollect(ah); + if (++cal->calSamples >= currCal->calData->calNumSamples) { + int i, numChains = 0; + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + if (rxchainmask & (1 << i)) + numChains++; + } + /* + * Process accumulated data + */ + currCal->calData->calPostProc(ah, numChains); + + /* Calibration has finished. */ + ichan->calValid |= currCal->calData->calType; + currCal->calState = CAL_DONE; + *isCalDone = AH_TRUE; + } else { + /* + * Set-up to collect of another sub-sample. + */ + ar5416SetupMeasurement(ah, currCal); + } + } + } else if (!(ichan->calValid & currCal->calData->calType)) { + /* If current cal is marked invalid in channel, kick it off */ + ar5416ResetMeasurement(ah, currCal); + } +} + +/* + * Internal interface to schedule periodic calibration work. + */ +HAL_BOOL +ar5416PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan, + u_int rxchainmask, HAL_BOOL longcal, HAL_BOOL *isCalDone) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CAL_LIST *currCal = cal->cal_curr; + HAL_CHANNEL_INTERNAL *ichan; + int r; + + OS_MARK(ah, AH_MARK_PERCAL, chan->ic_freq); + + *isCalDone = AH_TRUE; + + /* + * Since ath_hal calls the PerCal method with rxchainmask=0x1; + * override it with the current chainmask. The upper levels currently + * doesn't know about the chainmask. + */ + rxchainmask = AH5416(ah)->ah_rx_chainmask; + + /* Invalid channel check */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->ic_freq, chan->ic_flags); + return AH_FALSE; + } + + /* + * For given calibration: + * 1. Call generic cal routine + * 2. When this cal is done (isCalDone) if we have more cals waiting + * (eg after reset), mask this to upper layers by not propagating + * isCalDone if it is set to TRUE. + * Instead, change isCalDone to FALSE and setup the waiting cal(s) + * to be run. + */ + if (currCal != AH_NULL && + (currCal->calState == CAL_RUNNING || + currCal->calState == CAL_WAITING)) { + ar5416DoCalibration(ah, ichan, rxchainmask, currCal, isCalDone); + if (*isCalDone == AH_TRUE) { + cal->cal_curr = currCal = currCal->calNext; + if (currCal->calState == CAL_WAITING) { + *isCalDone = AH_FALSE; + ar5416ResetMeasurement(ah, currCal); + } + } + } + + /* Do NF cal only at longer intervals */ + if (longcal) { + /* Do PA calibration if the chipset supports */ + if (AH5416(ah)->ah_cal_pacal) + AH5416(ah)->ah_cal_pacal(ah, AH_FALSE); + + /* Do open-loop temperature compensation if the chipset needs it */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) + AH5416(ah)->ah_olcTempCompensation(ah); + + /* + * Get the value from the previous NF cal + * and update the history buffer. + */ + r = ar5416GetNf(ah, chan); + if (r == 0 || r == -1) { + /* NF calibration result isn't valid */ + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: NF calibration" + " didn't finish; delaying CCA\n", __func__); + } else { + /* + * NF calibration result is valid. + * + * Load the NF from history buffer of the current channel. + * NF is slow time-variant, so it is OK to use a + * historical value. + */ + ar5416LoadNF(ah, AH_PRIVATE(ah)->ah_curchan); + + /* start NF calibration, without updating BB NF register*/ + ar5416StartNFCal(ah); + } + } + return AH_TRUE; +} + +/* + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +HAL_BOOL +ar5416PerCalibration(struct ath_hal *ah, struct ieee80211_channel *chan, + HAL_BOOL *isIQdone) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CAL_LIST *curCal = cal->cal_curr; + + if (curCal != AH_NULL && curCal->calData->calType == IQ_MISMATCH_CAL) { + return ar5416PerCalibrationN(ah, chan, ahp->ah_rx_chainmask, + AH_TRUE, isIQdone); + } else { + HAL_BOOL isCalDone; + + *isIQdone = AH_FALSE; + return ar5416PerCalibrationN(ah, chan, ahp->ah_rx_chainmask, + AH_TRUE, &isCalDone); + } +} + +static HAL_BOOL +ar5416GetEepromNoiseFloorThresh(struct ath_hal *ah, + const struct ieee80211_channel *chan, int16_t *nft) +{ + if (IEEE80211_IS_CHAN_5GHZ(chan)) { + ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_5, nft); + return AH_TRUE; + } + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_2, nft); + return AH_TRUE; + } + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->ic_flags); + return AH_FALSE; +} + +static void +ar5416StartNFCal(struct ath_hal *ah) +{ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); +} + +static void +ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + static const uint32_t ar5416_cca_regs[] = { + AR_PHY_CCA, + AR_PHY_CH1_CCA, + AR_PHY_CH2_CCA, + AR_PHY_EXT_CCA, + AR_PHY_CH1_EXT_CCA, + AR_PHY_CH2_EXT_CCA + }; + struct ar5212NfCalHist *h; + int i; + int32_t val; + uint8_t chainmask; + int16_t default_nf = ar5416GetDefaultNF(ah, chan); + + /* + * Force NF calibration for all chains. + */ + if (AR_SREV_KITE(ah)) { + /* Kite has only one chain */ + chainmask = 0x9; + } else if (AR_SREV_MERLIN(ah) || AR_SREV_KIWI(ah)) { + /* Merlin/Kiwi has only two chains */ + chainmask = 0x1B; + } else { + chainmask = 0x3F; + } + + /* + * Write filtered NF values into maxCCApwr register parameter + * so we can load below. + */ + h = AH5416(ah)->ah_cal.nfCalHist; + HALDEBUG(ah, HAL_DEBUG_NFCAL, "CCA: "); + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { + + /* Don't write to EXT radio CCA registers unless in HT/40 mode */ + /* XXX this check should really be cleaner! */ + if (i > 2 && !IEEE80211_IS_CHAN_HT40(chan)) + continue; + + if (chainmask & (1 << i)) { + int16_t nf_val; + + if (h) + nf_val = h[i].privNF; + else + nf_val = default_nf; + + val = OS_REG_READ(ah, ar5416_cca_regs[i]); + val &= 0xFFFFFE00; + val |= (((uint32_t) nf_val << 1) & 0x1ff); + HALDEBUG(ah, HAL_DEBUG_NFCAL, "[%d: %d]", i, nf_val); + OS_REG_WRITE(ah, ar5416_cca_regs[i], val); + } + } + HALDEBUG(ah, HAL_DEBUG_NFCAL, "\n"); + + /* Load software filtered NF value into baseband internal minCCApwr variable. */ + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + + /* Wait for load to complete, should be fast, a few 10s of us. */ + if (! ar5212WaitNFCalComplete(ah, 1000)) { + /* + * We timed out waiting for the noisefloor to load, probably due to an + * in-progress rx. Simply return here and allow the load plenty of time + * to complete before the next calibration interval. We need to avoid + * trying to load -50 (which happens below) while the previous load is + * still in progress as this can cause rx deafness. Instead by returning + * here, the baseband nf cal will just be capped by our present + * noisefloor until the next calibration timer. + */ + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "Timeout while waiting for " + "nf to load: AR_PHY_AGC_CONTROL=0x%x\n", + OS_REG_READ(ah, AR_PHY_AGC_CONTROL)); + return; + } + + /* + * Restore maxCCAPower register parameter again so that we're not capped + * by the median we just loaded. This will be initial (and max) value + * of next noise floor calibration the baseband does. + */ + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { + + /* Don't write to EXT radio CCA registers unless in HT/40 mode */ + /* XXX this check should really be cleaner! */ + if (i > 2 && !IEEE80211_IS_CHAN_HT40(chan)) + continue; + + if (chainmask & (1 << i)) { + val = OS_REG_READ(ah, ar5416_cca_regs[i]); + val &= 0xFFFFFE00; + val |= (((uint32_t)(-50) << 1) & 0x1ff); + OS_REG_WRITE(ah, ar5416_cca_regs[i], val); + } + } +} + +/* + * This just initialises the "good" values for AR5416 which + * may not be right; it'lll be overridden by ar5416SanitizeNF() + * to nominal values. + */ +void +ar5416InitNfHistBuff(struct ar5212NfCalHist *h) +{ + int i, j; + + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { + h[i].currIndex = 0; + h[i].privNF = AR5416_CCA_MAX_GOOD_VALUE; + h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX; + for (j = 0; j < AR512_NF_CAL_HIST_MAX; j ++) + h[i].nfCalBuffer[j] = AR5416_CCA_MAX_GOOD_VALUE; + } +} + +/* + * Update the noise floor buffer as a ring buffer + */ +static void +ar5416UpdateNFHistBuff(struct ath_hal *ah, struct ar5212NfCalHist *h, + int16_t *nfarray) +{ + int i; + + /* XXX TODO: don't record nfarray[] entries for inactive chains */ + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { + h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; + + if (++h[i].currIndex >= AR512_NF_CAL_HIST_MAX) + h[i].currIndex = 0; + if (h[i].invalidNFcount > 0) { + if (nfarray[i] < AR5416_CCA_MIN_BAD_VALUE || + nfarray[i] > AR5416_CCA_MAX_HIGH_VALUE) { + h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX; + } else { + h[i].invalidNFcount--; + h[i].privNF = nfarray[i]; + } + } else { + h[i].privNF = ar5212GetNfHistMid(h[i].nfCalBuffer); + } + } +} + +static uint16_t +ar5416GetDefaultNF(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + struct ar5416NfLimits *limit; + + if (!chan || IEEE80211_IS_CHAN_2GHZ(chan)) + limit = &AH5416(ah)->nf_2g; + else + limit = &AH5416(ah)->nf_5g; + + return limit->nominal; +} + +static void +ar5416SanitizeNF(struct ath_hal *ah, int16_t *nf) +{ + + struct ar5416NfLimits *limit; + int i; + + if (IEEE80211_IS_CHAN_2GHZ(AH_PRIVATE(ah)->ah_curchan)) + limit = &AH5416(ah)->nf_2g; + else + limit = &AH5416(ah)->nf_5g; + + for (i = 0; i < AR5416_NUM_NF_READINGS; i++) { + if (!nf[i]) + continue; + + if (nf[i] > limit->max) { + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF[%d] (%d) > MAX (%d), correcting to MAX\n", + i, nf[i], limit->max); + nf[i] = limit->max; + } else if (nf[i] < limit->min) { + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF[%d] (%d) < MIN (%d), correcting to NOM\n", + i, nf[i], limit->min); + nf[i] = limit->nominal; + } + } +} + + +/* + * Read the NF and check it against the noise floor threshhold + * + * Return 0 if the NF calibration hadn't finished, 0 if it was + * invalid, or > 0 for a valid NF reading. + */ +static int16_t +ar5416GetNf(struct ath_hal *ah, struct ieee80211_channel *chan) +{ + int16_t nf, nfThresh; + int i; + int retval = 0; + + if (ar5212IsNFCalInProgress(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: NF didn't complete in calibration window\n", __func__); + nf = 0; + retval = -1; /* NF didn't finish */ + } else { + /* Finished NF cal, check against threshold */ + int16_t nfarray[NUM_NOISEFLOOR_READINGS] = { 0 }; + HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); + + /* TODO - enhance for multiple chains and ext ch */ + ath_hal_getNoiseFloor(ah, nfarray); + nf = nfarray[0]; + ar5416SanitizeNF(ah, nfarray); + if (ar5416GetEepromNoiseFloorThresh(ah, chan, &nfThresh)) { + if (nf > nfThresh) { + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, + "%s: noise floor failed detected; " + "detected %d, threshold %d\n", __func__, + nf, nfThresh); + /* + * NB: Don't discriminate 2.4 vs 5Ghz, if this + * happens it indicates a problem regardless + * of the band. + */ + chan->ic_state |= IEEE80211_CHANSTATE_CWINT; + nf = 0; + retval = 0; + } + } else { + nf = 0; + retval = 0; + } + /* Update MIMO channel statistics, regardless of validity or not (for now) */ + for (i = 0; i < 3; i++) { + ichan->noiseFloorCtl[i] = nfarray[i]; + ichan->noiseFloorExt[i] = nfarray[i + 3]; + } + ichan->privFlags |= CHANNEL_MIMO_NF_VALID; + + ar5416UpdateNFHistBuff(ah, AH5416(ah)->ah_cal.nfCalHist, nfarray); + ichan->rawNoiseFloor = nf; + retval = nf; + } + return retval; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal.h b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal.h new file mode 100644 index 0000000..a4f19e5 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AR5416_CAL_H_ +#define _ATH_AR5416_CAL_H_ + +typedef enum { + ADC_DC_INIT_CAL = 0x1, + ADC_GAIN_CAL = 0x2, + ADC_DC_CAL = 0x4, + IQ_MISMATCH_CAL = 0x8 +} HAL_CAL_TYPE; + +/* Calibrate state */ +typedef enum { + CAL_INACTIVE, + CAL_WAITING, + CAL_RUNNING, + CAL_DONE +} HAL_CAL_STATE; + +typedef union { + uint32_t u; + int32_t s; +} HAL_CAL_SAMPLE; + +#define MIN_CAL_SAMPLES 1 +#define MAX_CAL_SAMPLES 64 +#define INIT_LOG_COUNT 5 +#define PER_MIN_LOG_COUNT 2 +#define PER_MAX_LOG_COUNT 10 + +/* Per Calibration data structure */ +typedef struct per_cal_data { + const char *calName; /* for diagnostics */ + HAL_CAL_TYPE calType; /* Type of calibration */ + uint32_t calNumSamples; /* # SW samples to collect */ + uint32_t calCountMax; /* # HW samples to collect */ + void (*calCollect)(struct ath_hal *); /* Accumulator function */ + /* Post-processing function */ + void (*calPostProc)(struct ath_hal *, uint8_t); +} HAL_PERCAL_DATA; + +/* List structure for calibration data */ +typedef struct cal_list { + struct cal_list *calNext; + HAL_CAL_STATE calState; + const HAL_PERCAL_DATA *calData; +} HAL_CAL_LIST; + +struct ar5416PerCal { + /* + * Periodic calibration state. + */ + HAL_CAL_TYPE suppCals; + HAL_CAL_LIST iqCalData; + HAL_CAL_LIST adcGainCalData; + HAL_CAL_LIST adcDcCalInitData; + HAL_CAL_LIST adcDcCalData; + HAL_CAL_LIST *cal_list; + HAL_CAL_LIST *cal_last; + HAL_CAL_LIST *cal_curr; +#define AR5416_MAX_CHAINS 3 /* XXX dup's eeprom def */ + HAL_CAL_SAMPLE caldata[4][AR5416_MAX_CHAINS]; + int calSamples; + /* + * Noise floor cal histogram support. + * XXX be nice to re-use space in ar5212 + */ +#define AR5416_NUM_NF_READINGS 6 /* (3 chains * (ctl + ext) */ + struct ar5212NfCalHist nfCalHist[AR5416_NUM_NF_READINGS]; +}; + +#define INIT_CAL(_perCal) do { \ + (_perCal)->calState = CAL_WAITING; \ + (_perCal)->calNext = AH_NULL; \ +} while (0) + +#define INSERT_CAL(_cal, _perCal) do { \ + if ((_cal)->cal_last == AH_NULL) { \ + (_cal)->cal_list = (_cal)->cal_last = (_perCal); \ + ((_cal)->cal_last)->calNext = (_perCal); \ + } else { \ + ((_cal)->cal_last)->calNext = (_perCal); \ + (_cal)->cal_last = (_perCal); \ + (_perCal)->calNext = (_cal)->cal_list; \ + } \ +} while (0) + +HAL_BOOL ar5416InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan); +HAL_BOOL ar5416InitCal(struct ath_hal *, const struct ieee80211_channel *); +HAL_BOOL ar5416PerCalibration(struct ath_hal *, struct ieee80211_channel *, + HAL_BOOL *isIQdone); +HAL_BOOL ar5416PerCalibrationN(struct ath_hal *, struct ieee80211_channel *, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); +HAL_BOOL ar5416ResetCalValid(struct ath_hal *, + const struct ieee80211_channel *); + +void ar5416IQCalCollect(struct ath_hal *ah); +void ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains); +void ar5416AdcGainCalCollect(struct ath_hal *ah); +void ar5416AdcGainCalibration(struct ath_hal *ah, uint8_t numChains); +void ar5416AdcDcCalCollect(struct ath_hal *ah); +void ar5416AdcDcCalibration(struct ath_hal *ah, uint8_t numChains); +void ar5416InitNfHistBuff(struct ar5212NfCalHist *h); +#endif /* _ATH_AR5416_CAL_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_adcdc.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_adcdc.c new file mode 100644 index 0000000..9083d3a --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_adcdc.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* Adc DC Offset Cal aliases */ +#define totalAdcDcOffsetIOddPhase(i) caldata[0][i].s +#define totalAdcDcOffsetIEvenPhase(i) caldata[1][i].s +#define totalAdcDcOffsetQOddPhase(i) caldata[2][i].s +#define totalAdcDcOffsetQEvenPhase(i) caldata[3][i].s + +void +ar5416AdcDcCalCollect(struct ath_hal *ah) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + int i; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + cal->totalAdcDcOffsetIOddPhase(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + cal->totalAdcDcOffsetIEvenPhase(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + cal->totalAdcDcOffsetQOddPhase(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + cal->totalAdcDcOffsetQEvenPhase(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", + cal->calSamples, i, + cal->totalAdcDcOffsetIOddPhase(i), + cal->totalAdcDcOffsetIEvenPhase(i), + cal->totalAdcDcOffsetQOddPhase(i), + cal->totalAdcDcOffsetQEvenPhase(i)); + } +} + +void +ar5416AdcDcCalibration(struct ath_hal *ah, uint8_t numChains) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + const HAL_PERCAL_DATA *calData = cal->cal_curr->calData; + uint32_t numSamples; + int i; + + numSamples = (1 << (calData->calCountMax + 5)) * calData->calNumSamples; + for (i = 0; i < numChains; i++) { + uint32_t iOddMeasOffset = cal->totalAdcDcOffsetIOddPhase(i); + uint32_t iEvenMeasOffset = cal->totalAdcDcOffsetIEvenPhase(i); + int32_t qOddMeasOffset = cal->totalAdcDcOffsetQOddPhase(i); + int32_t qEvenMeasOffset = cal->totalAdcDcOffsetQEvenPhase(i); + int32_t qDcMismatch, iDcMismatch; + uint32_t val; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "Starting ADC DC Offset Cal for Chain %d\n", i); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_i = %d\n", + iOddMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_i = %d\n", + iEvenMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_q = %d\n", + qOddMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_q = %d\n", + qEvenMeasOffset); + + HALASSERT(numSamples); + + iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / + numSamples) & 0x1ff; + qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / + numSamples) & 0x1ff; + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " dc_offset_mismatch_i = 0x%08x\n", iDcMismatch); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " dc_offset_mismatch_q = 0x%08x\n", qDcMismatch); + + val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); + val &= 0xc0000fff; + val |= (qDcMismatch << 12) | (iDcMismatch << 21); + OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "ADC DC Offset Cal done for Chain %d\n", i); + } + OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), + AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_adcgain.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_adcgain.c new file mode 100644 index 0000000..4af1ca4 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_adcgain.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* Adc Gain Cal aliases */ +#define totalAdcIOddPhase(i) caldata[0][i].u +#define totalAdcIEvenPhase(i) caldata[1][i].u +#define totalAdcQOddPhase(i) caldata[2][i].u +#define totalAdcQEvenPhase(i) caldata[3][i].u + +/* + * Collect data from HW to later perform ADC Gain Calibration + */ +void +ar5416AdcGainCalCollect(struct ath_hal *ah) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + int i; + + /* + * Accumulate ADC Gain cal measures for active chains + */ + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + cal->totalAdcIOddPhase(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + cal->totalAdcIEvenPhase(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + cal->totalAdcQOddPhase(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + cal->totalAdcQEvenPhase(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", + cal->calSamples, i, cal->totalAdcIOddPhase(i), + cal->totalAdcIEvenPhase(i), cal->totalAdcQOddPhase(i), + cal->totalAdcQEvenPhase(i)); + } +} + +/* + * Use HW data to do ADC Gain Calibration + */ +void +ar5416AdcGainCalibration(struct ath_hal *ah, uint8_t numChains) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + uint32_t i; + + for (i = 0; i < numChains; i++) { + uint32_t iOddMeasOffset = cal->totalAdcIOddPhase(i); + uint32_t iEvenMeasOffset = cal->totalAdcIEvenPhase(i); + uint32_t qOddMeasOffset = cal->totalAdcQOddPhase(i); + uint32_t qEvenMeasOffset = cal->totalAdcQEvenPhase(i); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "Start ADC Gain Cal for Chain %d\n", i); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " pwr_meas_odd_i = 0x%08x\n", iOddMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " pwr_meas_even_i = 0x%08x\n", iEvenMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " pwr_meas_odd_q = 0x%08x\n", qOddMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " pwr_meas_even_q = 0x%08x\n", qEvenMeasOffset); + + if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { + uint32_t iGainMismatch = + ((iEvenMeasOffset*32)/iOddMeasOffset) & 0x3f; + uint32_t qGainMismatch = + ((qOddMeasOffset*32)/qEvenMeasOffset) & 0x3f; + uint32_t val; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " gain_mismatch_i = 0x%08x\n", + iGainMismatch); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " gain_mismatch_q = 0x%08x\n", + qGainMismatch); + + val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); + val &= 0xfffff000; + val |= (qGainMismatch) | (iGainMismatch << 6); + OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "ADC Gain Cal done for Chain %d\n", i); + } + } + OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), + AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_iq.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_iq.c new file mode 100644 index 0000000..939ba12 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_iq.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* IQ Cal aliases */ +#define totalPowerMeasI(i) caldata[0][i].u +#define totalPowerMeasQ(i) caldata[1][i].u +#define totalIqCorrMeas(i) caldata[2][i].s + +/* + * Collect data from HW to later perform IQ Mismatch Calibration + */ +void +ar5416IQCalCollect(struct ath_hal *ah) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + int i; + + /* + * Accumulate IQ cal measures for active chains + */ + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + cal->totalPowerMeasI(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + cal->totalPowerMeasQ(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + cal->totalIqCorrMeas(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", + cal->calSamples, i, cal->totalPowerMeasI(i), + cal->totalPowerMeasQ(i), cal->totalIqCorrMeas(i)); + } +} + +/* + * Use HW data to do IQ Mismatch Calibration + */ +void +ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + int i; + + for (i = 0; i < numChains; i++) { + uint32_t powerMeasI = cal->totalPowerMeasI(i); + uint32_t powerMeasQ = cal->totalPowerMeasQ(i); + uint32_t iqCorrMeas = cal->totalIqCorrMeas(i); + uint32_t qCoffDenom, iCoffDenom; + int iqCorrNeg; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "Start IQ Cal and Correction for Chain %d\n", i); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "Orignal: iq_corr_meas = 0x%08x\n", iqCorrMeas); + + iqCorrNeg = 0; + /* iqCorrMeas is always negative. */ + if (iqCorrMeas > 0x80000000) { + iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; + iqCorrNeg = 1; + } + + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_i = 0x%08x\n", + powerMeasI); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_q = 0x%08x\n", + powerMeasQ); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " iqCorrNeg is 0x%08x\n", + iqCorrNeg); + + iCoffDenom = (powerMeasI/2 + powerMeasQ/2)/ 128; + qCoffDenom = powerMeasQ / 64; + /* Protect against divide-by-0 */ + if (powerMeasQ != 0) { + /* IQ corr_meas is already negated if iqcorr_neg == 1 */ + int32_t iCoff = iqCorrMeas/iCoffDenom; + int32_t qCoff = powerMeasI/qCoffDenom - 64; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, " iCoff = 0x%08x\n", + iCoff); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " qCoff = 0x%08x\n", + qCoff); + + /* Negate iCoff if iqCorrNeg == 0 */ + iCoff = iCoff & 0x3f; + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "New: iCoff = 0x%08x\n", iCoff); + + if (iqCorrNeg == 0x0) + iCoff = 0x40 - iCoff; + if (qCoff > 15) + qCoff = 15; + else if (qCoff <= -16) + qCoff = -16; + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " : iCoff = 0x%x qCoff = 0x%x\n", iCoff, qCoff); + + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i), + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i), + AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "IQ Cal and Correction done for Chain %d\n", i); + } + } + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_eeprom.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_eeprom.c new file mode 100644 index 0000000..2947726 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_eeprom.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* + * Read 16 bits of data from offset into *data + */ +HAL_BOOL +ar5416EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) +{ + OS_REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); + if (!ath_hal_wait(ah, AR_EEPROM_STATUS_DATA, + AR_EEPROM_STATUS_DATA_BUSY | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) + return AH_FALSE; + *data = MS(OS_REG_READ(ah, AR_EEPROM_STATUS_DATA), + AR_EEPROM_STATUS_DATA_VAL); + return AH_TRUE; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_gpio.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_gpio.c new file mode 100644 index 0000000..3c493b4 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_gpio.c @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#define AR_GPIO_BIT(_gpio) (1 << _gpio) + +/* + * Configure GPIO Output Mux control + */ +static void +cfgOutputMux(struct ath_hal *ah, uint32_t gpio, uint32_t type) +{ + int addr; + uint32_t gpio_shift, tmp; + + HALDEBUG(ah, HAL_DEBUG_GPIO, "%s: gpio=%d, type=%d\n", + __func__, gpio, type); + + /* each MUX controls 6 GPIO pins */ + if (gpio > 11) + addr = AR_GPIO_OUTPUT_MUX3; + else if (gpio > 5) + addr = AR_GPIO_OUTPUT_MUX2; + else + addr = AR_GPIO_OUTPUT_MUX1; + + /* + * 5 bits per GPIO pin. Bits 0..4 for 1st pin in that mux, + * bits 5..9 for 2nd pin, etc. + */ + gpio_shift = (gpio % 6) * 5; + + /* + * From Owl to Merlin 1.0, the value read from MUX1 bit 4 to bit + * 9 are wrong. Here is hardware's coding: + * PRDATA[4:0] <= gpio_output_mux[0]; + * PRDATA[9:4] <= gpio_output_mux[1]; + * <==== Bit 4 is used by both gpio_output_mux[0] [1]. + * Currently the max value for gpio_output_mux[] is 6. So bit 4 + * will never be used. So it should be fine that bit 4 won't be + * able to recover. + */ + if (AR_SREV_MERLIN_20_OR_LATER(ah) || + (addr != AR_GPIO_OUTPUT_MUX1)) { + OS_REG_RMW(ah, addr, (type << gpio_shift), + (0x1f << gpio_shift)); + } else { + tmp = OS_REG_READ(ah, addr); + tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0); + tmp &= ~(0x1f << gpio_shift); + tmp |= type << gpio_shift; + OS_REG_WRITE(ah, addr, tmp); + } +} + +/* + * Configure GPIO Output lines + */ +HAL_BOOL +ar5416GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) +{ + uint32_t gpio_shift, reg; + +#define N(a) (sizeof(a) / sizeof(a[0])) + + HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); + + /* + * This table maps the HAL GPIO pins to the actual hardware + * values. + */ + static const u_int32_t MuxSignalConversionTable[] = { + AR_GPIO_OUTPUT_MUX_AS_OUTPUT, + AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED, + AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, + AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED, + AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, + AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL, + AR_GPIO_OUTPUT_MUX_AS_TX_FRAME, + }; + + HALDEBUG(ah, HAL_DEBUG_GPIO, + "%s: gpio=%d, type=%d\n", __func__, gpio, type); + + /* + * Convert HAL signal type definitions to hardware-specific values. + */ + if (type >= N(MuxSignalConversionTable)) { + ath_hal_printf(ah, "%s: mux %d is invalid!\n", + __func__, + type); + return AH_FALSE; + } + cfgOutputMux(ah, gpio, MuxSignalConversionTable[type]); + + /* 2 bits per output mode */ + gpio_shift = gpio << 1; + + /* Always drive, rather than tristate/drive low/drive high */ + reg = OS_REG_READ(ah, AR_GPIO_OE_OUT); + reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift); + reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift; + OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg); + + return AH_TRUE; +#undef N +} + +/* + * Configure GPIO Input lines + */ +HAL_BOOL +ar5416GpioCfgInput(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t gpio_shift, reg; + + HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); + + HALDEBUG(ah, HAL_DEBUG_GPIO, "%s: gpio=%d\n", __func__, gpio); + + /* TODO: configure input mux for AR5416 */ + /* If configured as input, set output to tristate */ + gpio_shift = gpio << 1; + + reg = OS_REG_READ(ah, AR_GPIO_OE_OUT); + reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift); + reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift; + OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg); + + return AH_TRUE; +} + +/* + * Once configured for I/O - set output lines + */ +HAL_BOOL +ar5416GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) +{ + uint32_t reg; + + HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); + HALDEBUG(ah, HAL_DEBUG_GPIO, + "%s: gpio=%d, val=%d\n", __func__, gpio, val); + + reg = OS_REG_READ(ah, AR_GPIO_IN_OUT); + if (val & 1) + reg |= AR_GPIO_BIT(gpio); + else + reg &= ~AR_GPIO_BIT(gpio); + OS_REG_WRITE(ah, AR_GPIO_IN_OUT, reg); + return AH_TRUE; +} + +/* + * Once configured for I/O - get input lines + */ +uint32_t +ar5416GpioGet(struct ath_hal *ah, uint32_t gpio) +{ + uint32_t bits; + + if (gpio >= AH_PRIVATE(ah)->ah_caps.halNumGpioPins) + return 0xffffffff; + /* + * Read output value for all gpio's, shift it, + * and verify whether the specific bit is set. + */ + if (AR_SREV_KIWI_10_OR_LATER(ah)) + bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9287_GPIO_IN_VAL); + if (AR_SREV_KITE_10_OR_LATER(ah)) + bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9285_GPIO_IN_VAL); + else if (AR_SREV_MERLIN_10_OR_LATER(ah)) + bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR928X_GPIO_IN_VAL); + else + bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL); + return ((bits & AR_GPIO_BIT(gpio)) != 0); +} + +/* + * Set the GPIO Interrupt Sync and Async interrupts are both set/cleared. + * Async GPIO interrupts may not be raised when the chip is put to sleep. + */ +void +ar5416GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) +{ + uint32_t val, mask; + + HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); + HALDEBUG(ah, HAL_DEBUG_GPIO, + "%s: gpio=%d, ilevel=%d\n", __func__, gpio, ilevel); + + if (ilevel == HAL_GPIO_INTR_DISABLE) { + val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), + AR_INTR_ASYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, + AR_INTR_ASYNC_ENABLE_GPIO, val); + + mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), + AR_INTR_ASYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, + AR_INTR_ASYNC_MASK_GPIO, mask); + + /* Clear synchronous GPIO interrupt registers and pending interrupt flag */ + val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE), + AR_INTR_SYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE, + AR_INTR_SYNC_ENABLE_GPIO, val); + + mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK), + AR_INTR_SYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK, + AR_INTR_SYNC_MASK_GPIO, mask); + + val = MS(OS_REG_READ(ah, AR_INTR_SYNC_CAUSE), + AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_CAUSE, + AR_INTR_SYNC_ENABLE_GPIO, val); + } else { + val = MS(OS_REG_READ(ah, AR_GPIO_INTR_POL), + AR_GPIO_INTR_POL_VAL); + if (ilevel == HAL_GPIO_INTR_HIGH) { + /* 0 == interrupt on pin high */ + val &= ~AR_GPIO_BIT(gpio); + } else if (ilevel == HAL_GPIO_INTR_LOW) { + /* 1 == interrupt on pin low */ + val |= AR_GPIO_BIT(gpio); + } + OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_POL, + AR_GPIO_INTR_POL_VAL, val); + + /* Change the interrupt mask. */ + val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), + AR_INTR_ASYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, + AR_INTR_ASYNC_ENABLE_GPIO, val); + + mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), + AR_INTR_ASYNC_MASK_GPIO) | AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, + AR_INTR_ASYNC_MASK_GPIO, mask); + + /* Set synchronous GPIO interrupt registers as well */ + val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE), + AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE, + AR_INTR_SYNC_ENABLE_GPIO, val); + + mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK), + AR_INTR_SYNC_MASK_GPIO) | AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK, + AR_INTR_SYNC_MASK_GPIO, mask); + } + AH5416(ah)->ah_gpioMask = mask; /* for ar5416SetInterrupts */ +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_interrupts.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_interrupts.c new file mode 100644 index 0000000..32ce2ed --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_interrupts.c @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" + +/* + * Checks to see if an interrupt is pending on our NIC + * + * Returns: TRUE if an interrupt is pending + * FALSE if not + */ +HAL_BOOL +ar5416IsInterruptPending(struct ath_hal *ah) +{ + uint32_t isr; + + if (AR_SREV_HOWL(ah)) + return AH_TRUE; + + /* + * Some platforms trigger our ISR before applying power to + * the card, so make sure the INTPEND is really 1, not 0xffffffff. + */ + isr = OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE); + if (isr != AR_INTR_SPURIOUS && (isr & AR_INTR_MAC_IRQ) != 0) + return AH_TRUE; + + isr = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE); + if (isr != AR_INTR_SPURIOUS && (isr & AR_INTR_SYNC_DEFAULT)) + return AH_TRUE; + + return AH_FALSE; +} + +/* + * Reads the Interrupt Status Register value from the NIC, thus deasserting + * the interrupt line, and returns both the masked and unmasked mapped ISR + * values. The value returned is mapped to abstract the hw-specific bit + * locations in the Interrupt Status Register. + * + * (*masked) is cleared on initial call. + * + * Returns: A hardware-abstracted bitmap of all non-masked-out + * interrupts pending, as well as an unmasked value + */ +HAL_BOOL +ar5416GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) +{ + uint32_t isr, isr0, isr1, sync_cause = 0, o_sync_cause = 0; + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + +#ifdef AH_INTERRUPT_DEBUGGING + /* + * Blank the interrupt debugging area regardless. + */ + bzero(&ah->ah_intrstate, sizeof(ah->ah_intrstate)); + ah->ah_syncstate = 0; +#endif + + /* + * Verify there's a mac interrupt and the RTC is on. + */ + if (AR_SREV_HOWL(ah)) { + *masked = 0; + isr = OS_REG_READ(ah, AR_ISR); + } else { + if ((OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) && + (OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_ON) + isr = OS_REG_READ(ah, AR_ISR); + else + isr = 0; +#ifdef AH_INTERRUPT_DEBUGGING + ah->ah_syncstate = +#endif + o_sync_cause = sync_cause = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE); + sync_cause &= AR_INTR_SYNC_DEFAULT; + *masked = 0; + + if (isr == 0 && sync_cause == 0) + return AH_FALSE; + } + +#ifdef AH_INTERRUPT_DEBUGGING + ah->ah_intrstate[0] = isr; + ah->ah_intrstate[1] = OS_REG_READ(ah, AR_ISR_S0); + ah->ah_intrstate[2] = OS_REG_READ(ah, AR_ISR_S1); + ah->ah_intrstate[3] = OS_REG_READ(ah, AR_ISR_S2); + ah->ah_intrstate[4] = OS_REG_READ(ah, AR_ISR_S3); + ah->ah_intrstate[5] = OS_REG_READ(ah, AR_ISR_S4); + ah->ah_intrstate[6] = OS_REG_READ(ah, AR_ISR_S5); +#endif + + if (isr != 0) { + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t mask2; + + mask2 = 0; + if (isr & AR_ISR_BCNMISC) { + uint32_t isr2 = OS_REG_READ(ah, AR_ISR_S2); + if (isr2 & AR_ISR_S2_TIM) + mask2 |= HAL_INT_TIM; + if (isr2 & AR_ISR_S2_DTIM) + mask2 |= HAL_INT_DTIM; + if (isr2 & AR_ISR_S2_DTIMSYNC) + mask2 |= HAL_INT_DTIMSYNC; + if (isr2 & (AR_ISR_S2_CABEND )) + mask2 |= HAL_INT_CABEND; + if (isr2 & AR_ISR_S2_GTT) + mask2 |= HAL_INT_GTT; + if (isr2 & AR_ISR_S2_CST) + mask2 |= HAL_INT_CST; + if (isr2 & AR_ISR_S2_TSFOOR) + mask2 |= HAL_INT_TSFOOR; + + /* + * Don't mask out AR_BCNMISC; instead mask + * out what causes it. + */ + OS_REG_WRITE(ah, AR_ISR_S2, isr2); + isr &= ~AR_ISR_BCNMISC; + } + + if (isr == 0xffffffff) { + *masked = 0; + return AH_FALSE; + } + + *masked = isr & HAL_INT_COMMON; + + if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) + *masked |= HAL_INT_RX; + if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) + *masked |= HAL_INT_TX; + + /* + * When doing RX interrupt mitigation, the RXOK bit is set + * in AR_ISR even if the relevant bit in AR_IMR is clear. + * Since this interrupt may be due to another source, don't + * just automatically set HAL_INT_RX if it's set, otherwise + * we could prematurely service the RX queue. + * + * In some cases, the driver can even handle all the RX + * frames just before the mitigation interrupt fires. + * The subsequent RX processing trip will then end up + * processing 0 frames. + */ +#ifdef AH_AR5416_INTERRUPT_MITIGATION + if (isr & AR_ISR_RXERR) + *masked |= HAL_INT_RX; +#else + if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) + *masked |= HAL_INT_RX; +#endif + + if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | + AR_ISR_TXEOL)) { + *masked |= HAL_INT_TX; + + isr0 = OS_REG_READ(ah, AR_ISR_S0); + OS_REG_WRITE(ah, AR_ISR_S0, isr0); + isr1 = OS_REG_READ(ah, AR_ISR_S1); + OS_REG_WRITE(ah, AR_ISR_S1, isr1); + + /* + * Don't clear the primary ISR TX bits, clear + * what causes them (S0/S1.) + */ + isr &= ~(AR_ISR_TXOK | AR_ISR_TXDESC | + AR_ISR_TXERR | AR_ISR_TXEOL); + + ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXOK); + ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXDESC); + ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXERR); + ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL); + } + + if ((isr & AR_ISR_GENTMR) || (! pCap->halAutoSleepSupport)) { + uint32_t isr5; + isr5 = OS_REG_READ(ah, AR_ISR_S5); + OS_REG_WRITE(ah, AR_ISR_S5, isr5); + isr &= ~AR_ISR_GENTMR; + + if (! pCap->halAutoSleepSupport) + if (isr5 & AR_ISR_S5_TIM_TIMER) + *masked |= HAL_INT_TIM_TIMER; + } + *masked |= mask2; + } + + /* + * Since we're not using AR_ISR_RAC, clear the status bits + * for handled interrupts here. For bits whose interrupt + * source is a secondary register, those bits should've been + * masked out - instead of those bits being written back, + * their source (ie, the secondary status registers) should + * be cleared. That way there are no race conditions with + * new triggers coming in whilst they've been read/cleared. + */ + OS_REG_WRITE(ah, AR_ISR, isr); + /* Flush previous write */ + OS_REG_READ(ah, AR_ISR); + + if (AR_SREV_HOWL(ah)) + return AH_TRUE; + + if (sync_cause != 0) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: sync_cause=0x%x\n", + __func__, + o_sync_cause); + if (sync_cause & (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) { + *masked |= HAL_INT_FATAL; + } + if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RADM CPL timeout\n", + __func__); + OS_REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); + OS_REG_WRITE(ah, AR_RC, 0); + *masked |= HAL_INT_FATAL; + } + /* + * On fatal errors collect ISR state for debugging. + */ + if (*masked & HAL_INT_FATAL) { + AH_PRIVATE(ah)->ah_fatalState[0] = isr; + AH_PRIVATE(ah)->ah_fatalState[1] = sync_cause; + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: fatal error, ISR_RAC 0x%x SYNC_CAUSE 0x%x\n", + __func__, isr, sync_cause); + } + + OS_REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); + /* NB: flush write */ + (void) OS_REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); + } + return AH_TRUE; +} + +/* + * Atomically enables NIC interrupts. Interrupts are passed in + * via the enumerated bitmask in ints. + */ +HAL_INT +ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t omask = ahp->ah_maskReg; + uint32_t mask, mask2; + + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n", + __func__, omask, ints); + + if (omask & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + (void) OS_REG_READ(ah, AR_IER); + + if (! AR_SREV_HOWL(ah)) { + OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); + (void) OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE); + + OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); + (void) OS_REG_READ(ah, AR_INTR_SYNC_ENABLE); + } + } + + mask = ints & HAL_INT_COMMON; + mask2 = 0; + +#ifdef AH_AR5416_INTERRUPT_MITIGATION + /* + * Overwrite default mask if Interrupt mitigation + * is specified for AR5416 + */ + if (ints & HAL_INT_RX) + mask |= AR_IMR_RXERR | AR_IMR_RXMINTR | AR_IMR_RXINTM; +#else + if (ints & HAL_INT_RX) + mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC; +#endif + if (ints & HAL_INT_TX) { + if (ahp->ah_txOkInterruptMask) + mask |= AR_IMR_TXOK; + if (ahp->ah_txErrInterruptMask) + mask |= AR_IMR_TXERR; + if (ahp->ah_txDescInterruptMask) + mask |= AR_IMR_TXDESC; + if (ahp->ah_txEolInterruptMask) + mask |= AR_IMR_TXEOL; + if (ahp->ah_txUrnInterruptMask) + mask |= AR_IMR_TXURN; + } + if (ints & (HAL_INT_BMISC)) { + mask |= AR_IMR_BCNMISC; + if (ints & HAL_INT_TIM) + mask2 |= AR_IMR_S2_TIM; + if (ints & HAL_INT_DTIM) + mask2 |= AR_IMR_S2_DTIM; + if (ints & HAL_INT_DTIMSYNC) + mask2 |= AR_IMR_S2_DTIMSYNC; + if (ints & HAL_INT_CABEND) + mask2 |= (AR_IMR_S2_CABEND ); + if (ints & HAL_INT_CST) + mask2 |= AR_IMR_S2_CST; + if (ints & HAL_INT_TSFOOR) + mask2 |= AR_IMR_S2_TSFOOR; + } + + if (ints & (HAL_INT_GTT | HAL_INT_CST)) { + mask |= AR_IMR_BCNMISC; + if (ints & HAL_INT_GTT) + mask2 |= AR_IMR_S2_GTT; + if (ints & HAL_INT_CST) + mask2 |= AR_IMR_S2_CST; + } + + /* Write the new IMR and store off our SW copy. */ + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); + OS_REG_WRITE(ah, AR_IMR, mask); + /* Flush write */ + (void) OS_REG_READ(ah, AR_IMR); + + mask = OS_REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM | + AR_IMR_S2_DTIM | + AR_IMR_S2_DTIMSYNC | + AR_IMR_S2_CABEND | + AR_IMR_S2_CABTO | + AR_IMR_S2_TSFOOR | + AR_IMR_S2_GTT | + AR_IMR_S2_CST); + OS_REG_WRITE(ah, AR_IMR_S2, mask | mask2); + + ahp->ah_maskReg = ints; + + /* Re-enable interrupts if they were enabled before. */ + if (ints & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + + if (! AR_SREV_HOWL(ah)) { + mask = AR_INTR_MAC_IRQ; + if (ints & HAL_INT_GPIO) + mask |= SM(AH5416(ah)->ah_gpioMask, + AR_INTR_ASYNC_MASK_GPIO); + OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, mask); + OS_REG_WRITE(ah, AR_INTR_ASYNC_MASK, mask); + + mask = AR_INTR_SYNC_DEFAULT; + if (ints & HAL_INT_GPIO) + mask |= SM(AH5416(ah)->ah_gpioMask, + AR_INTR_SYNC_MASK_GPIO); + OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, mask); + OS_REG_WRITE(ah, AR_INTR_SYNC_MASK, mask); + } + } + + return omask; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_keycache.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_keycache.c new file mode 100644 index 0000000..533fe03 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_keycache.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" + +static const int keyType[] = { + 1, /* HAL_CIPHER_WEP */ + 0, /* HAL_CIPHER_AES_OCB */ + 2, /* HAL_CIPHER_AES_CCM */ + 0, /* HAL_CIPHER_CKIP */ + 3, /* HAL_CIPHER_TKIP */ + 0, /* HAL_CIPHER_CLR */ +}; + +/* + * Clear the specified key cache entry and any associated MIC entry. + */ +HAL_BOOL +ar5416ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + if (ar5212ResetKeyCacheEntry(ah, entry)) { + ahp->ah_keytype[entry] = keyType[HAL_CIPHER_CLR]; + return AH_TRUE; + } else + return AH_FALSE; +} + +/* + * Sets the contents of the specified key cache entry + * and any associated MIC entry. + */ +HAL_BOOL +ar5416SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, + const HAL_KEYVAL *k, const uint8_t *mac, + int xorKey) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + if (ar5212SetKeyCacheEntry(ah, entry, k, mac, xorKey)) { + ahp->ah_keytype[entry] = keyType[k->kv_type]; + return AH_TRUE; + } else + return AH_FALSE; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_misc.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_misc.c new file mode 100644 index 0000000..dd76843 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_misc.c @@ -0,0 +1,754 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#include "ah_desc.h" /* NB: for HAL_PHYERR* */ + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ah_eeprom_v14.h" /* for owl_get_ntxchains() */ + +/* + * Return the wireless modes (a,b,g,n,t) supported by hardware. + * + * This value is what is actually supported by the hardware + * and is unaffected by regulatory/country code settings. + * + */ +u_int +ar5416GetWirelessModes(struct ath_hal *ah) +{ + u_int mode; + struct ath_hal_private *ahpriv = AH_PRIVATE(ah); + HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; + + mode = ar5212GetWirelessModes(ah); + + /* Only enable HT modes if the NIC supports HT */ + if (pCap->halHTSupport == AH_TRUE && (mode & HAL_MODE_11A)) + mode |= HAL_MODE_11NA_HT20 + | HAL_MODE_11NA_HT40PLUS + | HAL_MODE_11NA_HT40MINUS + ; + if (pCap->halHTSupport == AH_TRUE && (mode & HAL_MODE_11G)) + mode |= HAL_MODE_11NG_HT20 + | HAL_MODE_11NG_HT40PLUS + | HAL_MODE_11NG_HT40MINUS + ; + return mode; +} + +/* + * Change the LED blinking pattern to correspond to the connectivity + */ +void +ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state) +{ + static const uint32_t ledbits[8] = { + AR_MAC_LED_ASSOC_NONE, /* HAL_LED_INIT */ + AR_MAC_LED_ASSOC_PEND, /* HAL_LED_SCAN */ + AR_MAC_LED_ASSOC_PEND, /* HAL_LED_AUTH */ + AR_MAC_LED_ASSOC_ACTIVE, /* HAL_LED_ASSOC*/ + AR_MAC_LED_ASSOC_ACTIVE, /* HAL_LED_RUN */ + AR_MAC_LED_ASSOC_NONE, + AR_MAC_LED_ASSOC_NONE, + AR_MAC_LED_ASSOC_NONE, + }; + + if (AR_SREV_HOWL(ah)) + return; + + /* + * Set the blink operating mode. + */ + OS_REG_RMW_FIELD(ah, AR_MAC_LED, + AR_MAC_LED_ASSOC, ledbits[state & 0x7]); + + /* XXX Blink slow mode? */ + /* XXX Blink threshold? */ + /* XXX Blink sleep hystersis? */ + + /* + * Set the LED blink configuration to be proportional + * to the current TX and RX filter bytes. (Ie, RX'ed + * frames that don't match the filter are ignored.) + * This means that higher TX/RX throughput will result + * in the blink rate increasing. + */ + OS_REG_RMW_FIELD(ah, AR_MAC_LED, AR_MAC_LED_MODE, + AR_MAC_LED_MODE_PROP); +} + +/* + * Get the current hardware tsf for stamlme + */ +uint64_t +ar5416GetTsf64(struct ath_hal *ah) +{ + uint32_t low1, low2, u32; + + /* sync multi-word read */ + low1 = OS_REG_READ(ah, AR_TSF_L32); + u32 = OS_REG_READ(ah, AR_TSF_U32); + low2 = OS_REG_READ(ah, AR_TSF_L32); + if (low2 < low1) { /* roll over */ + /* + * If we are not preempted this will work. If we are + * then we re-reading AR_TSF_U32 does no good as the + * low bits will be meaningless. Likewise reading + * L32, U32, U32, then comparing the last two reads + * to check for rollover doesn't help if preempted--so + * we take this approach as it costs one less PCI read + * which can be noticeable when doing things like + * timestamping packets in monitor mode. + */ + u32++; + } + return (((uint64_t) u32) << 32) | ((uint64_t) low2); +} + +/* + * Update the TSF. + * + * The full TSF is only updated once the upper 32 bits have + * been written. Writing only the lower 32 bits of the TSF + * will not actually correctly update the TSF. + * + * The #if 0'ed code is to check whether the previous TSF + * reset or write has completed before writing to the + * TSF. Strictly speaking, it should be also checked before + * reading the TSF as the write/reset may not have completed. + */ +void +ar5416SetTsf64(struct ath_hal *ah, uint64_t tsf64) +{ + /* XXX check if this is correct! */ +#if 0 + int i; + uint32_t v; + + for (i = 0; i < 10; i++) { + v = OS_REG_READ(ah, AR_SLP32_MODE); + if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0) + break; + OS_DELAY(10); + } + if (i == 10) + ath_hal_printf(ah, "%s: couldn't slew things right!\n", __func__); +#endif + + OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); + OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); +} + +/* + * Reset the current hardware tsf for stamlme. + */ +void +ar5416ResetTsf(struct ath_hal *ah) +{ + uint32_t v; + int i; + + for (i = 0; i < 10; i++) { + v = OS_REG_READ(ah, AR_SLP32_MODE); + if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0) + break; + OS_DELAY(10); + } + OS_REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); +} + +uint32_t +ar5416GetCurRssi(struct ath_hal *ah) +{ + if (AR_SREV_OWL(ah)) + return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff); + return (OS_REG_READ(ah, AR9130_PHY_CURRENT_RSSI) & 0xff); +} + +HAL_BOOL +ar5416SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) +{ + return AH_TRUE; +} + +/* Setup decompression for given key index */ +HAL_BOOL +ar5416SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) +{ + return AH_TRUE; +} + +/* Setup coverage class */ +void +ar5416SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) +{ + + ar5212SetCoverageClass(ah, coverageclass, now); +} + +/* + * Return the busy for rx_frame, rx_clear, and tx_frame + */ +HAL_BOOL +ar5416GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + u_int32_t good = AH_TRUE; + + /* XXX freeze/unfreeze mib counters */ + uint32_t rc = OS_REG_READ(ah, AR_RCCNT); + uint32_t ec = OS_REG_READ(ah, AR_EXTRCCNT); + uint32_t rf = OS_REG_READ(ah, AR_RFCNT); + uint32_t tf = OS_REG_READ(ah, AR_TFCNT); + uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */ + + if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) { + /* + * Cycle counter wrap (or initial call); it's not possible + * to accurately calculate a value because the registers + * right shift rather than wrap--so punt and return 0. + */ + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cycle counter wrap. ExtBusy = 0\n", __func__); + good = AH_FALSE; + } else { + hsample->cycle_count = cc - ahp->ah_cycleCount; + hsample->chan_busy = rc - ahp->ah_ctlBusy; + hsample->ext_chan_busy = ec - ahp->ah_extBusy; + hsample->rx_busy = rf - ahp->ah_rxBusy; + hsample->tx_busy = tf - ahp->ah_txBusy; + } + + /* + * Keep a copy of the MIB results so the next sample has something + * to work from. + */ + ahp->ah_cycleCount = cc; + ahp->ah_rxBusy = rf; + ahp->ah_ctlBusy = rc; + ahp->ah_txBusy = tf; + ahp->ah_extBusy = ec; + + return (good); +} + +/* + * Setup the TX/RX chainmasks - this needs to be done before a call + * to the reset method as it doesn't update the hardware. + */ +void +ar5416SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask, + uint32_t rx_chainmask) +{ + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + AH5416(ah)->ah_tx_chainmask = tx_chainmask & pCap->halTxChainMask; + AH5416(ah)->ah_rx_chainmask = rx_chainmask & pCap->halRxChainMask; +} + +/* + * Return approximation of extension channel busy over an time interval + * 0% (clear) -> 100% (busy) + * + * XXX TODO: update this to correctly sample all the counters, + * rather than a subset of it. + */ +uint32_t +ar5416Get11nExtBusy(struct ath_hal *ah) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + uint32_t busy; /* percentage */ + uint32_t cycleCount, ctlBusy, extBusy; + + ctlBusy = OS_REG_READ(ah, AR_RCCNT); + extBusy = OS_REG_READ(ah, AR_EXTRCCNT); + cycleCount = OS_REG_READ(ah, AR_CCCNT); + + if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cycleCount) { + /* + * Cycle counter wrap (or initial call); it's not possible + * to accurately calculate a value because the registers + * right shift rather than wrap--so punt and return 0. + */ + busy = 0; + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycle counter wrap. ExtBusy = 0\n", + __func__); + + } else { + uint32_t cycleDelta = cycleCount - ahp->ah_cycleCount; + uint32_t ctlBusyDelta = ctlBusy - ahp->ah_ctlBusy; + uint32_t extBusyDelta = extBusy - ahp->ah_extBusy; + uint32_t ctlClearDelta = 0; + + /* Compute control channel rxclear. + * The cycle delta may be less than the control channel delta. + * This could be solved by freezing the timers (or an atomic read, + * if one was available). Checking for the condition should be + * sufficient. + */ + if (cycleDelta > ctlBusyDelta) { + ctlClearDelta = cycleDelta - ctlBusyDelta; + } + + /* Compute ratio of extension channel busy to control channel clear + * as an approximation to extension channel cleanliness. + * + * According to the hardware folks, ext rxclear is undefined + * if the ctrl rxclear is de-asserted (i.e. busy) + */ + if (ctlClearDelta) { + busy = (extBusyDelta * 100) / ctlClearDelta; + } else { + busy = 100; + } + if (busy > 100) { + busy = 100; + } +#if 0 + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycleDelta 0x%x, ctlBusyDelta 0x%x, " + "extBusyDelta 0x%x, ctlClearDelta 0x%x, " + "busy %d\n", + __func__, cycleDelta, ctlBusyDelta, extBusyDelta, ctlClearDelta, busy); +#endif + } + + ahp->ah_cycleCount = cycleCount; + ahp->ah_ctlBusy = ctlBusy; + ahp->ah_extBusy = extBusy; + + return busy; +} + +/* + * Configure 20/40 operation + * + * 20/40 = joint rx clear (control and extension) + * 20 = rx clear (control) + * + * - NOTE: must stop MAC (tx) and requeue 40 MHz packets as 20 MHz when changing + * from 20/40 => 20 only + */ +void +ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode) +{ + uint32_t macmode; + + /* Configure MAC for 20/40 operation */ + if (mode == HAL_HT_MACMODE_2040) { + macmode = AR_2040_JOINED_RX_CLEAR; + } else { + macmode = 0; + } + OS_REG_WRITE(ah, AR_2040_MODE, macmode); +} + +/* + * Get Rx clear (control/extension channel) + * + * Returns active low (busy) for ctrl/ext channel + * Owl 2.0 + */ +HAL_HT_RXCLEAR +ar5416Get11nRxClear(struct ath_hal *ah) +{ + HAL_HT_RXCLEAR rxclear = 0; + uint32_t val; + + val = OS_REG_READ(ah, AR_DIAG_SW); + + /* control channel */ + if (val & AR_DIAG_RXCLEAR_CTL_LOW) { + rxclear |= HAL_RX_CLEAR_CTL_LOW; + } + /* extension channel */ + if (val & AR_DIAG_RXCLEAR_EXT_LOW) { + rxclear |= HAL_RX_CLEAR_EXT_LOW; + } + return rxclear; +} + +/* + * Set Rx clear (control/extension channel) + * + * Useful for forcing the channel to appear busy for + * debugging/diagnostics + * Owl 2.0 + */ +void +ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear) +{ + /* control channel */ + if (rxclear & HAL_RX_CLEAR_CTL_LOW) { + OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW); + } else { + OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW); + } + /* extension channel */ + if (rxclear & HAL_RX_CLEAR_EXT_LOW) { + OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW); + } else { + OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW); + } +} + +/* XXX shouldn't be here! */ +#define TU_TO_USEC(_tu) ((_tu) << 10) + +HAL_STATUS +ar5416SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration, + uint32_t nextStart, HAL_QUIET_FLAG flag) +{ + uint32_t period_us = TU_TO_USEC(period); /* convert to us unit */ + uint32_t nextStart_us = TU_TO_USEC(nextStart); /* convert to us unit */ + if (flag & HAL_QUIET_ENABLE) { + if ((!nextStart) || (flag & HAL_QUIET_ADD_CURRENT_TSF)) { + /* Add the nextStart offset to the current TSF */ + nextStart_us += OS_REG_READ(ah, AR_TSF_L32); + } + if (flag & HAL_QUIET_ADD_SWBA_RESP_TIME) { + nextStart_us += ah->ah_config.ah_sw_beacon_response_time; + } + OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); + OS_REG_WRITE(ah, AR_QUIET2, SM(duration, AR_QUIET2_QUIET_DUR)); + OS_REG_WRITE(ah, AR_QUIET_PERIOD, period_us); + OS_REG_WRITE(ah, AR_NEXT_QUIET, nextStart_us); + OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET); + } else { + OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET); + } + return HAL_OK; +} +#undef TU_TO_USEC + +HAL_STATUS +ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t *result) +{ + switch (type) { + case HAL_CAP_BB_HANG: + switch (capability) { + case HAL_BB_HANG_RIFS: + return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP; + case HAL_BB_HANG_DFS: + return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP; + case HAL_BB_HANG_RX_CLEAR: + return AR_SREV_MERLIN(ah) ? HAL_OK : HAL_ENOTSUPP; + } + break; + case HAL_CAP_MAC_HANG: + return ((ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) || + (ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE) || + AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? + HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_DIVERSITY: /* disable classic fast diversity */ + return HAL_ENXIO; + case HAL_CAP_ENFORCE_TXOP: + if (capability == 0) + return (HAL_OK); + if (capability != 1) + return (HAL_ENOTSUPP); + (*result) = + !! (AH5212(ah)->ah_miscMode & AR_PCU_TXOP_TBTT_LIMIT_ENA); + return (HAL_OK); + default: + break; + } + return ar5212GetCapability(ah, type, capability, result); +} + +HAL_BOOL +ar5416SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + u_int32_t capability, u_int32_t setting, HAL_STATUS *status) +{ + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + switch (type) { + case HAL_CAP_RX_CHAINMASK: + setting &= ath_hal_eepromGet(ah, AR_EEP_RXMASK, NULL); + pCap->halRxChainMask = setting; + if (owl_get_ntxchains(setting) > 2) + pCap->halRxStreams = 2; + else + pCap->halRxStreams = 1; + return AH_TRUE; + case HAL_CAP_TX_CHAINMASK: + setting &= ath_hal_eepromGet(ah, AR_EEP_TXMASK, NULL); + pCap->halTxChainMask = setting; + if (owl_get_ntxchains(setting) > 2) + pCap->halTxStreams = 2; + else + pCap->halTxStreams = 1; + return AH_TRUE; + case HAL_CAP_ENFORCE_TXOP: + if (capability != 1) + return AH_FALSE; + if (setting) { + AH5212(ah)->ah_miscMode + |= AR_PCU_TXOP_TBTT_LIMIT_ENA; + OS_REG_SET_BIT(ah, AR_MISC_MODE, + AR_PCU_TXOP_TBTT_LIMIT_ENA); + } else { + AH5212(ah)->ah_miscMode + &= ~AR_PCU_TXOP_TBTT_LIMIT_ENA; + OS_REG_CLR_BIT(ah, AR_MISC_MODE, + AR_PCU_TXOP_TBTT_LIMIT_ENA); + } + return AH_TRUE; + default: + break; + } + return ar5212SetCapability(ah, type, capability, setting, status); +} + +static int ar5416DetectMacHang(struct ath_hal *ah); +static int ar5416DetectBBHang(struct ath_hal *ah); + +HAL_BOOL +ar5416GetDiagState(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, + void **result, uint32_t *resultsize) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + int hangs; + + if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) + return AH_TRUE; + switch (request) { + case HAL_DIAG_EEPROM: + return ath_hal_eepromDiag(ah, request, + args, argsize, result, resultsize); + case HAL_DIAG_CHECK_HANGS: + if (argsize != sizeof(int)) + return AH_FALSE; + hangs = *(const int *) args; + ahp->ah_hangs = 0; + if (hangs & HAL_BB_HANGS) + ahp->ah_hangs |= ar5416DetectBBHang(ah); + /* NB: if BB is hung MAC will be hung too so skip check */ + if (ahp->ah_hangs == 0 && (hangs & HAL_MAC_HANGS)) + ahp->ah_hangs |= ar5416DetectMacHang(ah); + *result = &ahp->ah_hangs; + *resultsize = sizeof(ahp->ah_hangs); + return AH_TRUE; + } + return ar5212GetDiagState(ah, request, + args, argsize, result, resultsize); +} + +HAL_BOOL +ar5416SetRifsDelay(struct ath_hal *ah, const struct ieee80211_channel *chan, + HAL_BOOL enable) +{ + uint32_t val; + HAL_BOOL is_chan_2g = AH_FALSE; + HAL_BOOL is_ht40 = AH_FALSE; + + if (chan) + is_chan_2g = IEEE80211_IS_CHAN_2GHZ(chan); + + if (chan) + is_ht40 = IEEE80211_IS_CHAN_HT40(chan); + + /* Only support disabling RIFS delay for now */ + HALASSERT(enable == AH_FALSE); + + if (enable == AH_TRUE) + return AH_FALSE; + + /* Change RIFS init delay to 0 */ + val = OS_REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS); + val &= ~AR_PHY_RIFS_INIT_DELAY; + OS_REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val); + + /* + * For Owl, RIFS RX parameters are controlled differently; + * it isn't enabled in the inivals by default. + * + * For Sowl/Howl, RIFS RX is enabled in the inivals by default; + * the following code sets them back to non-RIFS values. + * + * For > Sowl/Howl, RIFS RX can be left on by default and so + * this function shouldn't be called. + */ + if ((! AR_SREV_SOWL(ah)) && (! AR_SREV_HOWL(ah))) + return AH_TRUE; + + /* Reset search delay to default values */ + if (is_chan_2g) + if (is_ht40) + OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x268); + else + OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x134); + else + if (is_ht40) + OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x370); + else + OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x1b8); + + return AH_TRUE; +} + +static HAL_BOOL +ar5416CompareDbgHang(struct ath_hal *ah, const mac_dbg_regs_t *regs, + const hal_mac_hang_check_t *check) +{ + int found_states; + + found_states = 0; + if (check->states & dcu_chain_state) { + int i; + + for (i = 0; i < 6; i++) { + if (((regs->dma_dbg_4 >> (5*i)) & 0x1f) == + check->dcu_chain_state) + found_states |= dcu_chain_state; + } + for (i = 0; i < 4; i++) { + if (((regs->dma_dbg_5 >> (5*i)) & 0x1f) == + check->dcu_chain_state) + found_states |= dcu_chain_state; + } + } + if (check->states & dcu_complete_state) { + if ((regs->dma_dbg_6 & 0x3) == check->dcu_complete_state) + found_states |= dcu_complete_state; + } + if (check->states & qcu_stitch_state) { + if (((regs->dma_dbg_3 >> 18) & 0xf) == check->qcu_stitch_state) + found_states |= qcu_stitch_state; + } + if (check->states & qcu_fetch_state) { + if (((regs->dma_dbg_3 >> 22) & 0xf) == check->qcu_fetch_state) + found_states |= qcu_fetch_state; + } + if (check->states & qcu_complete_state) { + if (((regs->dma_dbg_3 >> 26) & 0x7) == check->qcu_complete_state) + found_states |= qcu_complete_state; + } + return (found_states == check->states); +} + +#define NUM_STATUS_READS 50 + +static int +ar5416DetectMacHang(struct ath_hal *ah) +{ + static const hal_mac_hang_check_t hang_sig1 = { + .dcu_chain_state = 0x6, + .dcu_complete_state = 0x1, + .states = dcu_chain_state + | dcu_complete_state, + }; + static const hal_mac_hang_check_t hang_sig2 = { + .qcu_stitch_state = 0x9, + .qcu_fetch_state = 0x8, + .qcu_complete_state = 0x4, + .states = qcu_stitch_state + | qcu_fetch_state + | qcu_complete_state, + }; + mac_dbg_regs_t mac_dbg; + int i; + + mac_dbg.dma_dbg_3 = OS_REG_READ(ah, AR_DMADBG_3); + mac_dbg.dma_dbg_4 = OS_REG_READ(ah, AR_DMADBG_4); + mac_dbg.dma_dbg_5 = OS_REG_READ(ah, AR_DMADBG_5); + mac_dbg.dma_dbg_6 = OS_REG_READ(ah, AR_DMADBG_6); + for (i = 1; i <= NUM_STATUS_READS; i++) { + if (mac_dbg.dma_dbg_3 != OS_REG_READ(ah, AR_DMADBG_3) || + mac_dbg.dma_dbg_4 != OS_REG_READ(ah, AR_DMADBG_4) || + mac_dbg.dma_dbg_5 != OS_REG_READ(ah, AR_DMADBG_5) || + mac_dbg.dma_dbg_6 != OS_REG_READ(ah, AR_DMADBG_6)) + return 0; + } + + if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig1)) + return HAL_MAC_HANG_SIG1; + if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig2)) + return HAL_MAC_HANG_SIG2; + + HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown MAC hang signature " + "DMADBG_3=0x%x DMADBG_4=0x%x DMADBG_5=0x%x DMADBG_6=0x%x\n", + __func__, mac_dbg.dma_dbg_3, mac_dbg.dma_dbg_4, mac_dbg.dma_dbg_5, + mac_dbg.dma_dbg_6); + + return 0; +} + +/* + * Determine if the baseband using the Observation Bus Register + */ +static int +ar5416DetectBBHang(struct ath_hal *ah) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + /* + * Check the PCU Observation Bus 1 register (0x806c) + * NUM_STATUS_READS times + * + * 4 known BB hang signatures - + * [1] bits 8,9,11 are 0. State machine state (bits 25-31) is 0x1E + * [2] bits 8,9 are 1, bit 11 is 0. State machine state + * (bits 25-31) is 0x52 + * [3] bits 8,9 are 1, bit 11 is 0. State machine state + * (bits 25-31) is 0x18 + * [4] bit 10 is 1, bit 11 is 0. WEP state (bits 12-17) is 0x2, + * Rx State (bits 20-24) is 0x7. + */ + static const struct { + uint32_t val; + uint32_t mask; + int code; + } hang_list[] = { + /* Reg Value Reg Mask Hang Code XXX */ + { 0x1E000000, 0x7E000B00, HAL_BB_HANG_DFS }, + { 0x52000B00, 0x7E000B00, HAL_BB_HANG_RIFS }, + { 0x18000B00, 0x7E000B00, HAL_BB_HANG_RX_CLEAR }, + { 0x00702400, 0x7E7FFFEF, HAL_BB_HANG_RX_CLEAR } + }; + uint32_t hang_sig; + int i; + + hang_sig = OS_REG_READ(ah, AR_OBSERV_1); + for (i = 1; i <= NUM_STATUS_READS; i++) { + if (hang_sig != OS_REG_READ(ah, AR_OBSERV_1)) + return 0; + } + for (i = 0; i < N(hang_list); i++) + if ((hang_sig & hang_list[i].mask) == hang_list[i].val) { + HALDEBUG(ah, HAL_DEBUG_HANG, + "%s BB hang, signature 0x%x, code 0x%x\n", + __func__, hang_sig, hang_list[i].code); + return hang_list[i].code; + } + + HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown BB hang signature! " + "<0x806c>=0x%x\n", __func__, hang_sig); + + return 0; +#undef N +} +#undef NUM_STATUS_READS diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_phy.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_phy.c new file mode 100644 index 0000000..1cfd964 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_phy.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" + +/* shorthands to compact tables for readability */ +#define OFDM IEEE80211_T_OFDM +#define CCK IEEE80211_T_CCK +#define HT IEEE80211_T_HT + +HAL_RATE_TABLE ar5416_11ng_table = { + 28, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80| 2), 0 }, +/* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80| 4), 1 }, +/* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80|11), 2 }, +/* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80|22), 3 }, +/* Remove rates 6, 9 from rate ctrl */ +/* 6 Mb */ { AH_FALSE, OFDM, 6000, 0x0b, 0x00, 12, 4 }, +/* 9 Mb */ { AH_FALSE, OFDM, 9000, 0x0f, 0x00, 18, 4 }, +/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, 24, 6 }, +/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 6 }, +/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, 48, 8 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8 }, +/* 6.5 Mb */ { AH_TRUE, HT, 6500, 0x80, 0x00, 0, 8 }, +/* 13 Mb */ { AH_TRUE, HT, 13000, 0x81, 0x00, 1, 8 }, +/*19.5 Mb */ { AH_TRUE, HT, 19500, 0x82, 0x00, 2, 8 }, +/* 26 Mb */ { AH_TRUE, HT, 26000, 0x83, 0x00, 3, 8 }, +/* 39 Mb */ { AH_TRUE, HT, 39000, 0x84, 0x00, 4, 8 }, +/* 52 Mb */ { AH_TRUE, HT, 52000, 0x85, 0x00, 5, 8 }, +/*58.5 Mb */ { AH_TRUE, HT, 58500, 0x86, 0x00, 6, 8 }, +/* 65 Mb */ { AH_TRUE, HT, 65000, 0x87, 0x00, 7, 8 }, +/* 13 Mb */ { AH_TRUE, HT, 13000, 0x88, 0x00, 8, 8 }, +/* 26 Mb */ { AH_TRUE, HT, 26000, 0x89, 0x00, 9, 8 }, +/* 39 Mb */ { AH_TRUE, HT, 39000, 0x8a, 0x00, 10, 8 }, +/* 52 Mb */ { AH_TRUE, HT, 52000, 0x8b, 0x00, 11, 8 }, +/* 78 Mb */ { AH_TRUE, HT, 78000, 0x8c, 0x00, 12, 8 }, +/* 104 Mb */ { AH_TRUE, HT, 104000, 0x8d, 0x00, 13, 8 }, +/* 117 Mb */ { AH_TRUE, HT, 117000, 0x8e, 0x00, 14, 8 }, +/* 130 Mb */ { AH_TRUE, HT, 130000, 0x8f, 0x00, 15, 8 }, + }, +}; + +static HAL_RATE_TABLE ar5416_11na_table = { + 24, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 }, +/* 6.5 Mb */ { AH_TRUE, HT, 6500, 0x80, 0x00, 0, 4 }, +/* 13 Mb */ { AH_TRUE, HT, 13000, 0x81, 0x00, 1, 4 }, +/*19.5 Mb */ { AH_TRUE, HT, 19500, 0x82, 0x00, 2, 4 }, +/* 26 Mb */ { AH_TRUE, HT, 26000, 0x83, 0x00, 3, 4 }, +/* 39 Mb */ { AH_TRUE, HT, 39000, 0x84, 0x00, 4, 4 }, +/* 52 Mb */ { AH_TRUE, HT, 52000, 0x85, 0x00, 5, 4 }, +/*58.5 Mb */ { AH_TRUE, HT, 58500, 0x86, 0x00, 6, 4 }, +/* 65 Mb */ { AH_TRUE, HT, 65000, 0x87, 0x00, 7, 4 }, +/* 13 Mb */ { AH_TRUE, HT, 13000, 0x88, 0x00, 8, 4 }, +/* 26 Mb */ { AH_TRUE, HT, 26000, 0x89, 0x00, 9, 4 }, +/* 39 Mb */ { AH_TRUE, HT, 39000, 0x8a, 0x00, 10, 4 }, +/* 52 Mb */ { AH_TRUE, HT, 52000, 0x8b, 0x00, 11, 4 }, +/* 78 Mb */ { AH_TRUE, HT, 78000, 0x8c, 0x00, 12, 4 }, +/* 104 Mb */ { AH_TRUE, HT, 104000, 0x8d, 0x00, 13, 4 }, +/* 117 Mb */ { AH_TRUE, HT, 117000, 0x8e, 0x00, 14, 4 }, +/* 130 Mb */ { AH_TRUE, HT, 130000, 0x8f, 0x00, 15, 4 }, + }, +}; + +#undef OFDM +#undef CCK +#undef HT + +const HAL_RATE_TABLE * +ar5416GetRateTable(struct ath_hal *ah, u_int mode) +{ + HAL_RATE_TABLE *rt; + switch (mode) { + case HAL_MODE_11NG_HT20: + case HAL_MODE_11NG_HT40PLUS: + case HAL_MODE_11NG_HT40MINUS: + rt = &ar5416_11ng_table; + break; + case HAL_MODE_11NA_HT20: + case HAL_MODE_11NA_HT40PLUS: + case HAL_MODE_11NA_HT40MINUS: + rt = &ar5416_11na_table; + break; + default: + return ar5212GetRateTable(ah, mode); + } + ath_hal_setupratetable(ah, rt); + return rt; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_power.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_power.c new file mode 100644 index 0000000..dff9a85 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_power.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" + +/* + * Notify Power Mgt is enabled in self-generated frames. + * If requested, force chip awake. + * + * Returns A_OK if chip is awake or successfully forced awake. + * + * WARNING WARNING WARNING + * There is a problem with the chip where sometimes it will not wake up. + */ +static HAL_BOOL +ar5416SetPowerModeAwake(struct ath_hal *ah, int setChip) +{ +#define POWER_UP_TIME 200000 + uint32_t val; + int i = 0; + + if (setChip) { + /* + * Do a Power-On-Reset if OWL is shutdown + * the NetBSD driver power-cycles the Cardbus slot + * as part of the reset procedure. + */ + if ((OS_REG_READ(ah, AR_RTC_STATUS) + & AR_RTC_PM_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) + goto bad; + AH5416(ah)->ah_initPLL(ah, AH_NULL); + } + + if (AR_SREV_HOWL(ah)) + OS_REG_SET_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); + + OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); + if (AR_SREV_HOWL(ah)) + OS_DELAY(10000); + else + OS_DELAY(50); /* Give chip the chance to awake */ + + for (i = POWER_UP_TIME / 50; i != 0; i--) { + val = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; + if (val == AR_RTC_STATUS_ON) + break; + OS_DELAY(50); + OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); + } + bad: + if (i == 0) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n", + __func__, POWER_UP_TIME/1000); +#endif + return AH_FALSE; + } + } + + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + return AH_TRUE; +#undef POWER_UP_TIME +} + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, force chip to sleep. + */ +static void +ar5416SetPowerModeSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) { + /* Clear the RTC force wake bit to allow the mac to sleep */ + OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); + if (! AR_SREV_HOWL(ah)) + OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF); + /* Shutdown chip. Active low */ + if (! AR_SREV_OWL(ah)) + OS_REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); + } +} + +/* + * Notify Power Management is enabled in self-generating + * fames. If request, set power mode of chip to + * auto/normal. Duration in units of 128us (1/8 TU). + */ +static void +ar5416SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + + if (setChip) + OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); +} + +/* + * Set power mgt to the requested mode, and conditionally set + * the chip as well + */ +HAL_BOOL +ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) +{ +#ifdef AH_DEBUG + static const char* modes[] = { + "AWAKE", + "FULL-SLEEP", + "NETWORK SLEEP", + "UNDEFINED" + }; +#endif + int status = AH_TRUE; + +#if 0 + if (!setChip) + return AH_TRUE; +#endif + + HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, + modes[ah->ah_powerMode], modes[mode], setChip ? "set chip " : ""); + switch (mode) { + case HAL_PM_AWAKE: + if (setChip) + ah->ah_powerMode = mode; + status = ar5416SetPowerModeAwake(ah, setChip); + break; + case HAL_PM_FULL_SLEEP: + ar5416SetPowerModeSleep(ah, setChip); + if (setChip) + ah->ah_powerMode = mode; + break; + case HAL_PM_NETWORK_SLEEP: + ar5416SetPowerModeNetworkSleep(ah, setChip); + if (setChip) + ah->ah_powerMode = mode; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode 0x%x\n", + __func__, mode); + return AH_FALSE; + } + return status; +} + +/* + * Return the current sleep mode of the chip + */ +HAL_POWER_MODE +ar5416GetPowerMode(struct ath_hal *ah) +{ + int mode = OS_REG_READ(ah, AR_RTC_STATUS); + switch (mode & AR_RTC_PM_STATUS_M) { + case AR_RTC_STATUS_ON: + case AR_RTC_STATUS_WAKEUP: + return HAL_PM_AWAKE; + case AR_RTC_STATUS_SLEEP: + return HAL_PM_NETWORK_SLEEP; + case AR_RTC_STATUS_SHUTDOWN: + return HAL_PM_FULL_SLEEP; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unknown power mode, RTC_STATUS 0x%x\n", + __func__, mode); + return HAL_PM_UNDEFINED; + } +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_radar.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_radar.c new file mode 100644 index 0000000..9759b74 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_radar.c @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2010-2011 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#include "ah_desc.h" /* NB: for HAL_PHYERR* */ + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ah_eeprom_v14.h" /* for owl_get_ntxchains() */ + +/* + * These are default parameters for the AR5416 and + * later 802.11n NICs. They simply enable some + * radar pulse event generation. + * + * These are very likely not valid for the AR5212 era + * NICs. + * + * Since these define signal sizing and threshold + * parameters, they may need changing based on the + * specific antenna and receive amplifier + * configuration. + */ +#define AR5416_DFS_FIRPWR -33 +#define AR5416_DFS_RRSSI 20 +#define AR5416_DFS_HEIGHT 10 +#define AR5416_DFS_PRSSI 15 +#define AR5416_DFS_INBAND 15 +#define AR5416_DFS_RELPWR 8 +#define AR5416_DFS_RELSTEP 12 +#define AR5416_DFS_MAXLEN 255 + +HAL_BOOL +ar5416GetDfsDefaultThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ + + /* + * These are general examples of the parameter values + * to use when configuring radar pulse detection for + * the AR5416, AR91xx, AR92xx NICs. They are only + * for testing and do require tuning depending upon the + * hardware and deployment specifics. + */ + pe->pe_firpwr = AR5416_DFS_FIRPWR; + pe->pe_rrssi = AR5416_DFS_RRSSI; + pe->pe_height = AR5416_DFS_HEIGHT; + pe->pe_prssi = AR5416_DFS_PRSSI; + pe->pe_inband = AR5416_DFS_INBAND; + pe->pe_relpwr = AR5416_DFS_RELPWR; + pe->pe_relstep = AR5416_DFS_RELSTEP; + pe->pe_maxlen = AR5416_DFS_MAXLEN; + + return (AH_TRUE); +} + +/* + * Get the radar parameter values and return them in the pe + * structure + */ +void +ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ + uint32_t val, temp; + + val = OS_REG_READ(ah, AR_PHY_RADAR_0); + + temp = MS(val,AR_PHY_RADAR_0_FIRPWR); + temp |= 0xFFFFFF80; + pe->pe_firpwr = temp; + pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI); + pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT); + pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI); + pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND); + + /* RADAR_1 values */ + val = OS_REG_READ(ah, AR_PHY_RADAR_1); + pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH); + pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH); + pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN); + + pe->pe_extchannel = !! (OS_REG_READ(ah, AR_PHY_RADAR_EXT) & + AR_PHY_RADAR_EXT_ENA); + + pe->pe_usefir128 = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & + AR_PHY_RADAR_1_USE_FIR128); + pe->pe_blockradar = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & + AR_PHY_RADAR_1_BLOCK_CHECK); + pe->pe_enmaxrssi = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & + AR_PHY_RADAR_1_MAX_RRSSI); + pe->pe_enabled = !! + (OS_REG_READ(ah, AR_PHY_RADAR_0) & AR_PHY_RADAR_0_ENA); + pe->pe_enrelpwr = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & + AR_PHY_RADAR_1_RELPWR_ENA); + pe->pe_en_relstep_check = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & + AR_PHY_RADAR_1_RELSTEP_CHECK); +} + +/* + * Enable radar detection and set the radar parameters per the + * values in pe + */ +void +ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) +{ + uint32_t val; + + val = OS_REG_READ(ah, AR_PHY_RADAR_0); + + if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_FIRPWR; + val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR); + } + if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_RRSSI; + val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI); + } + if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_HEIGHT; + val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT); + } + if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_PRSSI; + val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); + } + if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) { + val &= ~AR_PHY_RADAR_0_INBAND; + val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND); + } + + /*Enable FFT data*/ + val |= AR_PHY_RADAR_0_FFT_ENA; + OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); + + /* Implicitly enable */ + if (pe->pe_enabled == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); + else if (pe->pe_enabled == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); + + if (pe->pe_usefir128 == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128); + else if (pe->pe_usefir128 == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128); + + if (pe->pe_enmaxrssi == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI); + else if (pe->pe_enmaxrssi == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI); + + if (pe->pe_blockradar == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK); + else if (pe->pe_blockradar == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK); + + if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) { + val = OS_REG_READ(ah, AR_PHY_RADAR_1); + val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH; + val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH); + OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); + } + if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) { + val = OS_REG_READ(ah, AR_PHY_RADAR_1); + val &= ~AR_PHY_RADAR_1_RELPWR_THRESH; + val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH); + OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); + } + + if (pe->pe_en_relstep_check == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, + AR_PHY_RADAR_1_RELSTEP_CHECK); + else if (pe->pe_en_relstep_check == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, + AR_PHY_RADAR_1_RELSTEP_CHECK); + + if (pe->pe_enrelpwr == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, + AR_PHY_RADAR_1_RELPWR_ENA); + else if (pe->pe_enrelpwr == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, + AR_PHY_RADAR_1_RELPWR_ENA); + + if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) { + val = OS_REG_READ(ah, AR_PHY_RADAR_1); + val &= ~AR_PHY_RADAR_1_MAXLEN; + val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN); + OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); + } + + /* + * Enable HT/40 if the upper layer asks; + * it should check the channel is HT/40 and HAL_CAP_EXT_CHAN_DFS + * is available. + */ + if (pe->pe_extchannel == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); + else if (pe->pe_extchannel == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); +} + +/* + * Extract the radar event information from the given phy error. + * + * Returns AH_TRUE if the phy error was actually a phy error, + * AH_FALSE if the phy error wasn't a phy error. + */ + +/* Flags for pulse_bw_info */ +#define PRI_CH_RADAR_FOUND 0x01 +#define EXT_CH_RADAR_FOUND 0x02 +#define EXT_CH_RADAR_EARLY_FOUND 0x04 + +HAL_BOOL +ar5416ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs, + uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event) +{ + HAL_BOOL doDfsExtCh; + HAL_BOOL doDfsEnhanced; + HAL_BOOL doDfsCombinedRssi; + + uint8_t rssi = 0, ext_rssi = 0; + uint8_t pulse_bw_info = 0, pulse_length_ext = 0, pulse_length_pri = 0; + uint32_t dur = 0; + int pri_found = 1, ext_found = 0; + int early_ext = 0; + int is_dc = 0; + uint16_t datalen; /* length from the RX status field */ + + /* Check whether the given phy error is a radar event */ + if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) && + (rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) { + return AH_FALSE; + } + + /* Grab copies of the capabilities; just to make the code clearer */ + doDfsExtCh = AH_PRIVATE(ah)->ah_caps.halExtChanDfsSupport; + doDfsEnhanced = AH_PRIVATE(ah)->ah_caps.halEnhancedDfsSupport; + doDfsCombinedRssi = AH_PRIVATE(ah)->ah_caps.halUseCombinedRadarRssi; + + datalen = rxs->rs_datalen; + + /* If hardware supports it, use combined RSSI, else use chain 0 RSSI */ + if (doDfsCombinedRssi) + rssi = (uint8_t) rxs->rs_rssi; + else + rssi = (uint8_t) rxs->rs_rssi_ctl[0]; + + /* Set this; but only use it if doDfsExtCh is set */ + ext_rssi = (uint8_t) rxs->rs_rssi_ext[0]; + + /* Cap it at 0 if the RSSI is a negative number */ + if (rssi & 0x80) + rssi = 0; + + if (ext_rssi & 0x80) + ext_rssi = 0; + + /* + * Fetch the relevant data from the frame + */ + if (doDfsExtCh) { + if (datalen < 3) + return AH_FALSE; + + /* Last three bytes of the frame are of interest */ + pulse_length_pri = *(buf + datalen - 3); + pulse_length_ext = *(buf + datalen - 2); + pulse_bw_info = *(buf + datalen - 1); + HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, ext_rssi=%d, pulse_length_pri=%d," + " pulse_length_ext=%d, pulse_bw_info=%x\n", + __func__, rssi, ext_rssi, pulse_length_pri, pulse_length_ext, + pulse_bw_info); + } else { + /* The pulse width is byte 0 of the data */ + if (datalen >= 1) + dur = ((uint8_t) buf[0]) & 0xff; + else + dur = 0; + + if (dur == 0 && rssi == 0) { + HALDEBUG(ah, HAL_DEBUG_DFS, "%s: dur and rssi are 0\n", __func__); + return AH_FALSE; + } + + HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", __func__, rssi, dur); + + /* Single-channel only */ + pri_found = 1; + ext_found = 0; + } + + /* + * If doing extended channel data, pulse_bw_info must + * have one of the flags set. + */ + if (doDfsExtCh && pulse_bw_info == 0x0) + return AH_FALSE; + + /* + * If the extended channel data is available, calculate + * which to pay attention to. + */ + if (doDfsExtCh) { + /* If pulse is on DC, take the larger duration of the two */ + if ((pulse_bw_info & EXT_CH_RADAR_FOUND) && + (pulse_bw_info & PRI_CH_RADAR_FOUND)) { + is_dc = 1; + if (pulse_length_ext > pulse_length_pri) { + dur = pulse_length_ext; + pri_found = 0; + ext_found = 1; + } else { + dur = pulse_length_pri; + pri_found = 1; + ext_found = 0; + } + } else if (pulse_bw_info & EXT_CH_RADAR_EARLY_FOUND) { + dur = pulse_length_ext; + pri_found = 0; + ext_found = 1; + early_ext = 1; + } else if (pulse_bw_info & PRI_CH_RADAR_FOUND) { + dur = pulse_length_pri; + pri_found = 1; + ext_found = 0; + } else if (pulse_bw_info & EXT_CH_RADAR_FOUND) { + dur = pulse_length_ext; + pri_found = 0; + ext_found = 1; + } + + } + + /* + * For enhanced DFS (Merlin and later), pulse_bw_info has + * implications for selecting the correct RSSI value. + */ + if (doDfsEnhanced) { + switch (pulse_bw_info & 0x03) { + case 0: + /* No radar? */ + rssi = 0; + break; + case PRI_CH_RADAR_FOUND: + /* Radar in primary channel */ + /* Cannot use ctrl channel RSSI if ext channel is stronger */ + if (ext_rssi >= (rssi + 3)) { + rssi = 0; + } + break; + case EXT_CH_RADAR_FOUND: + /* Radar in extended channel */ + /* Cannot use ext channel RSSI if ctrl channel is stronger */ + if (rssi >= (ext_rssi + 12)) { + rssi = 0; + } else { + rssi = ext_rssi; + } + break; + case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND): + /* When both are present, use stronger one */ + if (rssi < ext_rssi) + rssi = ext_rssi; + break; + } + } + + /* + * If not doing enhanced DFS, choose the ext channel if + * it is stronger than the main channel + */ + if (doDfsExtCh && !doDfsEnhanced) { + if ((ext_rssi > rssi) && (ext_rssi < 128)) + rssi = ext_rssi; + } + + /* + * XXX what happens if the above code decides the RSSI + * XXX wasn't valid, an sets it to 0? + */ + + /* + * Fill out dfs_event structure. + */ + event->re_full_ts = fulltsf; + event->re_ts = rxs->rs_tstamp; + event->re_rssi = rssi; + event->re_dur = dur; + + event->re_flags = 0; + if (pri_found) + event->re_flags |= HAL_DFS_EVENT_PRICH; + if (ext_found) + event->re_flags |= HAL_DFS_EVENT_EXTCH; + if (early_ext) + event->re_flags |= HAL_DFS_EVENT_EXTEARLY; + if (is_dc) + event->re_flags |= HAL_DFS_EVENT_ISDC; + + return AH_TRUE; +} + +/* + * Return whether fast-clock is currently enabled for this + * channel. + */ +HAL_BOOL +ar5416IsFastClockEnabled(struct ath_hal *ah) +{ + struct ath_hal_private *ahp = AH_PRIVATE(ah); + + return IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan); +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_recv.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_recv.c new file mode 100644 index 0000000..df096f9 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_recv.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_desc.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416desc.h" + +/* + * Get the receive filter. + */ +uint32_t +ar5416GetRxFilter(struct ath_hal *ah) +{ + uint32_t bits = OS_REG_READ(ah, AR_RX_FILTER); + uint32_t phybits = OS_REG_READ(ah, AR_PHY_ERR); + + if (phybits & AR_PHY_ERR_RADAR) + bits |= HAL_RX_FILTER_PHYRADAR; + if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) + bits |= HAL_RX_FILTER_PHYERR; + return bits; +} + +/* + * Set the receive filter. + */ +void +ar5416SetRxFilter(struct ath_hal *ah, u_int32_t bits) +{ + uint32_t phybits; + + OS_REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff)); + phybits = 0; + if (bits & HAL_RX_FILTER_PHYRADAR) + phybits |= AR_PHY_ERR_RADAR; + if (bits & HAL_RX_FILTER_PHYERR) + phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING; + OS_REG_WRITE(ah, AR_PHY_ERR, phybits); + if (phybits) { + OS_REG_WRITE(ah, AR_RXCFG, + OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); + } else { + OS_REG_WRITE(ah, AR_RXCFG, + OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA); + } +} + +/* + * Stop Receive at the DMA engine + */ +HAL_BOOL +ar5416StopDmaReceive(struct ath_hal *ah) +{ + HAL_BOOL status; + + OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP); + OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */ + if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0)) { + OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP_ERR); +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: dma failed to stop in 10ms\n" + "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", + __func__, + OS_REG_READ(ah, AR_CR), + OS_REG_READ(ah, AR_DIAG_SW)); +#endif + status = AH_FALSE; + } else { + status = AH_TRUE; + } + + /* + * XXX Is this to flush whatever is in a FIFO somewhere? + * XXX If so, what should the correct behaviour should be? + */ + if (AR_SREV_9100(ah)) + OS_DELAY(3000); + + return (status); +} + +/* + * Start receive at the PCU engine + */ +void +ar5416StartPcuReceive(struct ath_hal *ah) +{ + struct ath_hal_private *ahp = AH_PRIVATE(ah); + + HALDEBUG(ah, HAL_DEBUG_RX, "%s: Start PCU Receive \n", __func__); + ar5212EnableMibCounters(ah); + /* NB: restore current settings */ + ar5416AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, AH_TRUE); + /* + * NB: must do after enabling phy errors to avoid rx + * frames w/ corrupted descriptor status. + */ + OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT); +} + +/* + * Stop receive at the PCU engine + * and abort current frame in PCU + */ +void +ar5416StopPcuReceive(struct ath_hal *ah) +{ + OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT); + + HALDEBUG(ah, HAL_DEBUG_RX, "%s: Stop PCU Receive \n", __func__); + ar5212DisableMibCounters(ah); +} + +/* + * Initialize RX descriptor, by clearing the status and setting + * the size (and any other flags). + */ +HAL_BOOL +ar5416SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds, + uint32_t size, u_int flags) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + HALASSERT((size &~ AR_BufLen) == 0); + + ads->ds_ctl1 = size & AR_BufLen; + if (flags & HAL_RXDESC_INTREQ) + ads->ds_ctl1 |= AR_RxIntrReq; + + /* this should be enough */ + ads->ds_rxstatus8 &= ~AR_RxDone; + + /* clear the rest of the status fields */ + OS_MEMZERO(&(ads->u), sizeof(ads->u)); + + return AH_TRUE; +} + +/* + * Process an RX descriptor, and return the status to the caller. + * Copy some hardware specific items into the software portion + * of the descriptor. + * + * NB: the caller is responsible for validating the memory contents + * of the descriptor (e.g. flushing any cached copy). + */ +HAL_STATUS +ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, + uint32_t pa, struct ath_desc *nds, uint64_t tsf, + struct ath_rx_status *rs) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + if ((ads->ds_rxstatus8 & AR_RxDone) == 0) + return HAL_EINPROGRESS; + + rs->rs_status = 0; + rs->rs_flags = 0; + + rs->rs_datalen = ads->ds_rxstatus1 & AR_DataLen; + rs->rs_tstamp = ads->AR_RcvTimestamp; + + /* XXX what about KeyCacheMiss? */ + + rs->rs_rssi = MS(ads->ds_rxstatus4, AR_RxRSSICombined); + rs->rs_rssi_ctl[0] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt00); + rs->rs_rssi_ctl[1] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt01); + rs->rs_rssi_ctl[2] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt02); + rs->rs_rssi_ext[0] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt10); + rs->rs_rssi_ext[1] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt11); + rs->rs_rssi_ext[2] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt12); + + if (ads->ds_rxstatus8 & AR_RxKeyIdxValid) + rs->rs_keyix = MS(ads->ds_rxstatus8, AR_KeyIdx); + else + rs->rs_keyix = HAL_RXKEYIX_INVALID; + + /* NB: caller expected to do rate table mapping */ + rs->rs_rate = RXSTATUS_RATE(ah, ads); + rs->rs_more = (ads->ds_rxstatus1 & AR_RxMore) ? 1 : 0; + + rs->rs_isaggr = (ads->ds_rxstatus8 & AR_RxAggr) ? 1 : 0; + rs->rs_moreaggr = (ads->ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; + rs->rs_antenna = MS(ads->ds_rxstatus3, AR_RxAntenna); + + if (ads->ds_rxstatus3 & AR_GI) + rs->rs_flags |= HAL_RX_GI; + if (ads->ds_rxstatus3 & AR_2040) + rs->rs_flags |= HAL_RX_2040; + + /* + * Only the AR9280 and later chips support STBC RX, so + * ensure we only set this bit for those chips. + */ + if (AR_SREV_MERLIN_10_OR_LATER(ah) + && ads->ds_rxstatus3 & AR_STBCFrame) + rs->rs_flags |= HAL_RX_STBC; + + if (ads->ds_rxstatus8 & AR_PreDelimCRCErr) + rs->rs_flags |= HAL_RX_DELIM_CRC_PRE; + if (ads->ds_rxstatus8 & AR_PostDelimCRCErr) + rs->rs_flags |= HAL_RX_DELIM_CRC_POST; + if (ads->ds_rxstatus8 & AR_DecryptBusyErr) + rs->rs_flags |= HAL_RX_DECRYPT_BUSY; + if (ads->ds_rxstatus8 & AR_HiRxChain) + rs->rs_flags |= HAL_RX_HI_RX_CHAIN; + + if ((ads->ds_rxstatus8 & AR_RxFrameOK) == 0) { + /* + * These four bits should not be set together. The + * 5416 spec states a Michael error can only occur if + * DecryptCRCErr not set (and TKIP is used). Experience + * indicates however that you can also get Michael errors + * when a CRC error is detected, but these are specious. + * Consequently we filter them out here so we don't + * confuse and/or complicate drivers. + */ + + /* + * The AR5416 sometimes sets both AR_CRCErr and AR_PHYErr + * when reporting radar pulses. In this instance + * set HAL_RXERR_PHY as well as HAL_RXERR_CRC and + * let the driver layer figure out what to do. + * + * See PR kern/169362. + */ + if (ads->ds_rxstatus8 & AR_PHYErr) { + u_int phyerr; + + /* + * Packets with OFDM_RESTART on post delimiter are CRC OK and + * usable and MAC ACKs them. + * To avoid packet from being lost, we remove the PHY Err flag + * so that driver layer does not drop them. + */ + phyerr = MS(ads->ds_rxstatus8, AR_PHYErrCode); + + if ((phyerr == HAL_PHYERR_OFDM_RESTART) && + (ads->ds_rxstatus8 & AR_PostDelimCRCErr)) { + ath_hal_printf(ah, + "%s: OFDM_RESTART on post-delim CRC error\n", + __func__); + rs->rs_phyerr = 0; + } else { + rs->rs_status |= HAL_RXERR_PHY; + rs->rs_phyerr = phyerr; + } + } + if (ads->ds_rxstatus8 & AR_CRCErr) + rs->rs_status |= HAL_RXERR_CRC; + else if (ads->ds_rxstatus8 & AR_DecryptCRCErr) + rs->rs_status |= HAL_RXERR_DECRYPT; + else if (ads->ds_rxstatus8 & AR_MichaelErr) + rs->rs_status |= HAL_RXERR_MIC; + } + + return HAL_OK; +} diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_reset.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_reset.c new file mode 100644 index 0000000..6abb7b4 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_reset.c @@ -0,0 +1,2891 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */ +#define EEP_MINOR(_ah) \ + (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK) +#define IS_EEP_MINOR_V2(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2) +#define IS_EEP_MINOR_V3(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_3) + +/* Additional Time delay to wait after activiting the Base band */ +#define BASE_ACTIVATE_DELAY 100 /* 100 usec */ +#define PLL_SETTLE_DELAY 300 /* 300 usec */ +#define RTC_PLL_SETTLE_DELAY 1000 /* 1 ms */ + +static void ar5416InitDMA(struct ath_hal *ah); +static void ar5416InitBB(struct ath_hal *ah, const struct ieee80211_channel *); +static void ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode); +static void ar5416InitQoS(struct ath_hal *ah); +static void ar5416InitUserSettings(struct ath_hal *ah); +static void ar5416OverrideIni(struct ath_hal *ah, const struct ieee80211_channel *); + +#if 0 +static HAL_BOOL ar5416ChannelChange(struct ath_hal *, const struct ieee80211_channel *); +#endif +static void ar5416SetDeltaSlope(struct ath_hal *, const struct ieee80211_channel *); + +static HAL_BOOL ar5416SetResetPowerOn(struct ath_hal *ah); +static HAL_BOOL ar5416SetReset(struct ath_hal *ah, int type); +static HAL_BOOL ar5416SetPowerPerRateTable(struct ath_hal *ah, + struct ar5416eeprom *pEepData, + const struct ieee80211_channel *chan, int16_t *ratesArray, + uint16_t cfgCtl, uint16_t AntennaReduction, + uint16_t twiceMaxRegulatoryPower, + uint16_t powerLimit); +static void ar5416Set11nRegs(struct ath_hal *ah, const struct ieee80211_channel *chan); +static void ar5416MarkPhyInactive(struct ath_hal *ah); +static void ar5416SetIFSTiming(struct ath_hal *ah, + const struct ieee80211_channel *chan); + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + * + * bChannelChange is used to preserve DMA/PCU registers across + * a HW Reset during channel change. + */ +HAL_BOOL +ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, + struct ieee80211_channel *chan, + HAL_BOOL bChannelChange, + HAL_RESET_TYPE resetType, + HAL_STATUS *status) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) +#define FAIL(_code) do { ecode = _code; goto bad; } while (0) + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *ichan; + uint32_t saveDefAntenna, saveLedState; + uint32_t macStaId1; + uint16_t rfXpdGain[2]; + HAL_STATUS ecode; + uint32_t powerVal, rssiThrReg; + uint32_t ackTpcPow, ctsTpcPow, chirpTpcPow; + int i; + uint64_t tsf = 0; + + OS_MARK(ah, AH_MARK_RESET, bChannelChange); + + /* Bring out of sleep mode */ + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip did not wakeup\n", + __func__); + FAIL(HAL_EIO); + } + + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) + FAIL(HAL_EINVAL); + switch (opmode) { + case HAL_M_STA: + case HAL_M_IBSS: + case HAL_M_HOSTAP: + case HAL_M_MONITOR: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n", + __func__, opmode); + FAIL(HAL_EINVAL); + break; + } + HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); + + /* Blank the channel survey statistics */ + ath_hal_survey_clear(ah); + + /* XXX Turn on fast channel change for 5416 */ + + /* + * Preserve the bmiss rssi threshold and count threshold + * across resets + */ + rssiThrReg = OS_REG_READ(ah, AR_RSSI_THR); + /* If reg is zero, first time thru set to default val */ + if (rssiThrReg == 0) + rssiThrReg = INIT_RSSI_THR; + + /* + * Preserve the antenna on a channel change + */ + saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA); + + /* + * Don't do this for the AR9285 - it breaks RX for single + * antenna designs when diversity is disabled. + * + * I'm not sure what this was working around; it may be + * something to do with the AR5416. Certainly this register + * isn't supposed to be used by the MIMO chips for anything + * except for defining the default antenna when an external + * phase array / smart antenna is connected. + * + * See PR: kern/179269 . + */ + if ((! AR_SREV_KITE(ah)) && saveDefAntenna == 0) /* XXX magic constants */ + saveDefAntenna = 1; + + /* Save hardware flag before chip reset clears the register */ + macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & + (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT); + + /* Save led state from pci config register */ + saveLedState = OS_REG_READ(ah, AR_MAC_LED) & + (AR_MAC_LED_ASSOC | AR_MAC_LED_MODE | + AR_MAC_LED_BLINK_THRESH_SEL | AR_MAC_LED_BLINK_SLOW); + + /* For chips on which the RTC reset is done, save TSF before it gets cleared */ + if (AR_SREV_HOWL(ah) || + (AR_SREV_MERLIN(ah) && + ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) || + (ah->ah_config.ah_force_full_reset)) + tsf = ar5416GetTsf64(ah); + + /* Mark PHY as inactive; marked active in ar5416InitBB() */ + ar5416MarkPhyInactive(ah); + + if (!ar5416ChipReset(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + FAIL(HAL_EIO); + } + + /* Restore TSF */ + if (tsf) + ar5416SetTsf64(ah, tsf); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + if (AR_SREV_MERLIN_10_OR_LATER(ah)) + OS_REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); + + AH5416(ah)->ah_writeIni(ah, chan); + + if(AR_SREV_KIWI_13_OR_LATER(ah) ) { + /* Enable ASYNC FIFO */ + OS_REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, + AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); + OS_REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); + OS_REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, + AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); + OS_REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, + AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); + } + + /* Override ini values (that can be overriden in this fashion) */ + ar5416OverrideIni(ah, chan); + + /* Setup 11n MAC/Phy mode registers */ + ar5416Set11nRegs(ah, chan); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + /* + * Some AR91xx SoC devices frequently fail to accept TSF writes + * right after the chip reset. When that happens, write a new + * value after the initvals have been applied, with an offset + * based on measured time difference + */ + if (AR_SREV_HOWL(ah) && (ar5416GetTsf64(ah) < tsf)) { + tsf += 1500; + ar5416SetTsf64(ah, tsf); + } + + HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_DAG_CTRLCCK=0x%x\n", + __func__, OS_REG_READ(ah,AR_PHY_DAG_CTRLCCK)); + HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_ADC_CTL=0x%x\n", + __func__, OS_REG_READ(ah,AR_PHY_ADC_CTL)); + + /* + * This routine swaps the analog chains - it should be done + * before any radio register twiddling is done. + */ + ar5416InitChainMasks(ah); + + /* Setup the open-loop power calibration if required */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + AH5416(ah)->ah_olcInit(ah); + AH5416(ah)->ah_olcTempCompensation(ah); + } + + /* Setup the transmit power values. */ + if (!ah->ah_setTxPower(ah, chan, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + FAIL(HAL_EIO); + } + + /* Write the analog registers */ + if (!ahp->ah_rfHal->setRfRegs(ah, chan, + IEEE80211_IS_CHAN_2GHZ(chan) ? 2: 1, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: ar5212SetRfRegs failed\n", __func__); + FAIL(HAL_EIO); + } + + /* Write delta slope for OFDM enabled modes (A, G, Turbo) */ + if (IEEE80211_IS_CHAN_OFDM(chan)|| IEEE80211_IS_CHAN_HT(chan)) + ar5416SetDeltaSlope(ah, chan); + + AH5416(ah)->ah_spurMitigate(ah, chan); + + /* Setup board specific options for EEPROM version 3 */ + if (!ah->ah_setBoardValues(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error setting board options\n", __func__); + FAIL(HAL_EIO); + } + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); + OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4) + | macStaId1 + | AR_STA_ID1_RTS_USE_DEF + | ahp->ah_staId1Defaults + ); + ar5212SetOperatingMode(ah, opmode); + + /* Set Venice BSSID mask according to current state */ + OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); + OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); + + /* Restore previous led state */ + if (AR_SREV_HOWL(ah)) + OS_REG_WRITE(ah, AR_MAC_LED, + AR_MAC_LED_ASSOC_ACTIVE | AR_CFG_SCLK_32KHZ); + else + OS_REG_WRITE(ah, AR_MAC_LED, OS_REG_READ(ah, AR_MAC_LED) | + saveLedState); + + /* Start TSF2 for generic timer 8-15 */ +#ifdef NOTYET + if (AR_SREV_KIWI(ah)) + ar5416StartTsf2(ah); +#endif + + /* + * Enable Bluetooth Coexistence if it's enabled. + */ + if (AH5416(ah)->ah_btCoexConfigType != HAL_BT_COEX_CFG_NONE) + ar5416InitBTCoex(ah); + + /* Restore previous antenna */ + OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); + + /* then our BSSID and associate id */ + OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); + OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4) | + (ahp->ah_assocId & 0x3fff) << AR_BSS_ID1_AID_S); + + /* Restore bmiss rssi & count thresholds */ + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + + OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */ + + /* Restore bmiss rssi & count thresholds */ + OS_REG_WRITE(ah, AR_RSSI_THR, rssiThrReg); + + if (!ar5212SetChannel(ah, chan)) + FAIL(HAL_EIO); + + OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); + + /* Set 1:1 QCU to DCU mapping for all queues */ + for (i = 0; i < AR_NUM_DCU; i++) + OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); + + ahp->ah_intrTxqs = 0; + for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++) + ah->ah_resetTxQueue(ah, i); + + ar5416InitIMR(ah, opmode); + ar5416SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1); + ar5416InitQoS(ah); + /* This may override the AR_DIAG_SW register */ + ar5416InitUserSettings(ah); + + /* XXX this won't work for AR9287! */ + if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan)) { + ar5416SetIFSTiming(ah, chan); +#if 0 + /* + * AR5413? + * Force window_length for 1/2 and 1/4 rate channels, + * the ini file sets this to zero otherwise. + */ + OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, + AR_PHY_FRAME_CTL_WINLEN, 3); + } +#endif + } + + if (AR_SREV_KIWI_13_OR_LATER(ah)) { + /* + * Enable ASYNC FIFO + * + * If Async FIFO is enabled, the following counters change + * as MAC now runs at 117 Mhz instead of 88/44MHz when + * async FIFO is disabled. + * + * Overwrite the delay/timeouts initialized in ProcessIni() + * above. + */ + OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, + AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); + OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, + AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR); + OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, + AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR); + + OS_REG_WRITE(ah, AR_TIME_OUT, + AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR); + OS_REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR); + + OS_REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER, + AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768); + OS_REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, + AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); + } + + if (AR_SREV_KIWI_13_OR_LATER(ah)) { + /* Enable AGGWEP to accelerate encryption engine */ + OS_REG_SET_BIT(ah, AR_PCU_MISC_MODE2, + AR_PCU_MISC_MODE2_ENABLE_AGGWEP); + } + + + /* + * disable seq number generation in hw + */ + OS_REG_WRITE(ah, AR_STA_ID1, + OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); + + ar5416InitDMA(ah); + + /* + * program OBS bus to see MAC interrupts + */ + OS_REG_WRITE(ah, AR_OBS, 8); + + /* + * Disable the "general" TX/RX mitigation timers. + */ + OS_REG_WRITE(ah, AR_MIRT, 0); + +#ifdef AH_AR5416_INTERRUPT_MITIGATION + /* + * This initialises the RX interrupt mitigation timers. + * + * The mitigation timers begin at idle and are triggered + * upon the RXOK of a single frame (or sub-frame, for A-MPDU.) + * Then, the RX mitigation interrupt will fire: + * + * + 250uS after the last RX'ed frame, or + * + 700uS after the first RX'ed frame + * + * Thus, the LAST field dictates the extra latency + * induced by the RX mitigation method and the FIRST + * field dictates how long to delay before firing an + * RX mitigation interrupt. + * + * Please note this only seems to be for RXOK frames; + * not CRC or PHY error frames. + * + */ + OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 250); + OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 700); +#endif + ar5416InitBB(ah, chan); + + /* Setup compression registers */ + ar5212SetCompRegs(ah); /* XXX not needed? */ + + /* + * 5416 baseband will check the per rate power table + * and select the lower of the two + */ + ackTpcPow = 63; + ctsTpcPow = 63; + chirpTpcPow = 63; + powerVal = SM(ackTpcPow, AR_TPC_ACK) | + SM(ctsTpcPow, AR_TPC_CTS) | + SM(chirpTpcPow, AR_TPC_CHIRP); + OS_REG_WRITE(ah, AR_TPC, powerVal); + + if (!ar5416InitCal(ah, chan)) + FAIL(HAL_ESELFTEST); + + ar5416RestoreChainMask(ah); + + AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ + + if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan)) + chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT; + + if (AR_SREV_HOWL(ah)) { + /* + * Enable the MBSSID block-ack fix for HOWL. + * This feature is only supported on Howl 1.4, but it is safe to + * set bit 22 of STA_ID1 on other Howl revisions (1.1, 1.2, 1.3), + * since bit 22 is unused in those Howl revisions. + */ + unsigned int reg; + reg = (OS_REG_READ(ah, AR_STA_ID1) | (1<<22)); + OS_REG_WRITE(ah,AR_STA_ID1, reg); + ath_hal_printf(ah, "MBSSID Set bit 22 of AR_STA_ID 0x%x\n", reg); + } + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); + + OS_MARK(ah, AH_MARK_RESET_DONE, 0); + + return AH_TRUE; +bad: + OS_MARK(ah, AH_MARK_RESET_DONE, ecode); + if (status != AH_NULL) + *status = ecode; + return AH_FALSE; +#undef FAIL +#undef N +} + +#if 0 +/* + * This channel change evaluates whether the selected hardware can + * perform a synthesizer-only channel change (no reset). If the + * TX is not stopped, or the RFBus cannot be granted in the given + * time, the function returns false as a reset is necessary + */ +HAL_BOOL +ar5416ChannelChange(struct ath_hal *ah, const structu ieee80211_channel *chan) +{ + uint32_t ulCount; + uint32_t data, synthDelay, qnum; + uint16_t rfXpdGain[4]; + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *ichan; + + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + + /* TX must be stopped or RF Bus grant will not work */ + for (qnum = 0; qnum < AH_PRIVATE(ah)->ah_caps.halTotalQueues; qnum++) { + if (ar5212NumTxPending(ah, qnum)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: frames pending on queue %d\n", __func__, qnum); + return AH_FALSE; + } + } + + /* + * Kill last Baseband Rx Frame - Request analog bus grant + */ + OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_REQUEST); + if (!ath_hal_wait(ah, AR_PHY_RFBUS_GNT, AR_PHY_RFBUS_GRANT_EN, AR_PHY_RFBUS_GRANT_EN)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: could not kill baseband rx\n", + __func__); + return AH_FALSE; + } + + ar5416Set11nRegs(ah, chan); /* NB: setup 5416-specific regs */ + + /* Change the synth */ + if (!ar5212SetChannel(ah, chan)) + return AH_FALSE; + + /* Setup the transmit power values. */ + if (!ah->ah_setTxPower(ah, chan, rfXpdGain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + return AH_FALSE; + } + + /* + * Wait for the frequency synth to settle (synth goes on + * via PHY_ACTIVE_EN). Read the phy active delay register. + * Value is in 100ns increments. + */ + data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IS_CHAN_CCK(ichan)) { + synthDelay = (4 * data) / 22; + } else { + synthDelay = data / 10; + } + + OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY); + + /* Release the RFBus Grant */ + OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); + + /* Write delta slope for OFDM enabled modes (A, G, Turbo) */ + if (IEEE80211_IS_CHAN_OFDM(ichan)|| IEEE80211_IS_CHAN_HT(chan)) { + HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3); + ar5212SetSpurMitigation(ah, chan); + ar5416SetDeltaSlope(ah, chan); + } + + /* XXX spur mitigation for Melin */ + + if (!IEEE80211_IS_CHAN_DFS(chan)) + chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT; + + ichan->channel_time = 0; + ichan->tsf_last = ar5416GetTsf64(ah); + ar5212TxEnable(ah, AH_TRUE); + return AH_TRUE; +} +#endif + +static void +ar5416InitDMA(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* + * set AHB_MODE not to do cacheline prefetches + */ + OS_REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN); + + /* + * let mac dma reads be in 128 byte chunks + */ + OS_REG_WRITE(ah, AR_TXCFG, + (OS_REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK) | AR_TXCFG_DMASZ_128B); + + /* + * let mac dma writes be in 128 byte chunks + */ + /* + * XXX If you change this, you must change the headroom + * assigned in ah_maxTxTrigLev - see ar5416InitState(). + */ + OS_REG_WRITE(ah, AR_RXCFG, + (OS_REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK) | AR_RXCFG_DMASZ_128B); + + /* restore TX trigger level */ + OS_REG_WRITE(ah, AR_TXCFG, + (OS_REG_READ(ah, AR_TXCFG) &~ AR_FTRIG) | + SM(ahp->ah_txTrigLev, AR_FTRIG)); + + /* + * Setup receive FIFO threshold to hold off TX activities + */ + OS_REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); + + /* + * reduce the number of usable entries in PCU TXBUF to avoid + * wrap around. + */ + if (AR_SREV_KITE(ah)) + /* + * For AR9285 the number of Fifos are reduced to half. + * So set the usable tx buf size also to half to + * avoid data/delimiter underruns + */ + OS_REG_WRITE(ah, AR_PCU_TXBUF_CTRL, AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE); + else + OS_REG_WRITE(ah, AR_PCU_TXBUF_CTRL, AR_PCU_TXBUF_CTRL_USABLE_SIZE); +} + +static void +ar5416InitBB(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t synthDelay; + + /* + * Wait for the frequency synth to settle (synth goes on + * via AR_PHY_ACTIVE_EN). Read the phy active delay register. + * Value is in 100ns increments. + */ + synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IEEE80211_IS_CHAN_CCK(chan)) { + synthDelay = (4 * synthDelay) / 22; + } else { + synthDelay /= 10; + } + + /* Turn on PLL on 5416 */ + HALDEBUG(ah, HAL_DEBUG_RESET, "%s %s channel\n", + __func__, IEEE80211_IS_CHAN_5GHZ(chan) ? "5GHz" : "2GHz"); + + /* Activate the PHY (includes baseband activate and synthesizer on) */ + OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + + /* + * If the AP starts the calibration before the base band timeout + * completes we could get rx_clear false triggering. Add an + * extra BASE_ACTIVATE_DELAY usecs to ensure this condition + * does not happen. + */ + if (IEEE80211_IS_CHAN_HALF(chan)) { + OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY); + } else if (IEEE80211_IS_CHAN_QUARTER(chan)) { + OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY); + } else { + OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY); + } +} + +static void +ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* + * Setup interrupt handling. Note that ar5212ResetTxQueue + * manipulates the secondary IMR's as queues are enabled + * and disabled. This is done with RMW ops to insure the + * settings we make here are preserved. + */ + ahp->ah_maskReg = AR_IMR_TXERR | AR_IMR_TXURN + | AR_IMR_RXERR | AR_IMR_RXORN + | AR_IMR_BCNMISC; + +#ifdef AH_AR5416_INTERRUPT_MITIGATION + ahp->ah_maskReg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; +#else + ahp->ah_maskReg |= AR_IMR_RXOK; +#endif + ahp->ah_maskReg |= AR_IMR_TXOK; + + if (opmode == HAL_M_HOSTAP) + ahp->ah_maskReg |= AR_IMR_MIB; + OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg); + +#ifdef ADRIAN_NOTYET + /* This is straight from ath9k */ + if (! AR_SREV_HOWL(ah)) { + OS_REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); + OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); + OS_REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); + } +#endif + + /* Enable bus errors that are OR'd to set the HIUERR bit */ +#if 0 + OS_REG_WRITE(ah, AR_IMR_S2, + OS_REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT | AR_IMR_S2_CST); +#endif +} + +static void +ar5416InitQoS(struct ath_hal *ah) +{ + /* QoS support */ + OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa); /* XXX magic */ + OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210); /* XXX magic */ + + /* Turn on NOACK Support for QoS packets */ + OS_REG_WRITE(ah, AR_NOACK, + SM(2, AR_NOACK_2BIT_VALUE) | + SM(5, AR_NOACK_BIT_OFFSET) | + SM(0, AR_NOACK_BYTE_OFFSET)); + + /* + * initialize TXOP for all TIDs + */ + OS_REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL); + OS_REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF); + OS_REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF); + OS_REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF); + OS_REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); +} + +static void +ar5416InitUserSettings(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + /* Restore user-specified settings */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) + | ahp->ah_miscMode); + if (ahp->ah_sifstime != (u_int) -1) + ar5212SetSifsTime(ah, ahp->ah_sifstime); + if (ahp->ah_slottime != (u_int) -1) + ar5212SetSlotTime(ah, ahp->ah_slottime); + if (ahp->ah_acktimeout != (u_int) -1) + ar5212SetAckTimeout(ah, ahp->ah_acktimeout); + if (ahp->ah_ctstimeout != (u_int) -1) + ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout); + if (AH_PRIVATE(ah)->ah_diagreg != 0) + OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); + if (AH5416(ah)->ah_globaltxtimeout != (u_int) -1) + ar5416SetGlobalTxTimeout(ah, AH5416(ah)->ah_globaltxtimeout); +} + +static void +ar5416SetRfMode(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t rfMode; + + if (chan == AH_NULL) + return; + + /* treat channel B as channel G , no B mode suport in owl */ + rfMode = IEEE80211_IS_CHAN_CCK(chan) ? + AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; + + if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { + /* phy mode bits for 5GHz channels require Fast Clock */ + rfMode |= AR_PHY_MODE_DYNAMIC + | AR_PHY_MODE_DYN_CCK_DISABLE; + } else if (!AR_SREV_MERLIN_10_OR_LATER(ah)) { + rfMode |= IEEE80211_IS_CHAN_5GHZ(chan) ? + AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; + } + + OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); +} + +/* + * Places the hardware into reset and then pulls it out of reset + */ +HAL_BOOL +ar5416ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0); + /* + * Warm reset is optimistic for open-loop TX power control. + */ + if (AR_SREV_MERLIN(ah) && + ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) + return AH_FALSE; + } else if (ah->ah_config.ah_force_full_reset) { + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) + return AH_FALSE; + } else { + if (!ar5416SetResetReg(ah, HAL_RESET_WARM)) + return AH_FALSE; + } + + /* Bring out of sleep mode (AGAIN) */ + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + +#ifdef notyet + ahp->ah_chipFullSleep = AH_FALSE; +#endif + + AH5416(ah)->ah_initPLL(ah, chan); + + /* + * Perform warm reset before the mode/PLL/turbo registers + * are changed in order to deactivate the radio. Mode changes + * with an active radio can result in corrupted shifts to the + * radio device. + */ + ar5416SetRfMode(ah, chan); + + return AH_TRUE; +} + +/* + * Delta slope coefficient computation. + * Required for OFDM operation. + */ +static void +ar5416GetDeltaSlopeValues(struct ath_hal *ah, uint32_t coef_scaled, + uint32_t *coef_mantissa, uint32_t *coef_exponent) +{ +#define COEF_SCALE_S 24 + uint32_t coef_exp, coef_man; + /* + * ALGO -> coef_exp = 14-floor(log2(coef)); + * floor(log2(x)) is the highest set bit position + */ + for (coef_exp = 31; coef_exp > 0; coef_exp--) + if ((coef_scaled >> coef_exp) & 0x1) + break; + /* A coef_exp of 0 is a legal bit position but an unexpected coef_exp */ + HALASSERT(coef_exp); + coef_exp = 14 - (coef_exp - COEF_SCALE_S); + + /* + * ALGO -> coef_man = floor(coef* 2^coef_exp+0.5); + * The coefficient is already shifted up for scaling + */ + coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1)); + + *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp); + *coef_exponent = coef_exp - 16; + +#undef COEF_SCALE_S +} + +void +ar5416SetDeltaSlope(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +#define INIT_CLOCKMHZSCALED 0x64000000 + uint32_t coef_scaled, ds_coef_exp, ds_coef_man; + uint32_t clockMhzScaled; + + CHAN_CENTERS centers; + + /* half and quarter rate can divide the scaled clock by 2 or 4 respectively */ + /* scale for selected channel bandwidth */ + clockMhzScaled = INIT_CLOCKMHZSCALED; + if (IEEE80211_IS_CHAN_TURBO(chan)) + clockMhzScaled <<= 1; + else if (IEEE80211_IS_CHAN_HALF(chan)) + clockMhzScaled >>= 1; + else if (IEEE80211_IS_CHAN_QUARTER(chan)) + clockMhzScaled >>= 2; + + /* + * ALGO -> coef = 1e8/fcarrier*fclock/40; + * scaled coef to provide precision for this floating calculation + */ + ar5416GetChannelCenters(ah, chan, ¢ers); + coef_scaled = clockMhzScaled / centers.synth_center; + + ar5416GetDeltaSlopeValues(ah, coef_scaled, &ds_coef_man, &ds_coef_exp); + + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_MAN, ds_coef_man); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); + + /* + * For Short GI, + * scaled coeff is 9/10 that of normal coeff + */ + coef_scaled = (9 * coef_scaled)/10; + + ar5416GetDeltaSlopeValues(ah, coef_scaled, &ds_coef_man, &ds_coef_exp); + + /* for short gi */ + OS_REG_RMW_FIELD(ah, AR_PHY_HALFGI, + AR_PHY_HALFGI_DSC_MAN, ds_coef_man); + OS_REG_RMW_FIELD(ah, AR_PHY_HALFGI, + AR_PHY_HALFGI_DSC_EXP, ds_coef_exp); +#undef INIT_CLOCKMHZSCALED +} + +/* + * Set a limit on the overall output power. Used for dynamic + * transmit power control and the like. + * + * NB: limit is in units of 0.5 dbM. + */ +HAL_BOOL +ar5416SetTxPowerLimit(struct ath_hal *ah, uint32_t limit) +{ + uint16_t dummyXpdGains[2]; + + AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER); + return ah->ah_setTxPower(ah, AH_PRIVATE(ah)->ah_curchan, + dummyXpdGains); +} + +HAL_BOOL +ar5416GetChipPowerLimits(struct ath_hal *ah, + struct ieee80211_channel *chan) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + int16_t minPower, maxPower; + + /* + * Get Pier table max and min powers. + */ + if (ahp->ah_rfHal->getChannelMaxMinPower(ah, chan, &maxPower, &minPower)) { + /* NB: rf code returns 1/4 dBm units, convert */ + chan->ic_maxpower = maxPower / 2; + chan->ic_minpower = minPower / 2; + } else { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: no min/max power for %u/0x%x\n", + __func__, chan->ic_freq, chan->ic_flags); + chan->ic_maxpower = AR5416_MAX_RATE_POWER; + chan->ic_minpower = 0; + } + HALDEBUG(ah, HAL_DEBUG_RESET, + "Chan %d: MaxPow = %d MinPow = %d\n", + chan->ic_freq, chan->ic_maxpower, chan->ic_minpower); + return AH_TRUE; +} + +/************************************************************** + * ar5416WriteTxPowerRateRegisters + * + * Write the TX power rate registers from the raw values given + * in ratesArray[]. + * + * The CCK and HT40 rate registers are only written if needed. + * HT20 and 11g/11a OFDM rate registers are always written. + * + * The values written are raw values which should be written + * to the registers - so it's up to the caller to pre-adjust + * them (eg CCK power offset value, or Merlin TX power offset, + * etc.) + */ +void +ar5416WriteTxPowerRateRegisters(struct ath_hal *ah, + const struct ieee80211_channel *chan, const int16_t ratesArray[]) +{ +#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) + + /* Write the OFDM power per rate set */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, + POW_SM(ratesArray[rate18mb], 24) + | POW_SM(ratesArray[rate12mb], 16) + | POW_SM(ratesArray[rate9mb], 8) + | POW_SM(ratesArray[rate6mb], 0) + ); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, + POW_SM(ratesArray[rate54mb], 24) + | POW_SM(ratesArray[rate48mb], 16) + | POW_SM(ratesArray[rate36mb], 8) + | POW_SM(ratesArray[rate24mb], 0) + ); + + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + /* Write the CCK power per rate set */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, + POW_SM(ratesArray[rate2s], 24) + | POW_SM(ratesArray[rate2l], 16) + | POW_SM(ratesArray[rateXr], 8) /* XR target power */ + | POW_SM(ratesArray[rate1l], 0) + ); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, + POW_SM(ratesArray[rate11s], 24) + | POW_SM(ratesArray[rate11l], 16) + | POW_SM(ratesArray[rate5_5s], 8) + | POW_SM(ratesArray[rate5_5l], 0) + ); + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s AR_PHY_POWER_TX_RATE3=0x%x AR_PHY_POWER_TX_RATE4=0x%x\n", + __func__, OS_REG_READ(ah,AR_PHY_POWER_TX_RATE3), + OS_REG_READ(ah,AR_PHY_POWER_TX_RATE4)); + } + + /* Write the HT20 power per rate set */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, + POW_SM(ratesArray[rateHt20_3], 24) + | POW_SM(ratesArray[rateHt20_2], 16) + | POW_SM(ratesArray[rateHt20_1], 8) + | POW_SM(ratesArray[rateHt20_0], 0) + ); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, + POW_SM(ratesArray[rateHt20_7], 24) + | POW_SM(ratesArray[rateHt20_6], 16) + | POW_SM(ratesArray[rateHt20_5], 8) + | POW_SM(ratesArray[rateHt20_4], 0) + ); + + if (IEEE80211_IS_CHAN_HT40(chan)) { + /* Write the HT40 power per rate set */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, + POW_SM(ratesArray[rateHt40_3], 24) + | POW_SM(ratesArray[rateHt40_2], 16) + | POW_SM(ratesArray[rateHt40_1], 8) + | POW_SM(ratesArray[rateHt40_0], 0) + ); + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, + POW_SM(ratesArray[rateHt40_7], 24) + | POW_SM(ratesArray[rateHt40_6], 16) + | POW_SM(ratesArray[rateHt40_5], 8) + | POW_SM(ratesArray[rateHt40_4], 0) + ); + /* Write the Dup/Ext 40 power per rate set */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, + POW_SM(ratesArray[rateExtOfdm], 24) + | POW_SM(ratesArray[rateExtCck], 16) + | POW_SM(ratesArray[rateDupOfdm], 8) + | POW_SM(ratesArray[rateDupCck], 0) + ); + } + + /* + * Set max power to 30 dBm and, optionally, + * enable TPC in tx descriptors. + */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER | + (AH5212(ah)->ah_tpcEnabled ? AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE : 0)); +#undef POW_SM +} + + +/************************************************************** + * ar5416SetTransmitPower + * + * Set the transmit power in the baseband for the given + * operating channel and mode. + */ +HAL_BOOL +ar5416SetTransmitPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) +#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) + + MODAL_EEP_HEADER *pModal; + struct ath_hal_5212 *ahp = AH5212(ah); + int16_t txPowerIndexOffset = 0; + int i; + + uint16_t cfgCtl; + uint16_t powerLimit; + uint16_t twiceAntennaReduction; + uint16_t twiceMaxRegulatoryPower; + int16_t maxPower; + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ar5416eeprom *pEepData = &ee->ee_base; + + HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); + + /* + * Default to 2, is overridden based on the EEPROM version / value. + */ + AH5416(ah)->ah_ht40PowerIncForPdadc = 2; + + /* Setup info for the actual eeprom */ + OS_MEMZERO(AH5416(ah)->ah_ratesArray, sizeof(AH5416(ah)->ah_ratesArray)); + cfgCtl = ath_hal_getctl(ah, chan); + powerLimit = chan->ic_maxregpower * 2; + twiceAntennaReduction = chan->ic_maxantgain; + twiceMaxRegulatoryPower = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit); + pModal = &pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)]; + HALDEBUG(ah, HAL_DEBUG_RESET, "%s Channel=%u CfgCtl=%u\n", + __func__,chan->ic_freq, cfgCtl ); + + if (IS_EEP_MINOR_V2(ah)) { + AH5416(ah)->ah_ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; + } + + if (!ar5416SetPowerPerRateTable(ah, pEepData, chan, + &AH5416(ah)->ah_ratesArray[0], + cfgCtl, + twiceAntennaReduction, + twiceMaxRegulatoryPower, powerLimit)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to set tx power per rate table\n", __func__); + return AH_FALSE; + } + + if (!AH5416(ah)->ah_setPowerCalTable(ah, pEepData, chan, &txPowerIndexOffset)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n", + __func__); + return AH_FALSE; + } + + maxPower = AH_MAX(AH5416(ah)->ah_ratesArray[rate6mb], + AH5416(ah)->ah_ratesArray[rateHt20_0]); + + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + maxPower = AH_MAX(maxPower, AH5416(ah)->ah_ratesArray[rate1l]); + } + + if (IEEE80211_IS_CHAN_HT40(chan)) { + maxPower = AH_MAX(maxPower, AH5416(ah)->ah_ratesArray[rateHt40_0]); + } + + ahp->ah_tx6PowerInHalfDbm = maxPower; + AH_PRIVATE(ah)->ah_maxPowerLevel = maxPower; + ahp->ah_txPowerIndexOffset = txPowerIndexOffset; + + /* + * txPowerIndexOffset is set by the SetPowerTable() call - + * adjust the rate table (0 offset if rates EEPROM not loaded) + */ + for (i = 0; i < N(AH5416(ah)->ah_ratesArray); i++) { + AH5416(ah)->ah_ratesArray[i] = + (int16_t)(txPowerIndexOffset + AH5416(ah)->ah_ratesArray[i]); + if (AH5416(ah)->ah_ratesArray[i] > AR5416_MAX_RATE_POWER) + AH5416(ah)->ah_ratesArray[i] = AR5416_MAX_RATE_POWER; + } + +#ifdef AH_EEPROM_DUMP + /* + * Dump the rate array whilst it represents the intended dBm*2 + * values versus what's being adjusted before being programmed + * in. Keep this in mind if you code up this function and enable + * this debugging; the values won't necessarily be what's being + * programmed into the hardware. + */ + ar5416PrintPowerPerRate(ah, AH5416(ah)->ah_ratesArray); +#endif + + /* + * Merlin and later have a power offset, so subtract + * pwr_table_offset * 2 from each value. The default + * power offset is -5 dBm - ie, a register value of 0 + * equates to a TX power of -5 dBm. + */ + if (AR_SREV_MERLIN_20_OR_LATER(ah)) { + int8_t pwr_table_offset; + + (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, + &pwr_table_offset); + /* Underflow power gets clamped at raw value 0 */ + /* Overflow power gets camped at AR5416_MAX_RATE_POWER */ + for (i = 0; i < N(AH5416(ah)->ah_ratesArray); i++) { + /* + * + pwr_table_offset is in dBm + * + ratesArray is in 1/2 dBm + */ + AH5416(ah)->ah_ratesArray[i] -= (pwr_table_offset * 2); + if (AH5416(ah)->ah_ratesArray[i] < 0) + AH5416(ah)->ah_ratesArray[i] = 0; + else if (AH5416(ah)->ah_ratesArray[i] > AR5416_MAX_RATE_POWER) + AH5416(ah)->ah_ratesArray[i] = AR5416_MAX_RATE_POWER; + } + } + + /* + * Adjust rates for OLC where needed + * + * The following CCK rates need adjusting when doing 2.4ghz + * CCK transmission. + * + * + rate2s, rate2l, rate1l, rate11s, rate11l, rate5_5s, rate5_5l + * + rateExtCck, rateDupCck + * + * They're adjusted here regardless. The hardware then gets + * programmed as needed. 5GHz operation doesn't program in CCK + * rates for legacy mode but they seem to be initialised for + * HT40 regardless of channel type. + */ + if (AR_SREV_MERLIN_20_OR_LATER(ah) && + ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + int adj[] = { + rate2s, rate2l, rate1l, rate11s, rate11l, + rate5_5s, rate5_5l, rateExtCck, rateDupCck + }; + int cck_ofdm_delta = 2; + int i; + for (i = 0; i < N(adj); i++) { + AH5416(ah)->ah_ratesArray[adj[i]] -= cck_ofdm_delta; + if (AH5416(ah)->ah_ratesArray[adj[i]] < 0) + AH5416(ah)->ah_ratesArray[adj[i]] = 0; + } + } + + /* + * Adjust the HT40 power to meet the correct target TX power + * for 40MHz mode, based on TX power curves that are established + * for 20MHz mode. + * + * XXX handle overflow/too high power level? + */ + if (IEEE80211_IS_CHAN_HT40(chan)) { + AH5416(ah)->ah_ratesArray[rateHt40_0] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_1] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_2] += AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_3] += AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_4] += AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_5] += AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_6] += AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_7] += AH5416(ah)->ah_ht40PowerIncForPdadc; + } + + /* Write the TX power rate registers */ + ar5416WriteTxPowerRateRegisters(ah, chan, AH5416(ah)->ah_ratesArray); + + /* Write the Power subtraction for dynamic chain changing, for per-packet powertx */ + OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB, + POW_SM(pModal->pwrDecreaseFor3Chain, 6) + | POW_SM(pModal->pwrDecreaseFor2Chain, 0) + ); + return AH_TRUE; +#undef POW_SM +#undef N +} + +/* + * Exported call to check for a recent gain reading and return + * the current state of the thermal calibration gain engine. + */ +HAL_RFGAIN +ar5416GetRfgain(struct ath_hal *ah) +{ + + return (HAL_RFGAIN_INACTIVE); +} + +/* + * Places all of hardware into reset + */ +HAL_BOOL +ar5416Disable(struct ath_hal *ah) +{ + + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + if (! ar5416SetResetReg(ah, HAL_RESET_COLD)) + return AH_FALSE; + + AH5416(ah)->ah_initPLL(ah, AH_NULL); + return (AH_TRUE); +} + +/* + * Places the PHY and Radio chips into reset. A full reset + * must be called to leave this state. The PCI/MAC/PCU are + * not placed into reset as we must receive interrupt to + * re-enable the hardware. + */ +HAL_BOOL +ar5416PhyDisable(struct ath_hal *ah) +{ + + if (! ar5416SetResetReg(ah, HAL_RESET_WARM)) + return AH_FALSE; + + AH5416(ah)->ah_initPLL(ah, AH_NULL); + return (AH_TRUE); +} + +/* + * Write the given reset bit mask into the reset register + */ +HAL_BOOL +ar5416SetResetReg(struct ath_hal *ah, uint32_t type) +{ + /* + * Set force wake + */ + OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); + + switch (type) { + case HAL_RESET_POWER_ON: + return ar5416SetResetPowerOn(ah); + case HAL_RESET_WARM: + case HAL_RESET_COLD: + return ar5416SetReset(ah, type); + default: + HALASSERT(AH_FALSE); + return AH_FALSE; + } +} + +static HAL_BOOL +ar5416SetResetPowerOn(struct ath_hal *ah) +{ + /* Power On Reset (Hard Reset) */ + + /* + * Set force wake + * + * If the MAC was running, previously calling + * reset will wake up the MAC but it may go back to sleep + * before we can start polling. + * Set force wake stops that + * This must be called before initiating a hard reset. + */ + OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); + + /* + * PowerOn reset can be used in open loop power control or failure recovery. + * If we do RTC reset while DMA is still running, hardware may corrupt memory. + * Therefore, we need to reset AHB first to stop DMA. + */ + if (! AR_SREV_HOWL(ah)) + OS_REG_WRITE(ah, AR_RC, AR_RC_AHB); + /* + * RTC reset and clear + */ + OS_REG_WRITE(ah, AR_RTC_RESET, 0); + OS_DELAY(20); + + if (! AR_SREV_HOWL(ah)) + OS_REG_WRITE(ah, AR_RC, 0); + + OS_REG_WRITE(ah, AR_RTC_RESET, 1); + + /* + * Poll till RTC is ON + */ + if (!ath_hal_wait(ah, AR_RTC_STATUS, AR_RTC_PM_STATUS_M, AR_RTC_STATUS_ON)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RTC not waking up\n", __func__); + return AH_FALSE; + } + + return ar5416SetReset(ah, HAL_RESET_COLD); +} + +static HAL_BOOL +ar5416SetReset(struct ath_hal *ah, int type) +{ + uint32_t tmpReg, mask; + uint32_t rst_flags; + +#ifdef AH_SUPPORT_AR9130 /* Because of the AR9130 specific registers */ + if (AR_SREV_HOWL(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "[ath] HOWL: Fiddling with derived clk!\n"); + uint32_t val = OS_REG_READ(ah, AR_RTC_DERIVED_CLK); + val &= ~AR_RTC_DERIVED_CLK_PERIOD; + val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD); + OS_REG_WRITE(ah, AR_RTC_DERIVED_CLK, val); + (void) OS_REG_READ(ah, AR_RTC_DERIVED_CLK); + } +#endif /* AH_SUPPORT_AR9130 */ + + /* + * Force wake + */ + OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); + +#ifdef AH_SUPPORT_AR9130 + if (AR_SREV_HOWL(ah)) { + rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD | + AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET; + } else { +#endif /* AH_SUPPORT_AR9130 */ + /* + * Reset AHB + * + * (In case the last interrupt source was a bus timeout.) + * XXX TODO: this is not the way to do it! It should be recorded + * XXX by the interrupt handler and passed _into_ the + * XXX reset path routine so this occurs. + */ + tmpReg = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE); + if (tmpReg & (AR_INTR_SYNC_LOCAL_TIMEOUT|AR_INTR_SYNC_RADM_CPL_TIMEOUT)) { + OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); + OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF); + } else { + OS_REG_WRITE(ah, AR_RC, AR_RC_AHB); + } + rst_flags = AR_RTC_RC_MAC_WARM; + if (type == HAL_RESET_COLD) + rst_flags |= AR_RTC_RC_MAC_COLD; +#ifdef AH_SUPPORT_AR9130 + } +#endif /* AH_SUPPORT_AR9130 */ + + OS_REG_WRITE(ah, AR_RTC_RC, rst_flags); + + if (AR_SREV_HOWL(ah)) + OS_DELAY(10000); + else + OS_DELAY(100); + + /* + * Clear resets and force wakeup + */ + OS_REG_WRITE(ah, AR_RTC_RC, 0); + if (!ath_hal_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RTC stuck in MAC reset\n", __func__); + return AH_FALSE; + } + + /* Clear AHB reset */ + if (! AR_SREV_HOWL(ah)) + OS_REG_WRITE(ah, AR_RC, 0); + + if (AR_SREV_HOWL(ah)) + OS_DELAY(50); + + if (AR_SREV_HOWL(ah)) { + uint32_t mask; + mask = OS_REG_READ(ah, AR_CFG); + if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { + HALDEBUG(ah, HAL_DEBUG_RESET, + "CFG Byte Swap Set 0x%x\n", mask); + } else { + mask = + INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; + OS_REG_WRITE(ah, AR_CFG, mask); + HALDEBUG(ah, HAL_DEBUG_RESET, + "Setting CFG 0x%x\n", OS_REG_READ(ah, AR_CFG)); + } + } else { + if (type == HAL_RESET_COLD) { + if (isBigEndian()) { + /* + * Set CFG, little-endian for descriptor accesses. + */ + mask = INIT_CONFIG_STATUS | AR_CFG_SWRD; +#ifndef AH_NEED_DESC_SWAP + mask |= AR_CFG_SWTD; +#endif + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s Applying descriptor swap\n", __func__); + OS_REG_WRITE(ah, AR_CFG, mask); + } else + OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS); + } + } + + return AH_TRUE; +} + +void +ar5416InitChainMasks(struct ath_hal *ah) +{ + int rx_chainmask = AH5416(ah)->ah_rx_chainmask; + + /* Flip this for this chainmask regardless of chip */ + if (rx_chainmask == 0x5) + OS_REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); + + /* + * Workaround for OWL 1.0 calibration failure; enable multi-chain; + * then set true mask after calibration. + */ + if (IS_5416V1(ah) && (rx_chainmask == 0x5 || rx_chainmask == 0x3)) { + OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); + OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7); + } else { + OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, AH5416(ah)->ah_rx_chainmask); + OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, AH5416(ah)->ah_rx_chainmask); + } + OS_REG_WRITE(ah, AR_SELFGEN_MASK, AH5416(ah)->ah_tx_chainmask); + + if (AH5416(ah)->ah_tx_chainmask == 0x5) + OS_REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); + + if (AR_SREV_HOWL(ah)) { + OS_REG_WRITE(ah, AR_PHY_ANALOG_SWAP, + OS_REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001); + } +} + +/* + * Work-around for Owl 1.0 calibration failure. + * + * ar5416InitChainMasks sets the RX chainmask to 0x7 if it's Owl 1.0 + * due to init calibration failures. ar5416RestoreChainMask restores + * these registers to the correct setting. + */ +void +ar5416RestoreChainMask(struct ath_hal *ah) +{ + int rx_chainmask = AH5416(ah)->ah_rx_chainmask; + + if (IS_5416V1(ah) && (rx_chainmask == 0x5 || rx_chainmask == 0x3)) { + OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); + OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); + } +} + +void +ar5416InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2; + if (chan != AH_NULL) { + if (IEEE80211_IS_CHAN_HALF(chan)) + pll |= SM(0x1, AR_RTC_PLL_CLKSEL); + else if (IEEE80211_IS_CHAN_QUARTER(chan)) + pll |= SM(0x2, AR_RTC_PLL_CLKSEL); + + if (IEEE80211_IS_CHAN_5GHZ(chan)) + pll |= SM(0xa, AR_RTC_PLL_DIV); + else + pll |= SM(0xb, AR_RTC_PLL_DIV); + } else + pll |= SM(0xb, AR_RTC_PLL_DIV); + + OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); + + /* TODO: + * For multi-band owl, switch between bands by reiniting the PLL. + */ + + OS_DELAY(RTC_PLL_SETTLE_DELAY); + + OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK); +} + +static void +ar5416SetDefGainValues(struct ath_hal *ah, + const MODAL_EEP_HEADER *pModal, + const struct ar5416eeprom *eep, + uint8_t txRxAttenLocal, int regChainOffset, int i) +{ + + if (IS_EEP_MINOR_V3(ah)) { + txRxAttenLocal = pModal->txRxAttenCh[i]; + + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, + pModal->bswMargin[i]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_DB, + pModal->bswAtten[i]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, + pModal->xatten2Margin[i]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN2_DB, + pModal->xatten2Db[i]); + } else { + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_BSW_MARGIN, + pModal->bswMargin[i]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_BSW_ATTEN, + pModal->bswAtten[i]); + } + } + + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + OS_REG_RMW_FIELD(ah, + AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); + OS_REG_RMW_FIELD(ah, + AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]); + } else { + OS_REG_RMW_FIELD(ah, + AR_PHY_RXGAIN + regChainOffset, + AR_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); + OS_REG_RMW_FIELD(ah, + AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_RXTX_MARGIN, pModal->rxTxMarginCh[i]); + } +} + +/* + * Get the register chain offset for the given chain. + * + * Take into account the register chain swapping with AR5416 v2.0. + * + * XXX make sure that the reg chain swapping is only done for + * XXX AR5416 v2.0 or greater, and not later chips? + */ +int +ar5416GetRegChainOffset(struct ath_hal *ah, int i) +{ + int regChainOffset; + + if (AR_SREV_5416_V20_OR_LATER(ah) && + (AH5416(ah)->ah_rx_chainmask == 0x5 || + AH5416(ah)->ah_tx_chainmask == 0x5) && (i != 0)) { + /* Regs are swapped from chain 2 to 1 for 5416 2_0 with + * only chains 0 and 2 populated + */ + regChainOffset = (i == 1) ? 0x2000 : 0x1000; + } else { + regChainOffset = i * 0x1000; + } + + return regChainOffset; +} + +/* + * Read EEPROM header info and program the device for correct operation + * given the channel value. + */ +HAL_BOOL +ar5416SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + const HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + const struct ar5416eeprom *eep = &ee->ee_base; + const MODAL_EEP_HEADER *pModal; + int i, regChainOffset; + uint8_t txRxAttenLocal; /* workaround for eeprom versions <= 14.2 */ + + HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); + pModal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)]; + + /* NB: workaround for eeprom versions <= 14.2 */ + txRxAttenLocal = IEEE80211_IS_CHAN_2GHZ(chan) ? 23 : 44; + + OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + if (AR_SREV_MERLIN(ah)) { + if (i >= 2) break; + } + regChainOffset = ar5416GetRegChainOffset(ah, i); + + OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, pModal->antCtrlChain[i]); + + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4 + regChainOffset, + (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4 + regChainOffset) & + ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | + SM(pModal->iqCalICh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | + SM(pModal->iqCalQCh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); + + /* + * Large signal upgrade, + * If 14.3 or later EEPROM, use + * txRxAttenLocal = pModal->txRxAttenCh[i] + * else txRxAttenLocal is fixed value above. + */ + + if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) + ar5416SetDefGainValues(ah, pModal, eep, txRxAttenLocal, regChainOffset, i); + + } + + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + OS_A_REG_RMW_FIELD(ah, AR_AN_RF2G1_CH0, AR_AN_RF2G1_CH0_OB, pModal->ob); + OS_A_REG_RMW_FIELD(ah, AR_AN_RF2G1_CH0, AR_AN_RF2G1_CH0_DB, pModal->db); + OS_A_REG_RMW_FIELD(ah, AR_AN_RF2G1_CH1, AR_AN_RF2G1_CH1_OB, pModal->ob_ch1); + OS_A_REG_RMW_FIELD(ah, AR_AN_RF2G1_CH1, AR_AN_RF2G1_CH1_DB, pModal->db_ch1); + } else { + OS_A_REG_RMW_FIELD(ah, AR_AN_RF5G1_CH0, AR_AN_RF5G1_CH0_OB5, pModal->ob); + OS_A_REG_RMW_FIELD(ah, AR_AN_RF5G1_CH0, AR_AN_RF5G1_CH0_DB5, pModal->db); + OS_A_REG_RMW_FIELD(ah, AR_AN_RF5G1_CH1, AR_AN_RF5G1_CH1_OB5, pModal->ob_ch1); + OS_A_REG_RMW_FIELD(ah, AR_AN_RF5G1_CH1, AR_AN_RF5G1_CH1_DB5, pModal->db_ch1); + } + OS_A_REG_RMW_FIELD(ah, AR_AN_TOP2, AR_AN_TOP2_XPABIAS_LVL, pModal->xpaBiasLvl); + OS_A_REG_RMW_FIELD(ah, AR_AN_TOP2, AR_AN_TOP2_LOCALBIAS, + !!(pModal->flagBits & AR5416_EEP_FLAG_LOCALBIAS)); + OS_A_REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, + !!(pModal->flagBits & AR5416_EEP_FLAG_FORCEXPAON)); + } + + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->switchSettling); + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize); + + if (! AR_SREV_MERLIN_10_OR_LATER(ah)) + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_PGA, pModal->pgaDesiredSize); + + OS_REG_WRITE(ah, AR_PHY_RF_CTL4, + SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) + | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) + | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) + | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); + + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, + pModal->txEndToRxOn); + + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, + pModal->thresh62); + OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, + pModal->thresh62); + } else { + OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62, + pModal->thresh62); + OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, AR_PHY_EXT_CCA_THRESH62, + pModal->thresh62); + } + + /* Minor Version Specific application */ + if (IS_EEP_MINOR_V2(ah)) { + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_DATA_START, + pModal->txFrameToDataStart); + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_PA_ON, + pModal->txFrameToPaOn); + } + + if (IS_EEP_MINOR_V3(ah) && IEEE80211_IS_CHAN_HT40(chan)) + /* Overwrite switch settling with HT40 value */ + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, + pModal->swSettleHt40); + + if (AR_SREV_MERLIN_20_OR_LATER(ah) && EEP_MINOR(ah) >= AR5416_EEP_MINOR_VER_19) + OS_REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL, AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, pModal->miscBits); + + if (AR_SREV_MERLIN_20(ah) && EEP_MINOR(ah) >= AR5416_EEP_MINOR_VER_20) { + if (IEEE80211_IS_CHAN_2GHZ(chan)) + OS_A_REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, + eep->baseEepHeader.dacLpMode); + else if (eep->baseEepHeader.dacHiPwrMode_5G) + OS_A_REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0); + else + OS_A_REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, + eep->baseEepHeader.dacLpMode); + + OS_DELAY(100); + + OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, + pModal->miscBits >> 2); + OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9, AR_PHY_TX_DESIRED_SCALE_CCK, + eep->baseEepHeader.desiredScaleCCK); + } + + return (AH_TRUE); +} + +/* + * Helper functions common for AP/CB/XB + */ + +/* + * Set the target power array "ratesArray" from the + * given set of target powers. + * + * This is used by the various chipset/EEPROM TX power + * setup routines. + */ +void +ar5416SetRatesArrayFromTargetPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *ratesArray, + const CAL_TARGET_POWER_LEG *targetPowerCck, + const CAL_TARGET_POWER_LEG *targetPowerCckExt, + const CAL_TARGET_POWER_LEG *targetPowerOfdm, + const CAL_TARGET_POWER_LEG *targetPowerOfdmExt, + const CAL_TARGET_POWER_HT *targetPowerHt20, + const CAL_TARGET_POWER_HT *targetPowerHt40) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + int i; + + /* Blank the rates array, to be consistent */ + for (i = 0; i < Ar5416RateSize; i++) + ratesArray[i] = 0; + + /* Set rates Array from collected data */ + ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = + ratesArray[rate18mb] = ratesArray[rate24mb] = + targetPowerOfdm->tPow2x[0]; + ratesArray[rate36mb] = targetPowerOfdm->tPow2x[1]; + ratesArray[rate48mb] = targetPowerOfdm->tPow2x[2]; + ratesArray[rate54mb] = targetPowerOfdm->tPow2x[3]; + ratesArray[rateXr] = targetPowerOfdm->tPow2x[0]; + + for (i = 0; i < N(targetPowerHt20->tPow2x); i++) { + ratesArray[rateHt20_0 + i] = targetPowerHt20->tPow2x[i]; + } + + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + ratesArray[rate1l] = targetPowerCck->tPow2x[0]; + ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck->tPow2x[1]; + ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck->tPow2x[2]; + ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck->tPow2x[3]; + } + if (IEEE80211_IS_CHAN_HT40(chan)) { + for (i = 0; i < N(targetPowerHt40->tPow2x); i++) { + ratesArray[rateHt40_0 + i] = targetPowerHt40->tPow2x[i]; + } + ratesArray[rateDupOfdm] = targetPowerHt40->tPow2x[0]; + ratesArray[rateDupCck] = targetPowerHt40->tPow2x[0]; + ratesArray[rateExtOfdm] = targetPowerOfdmExt->tPow2x[0]; + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + ratesArray[rateExtCck] = targetPowerCckExt->tPow2x[0]; + } + } +#undef N +} + +/* + * ar5416SetPowerPerRateTable + * + * Sets the transmit power in the baseband for the given + * operating channel and mode. + */ +static HAL_BOOL +ar5416SetPowerPerRateTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, + const struct ieee80211_channel *chan, + int16_t *ratesArray, uint16_t cfgCtl, + uint16_t AntennaReduction, + uint16_t twiceMaxRegulatoryPower, + uint16_t powerLimit) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) +/* Local defines to distinguish between extension and control CTL's */ +#define EXT_ADDITIVE (0x8000) +#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) +#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) +#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) + + uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + int i; + int16_t twiceLargestAntenna; + CAL_CTL_DATA *rep; + CAL_TARGET_POWER_LEG targetPowerOfdm, targetPowerCck = {0, {0, 0, 0, 0}}; + CAL_TARGET_POWER_LEG targetPowerOfdmExt = {0, {0, 0, 0, 0}}, targetPowerCckExt = {0, {0, 0, 0, 0}}; + CAL_TARGET_POWER_HT targetPowerHt20, targetPowerHt40 = {0, {0, 0, 0, 0}}; + int16_t scaledPower, minCtlPower; + +#define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */ +#define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ + static const uint16_t ctlModesFor11a[] = { + CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 + }; + static const uint16_t ctlModesFor11g[] = { + CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 + }; + const uint16_t *pCtlMode; + uint16_t numCtlModes, ctlMode, freq; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + /* Compute TxPower reduction due to Antenna Gain */ + + twiceLargestAntenna = AH_MAX(AH_MAX( + pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].antennaGainCh[0], + pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].antennaGainCh[1]), + pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].antennaGainCh[2]); +#if 0 + /* Turn it back on if we need to calculate per chain antenna gain reduction */ + /* Use only if the expected gain > 6dbi */ + /* Chain 0 is always used */ + twiceLargestAntenna = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].antennaGainCh[0]; + + /* Look at antenna gains of Chains 1 and 2 if the TX mask is set */ + if (ahp->ah_tx_chainmask & 0x2) + twiceLargestAntenna = AH_MAX(twiceLargestAntenna, + pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].antennaGainCh[1]); + + if (ahp->ah_tx_chainmask & 0x4) + twiceLargestAntenna = AH_MAX(twiceLargestAntenna, + pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].antennaGainCh[2]); +#endif + twiceLargestAntenna = (int16_t)AH_MIN((AntennaReduction) - twiceLargestAntenna, 0); + + /* XXX setup for 5212 use (really used?) */ + ath_hal_eepromSet(ah, + IEEE80211_IS_CHAN_2GHZ(chan) ? AR_EEP_ANTGAINMAX_2 : AR_EEP_ANTGAINMAX_5, + twiceLargestAntenna); + + /* + * scaledPower is the minimum of the user input power level and + * the regulatory allowed power level + */ + scaledPower = AH_MIN(powerLimit, twiceMaxRegulatoryPower + twiceLargestAntenna); + + /* Reduce scaled Power by number of chains active to get to per chain tx power level */ + /* TODO: better value than these? */ + switch (owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask)) { + case 1: + break; + case 2: + scaledPower -= pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].pwrDecreaseFor2Chain; + break; + case 3: + scaledPower -= pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].pwrDecreaseFor3Chain; + break; + default: + return AH_FALSE; /* Unsupported number of chains */ + } + + scaledPower = AH_MAX(0, scaledPower); + + /* Get target powers from EEPROM - our baseline for TX Power */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + /* Setup for CTL modes */ + numCtlModes = N(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; /* CTL_11B, CTL_11G, CTL_2GHT20 */ + pCtlMode = ctlModesFor11g; + + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck, + AR5416_NUM_2G_CCK_TARGET_POWERS, &targetPowerCck, 4, AH_FALSE); + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G, + AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE); + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT20, + AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE); + + if (IEEE80211_IS_CHAN_HT40(chan)) { + numCtlModes = N(ctlModesFor11g); /* All 2G CTL's */ + + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT40, + AR5416_NUM_2G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE); + /* Get target powers for extension channels */ + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck, + AR5416_NUM_2G_CCK_TARGET_POWERS, &targetPowerCckExt, 4, AH_TRUE); + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G, + AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE); + } + } else { + /* Setup for CTL modes */ + numCtlModes = N(ctlModesFor11a) - SUB_NUM_CTL_MODES_AT_5G_40; /* CTL_11A, CTL_5GHT20 */ + pCtlMode = ctlModesFor11a; + + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower5G, + AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE); + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower5GHT20, + AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE); + + if (IEEE80211_IS_CHAN_HT40(chan)) { + numCtlModes = N(ctlModesFor11a); /* All 5G CTL's */ + + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower5GHT40, + AR5416_NUM_5G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE); + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower5G, + AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE); + } + } + + /* + * For MIMO, need to apply regulatory caps individually across dynamically + * running modes: CCK, OFDM, HT20, HT40 + * + * The outer loop walks through each possible applicable runtime mode. + * The inner loop walks through each ctlIndex entry in EEPROM. + * The ctl value is encoded as [7:4] == test group, [3:0] == test mode. + * + */ + for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { + HAL_BOOL isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || + (pCtlMode[ctlMode] == CTL_2GHT40); + if (isHt40CtlMode) { + freq = centers.ctl_center; + } else if (pCtlMode[ctlMode] & EXT_ADDITIVE) { + freq = centers.ext_center; + } else { + freq = centers.ctl_center; + } + + /* walk through each CTL index stored in EEPROM */ + for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { + uint16_t twiceMinEdgePower; + + /* compare test group from regulatory channel list with test mode from pCtlMode list */ + if ((((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == pEepData->ctlIndex[i]) || + (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == + ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { + rep = &(pEepData->ctlData[i]); + twiceMinEdgePower = ar5416GetMaxEdgePower(freq, + rep->ctlEdges[owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask) - 1], + IEEE80211_IS_CHAN_2GHZ(chan)); + if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { + /* Find the minimum of all CTL edge powers that apply to this channel */ + twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower); + } else { + /* specific */ + twiceMaxEdgePower = twiceMinEdgePower; + break; + } + } + } + minCtlPower = (uint8_t)AH_MIN(twiceMaxEdgePower, scaledPower); + /* Apply ctl mode to correct target power set */ + switch(pCtlMode[ctlMode]) { + case CTL_11B: + for (i = 0; i < N(targetPowerCck.tPow2x); i++) { + targetPowerCck.tPow2x[i] = (uint8_t)AH_MIN(targetPowerCck.tPow2x[i], minCtlPower); + } + break; + case CTL_11A: + case CTL_11G: + for (i = 0; i < N(targetPowerOfdm.tPow2x); i++) { + targetPowerOfdm.tPow2x[i] = (uint8_t)AH_MIN(targetPowerOfdm.tPow2x[i], minCtlPower); + } + break; + case CTL_5GHT20: + case CTL_2GHT20: + for (i = 0; i < N(targetPowerHt20.tPow2x); i++) { + targetPowerHt20.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt20.tPow2x[i], minCtlPower); + } + break; + case CTL_11B_EXT: + targetPowerCckExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerCckExt.tPow2x[0], minCtlPower); + break; + case CTL_11A_EXT: + case CTL_11G_EXT: + targetPowerOfdmExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerOfdmExt.tPow2x[0], minCtlPower); + break; + case CTL_5GHT40: + case CTL_2GHT40: + for (i = 0; i < N(targetPowerHt40.tPow2x); i++) { + targetPowerHt40.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt40.tPow2x[i], minCtlPower); + } + break; + default: + return AH_FALSE; + break; + } + } /* end ctl mode checking */ + + /* Set rates Array from collected data */ + ar5416SetRatesArrayFromTargetPower(ah, chan, ratesArray, + &targetPowerCck, + &targetPowerCckExt, + &targetPowerOfdm, + &targetPowerOfdmExt, + &targetPowerHt20, + &targetPowerHt40); + return AH_TRUE; +#undef EXT_ADDITIVE +#undef CTL_11A_EXT +#undef CTL_11G_EXT +#undef CTL_11B_EXT +#undef SUB_NUM_CTL_MODES_AT_5G_40 +#undef SUB_NUM_CTL_MODES_AT_2G_40 +#undef N +} + +/************************************************************************** + * fbin2freq + * + * Get channel value from binary representation held in eeprom + * RETURNS: the frequency in MHz + */ +static uint16_t +fbin2freq(uint8_t fbin, HAL_BOOL is2GHz) +{ + /* + * Reserved value 0xFF provides an empty definition both as + * an fbin and as a frequency - do not convert + */ + if (fbin == AR5416_BCHAN_UNUSED) { + return fbin; + } + + return (uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); +} + +/* + * ar5416GetMaxEdgePower + * + * Find the maximum conformance test limit for the given channel and CTL info + */ +uint16_t +ar5416GetMaxEdgePower(uint16_t freq, CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz) +{ + uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + int i; + + /* Get the edge power */ + for (i = 0; (i < AR5416_NUM_BAND_EDGES) && (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED) ; i++) { + /* + * If there's an exact channel match or an inband flag set + * on the lower channel use the given rdEdgePower + */ + if (freq == fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) { + twiceMaxEdgePower = MS(pRdEdgesPower[i].tPowerFlag, CAL_CTL_EDGES_POWER); + break; + } else if ((i > 0) && (freq < fbin2freq(pRdEdgesPower[i].bChannel, is2GHz))) { + if (fbin2freq(pRdEdgesPower[i - 1].bChannel, is2GHz) < freq && (pRdEdgesPower[i - 1].tPowerFlag & CAL_CTL_EDGES_FLAG) != 0) { + twiceMaxEdgePower = MS(pRdEdgesPower[i - 1].tPowerFlag, CAL_CTL_EDGES_POWER); + } + /* Leave loop - no more affecting edges possible in this monotonic increasing list */ + break; + } + } + HALASSERT(twiceMaxEdgePower > 0); + return twiceMaxEdgePower; +} + +/************************************************************** + * ar5416GetTargetPowers + * + * Return the rates of target power for the given target power table + * channel, and number of channels + */ +void +ar5416GetTargetPowers(struct ath_hal *ah, const struct ieee80211_channel *chan, + CAL_TARGET_POWER_HT *powInfo, uint16_t numChannels, + CAL_TARGET_POWER_HT *pNewPower, uint16_t numRates, + HAL_BOOL isHt40Target) +{ + uint16_t clo, chi; + int i; + int matchIndex = -1, lowIndex = -1; + uint16_t freq; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + freq = isHt40Target ? centers.synth_center : centers.ctl_center; + + /* Copy the target powers into the temp channel list */ + if (freq <= fbin2freq(powInfo[0].bChannel, IEEE80211_IS_CHAN_2GHZ(chan))) { + matchIndex = 0; + } else { + for (i = 0; (i < numChannels) && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { + if (freq == fbin2freq(powInfo[i].bChannel, IEEE80211_IS_CHAN_2GHZ(chan))) { + matchIndex = i; + break; + } else if ((freq < fbin2freq(powInfo[i].bChannel, IEEE80211_IS_CHAN_2GHZ(chan))) && + (freq > fbin2freq(powInfo[i - 1].bChannel, IEEE80211_IS_CHAN_2GHZ(chan)))) + { + lowIndex = i - 1; + break; + } + } + if ((matchIndex == -1) && (lowIndex == -1)) { + HALASSERT(freq > fbin2freq(powInfo[i - 1].bChannel, IEEE80211_IS_CHAN_2GHZ(chan))); + matchIndex = i - 1; + } + } + + if (matchIndex != -1) { + OS_MEMCPY(pNewPower, &powInfo[matchIndex], sizeof(*pNewPower)); + } else { + HALASSERT(lowIndex != -1); + /* + * Get the lower and upper channels, target powers, + * and interpolate between them. + */ + clo = fbin2freq(powInfo[lowIndex].bChannel, IEEE80211_IS_CHAN_2GHZ(chan)); + chi = fbin2freq(powInfo[lowIndex + 1].bChannel, IEEE80211_IS_CHAN_2GHZ(chan)); + + for (i = 0; i < numRates; i++) { + pNewPower->tPow2x[i] = (uint8_t)ath_ee_interpolate(freq, clo, chi, + powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]); + } + } +} +/************************************************************** + * ar5416GetTargetPowersLeg + * + * Return the four rates of target power for the given target power table + * channel, and number of channels + */ +void +ar5416GetTargetPowersLeg(struct ath_hal *ah, + const struct ieee80211_channel *chan, + CAL_TARGET_POWER_LEG *powInfo, uint16_t numChannels, + CAL_TARGET_POWER_LEG *pNewPower, uint16_t numRates, + HAL_BOOL isExtTarget) +{ + uint16_t clo, chi; + int i; + int matchIndex = -1, lowIndex = -1; + uint16_t freq; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + freq = (isExtTarget) ? centers.ext_center :centers.ctl_center; + + /* Copy the target powers into the temp channel list */ + if (freq <= fbin2freq(powInfo[0].bChannel, IEEE80211_IS_CHAN_2GHZ(chan))) { + matchIndex = 0; + } else { + for (i = 0; (i < numChannels) && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { + if (freq == fbin2freq(powInfo[i].bChannel, IEEE80211_IS_CHAN_2GHZ(chan))) { + matchIndex = i; + break; + } else if ((freq < fbin2freq(powInfo[i].bChannel, IEEE80211_IS_CHAN_2GHZ(chan))) && + (freq > fbin2freq(powInfo[i - 1].bChannel, IEEE80211_IS_CHAN_2GHZ(chan)))) + { + lowIndex = i - 1; + break; + } + } + if ((matchIndex == -1) && (lowIndex == -1)) { + HALASSERT(freq > fbin2freq(powInfo[i - 1].bChannel, IEEE80211_IS_CHAN_2GHZ(chan))); + matchIndex = i - 1; + } + } + + if (matchIndex != -1) { + OS_MEMCPY(pNewPower, &powInfo[matchIndex], sizeof(*pNewPower)); + } else { + HALASSERT(lowIndex != -1); + /* + * Get the lower and upper channels, target powers, + * and interpolate between them. + */ + clo = fbin2freq(powInfo[lowIndex].bChannel, IEEE80211_IS_CHAN_2GHZ(chan)); + chi = fbin2freq(powInfo[lowIndex + 1].bChannel, IEEE80211_IS_CHAN_2GHZ(chan)); + + for (i = 0; i < numRates; i++) { + pNewPower->tPow2x[i] = (uint8_t)ath_ee_interpolate(freq, clo, chi, + powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]); + } + } +} + +/* + * Set the gain boundaries for the given radio chain. + * + * The gain boundaries tell the hardware at what point in the + * PDADC array to "switch over" from one PD gain setting + * to another. There's also a gain overlap between two + * PDADC array gain curves where there's valid PD values + * for 2 gain settings. + * + * The hardware uses the gain overlap and gain boundaries + * to determine which gain curve to use for the given + * target TX power. + */ +void +ar5416SetGainBoundariesClosedLoop(struct ath_hal *ah, int i, + uint16_t pdGainOverlap_t2, uint16_t gainBoundaries[]) +{ + int regChainOffset; + + regChainOffset = ar5416GetRegChainOffset(ah, i); + + HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: chain %d: gainOverlap_t2: %d," + " gainBoundaries: %d, %d, %d, %d\n", __func__, i, pdGainOverlap_t2, + gainBoundaries[0], gainBoundaries[1], gainBoundaries[2], + gainBoundaries[3]); + OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, + SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); +} + +/* + * Get the gain values and the number of gain levels given + * in xpdMask. + * + * The EEPROM xpdMask determines which power detector gain + * levels were used during calibration. Each of these mask + * bits maps to a fixed gain level in hardware. + */ +uint16_t +ar5416GetXpdGainValues(struct ath_hal *ah, uint16_t xpdMask, + uint16_t xpdGainValues[]) +{ + int i; + uint16_t numXpdGain = 0; + + for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { + if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { + if (numXpdGain >= AR5416_NUM_PD_GAINS) { + HALASSERT(0); + break; + } + xpdGainValues[numXpdGain] = (uint16_t)(AR5416_PD_GAINS_IN_MASK - i); + numXpdGain++; + } + } + return numXpdGain; +} + +/* + * Write the detector gain and biases. + * + * There are four power detector gain levels. The xpdMask in the EEPROM + * determines which power detector gain levels have TX power calibration + * data associated with them. This function writes the number of + * PD gain levels and their values into the hardware. + * + * This is valid for all TX chains - the calibration data itself however + * will likely differ per-chain. + */ +void +ar5416WriteDetectorGainBiases(struct ath_hal *ah, uint16_t numXpdGain, + uint16_t xpdGainValues[]) +{ + HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: numXpdGain: %d," + " xpdGainValues: %d, %d, %d\n", __func__, numXpdGain, + xpdGainValues[0], xpdGainValues[1], xpdGainValues[2]); + + OS_REG_WRITE(ah, AR_PHY_TPCRG1, (OS_REG_READ(ah, AR_PHY_TPCRG1) & + ~(AR_PHY_TPCRG1_NUM_PD_GAIN | AR_PHY_TPCRG1_PD_GAIN_1 | + AR_PHY_TPCRG1_PD_GAIN_2 | AR_PHY_TPCRG1_PD_GAIN_3)) | + SM(numXpdGain - 1, AR_PHY_TPCRG1_NUM_PD_GAIN) | + SM(xpdGainValues[0], AR_PHY_TPCRG1_PD_GAIN_1 ) | + SM(xpdGainValues[1], AR_PHY_TPCRG1_PD_GAIN_2) | + SM(xpdGainValues[2], AR_PHY_TPCRG1_PD_GAIN_3)); +} + +/* + * Write the PDADC array to the given radio chain i. + * + * The 32 PDADC registers are written without any care about + * their contents - so if various chips treat values as "special", + * this routine will not care. + */ +void +ar5416WritePdadcValues(struct ath_hal *ah, int i, uint8_t pdadcValues[]) +{ + int regOffset, regChainOffset; + int j; + int reg32; + + regChainOffset = ar5416GetRegChainOffset(ah, i); + regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; + + for (j = 0; j < 32; j++) { + reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0) | + ((pdadcValues[4*j + 1] & 0xFF) << 8) | + ((pdadcValues[4*j + 2] & 0xFF) << 16) | + ((pdadcValues[4*j + 3] & 0xFF) << 24) ; + OS_REG_WRITE(ah, regOffset, reg32); + HALDEBUG(ah, HAL_DEBUG_EEPROM, "PDADC: Chain %d |" + " PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d" + " Value %3d | PDADC %3d Value %3d |\n", + i, + 4*j, pdadcValues[4*j], + 4*j+1, pdadcValues[4*j + 1], + 4*j+2, pdadcValues[4*j + 2], + 4*j+3, pdadcValues[4*j + 3]); + regOffset += 4; + } +} + +/************************************************************** + * ar5416SetPowerCalTable + * + * Pull the PDADC piers from cal data and interpolate them across the given + * points as well as from the nearest pier(s) to get a power detector + * linear voltage to power level table. + */ +HAL_BOOL +ar5416SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, + const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset) +{ + CAL_DATA_PER_FREQ *pRawDataset; + uint8_t *pCalBChans = AH_NULL; + uint16_t pdGainOverlap_t2; + static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES]; + uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK]; + uint16_t numPiers, i; + int16_t tMinCalPower; + uint16_t numXpdGain, xpdMask; + uint16_t xpdGainValues[AR5416_NUM_PD_GAINS]; + uint32_t regChainOffset; + + OS_MEMZERO(xpdGainValues, sizeof(xpdGainValues)); + + xpdMask = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].xpdGain; + + if (IS_EEP_MINOR_V2(ah)) { + pdGainOverlap_t2 = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].pdGainOverlap; + } else { + pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); + } + + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + pCalBChans = pEepData->calFreqPier2G; + numPiers = AR5416_NUM_2G_CAL_PIERS; + } else { + pCalBChans = pEepData->calFreqPier5G; + numPiers = AR5416_NUM_5G_CAL_PIERS; + } + + /* Calculate the value of xpdgains from the xpdGain Mask */ + numXpdGain = ar5416GetXpdGainValues(ah, xpdMask, xpdGainValues); + + /* Write the detector gain biases and their number */ + ar5416WriteDetectorGainBiases(ah, numXpdGain, xpdGainValues); + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + regChainOffset = ar5416GetRegChainOffset(ah, i); + + if (pEepData->baseEepHeader.txMask & (1 << i)) { + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + pRawDataset = pEepData->calPierData2G[i]; + } else { + pRawDataset = pEepData->calPierData5G[i]; + } + + /* Fetch the gain boundaries and the PDADC values */ + ar5416GetGainBoundariesAndPdadcs(ah, chan, pRawDataset, + pCalBChans, numPiers, + pdGainOverlap_t2, + &tMinCalPower, gainBoundaries, + pdadcValues, numXpdGain); + + if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { + ar5416SetGainBoundariesClosedLoop(ah, i, pdGainOverlap_t2, + gainBoundaries); + } + + /* Write the power values into the baseband power table */ + ar5416WritePdadcValues(ah, i, pdadcValues); + } + } + *pTxPowerIndexOffset = 0; + + return AH_TRUE; +} + +/************************************************************** + * ar5416GetGainBoundariesAndPdadcs + * + * Uses the data points read from EEPROM to reconstruct the pdadc power table + * Called by ar5416SetPowerCalTable only. + */ +void +ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, + const struct ieee80211_channel *chan, + CAL_DATA_PER_FREQ *pRawDataSet, + uint8_t * bChans, uint16_t availPiers, + uint16_t tPdGainOverlap, int16_t *pMinCalPower, uint16_t * pPdGainBoundaries, + uint8_t * pPDADCValues, uint16_t numXpdGains) +{ + + int i, j, k; + int16_t ss; /* potentially -ve index for taking care of pdGainOverlap */ + uint16_t idxL, idxR, numPiers; /* Pier indexes */ + + /* filled out Vpd table for all pdGains (chanL) */ + static uint8_t vpdTableL[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + + /* filled out Vpd table for all pdGains (chanR) */ + static uint8_t vpdTableR[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + + /* filled out Vpd table for all pdGains (interpolated) */ + static uint8_t vpdTableI[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + + uint8_t *pVpdL, *pVpdR, *pPwrL, *pPwrR; + uint8_t minPwrT4[AR5416_NUM_PD_GAINS]; + uint8_t maxPwrT4[AR5416_NUM_PD_GAINS]; + int16_t vpdStep; + int16_t tmpVal; + uint16_t sizeCurrVpdTable, maxIndex, tgtIndex; + HAL_BOOL match; + int16_t minDelta = 0; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + /* Trim numPiers for the number of populated channel Piers */ + for (numPiers = 0; numPiers < availPiers; numPiers++) { + if (bChans[numPiers] == AR5416_BCHAN_UNUSED) { + break; + } + } + + /* Find pier indexes around the current channel */ + match = ath_ee_getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, + IEEE80211_IS_CHAN_2GHZ(chan)), bChans, numPiers, &idxL, &idxR); + + if (match) { + /* Directly fill both vpd tables from the matching index */ + for (i = 0; i < numXpdGains; i++) { + minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; + maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; + ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pRawDataSet[idxL].pwrPdg[i], + pRawDataSet[idxL].vpdPdg[i], AR5416_PD_GAIN_ICEPTS, vpdTableI[i]); + } + } else { + for (i = 0; i < numXpdGains; i++) { + pVpdL = pRawDataSet[idxL].vpdPdg[i]; + pPwrL = pRawDataSet[idxL].pwrPdg[i]; + pVpdR = pRawDataSet[idxR].vpdPdg[i]; + pPwrR = pRawDataSet[idxR].pwrPdg[i]; + + /* Start Vpd interpolation from the max of the minimum powers */ + minPwrT4[i] = AH_MAX(pPwrL[0], pPwrR[0]); + + /* End Vpd interpolation from the min of the max powers */ + maxPwrT4[i] = AH_MIN(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); + HALASSERT(maxPwrT4[i] > minPwrT4[i]); + + /* Fill pier Vpds */ + ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrL, pVpdL, AR5416_PD_GAIN_ICEPTS, vpdTableL[i]); + ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrR, pVpdR, AR5416_PD_GAIN_ICEPTS, vpdTableR[i]); + + /* Interpolate the final vpd */ + for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { + vpdTableI[i][j] = (uint8_t)(ath_ee_interpolate((uint16_t)FREQ2FBIN(centers.synth_center, + IEEE80211_IS_CHAN_2GHZ(chan)), + bChans[idxL], bChans[idxR], vpdTableL[i][j], vpdTableR[i][j])); + } + } + } + *pMinCalPower = (int16_t)(minPwrT4[0] / 2); + + k = 0; /* index for the final table */ + for (i = 0; i < numXpdGains; i++) { + if (i == (numXpdGains - 1)) { + pPdGainBoundaries[i] = (uint16_t)(maxPwrT4[i] / 2); + } else { + pPdGainBoundaries[i] = (uint16_t)((maxPwrT4[i] + minPwrT4[i+1]) / 4); + } + + pPdGainBoundaries[i] = (uint16_t)AH_MIN(AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); + + /* NB: only applies to owl 1.0 */ + if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah) ) { + /* + * fix the gain delta, but get a delta that can be applied to min to + * keep the upper power values accurate, don't think max needs to + * be adjusted because should not be at that area of the table? + */ + minDelta = pPdGainBoundaries[0] - 23; + pPdGainBoundaries[0] = 23; + } + else { + minDelta = 0; + } + + /* Find starting index for this pdGain */ + if (i == 0) { + if (AR_SREV_MERLIN_10_OR_LATER(ah)) + ss = (int16_t)(0 - (minPwrT4[i] / 2)); + else + ss = 0; /* for the first pdGain, start from index 0 */ + } else { + /* need overlap entries extrapolated below. */ + ss = (int16_t)((pPdGainBoundaries[i-1] - (minPwrT4[i] / 2)) - tPdGainOverlap + 1 + minDelta); + } + vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); + vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); + /* + *-ve ss indicates need to extrapolate data below for this pdGain + */ + while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { + tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); + pPDADCValues[k++] = (uint8_t)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = (uint8_t)((maxPwrT4[i] - minPwrT4[i]) / 2 +1); + tgtIndex = (uint8_t)(pPdGainBoundaries[i] + tPdGainOverlap - (minPwrT4[i] / 2)); + maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; + + while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { + pPDADCValues[k++] = vpdTableI[i][ss++]; + } + + vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - vpdTableI[i][sizeCurrVpdTable - 2]); + vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); + /* + * for last gain, pdGainBoundary == Pmax_t2, so will + * have to extrapolate + */ + if (tgtIndex >= maxIndex) { /* need to extrapolate above */ + while ((ss <= tgtIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { + tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + + (ss - maxIndex +1) * vpdStep)); + pPDADCValues[k++] = (uint8_t)((tmpVal > 255) ? 255 : tmpVal); + ss++; + } + } /* extrapolated above */ + } /* for all pdGainUsed */ + + /* Fill out pdGainBoundaries - only up to 2 allowed here, but hardware allows up to 4 */ + while (i < AR5416_PD_GAINS_IN_MASK) { + pPdGainBoundaries[i] = pPdGainBoundaries[i-1]; + i++; + } + + while (k < AR5416_NUM_PDADC_VALUES) { + pPDADCValues[k] = pPDADCValues[k-1]; + k++; + } + return; +} + +/* + * The linux ath9k driver and (from what I've been told) the reference + * Atheros driver enables the 11n PHY by default whether or not it's + * configured. + */ +static void +ar5416Set11nRegs(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t phymode; + uint32_t enableDacFifo = 0; + HAL_HT_MACMODE macmode; /* MAC - 20/40 mode */ + + if (AR_SREV_KITE_10_OR_LATER(ah)) + enableDacFifo = (OS_REG_READ(ah, AR_PHY_TURBO) & AR_PHY_FC_ENABLE_DAC_FIFO); + + /* Enable 11n HT, 20 MHz */ + phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 + | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo; + + /* Configure baseband for dynamic 20/40 operation */ + if (IEEE80211_IS_CHAN_HT40(chan)) { + phymode |= AR_PHY_FC_DYN2040_EN; + + /* Configure control (primary) channel at +-10MHz */ + if (IEEE80211_IS_CHAN_HT40U(chan)) + phymode |= AR_PHY_FC_DYN2040_PRI_CH; +#if 0 + /* Configure 20/25 spacing */ + if (ht->ht_extprotspacing == HAL_HT_EXTPROTSPACING_25) + phymode |= AR_PHY_FC_DYN2040_EXT_CH; +#endif + macmode = HAL_HT_MACMODE_2040; + } else + macmode = HAL_HT_MACMODE_20; + OS_REG_WRITE(ah, AR_PHY_TURBO, phymode); + + /* Configure MAC for 20/40 operation */ + ar5416Set11nMac2040(ah, macmode); + + /* global transmit timeout (25 TUs default)*/ + /* XXX - put this elsewhere??? */ + OS_REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S) ; + + /* carrier sense timeout */ + OS_REG_SET_BIT(ah, AR_GTTM, AR_GTTM_CST_USEC); + OS_REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); +} + +void +ar5416GetChannelCenters(struct ath_hal *ah, + const struct ieee80211_channel *chan, CHAN_CENTERS *centers) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + + centers->ctl_center = freq; + centers->synth_center = freq; + /* + * In 20/40 phy mode, the center frequency is + * "between" the control and extension channels. + */ + if (IEEE80211_IS_CHAN_HT40U(chan)) { + centers->synth_center += HT40_CHANNEL_CENTER_SHIFT; + centers->ext_center = + centers->synth_center + HT40_CHANNEL_CENTER_SHIFT; + } else if (IEEE80211_IS_CHAN_HT40D(chan)) { + centers->synth_center -= HT40_CHANNEL_CENTER_SHIFT; + centers->ext_center = + centers->synth_center - HT40_CHANNEL_CENTER_SHIFT; + } else { + centers->ext_center = freq; + } +} + +/* + * Override the INI vals being programmed. + */ +static void +ar5416OverrideIni(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t val; + + /* + * Set the RX_ABORT and RX_DIS and clear if off only after + * RXE is set for MAC. This prevents frames with corrupted + * descriptor status. + */ + OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); + + if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + val = OS_REG_READ(ah, AR_PCU_MISC_MODE2); + val &= (~AR_PCU_MISC_MODE2_ADHOC_MCAST_KEYID_ENABLE); + if (!AR_SREV_9271(ah)) + val &= ~AR_PCU_MISC_MODE2_HWWAR1; + + if (AR_SREV_KIWI_10_OR_LATER(ah)) + val = val & (~AR_PCU_MISC_MODE2_HWWAR2); + + OS_REG_WRITE(ah, AR_PCU_MISC_MODE2, val); + } + + /* + * Disable RIFS search on some chips to avoid baseband + * hang issues. + */ + if (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) + (void) ar5416SetRifsDelay(ah, chan, AH_FALSE); + + if (!AR_SREV_5416_V20_OR_LATER(ah) || AR_SREV_MERLIN(ah)) + return; + + /* + * Disable BB clock gating + * Necessary to avoid issues on AR5416 2.0 + */ + OS_REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); +} + +struct ini { + uint32_t *data; /* NB: !const */ + int rows, cols; +}; + +/* + * Override XPA bias level based on operating frequency. + * This is a v14 EEPROM specific thing for the AR9160. + */ +void +ar5416EepromSetAddac(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt]) + MODAL_EEP_HEADER *pModal; + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ar5416eeprom *eep = &ee->ee_base; + uint8_t biaslevel; + + if (! AR_SREV_SOWL(ah)) + return; + + if (EEP_MINOR(ah) < AR5416_EEP_MINOR_VER_7) + return; + + pModal = &(eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)]); + + if (pModal->xpaBiasLvl != 0xff) + biaslevel = pModal->xpaBiasLvl; + else { + uint16_t resetFreqBin, freqBin, freqCount = 0; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + resetFreqBin = FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)); + freqBin = XPA_LVL_FREQ(0) & 0xff; + biaslevel = (uint8_t) (XPA_LVL_FREQ(0) >> 14); + + freqCount++; + + while (freqCount < 3) { + if (XPA_LVL_FREQ(freqCount) == 0x0) + break; + + freqBin = XPA_LVL_FREQ(freqCount) & 0xff; + if (resetFreqBin >= freqBin) + biaslevel = (uint8_t)(XPA_LVL_FREQ(freqCount) >> 14); + else + break; + freqCount++; + } + } + + HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: overriding XPA bias level = %d\n", + __func__, biaslevel); + + /* + * This is a dirty workaround for the const initval data, + * which will upset multiple AR9160's on the same board. + * + * The HAL should likely just have a private copy of the addac + * data per instance. + */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) + HAL_INI_VAL((struct ini *) &AH5416(ah)->ah_ini_addac, 7, 1) = + (HAL_INI_VAL(&AH5416(ah)->ah_ini_addac, 7, 1) & (~0x18)) | biaslevel << 3; + else + HAL_INI_VAL((struct ini *) &AH5416(ah)->ah_ini_addac, 6, 1) = + (HAL_INI_VAL(&AH5416(ah)->ah_ini_addac, 6, 1) & (~0xc0)) | biaslevel << 6; +#undef XPA_LVL_FREQ +} + +static void +ar5416MarkPhyInactive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); +} + +#define AR5416_IFS_SLOT_FULL_RATE_40 0x168 /* 9 us half, 40 MHz core clock (9*40) */ +#define AR5416_IFS_SLOT_HALF_RATE_40 0x104 /* 13 us half, 20 MHz core clock (13*20) */ +#define AR5416_IFS_SLOT_QUARTER_RATE_40 0xD2 /* 21 us quarter, 10 MHz core clock (21*10) */ + +#define AR5416_IFS_EIFS_FULL_RATE_40 0xE60 /* (74 + (2 * 9)) * 40MHz core clock */ +#define AR5416_IFS_EIFS_HALF_RATE_40 0xDAC /* (149 + (2 * 13)) * 20MHz core clock */ +#define AR5416_IFS_EIFS_QUARTER_RATE_40 0xD48 /* (298 + (2 * 21)) * 10MHz core clock */ + +#define AR5416_IFS_SLOT_FULL_RATE_44 0x18c /* 9 us half, 44 MHz core clock (9*44) */ +#define AR5416_IFS_SLOT_HALF_RATE_44 0x11e /* 13 us half, 22 MHz core clock (13*22) */ +#define AR5416_IFS_SLOT_QUARTER_RATE_44 0xe7 /* 21 us quarter, 11 MHz core clock (21*11) */ + +#define AR5416_IFS_EIFS_FULL_RATE_44 0xfd0 /* (74 + (2 * 9)) * 44MHz core clock */ +#define AR5416_IFS_EIFS_HALF_RATE_44 0xf0a /* (149 + (2 * 13)) * 22MHz core clock */ +#define AR5416_IFS_EIFS_QUARTER_RATE_44 0xe9c /* (298 + (2 * 21)) * 11MHz core clock */ + +#define AR5416_INIT_USEC_40 40 +#define AR5416_HALF_RATE_USEC_40 19 /* ((40 / 2) - 1 ) */ +#define AR5416_QUARTER_RATE_USEC_40 9 /* ((40 / 4) - 1 ) */ + +#define AR5416_INIT_USEC_44 44 +#define AR5416_HALF_RATE_USEC_44 21 /* ((44 / 2) - 1 ) */ +#define AR5416_QUARTER_RATE_USEC_44 10 /* ((44 / 4) - 1 ) */ + + +/* XXX What should these be for 40/44MHz clocks (and half/quarter) ? */ +#define AR5416_RX_NON_FULL_RATE_LATENCY 63 +#define AR5416_TX_HALF_RATE_LATENCY 108 +#define AR5416_TX_QUARTER_RATE_LATENCY 216 + +/* + * Adjust various register settings based on half/quarter rate clock setting. + * This includes: + * + * + USEC, TX/RX latency, + * + IFS params: slot, eifs, misc etc. + * + * TODO: + * + * + Verify which other registers need to be tweaked; + * + Verify the behaviour of this for 5GHz fast and non-fast clock mode; + * + This just plain won't work for long distance links - the coverage class + * code isn't aware of the slot/ifs/ACK/RTS timeout values that need to + * change; + * + Verify whether the 32KHz USEC value needs to be kept for the 802.11n + * series chips? + * + Calculate/derive values for 2GHz, 5GHz, 5GHz fast clock + */ +static void +ar5416SetIFSTiming(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t txLat, rxLat, usec, slot, refClock, eifs, init_usec; + int clk_44 = 0; + + HALASSERT(IEEE80211_IS_CHAN_HALF(chan) || + IEEE80211_IS_CHAN_QUARTER(chan)); + + /* 2GHz and 5GHz fast clock - 44MHz; else 40MHz */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) + clk_44 = 1; + else if (IEEE80211_IS_CHAN_5GHZ(chan) && + IS_5GHZ_FAST_CLOCK_EN(ah, chan)) + clk_44 = 1; + + /* XXX does this need save/restoring for the 11n chips? */ + refClock = OS_REG_READ(ah, AR_USEC) & AR_USEC_USEC32; + + /* + * XXX This really should calculate things, not use + * hard coded values! Ew. + */ + if (IEEE80211_IS_CHAN_HALF(chan)) { + if (clk_44) { + slot = AR5416_IFS_SLOT_HALF_RATE_44; + rxLat = AR5416_RX_NON_FULL_RATE_LATENCY << + AR5416_USEC_RX_LAT_S; + txLat = AR5416_TX_HALF_RATE_LATENCY << + AR5416_USEC_TX_LAT_S; + usec = AR5416_HALF_RATE_USEC_44; + eifs = AR5416_IFS_EIFS_HALF_RATE_44; + init_usec = AR5416_INIT_USEC_44 >> 1; + } else { + slot = AR5416_IFS_SLOT_HALF_RATE_40; + rxLat = AR5416_RX_NON_FULL_RATE_LATENCY << + AR5416_USEC_RX_LAT_S; + txLat = AR5416_TX_HALF_RATE_LATENCY << + AR5416_USEC_TX_LAT_S; + usec = AR5416_HALF_RATE_USEC_40; + eifs = AR5416_IFS_EIFS_HALF_RATE_40; + init_usec = AR5416_INIT_USEC_40 >> 1; + } + } else { /* quarter rate */ + if (clk_44) { + slot = AR5416_IFS_SLOT_QUARTER_RATE_44; + rxLat = AR5416_RX_NON_FULL_RATE_LATENCY << + AR5416_USEC_RX_LAT_S; + txLat = AR5416_TX_QUARTER_RATE_LATENCY << + AR5416_USEC_TX_LAT_S; + usec = AR5416_QUARTER_RATE_USEC_44; + eifs = AR5416_IFS_EIFS_QUARTER_RATE_44; + init_usec = AR5416_INIT_USEC_44 >> 2; + } else { + slot = AR5416_IFS_SLOT_QUARTER_RATE_40; + rxLat = AR5416_RX_NON_FULL_RATE_LATENCY << + AR5416_USEC_RX_LAT_S; + txLat = AR5416_TX_QUARTER_RATE_LATENCY << + AR5416_USEC_TX_LAT_S; + usec = AR5416_QUARTER_RATE_USEC_40; + eifs = AR5416_IFS_EIFS_QUARTER_RATE_40; + init_usec = AR5416_INIT_USEC_40 >> 2; + } + } + + /* XXX verify these! */ + OS_REG_WRITE(ah, AR_USEC, (usec | refClock | txLat | rxLat)); + OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot); + OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs); + OS_REG_RMW_FIELD(ah, AR_D_GBL_IFS_MISC, + AR_D_GBL_IFS_MISC_USEC_DURATION, init_usec); +} + diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_spectral.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_spectral.c new file mode 100644 index 0000000..6bdd722 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_spectral.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#include "ah_desc.h" /* NB: for HAL_PHYERR* */ + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* + * Default AR9280 spectral scan parameters + */ +#define AR5416_SPECTRAL_SCAN_ENA 0 +#define AR5416_SPECTRAL_SCAN_ACTIVE 0 +#define AR5416_SPECTRAL_SCAN_FFT_PERIOD 8 +#define AR5416_SPECTRAL_SCAN_PERIOD 1 +#define AR5416_SPECTRAL_SCAN_COUNT 16 //used to be 128 +#define AR5416_SPECTRAL_SCAN_SHORT_REPEAT 1 + +/* constants */ +#define MAX_RADAR_RSSI_THRESH 0x3f +#define MAX_RADAR_HEIGHT 0x3f +#define ENABLE_ALL_PHYERR 0xffffffff + +static void ar5416DisableRadar(struct ath_hal *ah); +static void ar5416PrepSpectralScan(struct ath_hal *ah); + +static void +ar5416DisableRadar(struct ath_hal *ah) +{ + uint32_t val; + + // Enable radar FFT + val = OS_REG_READ(ah, AR_PHY_RADAR_0); + val |= AR_PHY_RADAR_0_FFT_ENA; + + // set radar detect thresholds to max to effectively disable radar + val &= ~AR_PHY_RADAR_0_RRSSI; + val |= SM(MAX_RADAR_RSSI_THRESH, AR_PHY_RADAR_0_RRSSI); + + val &= ~AR_PHY_RADAR_0_HEIGHT; + val |= SM(MAX_RADAR_HEIGHT, AR_PHY_RADAR_0_HEIGHT); + + val &= ~(AR_PHY_RADAR_0_ENA); + OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); + + // disable extension radar detect + val = OS_REG_READ(ah, AR_PHY_RADAR_EXT); + OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA); + + val = OS_REG_READ(ah, AR_RX_FILTER); + val |= (1<<13); + OS_REG_WRITE(ah, AR_RX_FILTER, val); +} + +static void +ar5416PrepSpectralScan(struct ath_hal *ah) +{ + + ar5416DisableRadar(ah); + OS_REG_WRITE(ah, AR_PHY_ERR, ENABLE_ALL_PHYERR); +} + +void +ar5416ConfigureSpectralScan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss) +{ + uint32_t val; + + ar5416PrepSpectralScan(ah); + + val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); + + if (ss->ss_fft_period != HAL_SPECTRAL_PARAM_NOVAL) { + val &= ~AR_PHY_SPECTRAL_SCAN_FFT_PERIOD; + val |= SM(ss->ss_fft_period, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD); + } + + if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) { + val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD; + val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD); + } + + if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) { + val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD; + val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD); + } + + /* This section is different for Kiwi and Merlin */ + if (AR_SREV_MERLIN(ah) ) { + if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) { + val &= ~AR_PHY_SPECTRAL_SCAN_COUNT; + val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT); + } + + if (ss->ss_short_report == AH_TRUE) { + val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; + } else if (ss->ss_short_report != HAL_SPECTRAL_PARAM_NOVAL) { + val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; + } + } else { + if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) { + /* + * In Merlin, for continous scan, scan_count = 128. + * In case of Kiwi, this value should be 0 + */ + if (ss->ss_count == 128) + ss->ss_count = 0; + val &= ~AR_PHY_SPECTRAL_SCAN_COUNT_KIWI; + val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI); + } + + if (ss->ss_short_report == AH_TRUE) { + val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI; + } else if (ss->ss_short_report != HAL_SPECTRAL_PARAM_NOVAL) { + val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI; + } + + //Select the mask to be same as before + val |= AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT_KIWI; + } + // Enable spectral scan + OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val | AR_PHY_SPECTRAL_SCAN_ENA); + + ar5416GetSpectralParams(ah, ss); +} + +/* + * Get the spectral parameter values and return them in the pe + * structure + */ +void +ar5416GetSpectralParams(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss) +{ + uint32_t val; + + val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); + + ss->ss_fft_period = MS(val, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD); + ss->ss_period = MS(val, AR_PHY_SPECTRAL_SCAN_PERIOD); + if (AR_SREV_MERLIN(ah) ) { + ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT); + ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT); + } else { + ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI); + ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI); + } + val = OS_REG_READ(ah, AR_PHY_RADAR_1); + ss->radar_bin_thresh_sel = MS(val, AR_PHY_RADAR_1_BIN_THRESH_SELECT); +} + +HAL_BOOL +ar5416IsSpectralActive(struct ath_hal *ah) +{ + uint32_t val; + + val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); + return MS(val, AR_PHY_SPECTRAL_SCAN_ACTIVE); +} + +HAL_BOOL +ar5416IsSpectralEnabled(struct ath_hal *ah) +{ + uint32_t val; + + val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); + return MS(val,AR_PHY_SPECTRAL_SCAN_ENA); +} + +void +ar5416StartSpectralScan(struct ath_hal *ah) +{ + uint32_t val; + + ar5416PrepSpectralScan(ah); + + // Activate spectral scan + val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); + val |= AR_PHY_SPECTRAL_SCAN_ENA; + val |= AR_PHY_SPECTRAL_SCAN_ACTIVE; + OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); + val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); + val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val | AR_PHY_ERR_RADAR); +} + +void +ar5416StopSpectralScan(struct ath_hal *ah) +{ + uint32_t val; + val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); + + // Deactivate spectral scan + val &= ~AR_PHY_SPECTRAL_SCAN_ENA; + val &= ~AR_PHY_SPECTRAL_SCAN_ACTIVE; + OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); + val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); + val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG) & (~AR_PHY_ERR_RADAR); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val); +} + +uint32_t +ar5416GetSpectralConfig(struct ath_hal *ah) +{ + uint32_t val; + + val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); + return val; +} + +void +ar5416RestoreSpectralConfig(struct ath_hal *ah, uint32_t restoreval) +{ + uint32_t curval; + + ar5416PrepSpectralScan(ah); + + curval = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); + + if (restoreval != curval) { + restoreval |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; + OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, restoreval); + } + return; +} + diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416_xmit.c b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_xmit.c new file mode 100644 index 0000000..47e8c35 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416_xmit.c @@ -0,0 +1,1494 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_desc.h" +#include "ah_internal.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar5416/ar5416desc.h" + +/* + * Stop transmit on the specified queue + */ +HAL_BOOL +ar5416StopTxDma(struct ath_hal *ah, u_int q) +{ +#define STOP_DMA_TIMEOUT 4000 /* us */ +#define STOP_DMA_ITER 100 /* us */ + u_int i; + + HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); + + HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); + + OS_REG_WRITE(ah, AR_Q_TXD, 1 << q); + for (i = STOP_DMA_TIMEOUT/STOP_DMA_ITER; i != 0; i--) { + if (ar5212NumTxPending(ah, q) == 0) + break; + OS_DELAY(STOP_DMA_ITER); + } +#ifdef AH_DEBUG + if (i == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: queue %u DMA did not stop in 400 msec\n", __func__, q); + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n", __func__, + OS_REG_READ(ah, AR_QSTS(q)), OS_REG_READ(ah, AR_Q_TXE), + OS_REG_READ(ah, AR_Q_TXD), OS_REG_READ(ah, AR_QCBRCFG(q))); + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n", + __func__, OS_REG_READ(ah, AR_QMISC(q)), + OS_REG_READ(ah, AR_QRDYTIMECFG(q)), + OS_REG_READ(ah, AR_Q_RDYTIMESHDN)); + } +#endif /* AH_DEBUG */ + + /* ar5416 and up can kill packets at the PCU level */ + if (ar5212NumTxPending(ah, q)) { + uint32_t j; + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: Num of pending TX Frames %d on Q %d\n", + __func__, ar5212NumTxPending(ah, q), q); + + /* Kill last PCU Tx Frame */ + /* TODO - save off and restore current values of Q1/Q2? */ + for (j = 0; j < 2; j++) { + uint32_t tsfLow = OS_REG_READ(ah, AR_TSF_L32); + OS_REG_WRITE(ah, AR_QUIET2, + SM(10, AR_QUIET2_QUIET_DUR)); + OS_REG_WRITE(ah, AR_QUIET_PERIOD, 100); + OS_REG_WRITE(ah, AR_NEXT_QUIET, tsfLow >> 10); + OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET); + + if ((OS_REG_READ(ah, AR_TSF_L32)>>10) == (tsfLow>>10)) + break; + + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: TSF moved while trying to set quiet time " + "TSF: 0x%08x\n", __func__, tsfLow); + HALASSERT(j < 1); /* TSF shouldn't count twice or reg access is taking forever */ + } + + OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE); + + /* Allow the quiet mechanism to do its work */ + OS_DELAY(200); + OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET); + + /* Verify the transmit q is empty */ + for (i = STOP_DMA_TIMEOUT/STOP_DMA_ITER; i != 0; i--) { + if (ar5212NumTxPending(ah, q) == 0) + break; + OS_DELAY(STOP_DMA_ITER); + } + if (i == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Failed to stop Tx DMA in %d msec after killing" + " last frame\n", __func__, STOP_DMA_TIMEOUT / 1000); + } + OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE); + } + + OS_REG_WRITE(ah, AR_Q_TXD, 0); + return (i != 0); +#undef STOP_DMA_ITER +#undef STOP_DMA_TIMEOUT +} + +#define VALID_KEY_TYPES \ + ((1 << HAL_KEY_TYPE_CLEAR) | (1 << HAL_KEY_TYPE_WEP)|\ + (1 << HAL_KEY_TYPE_AES) | (1 << HAL_KEY_TYPE_TKIP)) +#define isValidKeyType(_t) ((1 << (_t)) & VALID_KEY_TYPES) + +#define set11nTries(_series, _index) \ + (SM((_series)[_index].Tries, AR_XmitDataTries##_index)) + +#define set11nRate(_series, _index) \ + (SM((_series)[_index].Rate, AR_XmitRate##_index)) + +#define set11nPktDurRTSCTS(_series, _index) \ + (SM((_series)[_index].PktDuration, AR_PacketDur##_index) |\ + ((_series)[_index].RateFlags & HAL_RATESERIES_RTS_CTS ?\ + AR_RTSCTSQual##_index : 0)) + +#define set11nRateFlags(_series, _index) \ + ((_series)[_index].RateFlags & HAL_RATESERIES_2040 ? AR_2040_##_index : 0) \ + |((_series)[_index].RateFlags & HAL_RATESERIES_HALFGI ? AR_GI##_index : 0) \ + |((_series)[_index].RateFlags & HAL_RATESERIES_STBC ? AR_STBC##_index : 0) \ + |SM((_series)[_index].ChSel, AR_ChainSel##_index) + +/* + * Descriptor Access Functions + */ + +#define VALID_PKT_TYPES \ + ((1<ah_ratesArray[rate1l]); + case /* 2 Mb */ 0x1a: + return (AH5416(ah)->ah_ratesArray[rate2l]); + case /* 2 MbS*/ 0x1a | 0x4: + return (AH5416(ah)->ah_ratesArray[rate2s]); + case /* 5.5 Mb */ 0x19: + return (AH5416(ah)->ah_ratesArray[rate5_5l]); + case /* 5.5 MbS*/ 0x19 | 0x4: + return (AH5416(ah)->ah_ratesArray[rate5_5s]); + case /* 11 Mb */ 0x18: + return (AH5416(ah)->ah_ratesArray[rate11l]); + case /* 11 MbS*/ 0x18 | 0x4: + return (AH5416(ah)->ah_ratesArray[rate11s]); + } + + /* OFDM rates */ + switch (rate) { + case /* 6 Mb */ 0x0b: + return (AH5416(ah)->ah_ratesArray[rate6mb]); + case /* 9 Mb */ 0x0f: + return (AH5416(ah)->ah_ratesArray[rate9mb]); + case /* 12 Mb */ 0x0a: + return (AH5416(ah)->ah_ratesArray[rate12mb]); + case /* 18 Mb */ 0x0e: + return (AH5416(ah)->ah_ratesArray[rate18mb]); + case /* 24 Mb */ 0x09: + return (AH5416(ah)->ah_ratesArray[rate24mb]); + case /* 36 Mb */ 0x0d: + return (AH5416(ah)->ah_ratesArray[rate36mb]); + case /* 48 Mb */ 0x08: + return (AH5416(ah)->ah_ratesArray[rate48mb]); + case /* 54 Mb */ 0x0c: + return (AH5416(ah)->ah_ratesArray[rate54mb]); + } + + /* + * Handle HT20/HT40 - we only have to do MCS0-7; + * there's no stream differences. + */ + if ((rate & 0x80) && is_ht40) { + return (AH5416(ah)->ah_ratesArray[rateHt40_0 + (rate & 0x7)]); + } else if (rate & 0x80) { + return (AH5416(ah)->ah_ratesArray[rateHt20_0 + (rate & 0x7)]); + } + + /* XXX default (eg XR, bad bad person!) */ + return (AH5416(ah)->ah_ratesArray[rate6mb]); +} + +/* + * Return the TX power to be used for the given rate/chains/TX power. + * + * There are a bunch of tweaks to make to a given TX power based on + * the current configuration, so... + */ +static uint16_t +ar5416GetTxRatePower(struct ath_hal *ah, uint8_t rate, uint8_t tx_chainmask, + uint16_t txPower, HAL_BOOL is_ht40) +{ + int n_txpower, max_txpower; + const int cck_ofdm_delta = 2; +#define EEP_MINOR(_ah) \ + (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK) +#define IS_EEP_MINOR_V2(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2) + + /* Take a copy ; we may underflow and thus need to clamp things */ + n_txpower = txPower; + + /* HT40? Need to adjust the TX power by this */ + if (is_ht40) + n_txpower += AH5416(ah)->ah_ht40PowerIncForPdadc; + + /* + * Merlin? Offset the target TX power offset - it defaults to + * starting at -5.0dBm, but that can change! + * + * Kiwi/Kite? Always -5.0dBm offset. + */ + if (AR_SREV_KIWI_10_OR_LATER(ah)) { + n_txpower -= (AR5416_PWR_TABLE_OFFSET_DB * 2); + } else if (AR_SREV_MERLIN_20_OR_LATER(ah)) { + int8_t pwr_table_offset = 0; + /* This is in dBm, convert to 1/2 dBm */ + (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, + &pwr_table_offset); + n_txpower -= (pwr_table_offset * 2); + } + + /* + * If Open-loop TX power control is used, the CCK rates need + * to be offset by that. + * + * Rates: 2S, 2L, 1S, 1L, 5.5S, 5.5L + * + * XXX Odd, we don't have a PHY table entry for long preamble + * 1mbit CCK? + */ + if (AR_SREV_MERLIN_20_OR_LATER(ah) && + ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + + if (rate == 0x19 || rate == 0x1a || rate == 0x1b || + rate == (0x19 | 0x04) || rate == (0x1a | 0x04) || + rate == (0x1b | 0x04)) { + n_txpower -= cck_ofdm_delta; + } + } + + /* + * We're now offset by the same amount that the static maximum + * PHY power tables are. So, clamp the value based on that rate. + */ + max_txpower = ar5416RateToRateTable(ah, rate, is_ht40); +#if 0 + ath_hal_printf(ah, "%s: n_txpower = %d, max_txpower = %d, " + "rate = 0x%x , is_ht40 = %d\n", + __func__, + n_txpower, + max_txpower, + rate, + is_ht40); +#endif + n_txpower = MIN(max_txpower, n_txpower); + + /* + * We don't have to offset the TX power for two or three + * chain operation here - it's done by the AR_PHY_POWER_TX_SUB + * register setting via the EEPROM. + * + * So for vendors that programmed the maximum target power assuming + * that 2/3 chains are always on, things will just plain work. + * (They won't reach that target power if only one chain is on, but + * that's a different problem.) + */ + + /* Over/underflow? Adjust */ + if (n_txpower < 0) + n_txpower = 0; + else if (n_txpower > 63) + n_txpower = 63; + + /* + * For some odd reason the AR9160 with txpower=0 results in a + * much higher (max?) TX power. So, if it's a chipset before + * AR9220/AR9280, just clamp the minimum value at 1. + */ + if ((! AR_SREV_MERLIN_10_OR_LATER(ah)) && (n_txpower == 0)) + n_txpower = 1; + + return (n_txpower); +#undef EEP_MINOR +#undef IS_EEP_MINOR_V2 +} + +HAL_BOOL +ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int pktLen, + u_int hdrLen, + HAL_PKT_TYPE type, + u_int txPower, + u_int txRate0, u_int txTries0, + u_int keyIx, + u_int antMode, + u_int flags, + u_int rtsctsRate, + u_int rtsctsDuration, + u_int compicvLen, + u_int compivLen, + u_int comp) +{ +#define RTSCTS (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA) + struct ar5416_desc *ads = AR5416DESC(ds); + struct ath_hal_5416 *ahp = AH5416(ah); + + (void) hdrLen; + + HALASSERT(txTries0 != 0); + HALASSERT(isValidPktType(type)); + HALASSERT(isValidTxRate(txRate0)); + HALASSERT((flags & RTSCTS) != RTSCTS); + /* XXX validate antMode */ + + txPower = (txPower + AH5212(ah)->ah_txPowerIndexOffset); + if (txPower > 63) + txPower = 63; + + /* + * XXX For now, just assume that this isn't a HT40 frame. + */ + if (AH5212(ah)->ah_tpcEnabled) { + txPower = ar5416GetTxRatePower(ah, txRate0, + ahp->ah_tx_chainmask, + txPower, + AH_FALSE); + } + + ads->ds_ctl0 = (pktLen & AR_FrameLen) + | (txPower << AR_XmitPower_S) + | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0) + | (flags & HAL_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) + | (flags & HAL_TXDESC_INTREQ ? AR_TxIntrReq : 0) + ; + ads->ds_ctl1 = (type << AR_FrameType_S) + | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0) + ; + ads->ds_ctl2 = SM(txTries0, AR_XmitDataTries0) + | (flags & HAL_TXDESC_DURENA ? AR_DurUpdateEn : 0) + ; + ads->ds_ctl3 = (txRate0 << AR_XmitRate0_S) + ; + ads->ds_ctl4 = 0; + ads->ds_ctl5 = 0; + ads->ds_ctl6 = 0; + ads->ds_ctl7 = SM(ahp->ah_tx_chainmask, AR_ChainSel0) + | SM(ahp->ah_tx_chainmask, AR_ChainSel1) + | SM(ahp->ah_tx_chainmask, AR_ChainSel2) + | SM(ahp->ah_tx_chainmask, AR_ChainSel3) + ; + ads->ds_ctl8 = SM(0, AR_AntCtl0); + ads->ds_ctl9 = SM(0, AR_AntCtl1) | SM(txPower, AR_XmitPower1); + ads->ds_ctl10 = SM(0, AR_AntCtl2) | SM(txPower, AR_XmitPower2); + ads->ds_ctl11 = SM(0, AR_AntCtl3) | SM(txPower, AR_XmitPower3); + + if (keyIx != HAL_TXKEYIX_INVALID) { + /* XXX validate key index */ + ads->ds_ctl1 |= SM(keyIx, AR_DestIdx); + ads->ds_ctl0 |= AR_DestIdxValid; + ads->ds_ctl6 |= SM(ahp->ah_keytype[keyIx], AR_EncrType); + } + if (flags & RTSCTS) { + if (!isValidTxRate(rtsctsRate)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid rts/cts rate 0x%x\n", + __func__, rtsctsRate); + return AH_FALSE; + } + /* XXX validate rtsctsDuration */ + ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0) + | (flags & HAL_TXDESC_RTSENA ? AR_RTSEnable : 0) + ; + ads->ds_ctl7 |= (rtsctsRate << AR_RTSCTSRate_S); + } + + /* + * Set the TX antenna to 0 for Kite + * To preserve existing behaviour, also set the TPC bits to 0; + * when TPC is enabled these should be filled in appropriately. + * + * XXX TODO: when doing TPC, set the TX power up appropriately? + */ + if (AR_SREV_KITE(ah)) { + ads->ds_ctl8 = SM(0, AR_AntCtl0); + ads->ds_ctl9 = SM(0, AR_AntCtl1) | SM(0, AR_XmitPower1); + ads->ds_ctl10 = SM(0, AR_AntCtl2) | SM(0, AR_XmitPower2); + ads->ds_ctl11 = SM(0, AR_AntCtl3) | SM(0, AR_XmitPower3); + } + return AH_TRUE; +#undef RTSCTS +} + +HAL_BOOL +ar5416SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int txRate1, u_int txTries1, + u_int txRate2, u_int txTries2, + u_int txRate3, u_int txTries3) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + if (txTries1) { + HALASSERT(isValidTxRate(txRate1)); + ads->ds_ctl2 |= SM(txTries1, AR_XmitDataTries1); + ads->ds_ctl3 |= (txRate1 << AR_XmitRate1_S); + } + if (txTries2) { + HALASSERT(isValidTxRate(txRate2)); + ads->ds_ctl2 |= SM(txTries2, AR_XmitDataTries2); + ads->ds_ctl3 |= (txRate2 << AR_XmitRate2_S); + } + if (txTries3) { + HALASSERT(isValidTxRate(txRate3)); + ads->ds_ctl2 |= SM(txTries3, AR_XmitDataTries3); + ads->ds_ctl3 |= (txRate3 << AR_XmitRate3_S); + } + return AH_TRUE; +} + +HAL_BOOL +ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, + HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, u_int descId, + u_int qcuId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, + const struct ath_desc *ds0) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + uint32_t segLen = segLenList[0]; + + HALASSERT((segLen &~ AR_BufLen) == 0); + + ds->ds_data = bufAddrList[0]; + + if (firstSeg) { + /* + * First descriptor, don't clobber xmit control data + * setup by ar5212SetupTxDesc. + */ + ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); + } else if (lastSeg) { /* !firstSeg && lastSeg */ + /* + * Last descriptor in a multi-descriptor frame, + * copy the multi-rate transmit parameters from + * the first frame for processing on completion. + */ + ads->ds_ctl1 = segLen; +#ifdef AH_NEED_DESC_SWAP + ads->ds_ctl0 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl0) + & AR_TxIntrReq; + ads->ds_ctl2 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl2); + ads->ds_ctl3 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl3); + /* ctl6 - we only need encrtype; the rest are blank */ + ads->ds_ctl6 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl6 & AR_EncrType); +#else + ads->ds_ctl0 = AR5416DESC_CONST(ds0)->ds_ctl0 & AR_TxIntrReq; + ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; + ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; + /* ctl6 - we only need encrtype; the rest are blank */ + ads->ds_ctl6 = AR5416DESC_CONST(ds0)->ds_ctl6 & AR_EncrType; +#endif + } else { /* !firstSeg && !lastSeg */ + /* + * Intermediate descriptor in a multi-descriptor frame. + */ +#ifdef AH_NEED_DESC_SWAP + ads->ds_ctl0 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl0) + & AR_TxIntrReq; + ads->ds_ctl6 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl6 & AR_EncrType); +#else + ads->ds_ctl0 = AR5416DESC_CONST(ds0)->ds_ctl0 & AR_TxIntrReq; + ads->ds_ctl6 = AR5416DESC_CONST(ds0)->ds_ctl6 & AR_EncrType; +#endif + ads->ds_ctl1 = segLen | AR_TxMore; + ads->ds_ctl2 = 0; + ads->ds_ctl3 = 0; + } + /* XXX only on last descriptor? */ + OS_MEMZERO(ads->u.tx.status, sizeof(ads->u.tx.status)); + return AH_TRUE; +} + +/* + * NB: cipher is no longer used, it's calculated. + */ +HAL_BOOL +ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds, + HAL_DMA_ADDR *bufAddrList, + uint32_t *segLenList, + u_int pktLen, + u_int hdrLen, + HAL_PKT_TYPE type, + u_int keyIx, + HAL_CIPHER cipher, + uint8_t delims, + HAL_BOOL firstSeg, + HAL_BOOL lastSeg, + HAL_BOOL lastAggr) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads); + struct ath_hal_5416 *ahp = AH5416(ah); + u_int segLen = segLenList[0]; + + int isaggr = 0; + uint32_t last_aggr = 0; + + (void) hdrLen; + (void) ah; + + HALASSERT((segLen &~ AR_BufLen) == 0); + ds->ds_data = bufAddrList[0]; + + HALASSERT(isValidPktType(type)); + if (type == HAL_PKT_TYPE_AMPDU) { + type = HAL_PKT_TYPE_NORMAL; + isaggr = 1; + if (lastAggr == AH_FALSE) + last_aggr = AR_MoreAggr; + } + + /* + * Since this function is called before any of the other + * descriptor setup functions (at least in this particular + * 802.11n aggregation implementation), always bzero() the + * descriptor. Previously this would be done for all but + * the first segment. + * XXX TODO: figure out why; perhaps I'm using this slightly + * XXX incorrectly. + */ + OS_MEMZERO(ds->ds_hw, AR5416_DESC_TX_CTL_SZ); + + /* + * Note: VEOL should only be for the last descriptor in the chain. + */ + ads->ds_ctl0 = (pktLen & AR_FrameLen); + + /* + * For aggregates: + * + IsAggr must be set for all descriptors of all subframes of + * the aggregate + * + MoreAggr must be set for all descriptors of all subframes + * of the aggregate EXCEPT the last subframe; + * + MoreAggr must be _CLEAR_ for all descrpitors of the last + * subframe of the aggregate. + */ + ads->ds_ctl1 = (type << AR_FrameType_S) + | (isaggr ? (AR_IsAggr | last_aggr) : 0); + + ads->ds_ctl2 = 0; + ads->ds_ctl3 = 0; + if (keyIx != HAL_TXKEYIX_INVALID) { + /* XXX validate key index */ + ads->ds_ctl1 |= SM(keyIx, AR_DestIdx); + ads->ds_ctl0 |= AR_DestIdxValid; + } + + ads->ds_ctl6 |= SM(ahp->ah_keytype[keyIx], AR_EncrType); + if (isaggr) { + ads->ds_ctl6 |= SM(delims, AR_PadDelim); + } + + if (firstSeg) { + ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); + } else if (lastSeg) { /* !firstSeg && lastSeg */ + ads->ds_ctl0 = 0; + ads->ds_ctl1 |= segLen; + } else { /* !firstSeg && !lastSeg */ + /* + * Intermediate descriptor in a multi-descriptor frame. + */ + ads->ds_ctl0 = 0; + ads->ds_ctl1 |= segLen | AR_TxMore; + } + ds_txstatus[0] = ds_txstatus[1] = 0; + ds_txstatus[9] &= ~AR_TxDone; + + return AH_TRUE; +} + +HAL_BOOL +ar5416SetupFirstTxDesc(struct ath_hal *ah, struct ath_desc *ds, + u_int aggrLen, u_int flags, u_int txPower, + u_int txRate0, u_int txTries0, u_int antMode, + u_int rtsctsRate, u_int rtsctsDuration) +{ +#define RTSCTS (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA) + struct ar5416_desc *ads = AR5416DESC(ds); + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(txTries0 != 0); + HALASSERT(isValidTxRate(txRate0)); + HALASSERT((flags & RTSCTS) != RTSCTS); + /* XXX validate antMode */ + + txPower = (txPower + ahp->ah_txPowerIndexOffset ); + if(txPower > 63) txPower=63; + + ads->ds_ctl0 |= (txPower << AR_XmitPower_S) + | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0) + | (flags & HAL_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) + | (flags & HAL_TXDESC_INTREQ ? AR_TxIntrReq : 0); + ads->ds_ctl1 |= (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0); + ads->ds_ctl2 |= SM(txTries0, AR_XmitDataTries0); + ads->ds_ctl3 |= (txRate0 << AR_XmitRate0_S); + ads->ds_ctl7 = SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel0) + | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel1) + | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel2) + | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel3); + + /* NB: no V1 WAR */ + ads->ds_ctl8 = SM(0, AR_AntCtl0); + ads->ds_ctl9 = SM(0, AR_AntCtl1) | SM(txPower, AR_XmitPower1); + ads->ds_ctl10 = SM(0, AR_AntCtl2) | SM(txPower, AR_XmitPower2); + ads->ds_ctl11 = SM(0, AR_AntCtl3) | SM(txPower, AR_XmitPower3); + + ads->ds_ctl6 &= ~(0xffff); + ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); + + if (flags & RTSCTS) { + /* XXX validate rtsctsDuration */ + ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0) + | (flags & HAL_TXDESC_RTSENA ? AR_RTSEnable : 0); + } + + /* + * Set the TX antenna to 0 for Kite + * To preserve existing behaviour, also set the TPC bits to 0; + * when TPC is enabled these should be filled in appropriately. + */ + if (AR_SREV_KITE(ah)) { + ads->ds_ctl8 = SM(0, AR_AntCtl0); + ads->ds_ctl9 = SM(0, AR_AntCtl1) | SM(0, AR_XmitPower1); + ads->ds_ctl10 = SM(0, AR_AntCtl2) | SM(0, AR_XmitPower2); + ads->ds_ctl11 = SM(0, AR_AntCtl3) | SM(0, AR_XmitPower3); + } + + return AH_TRUE; +#undef RTSCTS +} + +HAL_BOOL +ar5416SetupLastTxDesc(struct ath_hal *ah, struct ath_desc *ds, + const struct ath_desc *ds0) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl1 &= ~AR_MoreAggr; + ads->ds_ctl6 &= ~AR_PadDelim; + + /* hack to copy rate info to last desc for later processing */ +#ifdef AH_NEED_DESC_SWAP + ads->ds_ctl2 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl2); + ads->ds_ctl3 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl3); +#else + ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; + ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; +#endif + return AH_TRUE; +} + +#ifdef AH_NEED_DESC_SWAP +/* Swap transmit descriptor */ +static __inline void +ar5416SwapTxDesc(struct ath_desc *ds) +{ + ds->ds_data = __bswap32(ds->ds_data); + ds->ds_ctl0 = __bswap32(ds->ds_ctl0); + ds->ds_ctl1 = __bswap32(ds->ds_ctl1); + ds->ds_hw[0] = __bswap32(ds->ds_hw[0]); + ds->ds_hw[1] = __bswap32(ds->ds_hw[1]); + ds->ds_hw[2] = __bswap32(ds->ds_hw[2]); + ds->ds_hw[3] = __bswap32(ds->ds_hw[3]); +} +#endif + +/* + * Processing of HW TX descriptor. + */ +HAL_STATUS +ar5416ProcTxDesc(struct ath_hal *ah, + struct ath_desc *ds, struct ath_tx_status *ts) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads); + +#ifdef AH_NEED_DESC_SWAP + if ((ds_txstatus[9] & __bswap32(AR_TxDone)) == 0) + return HAL_EINPROGRESS; + ar5416SwapTxDesc(ds); +#else + if ((ds_txstatus[9] & AR_TxDone) == 0) + return HAL_EINPROGRESS; +#endif + + /* Update software copies of the HW status */ + ts->ts_seqnum = MS(ds_txstatus[9], AR_SeqNum); + ts->ts_tstamp = AR_SendTimestamp(ds_txstatus); + ts->ts_tid = MS(ds_txstatus[9], AR_TxTid); + + ts->ts_status = 0; + if (ds_txstatus[1] & AR_ExcessiveRetries) + ts->ts_status |= HAL_TXERR_XRETRY; + if (ds_txstatus[1] & AR_Filtered) + ts->ts_status |= HAL_TXERR_FILT; + if (ds_txstatus[1] & AR_FIFOUnderrun) + ts->ts_status |= HAL_TXERR_FIFO; + if (ds_txstatus[9] & AR_TxOpExceeded) + ts->ts_status |= HAL_TXERR_XTXOP; + if (ds_txstatus[1] & AR_TxTimerExpired) + ts->ts_status |= HAL_TXERR_TIMER_EXPIRED; + + ts->ts_flags = 0; + if (ds_txstatus[0] & AR_TxBaStatus) { + ts->ts_flags |= HAL_TX_BA; + ts->ts_ba_low = AR_BaBitmapLow(ds_txstatus); + ts->ts_ba_high = AR_BaBitmapHigh(ds_txstatus); + } + if (ds->ds_ctl1 & AR_IsAggr) + ts->ts_flags |= HAL_TX_AGGR; + if (ds_txstatus[1] & AR_DescCfgErr) + ts->ts_flags |= HAL_TX_DESC_CFG_ERR; + if (ds_txstatus[1] & AR_TxDataUnderrun) + ts->ts_flags |= HAL_TX_DATA_UNDERRUN; + if (ds_txstatus[1] & AR_TxDelimUnderrun) + ts->ts_flags |= HAL_TX_DELIM_UNDERRUN; + + /* + * Extract the transmit rate used and mark the rate as + * ``alternate'' if it wasn't the series 0 rate. + */ + ts->ts_finaltsi = MS(ds_txstatus[9], AR_FinalTxIdx); + switch (ts->ts_finaltsi) { + case 0: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate0); + break; + case 1: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate1); + break; + case 2: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate2); + break; + case 3: + ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate3); + break; + } + + ts->ts_rssi = MS(ds_txstatus[5], AR_TxRSSICombined); + ts->ts_rssi_ctl[0] = MS(ds_txstatus[0], AR_TxRSSIAnt00); + ts->ts_rssi_ctl[1] = MS(ds_txstatus[0], AR_TxRSSIAnt01); + ts->ts_rssi_ctl[2] = MS(ds_txstatus[0], AR_TxRSSIAnt02); + ts->ts_rssi_ext[0] = MS(ds_txstatus[5], AR_TxRSSIAnt10); + ts->ts_rssi_ext[1] = MS(ds_txstatus[5], AR_TxRSSIAnt11); + ts->ts_rssi_ext[2] = MS(ds_txstatus[5], AR_TxRSSIAnt12); + ts->ts_evm0 = AR_TxEVM0(ds_txstatus); + ts->ts_evm1 = AR_TxEVM1(ds_txstatus); + ts->ts_evm2 = AR_TxEVM2(ds_txstatus); + + ts->ts_shortretry = MS(ds_txstatus[1], AR_RTSFailCnt); + ts->ts_longretry = MS(ds_txstatus[1], AR_DataFailCnt); + /* + * The retry count has the number of un-acked tries for the + * final series used. When doing multi-rate retry we must + * fixup the retry count by adding in the try counts for + * each series that was fully-processed. Beware that this + * takes values from the try counts in the final descriptor. + * These are not required by the hardware. We assume they + * are placed there by the driver as otherwise we have no + * access and the driver can't do the calculation because it + * doesn't know the descriptor format. + */ + switch (ts->ts_finaltsi) { + case 3: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries2); + case 2: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries1); + case 1: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries0); + } + + /* + * These fields are not used. Zero these to preserve compatability + * with existing drivers. + */ + ts->ts_virtcol = MS(ads->ds_ctl1, AR_VirtRetryCnt); + ts->ts_antenna = 0; /* We don't switch antennas on Owl*/ + + /* handle tx trigger level changes internally */ + if ((ts->ts_status & HAL_TXERR_FIFO) || + (ts->ts_flags & (HAL_TX_DATA_UNDERRUN | HAL_TX_DELIM_UNDERRUN))) + ar5212UpdateTxTrigLevel(ah, AH_TRUE); + + return HAL_OK; +} + +HAL_BOOL +ar5416SetGlobalTxTimeout(struct ath_hal *ah, u_int tu) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + if (tu > 0xFFFF) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad global tx timeout %u\n", + __func__, tu); + /* restore default handling */ + ahp->ah_globaltxtimeout = (u_int) -1; + return AH_FALSE; + } + OS_REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu); + ahp->ah_globaltxtimeout = tu; + return AH_TRUE; +} + +u_int +ar5416GetGlobalTxTimeout(struct ath_hal *ah) +{ + return MS(OS_REG_READ(ah, AR_GTXTO), AR_GTXTO_TIMEOUT_LIMIT); +} + +#define HT_RC_2_MCS(_rc) ((_rc) & 0x0f) +static const u_int8_t baDurationDelta[] = { + 24, // 0: BPSK + 12, // 1: QPSK 1/2 + 12, // 2: QPSK 3/4 + 4, // 3: 16-QAM 1/2 + 4, // 4: 16-QAM 3/4 + 4, // 5: 64-QAM 2/3 + 4, // 6: 64-QAM 3/4 + 4, // 7: 64-QAM 5/6 + 24, // 8: BPSK + 12, // 9: QPSK 1/2 + 12, // 10: QPSK 3/4 + 4, // 11: 16-QAM 1/2 + 4, // 12: 16-QAM 3/4 + 4, // 13: 64-QAM 2/3 + 4, // 14: 64-QAM 3/4 + 4, // 15: 64-QAM 5/6 +}; + +void +ar5416Set11nRateScenario(struct ath_hal *ah, struct ath_desc *ds, + u_int durUpdateEn, u_int rtsctsRate, + HAL_11N_RATE_SERIES series[], u_int nseries, u_int flags) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + uint32_t ds_ctl0; + + HALASSERT(nseries == 4); + (void)nseries; + + /* + * Only one of RTS and CTS enable must be set. + * If a frame has both set, just do RTS protection - + * that's enough to satisfy legacy protection. + */ + if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) { + ds_ctl0 = ads->ds_ctl0; + + if (flags & HAL_TXDESC_RTSENA) { + ds_ctl0 &= ~AR_CTSEnable; + ds_ctl0 |= AR_RTSEnable; + } else { + ds_ctl0 &= ~AR_RTSEnable; + ds_ctl0 |= AR_CTSEnable; + } + + ads->ds_ctl0 = ds_ctl0; + } else { + ads->ds_ctl0 = + (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable)); + } + + ads->ds_ctl2 = set11nTries(series, 0) + | set11nTries(series, 1) + | set11nTries(series, 2) + | set11nTries(series, 3) + | (durUpdateEn ? AR_DurUpdateEn : 0); + + ads->ds_ctl3 = set11nRate(series, 0) + | set11nRate(series, 1) + | set11nRate(series, 2) + | set11nRate(series, 3); + + ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) + | set11nPktDurRTSCTS(series, 1); + + ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) + | set11nPktDurRTSCTS(series, 3); + + ads->ds_ctl7 = set11nRateFlags(series, 0) + | set11nRateFlags(series, 1) + | set11nRateFlags(series, 2) + | set11nRateFlags(series, 3) + | SM(rtsctsRate, AR_RTSCTSRate); + + /* + * Doing per-packet TPC - update the TX power for the first + * field; program in the other series. + */ + if (AH5212(ah)->ah_tpcEnabled) { + uint32_t ds_ctl0; + uint16_t txPower; + + /* Modify the tx power field for rate 0 */ + txPower = ar5416GetTxRatePower(ah, series[0].Rate, + series[0].ChSel, + series[0].tx_power_cap, + !! (series[0].RateFlags & HAL_RATESERIES_2040)); + ds_ctl0 = ads->ds_ctl0 & ~AR_XmitPower; + ds_ctl0 |= (txPower << AR_XmitPower_S); + ads->ds_ctl0 = ds_ctl0; + + /* + * Override the whole descriptor field for each TX power. + * + * This will need changing if we ever support antenna control + * programming. + */ + txPower = ar5416GetTxRatePower(ah, series[1].Rate, + series[1].ChSel, + series[1].tx_power_cap, + !! (series[1].RateFlags & HAL_RATESERIES_2040)); + ads->ds_ctl9 = SM(0, AR_AntCtl1) | SM(txPower, AR_XmitPower1); + + txPower = ar5416GetTxRatePower(ah, series[2].Rate, + series[2].ChSel, + series[2].tx_power_cap, + !! (series[2].RateFlags & HAL_RATESERIES_2040)); + ads->ds_ctl10 = SM(0, AR_AntCtl2) | SM(txPower, AR_XmitPower2); + + txPower = ar5416GetTxRatePower(ah, series[3].Rate, + series[3].ChSel, + series[3].tx_power_cap, + !! (series[3].RateFlags & HAL_RATESERIES_2040)); + ads->ds_ctl11 = SM(0, AR_AntCtl3) | SM(txPower, AR_XmitPower3); + } +} + +/* + * Note: this should be called before calling ar5416SetBurstDuration() + * (if it is indeed called) in order to ensure that the burst duration + * is correctly updated with the BA delta workaround. + */ +void +ar5416Set11nAggrFirst(struct ath_hal *ah, struct ath_desc *ds, u_int aggrLen, + u_int numDelims) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + uint32_t flags; + uint32_t burstDur; + uint8_t rate; + + ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); + + ads->ds_ctl6 &= ~(AR_AggrLen | AR_PadDelim); + ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); + ads->ds_ctl6 |= SM(numDelims, AR_PadDelim); + + if (! AR_SREV_MERLIN_10_OR_LATER(ah)) { + /* + * XXX It'd be nice if I were passed in the rate scenario + * at this point.. + */ + rate = MS(ads->ds_ctl3, AR_XmitRate0); + flags = ads->ds_ctl0 & (AR_CTSEnable | AR_RTSEnable); + /* + * WAR - MAC assumes normal ACK time instead of + * block ACK while computing packet duration. + * Add this delta to the burst duration in the descriptor. + */ + if (flags && (ads->ds_ctl1 & AR_IsAggr)) { + burstDur = baDurationDelta[HT_RC_2_MCS(rate)]; + ads->ds_ctl2 &= ~(AR_BurstDur); + ads->ds_ctl2 |= SM(burstDur, AR_BurstDur); + } + } +} + +void +ar5416Set11nAggrMiddle(struct ath_hal *ah, struct ath_desc *ds, u_int numDelims) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads); + + ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); + + ads->ds_ctl6 &= ~AR_PadDelim; + ads->ds_ctl6 |= SM(numDelims, AR_PadDelim); + ads->ds_ctl6 &= ~AR_AggrLen; + + /* + * Clear the TxDone status here, may need to change + * func name to reflect this + */ + ds_txstatus[9] &= ~AR_TxDone; +} + +void +ar5416Set11nAggrLast(struct ath_hal *ah, struct ath_desc *ds) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl1 |= AR_IsAggr; + ads->ds_ctl1 &= ~AR_MoreAggr; + ads->ds_ctl6 &= ~AR_PadDelim; +} + +void +ar5416Clr11nAggr(struct ath_hal *ah, struct ath_desc *ds) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); + ads->ds_ctl6 &= ~AR_PadDelim; + ads->ds_ctl6 &= ~AR_AggrLen; +} + +void +ar5416Set11nVirtualMoreFrag(struct ath_hal *ah, struct ath_desc *ds, + u_int vmf) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + if (vmf) + ads->ds_ctl0 |= AR_VirtMoreFrag; + else + ads->ds_ctl0 &= ~AR_VirtMoreFrag; +} + +/* + * Program the burst duration, with the included BA delta if it's + * applicable. + */ +void +ar5416Set11nBurstDuration(struct ath_hal *ah, struct ath_desc *ds, + u_int burstDuration) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + uint32_t burstDur = 0; + uint8_t rate; + + if (! AR_SREV_MERLIN_10_OR_LATER(ah)) { + /* + * XXX It'd be nice if I were passed in the rate scenario + * at this point.. + */ + rate = MS(ads->ds_ctl3, AR_XmitDataTries0); + /* + * WAR - MAC assumes normal ACK time instead of + * block ACK while computing packet duration. + * Add this delta to the burst duration in the descriptor. + */ + if (ads->ds_ctl1 & AR_IsAggr) { + burstDur = baDurationDelta[HT_RC_2_MCS(rate)]; + } + } + + ads->ds_ctl2 &= ~AR_BurstDur; + ads->ds_ctl2 |= SM(burstDur + burstDuration, AR_BurstDur); +} + +/* + * Retrieve the rate table from the given TX completion descriptor + */ +HAL_BOOL +ar5416GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries) +{ + const struct ar5416_desc *ads = AR5416DESC_CONST(ds0); + + rates[0] = MS(ads->ds_ctl3, AR_XmitRate0); + rates[1] = MS(ads->ds_ctl3, AR_XmitRate1); + rates[2] = MS(ads->ds_ctl3, AR_XmitRate2); + rates[3] = MS(ads->ds_ctl3, AR_XmitRate3); + + tries[0] = MS(ads->ds_ctl2, AR_XmitDataTries0); + tries[1] = MS(ads->ds_ctl2, AR_XmitDataTries1); + tries[2] = MS(ads->ds_ctl2, AR_XmitDataTries2); + tries[3] = MS(ads->ds_ctl2, AR_XmitDataTries3); + + return AH_TRUE; +} + + +/* + * TX queue management routines - AR5416 and later chipsets + */ + +/* + * Allocate and initialize a tx DCU/QCU combination. + */ +int +ar5416SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_TX_QUEUE_INFO *qi; + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + int q, defqflags; + + /* by default enable OK+ERR+DESC+URN interrupts */ + defqflags = HAL_TXQ_TXOKINT_ENABLE + | HAL_TXQ_TXERRINT_ENABLE + | HAL_TXQ_TXDESCINT_ENABLE + | HAL_TXQ_TXURNINT_ENABLE; + /* XXX move queue assignment to driver */ + switch (type) { + case HAL_TX_QUEUE_BEACON: + q = pCap->halTotalQueues-1; /* highest priority */ + defqflags |= HAL_TXQ_DBA_GATED + | HAL_TXQ_CBR_DIS_QEMPTY + | HAL_TXQ_ARB_LOCKOUT_GLOBAL + | HAL_TXQ_BACKOFF_DISABLE; + break; + case HAL_TX_QUEUE_CAB: + q = pCap->halTotalQueues-2; /* next highest priority */ + defqflags |= HAL_TXQ_DBA_GATED + | HAL_TXQ_CBR_DIS_QEMPTY + | HAL_TXQ_CBR_DIS_BEMPTY + | HAL_TXQ_ARB_LOCKOUT_GLOBAL + | HAL_TXQ_BACKOFF_DISABLE; + break; + case HAL_TX_QUEUE_PSPOLL: + q = 1; /* lowest priority */ + defqflags |= HAL_TXQ_DBA_GATED + | HAL_TXQ_CBR_DIS_QEMPTY + | HAL_TXQ_CBR_DIS_BEMPTY + | HAL_TXQ_ARB_LOCKOUT_GLOBAL + | HAL_TXQ_BACKOFF_DISABLE; + break; + case HAL_TX_QUEUE_UAPSD: + q = pCap->halTotalQueues-3; /* nextest highest priority */ + if (ahp->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: no available UAPSD tx queue\n", __func__); + return -1; + } + break; + case HAL_TX_QUEUE_DATA: + for (q = 0; q < pCap->halTotalQueues; q++) + if (ahp->ah_txq[q].tqi_type == HAL_TX_QUEUE_INACTIVE) + break; + if (q == pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: no available tx queue\n", __func__); + return -1; + } + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: bad tx queue type %u\n", __func__, type); + return -1; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + + qi = &ahp->ah_txq[q]; + if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n", + __func__, q); + return -1; + } + OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); + qi->tqi_type = type; + if (qInfo == AH_NULL) { + qi->tqi_qflags = defqflags; + qi->tqi_aifs = INIT_AIFS; + qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ + qi->tqi_cwmax = INIT_CWMAX; + qi->tqi_shretry = INIT_SH_RETRY; + qi->tqi_lgretry = INIT_LG_RETRY; + qi->tqi_physCompBuf = 0; + } else { + qi->tqi_physCompBuf = qInfo->tqi_compBuf; + (void) ar5212SetTxQueueProps(ah, q, qInfo); + } + /* NB: must be followed by ar5212ResetTxQueue */ + return q; +} + +/* + * Update the h/w interrupt registers to reflect a tx q's configuration. + */ +static void +setTxQInterrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", __func__, + ahp->ah_txOkInterruptMask, ahp->ah_txErrInterruptMask, + ahp->ah_txDescInterruptMask, ahp->ah_txEolInterruptMask, + ahp->ah_txUrnInterruptMask); + + OS_REG_WRITE(ah, AR_IMR_S0, + SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK) + | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC) + ); + OS_REG_WRITE(ah, AR_IMR_S1, + SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR) + | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL) + ); + OS_REG_RMW_FIELD(ah, AR_IMR_S2, + AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask); +} + +/* + * Set the retry, aifs, cwmin/max, readyTime regs for specified queue + * Assumes: + * phwChannel has been set to point to the current channel + */ +#define TU_TO_USEC(_tu) ((_tu) << 10) +HAL_BOOL +ar5416ResetTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + HAL_TX_QUEUE_INFO *qi; + uint32_t cwMin, chanCwMin, qmisc, dmisc; + + if (q >= pCap->halTotalQueues) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_TRUE; /* XXX??? */ + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: reset queue %u\n", __func__, q); + + if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) { + /* + * Select cwmin according to channel type. + * NB: chan can be NULL during attach + */ + if (chan && IEEE80211_IS_CHAN_B(chan)) + chanCwMin = INIT_CWMIN_11B; + else + chanCwMin = INIT_CWMIN; + /* make sure that the CWmin is of the form (2^n - 1) */ + for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1) + ; + } else + cwMin = qi->tqi_cwmin; + + /* set cwMin/Max and AIFS values */ + OS_REG_WRITE(ah, AR_DLCL_IFS(q), + SM(cwMin, AR_D_LCL_IFS_CWMIN) + | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) + | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); + + /* Set retry limit values */ + OS_REG_WRITE(ah, AR_DRETRY_LIMIT(q), + SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) + | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) + | SM(qi->tqi_lgretry, AR_D_RETRY_LIMIT_FR_LG) + | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH) + ); + + /* NB: always enable early termination on the QCU */ + qmisc = AR_Q_MISC_DCU_EARLY_TERM_REQ + | SM(AR_Q_MISC_FSP_ASAP, AR_Q_MISC_FSP); + + /* NB: always enable DCU to wait for next fragment from QCU */ + dmisc = AR_D_MISC_FRAG_WAIT_EN; + + /* Enable exponential backoff window */ + dmisc |= AR_D_MISC_BKOFF_PERSISTENCE; + + /* + * The chip reset default is to use a DCU backoff threshold of 0x2. + * Restore this when programming the DCU MISC register. + */ + dmisc |= 0x2; + + /* multiqueue support */ + if (qi->tqi_cbrPeriod) { + OS_REG_WRITE(ah, AR_QCBRCFG(q), + SM(qi->tqi_cbrPeriod,AR_Q_CBRCFG_CBR_INTERVAL) + | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_CBR_OVF_THRESH)); + qmisc = (qmisc &~ AR_Q_MISC_FSP) | AR_Q_MISC_FSP_CBR; + if (qi->tqi_cbrOverflowLimit) + qmisc |= AR_Q_MISC_CBR_EXP_CNTR_LIMIT; + } + + if (qi->tqi_readyTime && (qi->tqi_type != HAL_TX_QUEUE_CAB)) { + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), + SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT) + | AR_Q_RDYTIMECFG_ENA); + } + + OS_REG_WRITE(ah, AR_DCHNTIME(q), + SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) + | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); + + if (qi->tqi_readyTime && + (qi->tqi_qflags & HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE)) + qmisc |= AR_Q_MISC_RDYTIME_EXP_POLICY; + if (qi->tqi_qflags & HAL_TXQ_DBA_GATED) + qmisc = (qmisc &~ AR_Q_MISC_FSP) | AR_Q_MISC_FSP_DBA_GATED; + if (MS(qmisc, AR_Q_MISC_FSP) != AR_Q_MISC_FSP_ASAP) { + /* + * These are meangingful only when not scheduled asap. + */ + if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_BEMPTY) + qmisc |= AR_Q_MISC_CBR_INCR_DIS0; + else + qmisc &= ~AR_Q_MISC_CBR_INCR_DIS0; + if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_QEMPTY) + qmisc |= AR_Q_MISC_CBR_INCR_DIS1; + else + qmisc &= ~AR_Q_MISC_CBR_INCR_DIS1; + } + + if (qi->tqi_qflags & HAL_TXQ_BACKOFF_DISABLE) + dmisc |= AR_D_MISC_POST_FR_BKOFF_DIS; + if (qi->tqi_qflags & HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE) + dmisc |= AR_D_MISC_FRAG_BKOFF_EN; + if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_GLOBAL) + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL); + else if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_INTRA) + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR, + AR_D_MISC_ARB_LOCKOUT_CNTRL); + if (qi->tqi_qflags & HAL_TXQ_IGNORE_VIRTCOL) + dmisc |= SM(AR_D_MISC_VIR_COL_HANDLING_IGNORE, + AR_D_MISC_VIR_COL_HANDLING); + if (qi->tqi_qflags & HAL_TXQ_SEQNUM_INC_DIS) + dmisc |= AR_D_MISC_SEQ_NUM_INCR_DIS; + + /* + * Fillin type-dependent bits. Most of this can be + * removed by specifying the queue parameters in the + * driver; it's here for backwards compatibility. + */ + switch (qi->tqi_type) { + case HAL_TX_QUEUE_BEACON: /* beacon frames */ + qmisc |= AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_BEACON_USE + | AR_Q_MISC_CBR_INCR_DIS1; + + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL) + | AR_D_MISC_BEACON_USE + | AR_D_MISC_POST_FR_BKOFF_DIS; + break; + case HAL_TX_QUEUE_CAB: /* CAB frames */ + /* + * No longer Enable AR_Q_MISC_RDYTIME_EXP_POLICY, + * There is an issue with the CAB Queue + * not properly refreshing the Tx descriptor if + * the TXE clear setting is used. + */ + qmisc |= AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_CBR_INCR_DIS1 + | AR_Q_MISC_CBR_INCR_DIS0; + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: CAB: tqi_readyTime = %d\n", + __func__, qi->tqi_readyTime); + if (qi->tqi_readyTime) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: using tqi_readyTime\n", __func__); + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), + SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT) | + AR_Q_RDYTIMECFG_ENA); + } else { + int value; + /* + * NB: don't set default ready time if driver + * has explicitly specified something. This is + * here solely for backwards compatibility. + */ + /* + * XXX for now, hard-code a CAB interval of 70% + * XXX of the total beacon interval. + * + * XXX This keeps Merlin and later based MACs + * XXX quite a bit happier (stops stuck beacons, + * XXX which I gather is because of such a long + * XXX cabq time.) + */ + value = (ahp->ah_beaconInterval * 50 / 100) + - ah->ah_config.ah_additional_swba_backoff + - ah->ah_config.ah_sw_beacon_response_time + + ah->ah_config.ah_dma_beacon_response_time; + /* + * XXX Ensure it isn't too low - nothing lower + * XXX than 10 TU + */ + if (value < 10) + value = 10; + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, + "%s: defaulting to rdytime = %d uS\n", + __func__, value); + OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), + SM(TU_TO_USEC(value), AR_Q_RDYTIMECFG_INT) | + AR_Q_RDYTIMECFG_ENA); + } + dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL); + break; + case HAL_TX_QUEUE_PSPOLL: + qmisc |= AR_Q_MISC_CBR_INCR_DIS1; + break; + case HAL_TX_QUEUE_UAPSD: + dmisc |= AR_D_MISC_POST_FR_BKOFF_DIS; + break; + default: /* NB: silence compiler */ + break; + } + + OS_REG_WRITE(ah, AR_QMISC(q), qmisc); + OS_REG_WRITE(ah, AR_DMISC(q), dmisc); + + /* Setup compression scratchpad buffer */ + /* + * XXX: calling this asynchronously to queue operation can + * cause unexpected behavior!!! + */ + if (qi->tqi_physCompBuf) { + HALASSERT(qi->tqi_type == HAL_TX_QUEUE_DATA || + qi->tqi_type == HAL_TX_QUEUE_UAPSD); + OS_REG_WRITE(ah, AR_Q_CBBS, (80 + 2*q)); + OS_REG_WRITE(ah, AR_Q_CBBA, qi->tqi_physCompBuf); + OS_REG_WRITE(ah, AR_Q_CBC, HAL_COMP_BUF_MAX_SIZE/1024); + OS_REG_WRITE(ah, AR_Q0_MISC + 4*q, + OS_REG_READ(ah, AR_Q0_MISC + 4*q) + | AR_Q_MISC_QCU_COMP_EN); + } + + /* + * Always update the secondary interrupt mask registers - this + * could be a new queue getting enabled in a running system or + * hw getting re-initialized during a reset! + * + * Since we don't differentiate between tx interrupts corresponding + * to individual queues - secondary tx mask regs are always unmasked; + * tx interrupts are enabled/disabled for all queues collectively + * using the primary mask reg + */ + if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) + ahp->ah_txOkInterruptMask |= 1 << q; + else + ahp->ah_txOkInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) + ahp->ah_txErrInterruptMask |= 1 << q; + else + ahp->ah_txErrInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE) + ahp->ah_txDescInterruptMask |= 1 << q; + else + ahp->ah_txDescInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) + ahp->ah_txEolInterruptMask |= 1 << q; + else + ahp->ah_txEolInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) + ahp->ah_txUrnInterruptMask |= 1 << q; + else + ahp->ah_txUrnInterruptMask &= ~(1 << q); + setTxQInterrupts(ah, qi); + + return AH_TRUE; +} +#undef TU_TO_USEC diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416desc.h b/sys/external/isc/atheros_hal/dist/ar5416/ar5416desc.h new file mode 100644 index 0000000..2730394 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416desc.h @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AR5416_DESC_H_ +#define _ATH_AR5416_DESC_H_ + +/* + * Hardware-specific descriptor structures. + */ + +/* XXX Need to replace this with a dynamic + * method of determining Owl2 if possible + */ +#define _get_index(_ah) ( IS_5416V1(_ah) ? -4 : 0 ) +#define AR5416_DS_TXSTATUS(_ah, _ads) \ + ((uint32_t*)(&(_ads)->u.tx.status[_get_index(_ah)])) +#define AR5416_DS_TXSTATUS_CONST(_ah, _ads) \ + ((const uint32_t*)(&(_ads)->u.tx.status[_get_index(_ah)])) + +#define AR5416_NUM_TX_STATUS 10 /* Number of TX status words */ +/* Clear the whole descriptor */ +#define AR5416_DESC_TX_CTL_SZ sizeof(struct ar5416_tx_desc) + +struct ar5416_tx_desc { /* tx desc has 12 control words + 10 status words */ + uint32_t ctl2; + uint32_t ctl3; + uint32_t ctl4; + uint32_t ctl5; + uint32_t ctl6; + uint32_t ctl7; + uint32_t ctl8; + uint32_t ctl9; + uint32_t ctl10; + uint32_t ctl11; + uint32_t status[AR5416_NUM_TX_STATUS]; +}; + +struct ar5416_rx_desc { /* rx desc has 2 control words + 9 status words */ + uint32_t status0; + uint32_t status1; + uint32_t status2; + uint32_t status3; + uint32_t status4; + uint32_t status5; + uint32_t status6; + uint32_t status7; + uint32_t status8; +}; + + +struct ar5416_desc { + uint32_t ds_link; /* link pointer */ + uint32_t ds_data; /* data buffer pointer */ + uint32_t ds_ctl0; /* DMA control 0 */ + uint32_t ds_ctl1; /* DMA control 1 */ + union { + struct ar5416_tx_desc tx; + struct ar5416_rx_desc rx; + } u; +} __packed; +#define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds)) +#define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds)) + +#define ds_ctl2 u.tx.ctl2 +#define ds_ctl3 u.tx.ctl3 +#define ds_ctl4 u.tx.ctl4 +#define ds_ctl5 u.tx.ctl5 +#define ds_ctl6 u.tx.ctl6 +#define ds_ctl7 u.tx.ctl7 +#define ds_ctl8 u.tx.ctl8 +#define ds_ctl9 u.tx.ctl9 +#define ds_ctl10 u.tx.ctl10 +#define ds_ctl11 u.tx.ctl11 + +#define ds_rxstatus0 u.rx.status0 +#define ds_rxstatus1 u.rx.status1 +#define ds_rxstatus2 u.rx.status2 +#define ds_rxstatus3 u.rx.status3 +#define ds_rxstatus4 u.rx.status4 +#define ds_rxstatus5 u.rx.status5 +#define ds_rxstatus6 u.rx.status6 +#define ds_rxstatus7 u.rx.status7 +#define ds_rxstatus8 u.rx.status8 + +/*********** + * TX Desc * + ***********/ + +/* ds_ctl0 */ +#define AR_FrameLen 0x00000fff +#define AR_VirtMoreFrag 0x00001000 +#define AR_TxCtlRsvd00 0x0000e000 +#define AR_XmitPower 0x003f0000 +#define AR_XmitPower_S 16 +#define AR_RTSEnable 0x00400000 +#define AR_VEOL 0x00800000 +#define AR_ClrDestMask 0x01000000 +#define AR_TxCtlRsvd01 0x1e000000 +#define AR_TxIntrReq 0x20000000 +#define AR_DestIdxValid 0x40000000 +#define AR_CTSEnable 0x80000000 + +/* ds_ctl1 */ +#define AR_BufLen 0x00000fff +#define AR_TxMore 0x00001000 +#define AR_DestIdx 0x000fe000 +#define AR_DestIdx_S 13 +#define AR_FrameType 0x00f00000 +#define AR_FrameType_S 20 +#define AR_NoAck 0x01000000 +#define AR_InsertTS 0x02000000 +#define AR_CorruptFCS 0x04000000 +#define AR_ExtOnly 0x08000000 +#define AR_ExtAndCtl 0x10000000 +#define AR_MoreAggr 0x20000000 +#define AR_IsAggr 0x40000000 +#define AR_MoreRifs 0x80000000 + +/* ds_ctl2 */ +#define AR_BurstDur 0x00007fff +#define AR_BurstDur_S 0 +#define AR_DurUpdateEn 0x00008000 +#define AR_XmitDataTries0 0x000f0000 +#define AR_XmitDataTries0_S 16 +#define AR_XmitDataTries1 0x00f00000 +#define AR_XmitDataTries1_S 20 +#define AR_XmitDataTries2 0x0f000000 +#define AR_XmitDataTries2_S 24 +#define AR_XmitDataTries3 0xf0000000 +#define AR_XmitDataTries3_S 28 + +/* ds_ctl3 */ +#define AR_XmitRate0 0x000000ff +#define AR_XmitRate0_S 0 +#define AR_XmitRate1 0x0000ff00 +#define AR_XmitRate1_S 8 +#define AR_XmitRate2 0x00ff0000 +#define AR_XmitRate2_S 16 +#define AR_XmitRate3 0xff000000 +#define AR_XmitRate3_S 24 + +/* ds_ctl4 */ +#define AR_PacketDur0 0x00007fff +#define AR_PacketDur0_S 0 +#define AR_RTSCTSQual0 0x00008000 +#define AR_PacketDur1 0x7fff0000 +#define AR_PacketDur1_S 16 +#define AR_RTSCTSQual1 0x80000000 + +/* ds_ctl5 */ +#define AR_PacketDur2 0x00007fff +#define AR_PacketDur2_S 0 +#define AR_RTSCTSQual2 0x00008000 +#define AR_PacketDur3 0x7fff0000 +#define AR_PacketDur3_S 16 +#define AR_RTSCTSQual3 0x80000000 + +/* ds_ctl6 */ +#define AR_AggrLen 0x0000ffff +#define AR_AggrLen_S 0 +#define AR_TxCtlRsvd60 0x00030000 +#define AR_PadDelim 0x03fc0000 +#define AR_PadDelim_S 18 +#define AR_EncrType 0x0c000000 +#define AR_EncrType_S 26 +#define AR_TxCtlRsvd61 0xf0000000 + +/* ds_ctl7 */ +#define AR_2040_0 0x00000001 +#define AR_GI0 0x00000002 +#define AR_ChainSel0 0x0000001c +#define AR_ChainSel0_S 2 +#define AR_2040_1 0x00000020 +#define AR_GI1 0x00000040 +#define AR_ChainSel1 0x00000380 +#define AR_ChainSel1_S 7 +#define AR_2040_2 0x00000400 +#define AR_GI2 0x00000800 +#define AR_ChainSel2 0x00007000 +#define AR_ChainSel2_S 12 +#define AR_2040_3 0x00008000 +#define AR_GI3 0x00010000 +#define AR_ChainSel3 0x000e0000 +#define AR_ChainSel3_S 17 +#define AR_RTSCTSRate 0x0ff00000 +#define AR_RTSCTSRate_S 20 +#define AR_STBC0 0x10000000 +#define AR_STBC1 0x20000000 +#define AR_STBC2 0x40000000 +#define AR_STBC3 0x80000000 + +/* ds_ctl8 */ +#define AR_AntCtl0 0x00ffffff +#define AR_AntCtl0_S 0 +/* Xmit 0 TPC is AR_XmitPower in ctl0 */ + +/* ds_ctl9 */ +#define AR_AntCtl1 0x00ffffff +#define AR_AntCtl1_S 0 +#define AR_XmitPower1 0xff000000 +#define AR_XmitPower1_S 24 + +/* ds_ctl10 */ +#define AR_AntCtl2 0x00ffffff +#define AR_AntCtl2_S 0 +#define AR_XmitPower2 0xff000000 +#define AR_XmitPower2_S 24 + +/* ds_ctl11 */ +#define AR_AntCtl3 0x00ffffff +#define AR_AntCtl3_S 0 +#define AR_XmitPower3 0xff000000 +#define AR_XmitPower3_S 24 + +/************* + * TX Status * + *************/ + +/* ds_status0 */ +#define AR_TxRSSIAnt00 0x000000ff +#define AR_TxRSSIAnt00_S 0 +#define AR_TxRSSIAnt01 0x0000ff00 +#define AR_TxRSSIAnt01_S 8 +#define AR_TxRSSIAnt02 0x00ff0000 +#define AR_TxRSSIAnt02_S 16 +#define AR_TxStatusRsvd00 0x3f000000 +#define AR_TxBaStatus 0x40000000 +#define AR_TxStatusRsvd01 0x80000000 + +/* ds_status1 */ +#define AR_FrmXmitOK 0x00000001 +#define AR_ExcessiveRetries 0x00000002 +#define AR_FIFOUnderrun 0x00000004 +#define AR_Filtered 0x00000008 +#define AR_RTSFailCnt 0x000000f0 +#define AR_RTSFailCnt_S 4 +#define AR_DataFailCnt 0x00000f00 +#define AR_DataFailCnt_S 8 +#define AR_VirtRetryCnt 0x0000f000 +#define AR_VirtRetryCnt_S 12 +#define AR_TxDelimUnderrun 0x00010000 +#define AR_TxDelimUnderrun_S 13 +#define AR_TxDataUnderrun 0x00020000 +#define AR_TxDataUnderrun_S 14 +#define AR_DescCfgErr 0x00040000 +#define AR_DescCfgErr_S 15 +#define AR_TxTimerExpired 0x00080000 +#define AR_TxStatusRsvd10 0xfff00000 + +/* ds_status2 */ +#define AR_SendTimestamp(_ptr) (_ptr)[2] + +/* ds_status3 */ +#define AR_BaBitmapLow(_ptr) (_ptr)[3] + +/* ds_status4 */ +#define AR_BaBitmapHigh(_ptr) (_ptr)[4] + +/* ds_status5 */ +#define AR_TxRSSIAnt10 0x000000ff +#define AR_TxRSSIAnt10_S 0 +#define AR_TxRSSIAnt11 0x0000ff00 +#define AR_TxRSSIAnt11_S 8 +#define AR_TxRSSIAnt12 0x00ff0000 +#define AR_TxRSSIAnt12_S 16 +#define AR_TxRSSICombined 0xff000000 +#define AR_TxRSSICombined_S 24 + +/* ds_status6 */ +#define AR_TxEVM0(_ptr) (_ptr)[6] + +/* ds_status7 */ +#define AR_TxEVM1(_ptr) (_ptr)[7] + +/* ds_status8 */ +#define AR_TxEVM2(_ptr) (_ptr)[8] + +/* ds_status9 */ +#define AR_TxDone 0x00000001 +#define AR_SeqNum 0x00001ffe +#define AR_SeqNum_S 1 +#define AR_TxStatusRsvd80 0x0001e000 +#define AR_TxOpExceeded 0x00020000 +#define AR_TxStatusRsvd81 0x001c0000 +#define AR_FinalTxIdx 0x00600000 +#define AR_FinalTxIdx_S 21 +#define AR_TxStatusRsvd82 0x01800000 +#define AR_PowerMgmt 0x02000000 +#define AR_TxTid 0xf0000000 +#define AR_TxTid_S 28 +#define AR_TxStatusRsvd83 0xfc000000 + +/*********** + * RX Desc * + ***********/ + +/* ds_ctl0 */ +#define AR_RxCTLRsvd00 0xffffffff + +/* ds_ctl1 */ +#define AR_BufLen 0x00000fff +#define AR_RxCtlRsvd00 0x00001000 +#define AR_RxIntrReq 0x00002000 +#define AR_RxCtlRsvd01 0xffffc000 + +/************* + * Rx Status * + *************/ + +/* ds_status0 */ +#define AR_RxRSSIAnt00 0x000000ff +#define AR_RxRSSIAnt00_S 0 +#define AR_RxRSSIAnt01 0x0000ff00 +#define AR_RxRSSIAnt01_S 8 +#define AR_RxRSSIAnt02 0x00ff0000 +#define AR_RxRSSIAnt02_S 16 +/* Rev specific */ +/* Owl 1.x only */ +#define AR_RxStatusRsvd00 0xff000000 +/* Owl 2.x only */ +#define AR_RxRate 0xff000000 +#define AR_RxRate_S 24 + +/* ds_status1 */ +#define AR_DataLen 0x00000fff +#define AR_RxMore 0x00001000 +#define AR_NumDelim 0x003fc000 +#define AR_NumDelim_S 14 +#define AR_RxStatusRsvd10 0xff800000 + +/* ds_status2 */ +#define AR_RcvTimestamp ds_rxstatus2 + +/* ds_status3 */ +#define AR_GI 0x00000001 +#define AR_2040 0x00000002 +/* Rev specific */ +/* Owl 1.x only */ +#define AR_RxRateV1 0x000003fc +#define AR_RxRateV1_S 2 +#define AR_Parallel40 0x00000400 +#define AR_RxStatusRsvd30 0xfffff800 +/* Owl 2.x only */ +#define AR_DupFrame 0x00000004 +#define AR_STBCFrame 0x00000008 +#define AR_RxAntenna 0xffffff00 +#define AR_RxAntenna_S 8 + +/* ds_status4 */ +#define AR_RxRSSIAnt10 0x000000ff +#define AR_RxRSSIAnt10_S 0 +#define AR_RxRSSIAnt11 0x0000ff00 +#define AR_RxRSSIAnt11_S 8 +#define AR_RxRSSIAnt12 0x00ff0000 +#define AR_RxRSSIAnt12_S 16 +#define AR_RxRSSICombined 0xff000000 +#define AR_RxRSSICombined_S 24 + +/* ds_status5 */ +#define AR_RxEVM0 ds_rxstatus5 + +/* ds_status6 */ +#define AR_RxEVM1 ds_rxstatus6 + +/* ds_status7 */ +#define AR_RxEVM2 ds_rxstatus7 + +/* ds_status8 */ +#define AR_RxDone 0x00000001 +#define AR_RxFrameOK 0x00000002 +#define AR_CRCErr 0x00000004 +#define AR_DecryptCRCErr 0x00000008 +#define AR_PHYErr 0x00000010 +#define AR_MichaelErr 0x00000020 +#define AR_PreDelimCRCErr 0x00000040 +#define AR_RxStatusRsvd70 0x00000080 +#define AR_RxKeyIdxValid 0x00000100 +#define AR_KeyIdx 0x0000fe00 +#define AR_KeyIdx_S 9 +#define AR_PHYErrCode 0x0000ff00 +#define AR_PHYErrCode_S 8 +#define AR_RxMoreAggr 0x00010000 +#define AR_RxAggr 0x00020000 +#define AR_PostDelimCRCErr 0x00040000 +#define AR_RxStatusRsvd71 0x2ff80000 +#define AR_HiRxChain 0x10000000 +#define AR_DecryptBusyErr 0x40000000 +#define AR_KeyMiss 0x80000000 + +#define TXCTL_OFFSET(ah) 2 +#define TXCTL_NUMWORDS(ah) (AR_SREV_5416_V20_OR_LATER(ah) ? 12 : 8) +#define TXSTATUS_OFFSET(ah) (AR_SREV_5416_V20_OR_LATER(ah) ? 14 : 10) +#define TXSTATUS_NUMWORDS(ah) 10 + +#define RXCTL_OFFSET(ah) 3 +#define RXCTL_NUMWORDS(ah) 1 +#define RXSTATUS_OFFSET(ah) 4 +#define RXSTATUS_NUMWORDS(ah) 9 +#define RXSTATUS_RATE(ah, ads) \ + (AR_SREV_5416_V20_OR_LATER(ah) ? \ + MS((ads)->ds_rxstatus0, AR_RxRate) : \ + ((ads)->ds_rxstatus3 >> 2) & 0xFF) +#define RXSTATUS_DUPLICATE(ah, ads) \ + (AR_SREV_5416_V20_OR_LATER(ah) ? \ + MS((ads)->ds_rxstatus3, AR_Parallel40) : \ + ((ads)->ds_rxstatus3 >> 10) & 0x1) +#endif /* _ATH_AR5416_DESC_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416phy.h b/sys/external/isc/atheros_hal/dist/ar5416/ar5416phy.h new file mode 100644 index 0000000..4884dac --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416phy.h @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _DEV_ATH_AR5416PHY_H_ +#define _DEV_ATH_AR5416PHY_H_ + +#include "ar5212/ar5212phy.h" + +#define AR_BT_COEX_MODE 0x8170 +#define AR_BT_TIME_EXTEND 0x000000ff +#define AR_BT_TIME_EXTEND_S 0 +#define AR_BT_TXSTATE_EXTEND 0x00000100 +#define AR_BT_TXSTATE_EXTEND_S 8 +#define AR_BT_TX_FRAME_EXTEND 0x00000200 +#define AR_BT_TX_FRAME_EXTEND_S 9 +#define AR_BT_MODE 0x00000c00 +#define AR_BT_MODE_S 10 +#define AR_BT_QUIET 0x00001000 +#define AR_BT_QUIET_S 12 +#define AR_BT_QCU_THRESH 0x0001e000 +#define AR_BT_QCU_THRESH_S 13 +#define AR_BT_RX_CLEAR_POLARITY 0x00020000 +#define AR_BT_RX_CLEAR_POLARITY_S 17 +#define AR_BT_PRIORITY_TIME 0x00fc0000 +#define AR_BT_PRIORITY_TIME_S 18 +#define AR_BT_FIRST_SLOT_TIME 0xff000000 +#define AR_BT_FIRST_SLOT_TIME_S 24 + +#define AR_BT_COEX_WEIGHT 0x8174 +#define AR_BT_BT_WGHT 0x0000ffff +#define AR_BT_BT_WGHT_S 0 +#define AR_BT_WL_WGHT 0xffff0000 +#define AR_BT_WL_WGHT_S 16 + +#define AR_BT_COEX_MODE2 0x817c +#define AR_BT_BCN_MISS_THRESH 0x000000ff +#define AR_BT_BCN_MISS_THRESH_S 0 +#define AR_BT_BCN_MISS_CNT 0x0000ff00 +#define AR_BT_BCN_MISS_CNT_S 8 +#define AR_BT_HOLD_RX_CLEAR 0x00010000 +#define AR_BT_HOLD_RX_CLEAR_S 16 +#define AR_BT_DISABLE_BT_ANT 0x00100000 +#define AR_BT_DISABLE_BT_ANT_S 20 + +#define AR_PHY_SPECTRAL_SCAN 0x9910 +#define AR_PHY_SPECTRAL_SCAN_ENA 0x00000001 +#define AR_PHY_SPECTRAL_SCAN_ENA_S 0 +#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 +#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4 +#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 +#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8 + +/* Scan count and Short repeat flags are different for Kiwi and Merlin */ +#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 +#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16 +#define AR_PHY_SPECTRAL_SCAN_COUNT_KIWI 0x0FFF0000 +#define AR_PHY_SPECTRAL_SCAN_COUNT_KIWI_S 16 + +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI 0x10000000 +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI_S 28 + +/* + * Kiwi only, bit 30 is used to set the error type, if set it is 0x5 (HAL_PHYERR_RADAR) + * Else it is 38 (new error type) + */ +#define AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT_KIWI 0x40000000 /* Spectral Error select bit mask */ +#define AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT_KIWI_S 30 /* Spectral Error select bit 30 */ + +#define AR_PHY_SPECTRAL_SCAN_PRIORITY_SELECT_KIWI 0x20000000 /* Spectral Error select bit mask */ +#define AR_PHY_SPECTRAL_SCAN_PRIORITY_SELECT_SELECT_KIWI_S 29 /* Spectral Error select bit 30 */ + +/* For AR_PHY_RADAR0 */ +#define AR_PHY_RADAR_0_FFT_ENA 0x80000000 + +#define AR_PHY_RADAR_EXT 0x9940 +#define AR_PHY_RADAR_EXT_ENA 0x00004000 + +#define AR_PHY_RADAR_1 0x9958 +#define AR_PHY_RADAR_1_BIN_THRESH_SELECT 0x07000000 +#define AR_PHY_RADAR_1_BIN_THRESH_SELECT_S 24 +#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000 +#define AR_PHY_RADAR_1_USE_FIR128 0x00400000 +#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000 +#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16 +#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000 +#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000 +#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000 +#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00 +#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8 +#define AR_PHY_RADAR_1_MAXLEN 0x000000FF +#define AR_PHY_RADAR_1_MAXLEN_S 0 + +#define AR_PHY_CHIP_ID_REV_0 0x80 /* 5416 Rev 0 (owl 1.0) BB */ +#define AR_PHY_CHIP_ID_REV_1 0x81 /* 5416 Rev 1 (owl 2.0) BB */ + +#define RFSILENT_BB 0x00002000 /* shush bb */ +#define AR_PHY_RESTART 0x9970 /* restart */ +#define AR_PHY_RESTART_DIV_GC 0x001C0000 /* bb_ant_fast_div_gc_limit */ +#define AR_PHY_RESTART_DIV_GC_S 18 + +/* PLL settling times */ +#define RTC_PLL_SETTLE_DELAY 1000 /* 1 ms */ +#define HT40_CHANNEL_CENTER_SHIFT 10 /* MHz */ + +#define AR_PHY_RFBUS_REQ 0x997C +#define AR_PHY_RFBUS_REQ_EN 0x00000001 + +#define AR_2040_MODE 0x8318 +#define AR_2040_JOINED_RX_CLEAR 0x00000001 // use ctl + ext rx_clear for cca + +#define AR_PHY_FC_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode setting */ +#define AR_PHY_FC_DYN2040_EN 0x00000004 /* Enable dyn 20/40 mode */ +#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008 /* dyn 20/40 - primary only */ +#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010 /* dyn 20/40 - primary ch offset (0=+10MHz, 1=-10MHz)*/ +#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020 /* dyn 20/40 - ext ch spacing (0=20MHz/ 1=25MHz) */ +#define AR_PHY_FC_HT_EN 0x00000040 /* ht enable */ +#define AR_PHY_FC_SHORT_GI_40 0x00000080 /* allow short GI for HT 40 */ +#define AR_PHY_FC_WALSH 0x00000100 /* walsh spatial spreading for 2 chains,2 streams TX */ +#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200 /* single length (4us) 1st HT long training symbol */ +#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800 + +#define AR_PHY_TIMING2 0x9810 /* Timing Control 2 */ +#define AR_PHY_TIMING2_USE_FORCE 0x00001000 +#define AR_PHY_TIMING2_FORCE_VAL 0x00000fff + +#define AR_PHY_TIMING_CTRL4_CHAIN(_i) \ + (AR_PHY_TIMING_CTRL4 + ((_i) << 12)) +#define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000 /* perform calibration */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F /* Mask for kcos_theta-1 for q correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0 /* shift for Q_COFF */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0 /* Mask for sin_theta for i correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 /* Shift for sin_theta for i correction */ +#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800 /* enable IQ correction */ +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000 /* Mask for max number of samples (logarithmic) */ +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 /* Shift for max number of samples */ + +#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000 +#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000 /* Enable spur filter */ +#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000 +#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000 + +#define AR_PHY_ADC_SERIAL_CTL 0x9830 +#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000 +#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001 + +#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00 +#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10 +#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F +#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0 + +#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003E0000 +#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17 +#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001F000 +#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12 +#define AR_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000FC0 +#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6 +#define AR_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003F +#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0 + +#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80 +#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7 +#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000 +#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14 + +#define AR_PHY_SEARCH_START_DELAY 0x9918 /* search start delay */ + +#define AR_PHY_EXT_CCA 0x99bc +#define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00 +#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 +#define AR_PHY_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_EXT_MINCCA_PWR_S 23 +#define AR_PHY_EXT_CCA_THRESH62 0x007F0000 +#define AR_PHY_EXT_CCA_THRESH62_S 16 + +#define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 +#define AR9280_PHY_EXT_MINCCA_PWR_S 16 + +#define AR_PHY_HALFGI 0x99D0 /* Timing control 3 */ +#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0 +#define AR_PHY_HALFGI_DSC_MAN_S 4 +#define AR_PHY_HALFGI_DSC_EXP 0x0000000F +#define AR_PHY_HALFGI_DSC_EXP_S 0 + +#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 + +#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS 0x99ec +#define AR_PHY_RIFS_INIT_DELAY 0x03ff0000 + +#define AR_PHY_M_SLEEP 0x99f0 /* sleep control registers */ +#define AR_PHY_REFCLKDLY 0x99f4 +#define AR_PHY_REFCLKPD 0x99f8 + +#define AR_PHY_CALMODE 0x99f0 +/* Calibration Types */ +#define AR_PHY_CALMODE_IQ 0x00000000 +#define AR_PHY_CALMODE_ADC_GAIN 0x00000001 +#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002 +#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003 +/* Calibration results */ +#define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12)) +/* This is AR9130 and later */ +#define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12)) + +/* + * AR5416 still uses AR_PHY(263) for current RSSI; + * AR9130 and later uses AR_PHY(271). + */ +#define AR9130_PHY_CURRENT_RSSI 0x9c3c /* rssi of current frame rx'd */ + +#define AR_PHY_CCA 0x9864 +#define AR_PHY_MINCCA_PWR 0x0FF80000 +#define AR_PHY_MINCCA_PWR_S 19 +#define AR9280_PHY_MINCCA_PWR 0x1FF00000 +#define AR9280_PHY_MINCCA_PWR_S 20 +#define AR9280_PHY_CCA_THRESH62 0x000FF000 +#define AR9280_PHY_CCA_THRESH62_S 12 + +#define AR_PHY_CH1_CCA 0xa864 +#define AR_PHY_CH1_MINCCA_PWR 0x0FF80000 +#define AR_PHY_CH1_MINCCA_PWR_S 19 +#define AR_PHY_CCA_THRESH62 0x0007F000 +#define AR_PHY_CCA_THRESH62_S 12 +#define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000 +#define AR9280_PHY_CH1_MINCCA_PWR_S 20 + +#define AR_PHY_CH2_CCA 0xb864 +#define AR_PHY_CH2_MINCCA_PWR 0x0FF80000 +#define AR_PHY_CH2_MINCCA_PWR_S 19 + +#define AR_PHY_CH1_EXT_CCA 0xa9bc +#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23 +#define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000 +#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16 + +#define AR_PHY_CH2_EXT_CCA 0xb9bc +#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23 + +#define AR_PHY_RX_CHAINMASK 0x99a4 + +#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12)) +#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 +#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 +#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac + +#define AR_PHY_EXT_CCA0 0x99b8 +#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF +#define AR_PHY_EXT_CCA0_THRESH62_S 0 + +#define AR_PHY_CH1_EXT_CCA 0xa9bc +#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23 + +#define AR_PHY_CH2_EXT_CCA 0xb9bc +#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23 +#define AR_PHY_ANALOG_SWAP 0xa268 +#define AR_PHY_SWAP_ALT_CHAIN 0x00000040 +#define AR_PHY_CAL_CHAINMASK 0xa39c + +#define AR_PHY_SWITCH_CHAIN_0 0x9960 +#define AR_PHY_SWITCH_COM 0x9964 + +#define AR_PHY_RF_CTL2 0x9824 +#define AR_PHY_TX_FRAME_TO_DATA_START 0x000000FF +#define AR_PHY_TX_FRAME_TO_DATA_START_S 0 +#define AR_PHY_TX_FRAME_TO_PA_ON 0x0000FF00 +#define AR_PHY_TX_FRAME_TO_PA_ON_S 8 + +#define AR_PHY_RF_CTL3 0x9828 +#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000 +#define AR_PHY_TX_END_TO_A2_RX_ON_S 16 + +#define AR_PHY_RF_CTL4 0x9834 +#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000 +#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24 +#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000 +#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16 +#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00 +#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8 +#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF +#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0 + +#define AR_PHY_SYNTH_CONTROL 0x9874 + +#define AR_PHY_FORCE_CLKEN_CCK 0xA22C +#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040 + +#define AR_PHY_POWER_TX_SUB 0xA3C8 +#define AR_PHY_POWER_TX_RATE5 0xA38C +#define AR_PHY_POWER_TX_RATE6 0xA390 +#define AR_PHY_POWER_TX_RATE7 0xA3CC +#define AR_PHY_POWER_TX_RATE8 0xA3D0 +#define AR_PHY_POWER_TX_RATE9 0xA3D4 + +#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000 +#define AR_PHY_TPCRG1_PD_GAIN_1_S 16 +#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000 +#define AR_PHY_TPCRG1_PD_GAIN_2_S 18 +#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 +#define AR_PHY_TPCRG1_PD_GAIN_3_S 20 + +#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000 +#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22 + +#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 +#define AR_PHY_MASK2_M_31_45 0xa3a4 +#define AR_PHY_MASK2_M_16_30 0xa3a8 +#define AR_PHY_MASK2_M_00_15 0xa3ac +#define AR_PHY_MASK2_P_15_01 0xa3b8 +#define AR_PHY_MASK2_P_30_16 0xa3bc +#define AR_PHY_MASK2_P_45_31 0xa3c0 +#define AR_PHY_MASK2_P_61_45 0xa3c4 + +#define AR_PHY_SPUR_REG 0x994c +#define AR_PHY_SFCORR_EXT 0x99c0 +#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F +#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0 +#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80 +#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 +#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 + +/* enable vit puncture per rate, 8 bits, lsb is low rate */ +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18) +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18 + +#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000 /* bins move with freq offset */ +#define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9) /* use mask1 or mask2, one per rate */ +#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9 +#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100 +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0 + +#define AR_PHY_PILOT_MASK_01_30 0xa3b0 +#define AR_PHY_PILOT_MASK_31_60 0xa3b4 + +#define AR_PHY_CHANNEL_MASK_01_30 0x99d4 +#define AR_PHY_CHANNEL_MASK_31_60 0x99d8 + +#define AR_PHY_CL_CAL_CTL 0xA358 /* carrier leak cal control */ +#define AR_PHY_CL_CAL_ENABLE 0x00000002 +#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001 + +/* empirically determined "good" CCA value ranges from atheros */ +#define AR_PHY_CCA_NOM_VAL_5416_2GHZ -90 +#define AR_PHY_CCA_NOM_VAL_5416_5GHZ -100 +#define AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ -100 +#define AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ -110 +#define AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ -80 +#define AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ -90 + +/* ar9280 specific? */ +#define AR_PHY_XPA_CFG 0xA3D8 +#define AR_PHY_FORCE_XPA_CFG 0x000000001 +#define AR_PHY_FORCE_XPA_CFG_S 0 + +#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C +#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2 + +#define AR_PHY_TX_PWRCTRL9 0xa27C +#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 +#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 +#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 +#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 + +#define AR_PHY_MODE_ASYNCFIFO 0x80 /* Enable async fifo */ + +#endif /* _DEV_ATH_AR5416PHY_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar5416/ar5416reg.h b/sys/external/isc/atheros_hal/dist/ar5416/ar5416reg.h new file mode 100644 index 0000000..0ee1e70 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar5416/ar5416reg.h @@ -0,0 +1,813 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _DEV_ATH_AR5416REG_H +#define _DEV_ATH_AR5416REG_H + +#include + +/* + * Register added starting with the AR5416 + */ +#define AR_MIRT 0x0020 /* interrupt rate threshold */ +#define AR_TIMT 0x0028 /* Tx Interrupt mitigation threshold */ +#define AR_RIMT 0x002C /* Rx Interrupt mitigation threshold */ +#define AR_GTXTO 0x0064 /* global transmit timeout */ +#define AR_GTTM 0x0068 /* global transmit timeout mode */ +#define AR_CST 0x006C /* carrier sense timeout */ +#define AR_MAC_LED 0x1f04 /* LED control */ +#define AR_WA 0x4004 /* PCIE work-arounds */ +#define AR_PCIE_PM_CTRL 0x4014 +#define AR_AHB_MODE 0x4024 /* AHB mode for dma */ +#define AR_INTR_SYNC_CAUSE_CLR 0x4028 /* clear interrupt */ +#define AR_INTR_SYNC_CAUSE 0x4028 /* check pending interrupts */ +#define AR_INTR_SYNC_ENABLE 0x402c /* enable interrupts */ +#define AR_INTR_ASYNC_MASK 0x4030 /* asynchronous interrupt mask */ +#define AR_INTR_SYNC_MASK 0x4034 /* synchronous interrupt mask */ +#define AR_INTR_ASYNC_CAUSE 0x4038 /* check pending interrupts */ +#define AR_INTR_ASYNC_CAUSE_CLR 0x4038 /* clear pending interrupts */ +#define AR_INTR_ASYNC_ENABLE 0x403c /* enable interrupts */ +#define AR5416_PCIE_SERDES 0x4040 +#define AR5416_PCIE_SERDES2 0x4044 +#define AR_GPIO_IN_OUT 0x4048 /* GPIO input/output register */ +#define AR_GPIO_OE_OUT 0x404c /* GPIO output enable register */ +#define AR_GPIO_INTR_POL 0x4050 /* GPIO interrupt polarity */ + +#define AR_GPIO_INPUT_EN_VAL 0x4054 /* GPIO input enable and value */ +#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004 +#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2 +#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008 +#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_S 3 +#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF 0x00000010 +#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S 4 +#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080 +#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7 +#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB 0x00000400 +#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S 10 +#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_BB 0x00000800 +#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_BB_S 11 +#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000 +#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12 +#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000 +#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15 +#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 +#define AR_GPIO_JTAG_DISABLE 0x00020000 + +#define AR_GPIO_INPUT_MUX1 0x4058 +#define AR_GPIO_INPUT_MUX1_BT_PRIORITY 0x00000f00 +#define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8 +#define AR_GPIO_INPUT_MUX1_BT_FREQUENCY 0x0000f000 +#define AR_GPIO_INPUT_MUX1_BT_FREQUENCY_S 12 +#define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 +#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 + +#define AR_GPIO_INPUT_MUX2 0x405c +#define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f +#define AR_GPIO_INPUT_MUX2_CLK25_S 0 +#define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0 +#define AR_GPIO_INPUT_MUX2_RFSILENT_S 4 +#define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00 +#define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8 + +#define AR_GPIO_OUTPUT_MUX1 0x4060 +#define AR_GPIO_OUTPUT_MUX2 0x4064 +#define AR_GPIO_OUTPUT_MUX3 0x4068 + +#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 +#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 +#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 +#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3 +#define AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL 4 +#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 +#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 + +#define AR_EEPROM_STATUS_DATA 0x407c +#define AR_OBS 0x4080 +#define AR_GPIO_PDPU 0x4088 + +#ifdef AH_SUPPORT_AR9130 +#define AR_RTC_BASE 0x20000 +#else +#define AR_RTC_BASE 0x7000 +#endif /* AH_SUPPORT_AR9130 */ + +#define AR_RTC_RC AR_RTC_BASE + 0x00 /* reset control */ +#define AR_RTC_PLL_CONTROL AR_RTC_BASE + 0x14 +#define AR_RTC_RESET AR_RTC_BASE + 0x40 /* RTC reset register */ +#define AR_RTC_STATUS AR_RTC_BASE + 0x44 /* system sleep status */ +#define AR_RTC_SLEEP_CLK AR_RTC_BASE + 0x48 +#define AR_RTC_FORCE_WAKE AR_RTC_BASE + 0x4c /* control MAC force wake */ +#define AR_RTC_INTR_CAUSE AR_RTC_BASE + 0x50 /* RTC interrupt cause/clear */ +#define AR_RTC_INTR_ENABLE AR_RTC_BASE + 0x54 /* RTC interrupt enable */ +#define AR_RTC_INTR_MASK AR_RTC_BASE + 0x58 /* RTC interrupt mask */ + +#ifdef AH_SUPPORT_AR9130 +/* RTC_DERIVED_* - only for AR9130 */ +#define AR_RTC_DERIVED_CLK (AR_RTC_BASE + 0x0038) +#define AR_RTC_DERIVED_CLK_PERIOD 0x0000fffe +#define AR_RTC_DERIVED_CLK_PERIOD_S 1 +#endif /* AH_SUPPORT_AR9130 */ + +/* AR_USEC: 0x801c */ +#define AR5416_USEC_TX_LAT 0x007FC000 /* tx latency to start of SIGNAL (usec) */ +#define AR5416_USEC_TX_LAT_S 14 /* tx latency to start of SIGNAL (usec) */ +#define AR5416_USEC_RX_LAT 0x1F800000 /* rx latency to start of SIGNAL (usec) */ +#define AR5416_USEC_RX_LAT_S 23 /* rx latency to start of SIGNAL (usec) */ + +#define AR_RESET_TSF 0x8020 + +/* + * AR_SLEEP1 / AR_SLEEP2 are in the same place as in + * AR5212, however the fields have changed. + */ +#define AR5416_SLEEP1 0x80d4 +#define AR5416_SLEEP2 0x80d8 +#define AR_RXFIFO_CFG 0x8114 +#define AR_PHY_ERR_1 0x812c +#define AR_PHY_ERR_MASK_1 0x8130 /* mask for AR_PHY_ERR_1 */ +#define AR_PHY_ERR_2 0x8134 +#define AR_PHY_ERR_MASK_2 0x8138 /* mask for AR_PHY_ERR_2 */ +#define AR_TSFOOR_THRESHOLD 0x813c +#define AR_PHY_ERR_3 0x8168 +#define AR_PHY_ERR_MASK_3 0x816c /* mask for AR_PHY_ERR_3 */ +#define AR_BT_COEX_WEIGHT2 0x81c4 +#define AR_TXOP_X 0x81ec /* txop for legacy non-qos */ +#define AR_TXOP_0_3 0x81f0 /* txop for various tid's */ +#define AR_TXOP_4_7 0x81f4 +#define AR_TXOP_8_11 0x81f8 +#define AR_TXOP_12_15 0x81fc +/* generic timers based on tsf - all uS */ +#define AR_NEXT_TBTT 0x8200 +#define AR_NEXT_DBA 0x8204 +#define AR_NEXT_SWBA 0x8208 +#define AR_NEXT_CFP 0x8208 +#define AR_NEXT_HCF 0x820C +#define AR_NEXT_TIM 0x8210 +#define AR_NEXT_DTIM 0x8214 +#define AR_NEXT_QUIET 0x8218 +#define AR_NEXT_NDP 0x821C +#define AR5416_BEACON_PERIOD 0x8220 +#define AR_DBA_PERIOD 0x8224 +#define AR_SWBA_PERIOD 0x8228 +#define AR_HCF_PERIOD 0x822C +#define AR_TIM_PERIOD 0x8230 +#define AR_DTIM_PERIOD 0x8234 +#define AR_QUIET_PERIOD 0x8238 +#define AR_NDP_PERIOD 0x823C +#define AR_TIMER_MODE 0x8240 +#define AR_SLP32_MODE 0x8244 +#define AR_SLP32_WAKE 0x8248 +#define AR_SLP32_INC 0x824c +#define AR_SLP_CNT 0x8250 /* 32kHz cycles with mac asleep */ +#define AR_SLP_CYCLE_CNT 0x8254 /* absolute number of 32kHz cycles */ +#define AR_SLP_MIB_CTRL 0x8258 +#define AR_2040_MODE 0x8318 +#define AR_EXTRCCNT 0x8328 /* extension channel rx clear count */ +#define AR_SELFGEN_MASK 0x832c /* rx and cal chain masks */ +#define AR_PHY_ERR_MASK_REG 0x8338 +#define AR_PCU_TXBUF_CTRL 0x8340 +#define AR_PCU_MISC_MODE2 0x8344 + +/* DMA & PCI Registers in PCI space (usable during sleep)*/ +#define AR_RC_AHB 0x00000001 /* AHB reset */ +#define AR_RC_APB 0x00000002 /* APB reset */ +#define AR_RC_HOSTIF 0x00000100 /* host interface reset */ + +#define AR_MIRT_VAL 0x0000ffff /* in uS */ +#define AR_MIRT_VAL_S 16 + +#define AR_TIMT_LAST 0x0000ffff /* Last packet threshold */ +#define AR_TIMT_LAST_S 0 +#define AR_TIMT_FIRST 0xffff0000 /* First packet threshold */ +#define AR_TIMT_FIRST_S 16 + +#define AR_RIMT_LAST 0x0000ffff /* Last packet threshold */ +#define AR_RIMT_LAST_S 0 +#define AR_RIMT_FIRST 0xffff0000 /* First packet threshold */ +#define AR_RIMT_FIRST_S 16 + +#define AR_GTXTO_TIMEOUT_COUNTER 0x0000FFFF // Mask for timeout counter (in TUs) +#define AR_GTXTO_TIMEOUT_LIMIT 0xFFFF0000 // Mask for timeout limit (in TUs) +#define AR_GTXTO_TIMEOUT_LIMIT_S 16 // Shift for timeout limit + +#define AR_GTTM_USEC 0x00000001 // usec strobe +#define AR_GTTM_IGNORE_IDLE 0x00000002 // ignore channel idle +#define AR_GTTM_RESET_IDLE 0x00000004 // reset counter on channel idle low +#define AR_GTTM_CST_USEC 0x00000008 // CST usec strobe + +#define AR_CST_TIMEOUT_COUNTER 0x0000FFFF // Mask for timeout counter (in TUs) +#define AR_CST_TIMEOUT_LIMIT 0xFFFF0000 // Mask for timeout limit (in TUs) +#define AR_CST_TIMEOUT_LIMIT_S 16 // Shift for timeout limit + +/* MAC tx DMA size config */ +#define AR_TXCFG_DMASZ_MASK 0x00000003 +#define AR_TXCFG_DMASZ_4B 0 +#define AR_TXCFG_DMASZ_8B 1 +#define AR_TXCFG_DMASZ_16B 2 +#define AR_TXCFG_DMASZ_32B 3 +#define AR_TXCFG_DMASZ_64B 4 +#define AR_TXCFG_DMASZ_128B 5 +#define AR_TXCFG_DMASZ_256B 6 +#define AR_TXCFG_DMASZ_512B 7 +#define AR_TXCFG_ATIM_TXPOLICY 0x00000800 + +/* MAC rx DMA size config */ +#define AR_RXCFG_DMASZ_MASK 0x00000007 +#define AR_RXCFG_DMASZ_4B 0 +#define AR_RXCFG_DMASZ_8B 1 +#define AR_RXCFG_DMASZ_16B 2 +#define AR_RXCFG_DMASZ_32B 3 +#define AR_RXCFG_DMASZ_64B 4 +#define AR_RXCFG_DMASZ_128B 5 +#define AR_RXCFG_DMASZ_256B 6 +#define AR_RXCFG_DMASZ_512B 7 + +/* MAC Led registers */ +#define AR_CFG_SCLK_RATE_IND 0x00000003 /* sleep clock indication */ +#define AR_CFG_SCLK_RATE_IND_S 0 +#define AR_CFG_SCLK_32MHZ 0x00000000 /* Sleep clock rate */ +#define AR_CFG_SCLK_4MHZ 0x00000001 /* Sleep clock rate */ +#define AR_CFG_SCLK_1MHZ 0x00000002 /* Sleep clock rate */ +#define AR_CFG_SCLK_32KHZ 0x00000003 /* Sleep clock rate */ +#define AR_MAC_LED_BLINK_SLOW 0x00000008 /* LED slowest blink rate mode */ +#define AR_MAC_LED_BLINK_THRESH_SEL 0x00000070 /* LED blink threshold select */ +#define AR_MAC_LED_MODE 0x00000380 /* LED mode select */ +#define AR_MAC_LED_MODE_S 7 +#define AR_MAC_LED_MODE_PROP 0 /* Blink prop to filtered tx/rx */ +#define AR_MAC_LED_MODE_RPROP 1 /* Blink prop to unfiltered tx/rx */ +#define AR_MAC_LED_MODE_SPLIT 2 /* Blink power for tx/net for rx */ +#define AR_MAC_LED_MODE_RAND 3 /* Blink randomly */ +#define AR_MAC_LED_MODE_POWON 5 /* Power LED on (s/w control) */ +#define AR_MAC_LED_MODE_NETON 6 /* Network LED on (s/w control) */ +#define AR_MAC_LED_ASSOC 0x00000c00 +#define AR_MAC_LED_ASSOC_NONE 0x0 /* STA is not associated or trying */ +#define AR_MAC_LED_ASSOC_ACTIVE 0x1 /* STA is associated */ +#define AR_MAC_LED_ASSOC_PEND 0x2 /* STA is trying to associate */ +#define AR_MAC_LED_ASSOC_S 10 + +#define AR_WA_BIT6 0x00000040 +#define AR_WA_BIT7 0x00000080 +#define AR_WA_D3_L1_DISABLE 0x00004000 /* */ +#define AR_WA_UNTIE_RESET_EN 0x00008000 /* ena PCI reset to POR */ +#define AR_WA_RESET_EN 0x00040000 /* ena AR_WA_UNTIE_RESET_EN */ +#define AR_WA_ANALOG_SHIFT 0x00100000 +#define AR_WA_POR_SHORT 0x00200000 /* PCIE phy reset control */ +#define AR_WA_BIT22 0x00400000 +#define AR_WA_BIT23 0x00800000 + +#define AR_WA_DEFAULT 0x0000073f +#define AR9280_WA_DEFAULT 0x0040073b /* disable bit 2, see commit */ +#define AR9285_WA_DEFAULT 0x004a05cb + +#define AR_PCIE_PM_CTRL_ENA 0x00080000 + +#define AR_AHB_EXACT_WR_EN 0x00000000 /* write exact bytes */ +#define AR_AHB_BUF_WR_EN 0x00000001 /* buffer write upto cacheline*/ +#define AR_AHB_EXACT_RD_EN 0x00000000 /* read exact bytes */ +#define AR_AHB_CACHELINE_RD_EN 0x00000002 /* read upto end of cacheline */ +#define AR_AHB_PREFETCH_RD_EN 0x00000004 /* prefetch upto page boundary*/ +#define AR_AHB_PAGE_SIZE_1K 0x00000000 /* set page-size as 1k */ +#define AR_AHB_PAGE_SIZE_2K 0x00000008 /* set page-size as 2k */ +#define AR_AHB_PAGE_SIZE_4K 0x00000010 /* set page-size as 4k */ +/* Kiwi */ +#define AR_AHB_CUSTOM_BURST_EN 0x000000C0 /* set Custom Burst Mode */ +#define AR_AHB_CUSTOM_BURST_EN_S 6 /* set Custom Burst Mode */ +#define AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL 3 /* set both bits in Async FIFO mode */ + +/* MAC PCU Registers */ +#define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000 /* Don't replace seq num */ + +/* Extended PCU DIAG_SW control fields */ +#define AR_DIAG_DUAL_CHAIN_INFO 0x01000000 /* dual chain channel info */ +#define AR_DIAG_RX_ABORT 0x02000000 /* abort rx */ +#define AR_DIAG_SATURATE_CCNT 0x04000000 /* sat. cycle cnts (no shift) */ +#define AR_DIAG_OBS_PT_SEL2 0x08000000 /* observation point sel */ +#define AR_DIAG_RXCLEAR_CTL_LOW 0x10000000 /* force rx_clear(ctl) low/busy */ +#define AR_DIAG_RXCLEAR_EXT_LOW 0x20000000 /* force rx_clear(ext) low/busy */ + +#define AR_TXOP_X_VAL 0x000000FF + +#define AR_RESET_TSF_ONCE 0x01000000 /* reset tsf once; self-clears*/ + +/* Interrupts */ +#define AR_ISR_TXMINTR 0x00080000 /* Maximum interrupt tx rate */ +#define AR_ISR_RXMINTR 0x01000000 /* Maximum interrupt rx rate */ +#define AR_ISR_GENTMR 0x10000000 /* OR of generic timer bits in S5 */ +#define AR_ISR_TXINTM 0x40000000 /* Tx int after mitigation */ +#define AR_ISR_RXINTM 0x80000000 /* Rx int after mitigation */ + +#define AR_ISR_S2_CST 0x00400000 /* Carrier sense timeout */ +#define AR_ISR_S2_GTT 0x00800000 /* Global transmit timeout */ +#define AR_ISR_S2_TSFOOR 0x40000000 /* RX TSF out of range */ + +#define AR_ISR_S5 0x0098 +#define AR_ISR_S5_S 0x00d8 +#define AR_ISR_S5_GENTIMER7 0x00000080 // Mask for timer 7 trigger +#define AR_ISR_S5_TIM_TIMER 0x00000010 // TIM Timer ISR +#define AR_ISR_S5_DTIM_TIMER 0x00000020 // DTIM Timer ISR +#define AR_ISR_S5_GENTIMER_TRIG 0x0000FF80 // ISR for generic timer trigger 7-15 +#define AR_ISR_S5_GENTIMER_TRIG_S 0 +#define AR_ISR_S5_GENTIMER_THRESH 0xFF800000 // ISR for generic timer threshold 7-15 +#define AR_ISR_S5_GENTIMER_THRESH_S 16 + +#define AR_INTR_SPURIOUS 0xffffffff +#define AR_INTR_RTC_IRQ 0x00000001 /* rtc in shutdown state */ +#define AR_INTR_MAC_IRQ 0x00000002 /* pending mac interrupt */ +#define AR_INTR_EEP_PROT_ACCESS 0x00000004 /* eeprom protected access */ +#define AR_INTR_MAC_AWAKE 0x00020000 /* mac is awake */ +#define AR_INTR_MAC_ASLEEP 0x00040000 /* mac is asleep */ + +/* Interrupt Mask Registers */ +#define AR_IMR_TXMINTR 0x00080000 /* Maximum interrupt tx rate */ +#define AR_IMR_RXMINTR 0x01000000 /* Maximum interrupt rx rate */ +#define AR_IMR_TXINTM 0x40000000 /* Tx int after mitigation */ +#define AR_IMR_RXINTM 0x80000000 /* Rx int after mitigation */ + +#define AR_IMR_S2_CST 0x00400000 /* Carrier sense timeout */ +#define AR_IMR_S2_GTT 0x00800000 /* Global transmit timeout */ + +/* synchronous interrupt signals */ +#define AR_INTR_SYNC_RTC_IRQ 0x00000001 +#define AR_INTR_SYNC_MAC_IRQ 0x00000002 +#define AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS 0x00000004 +#define AR_INTR_SYNC_APB_TIMEOUT 0x00000008 +#define AR_INTR_SYNC_PCI_MODE_CONFLICT 0x00000010 +#define AR_INTR_SYNC_HOST1_FATAL 0x00000020 +#define AR_INTR_SYNC_HOST1_PERR 0x00000040 +#define AR_INTR_SYNC_TRCV_FIFO_PERR 0x00000080 +#define AR_INTR_SYNC_RADM_CPL_EP 0x00000100 +#define AR_INTR_SYNC_RADM_CPL_DLLP_ABORT 0x00000200 +#define AR_INTR_SYNC_RADM_CPL_TLP_ABORT 0x00000400 +#define AR_INTR_SYNC_RADM_CPL_ECRC_ERR 0x00000800 +#define AR_INTR_SYNC_RADM_CPL_TIMEOUT 0x00001000 +#define AR_INTR_SYNC_LOCAL_TIMEOUT 0x00002000 +#define AR_INTR_SYNC_PM_ACCESS 0x00004000 +#define AR_INTR_SYNC_MAC_AWAKE 0x00008000 +#define AR_INTR_SYNC_MAC_ASLEEP 0x00010000 +#define AR_INTR_SYNC_MAC_SLEEP_ACCESS 0x00020000 +#define AR_INTR_SYNC_ALL 0x0003FFFF + +/* default synchronous interrupt signals enabled */ +#define AR_INTR_SYNC_DEFAULT \ + (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR | \ + AR_INTR_SYNC_RADM_CPL_EP | AR_INTR_SYNC_RADM_CPL_DLLP_ABORT | \ + AR_INTR_SYNC_RADM_CPL_TLP_ABORT | AR_INTR_SYNC_RADM_CPL_ECRC_ERR | \ + AR_INTR_SYNC_RADM_CPL_TIMEOUT | AR_INTR_SYNC_LOCAL_TIMEOUT | \ + AR_INTR_SYNC_MAC_SLEEP_ACCESS) + +#define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 +#define AR_INTR_SYNC_MASK_GPIO_S 18 + +#define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000 +#define AR_INTR_SYNC_ENABLE_GPIO_S 18 + +#define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 /* async int mask */ +#define AR_INTR_ASYNC_MASK_GPIO_S 18 + +#define AR_INTR_ASYNC_CAUSE_GPIO 0xFFFC0000 /* GPIO interrupts */ +#define AR_INTR_ASYNC_USED (AR_INTR_MAC_IRQ | AR_INTR_ASYNC_CAUSE_GPIO) + +#define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 /* enable interrupts */ +#define AR_INTR_ASYNC_ENABLE_GPIO_S 18 + +/* RTC registers */ +#define AR_RTC_RC_M 0x00000003 +#define AR_RTC_RC_MAC_WARM 0x00000001 +#define AR_RTC_RC_MAC_COLD 0x00000002 +#ifdef AH_SUPPORT_AR9130 +#define AR_RTC_RC_COLD_RESET 0x00000004 +#define AR_RTC_RC_WARM_RESET 0x00000008 +#endif /* AH_SUPPORT_AR9130 */ +#define AR_RTC_PLL_DIV 0x0000001f +#define AR_RTC_PLL_DIV_S 0 +#define AR_RTC_PLL_DIV2 0x00000020 +#define AR_RTC_PLL_REFDIV_5 0x000000c0 + +#define AR_RTC_SOWL_PLL_DIV 0x000003ff +#define AR_RTC_SOWL_PLL_DIV_S 0 +#define AR_RTC_SOWL_PLL_REFDIV 0x00003C00 +#define AR_RTC_SOWL_PLL_REFDIV_S 10 +#define AR_RTC_SOWL_PLL_CLKSEL 0x0000C000 +#define AR_RTC_SOWL_PLL_CLKSEL_S 14 + +#define AR_RTC_RESET_EN 0x00000001 /* Reset RTC bit */ + +#define AR_RTC_PM_STATUS_M 0x0000000f /* Pwr Mgmt Status */ +#ifdef AH_SUPPORT_AR9130 +#define AR_RTC_STATUS_M 0x0000000f /* RTC Status */ +#else +#define AR_RTC_STATUS_M 0x0000003f /* RTC Status */ +#endif /* AH_SUPPORT_AR9130 */ +#define AR_RTC_STATUS_SHUTDOWN 0x00000001 +#define AR_RTC_STATUS_ON 0x00000002 +#define AR_RTC_STATUS_SLEEP 0x00000004 +#define AR_RTC_STATUS_WAKEUP 0x00000008 +#define AR_RTC_STATUS_COLDRESET 0x00000010 /* Not currently used */ +#define AR_RTC_STATUS_PLLCHANGE 0x00000020 /* Not currently used */ + +#define AR_RTC_SLEEP_DERIVED_CLK 0x2 + +#define AR_RTC_FORCE_WAKE_EN 0x00000001 /* enable force wake */ +#define AR_RTC_FORCE_WAKE_ON_INT 0x00000002 /* auto-wake on MAC interrupt */ + +#define AR_RTC_PLL_CLKSEL 0x00000300 +#define AR_RTC_PLL_CLKSEL_S 8 + +/* AR9280: rf long shift registers */ +#define AR_AN_RF2G1_CH0 0x7810 +#define AR_AN_RF5G1_CH0 0x7818 +#define AR_AN_RF2G1_CH1 0x7834 +#define AR_AN_RF5G1_CH1 0x783C +#define AR_AN_TOP2 0x7894 +#define AR_AN_SYNTH9 0x7868 + +#define AR_AN_RF2G1_CH0_OB 0x03800000 +#define AR_AN_RF2G1_CH0_OB_S 23 +#define AR_AN_RF2G1_CH0_DB 0x1C000000 +#define AR_AN_RF2G1_CH0_DB_S 26 + +#define AR_AN_RF5G1_CH0_OB5 0x00070000 +#define AR_AN_RF5G1_CH0_OB5_S 16 +#define AR_AN_RF5G1_CH0_DB5 0x00380000 +#define AR_AN_RF5G1_CH0_DB5_S 19 + +#define AR_AN_RF2G1_CH1_OB 0x03800000 +#define AR_AN_RF2G1_CH1_OB_S 23 +#define AR_AN_RF2G1_CH1_DB 0x1C000000 +#define AR_AN_RF2G1_CH1_DB_S 26 + +#define AR_AN_RF5G1_CH1_OB5 0x00070000 +#define AR_AN_RF5G1_CH1_OB5_S 16 +#define AR_AN_RF5G1_CH1_DB5 0x00380000 +#define AR_AN_RF5G1_CH1_DB5_S 19 + +#define AR_AN_TOP1 0x7890 +#define AR_AN_TOP1_DACIPMODE 0x00040000 +#define AR_AN_TOP1_DACIPMODE_S 18 + +#define AR_AN_TOP2_XPABIAS_LVL 0xC0000000 +#define AR_AN_TOP2_XPABIAS_LVL_S 30 +#define AR_AN_TOP2_LOCALBIAS 0x00200000 +#define AR_AN_TOP2_LOCALBIAS_S 21 +#define AR_AN_TOP2_PWDCLKIND 0x00400000 +#define AR_AN_TOP2_PWDCLKIND_S 22 + +#define AR_AN_SYNTH9_REFDIVA 0xf8000000 +#define AR_AN_SYNTH9_REFDIVA_S 27 + +#define AR9271_AN_RF2G6_OFFS 0x07f00000 +#define AR9271_AN_RF2G6_OFFS_S 20 + +/* Sleep control */ +#define AR5416_SLEEP1_ASSUME_DTIM 0x00080000 +#define AR5416_SLEEP1_CAB_TIMEOUT 0xFFE00000 /* Cab timeout (TU) */ +#define AR5416_SLEEP1_CAB_TIMEOUT_S 21 + +#define AR5416_SLEEP2_BEACON_TIMEOUT 0xFFE00000 /* Beacon timeout (TU)*/ +#define AR5416_SLEEP2_BEACON_TIMEOUT_S 21 + +/* Sleep Registers */ +#define AR_SLP32_HALFCLK_LATENCY 0x000FFFFF /* rising <-> falling edge */ +#define AR_SLP32_ENA 0x00100000 +#define AR_SLP32_TSF_WRITE_STATUS 0x00200000 /* tsf update in progress */ + +#define AR_SLP32_WAKE_XTL_TIME 0x0000FFFF /* time to wake crystal */ + +#define AR_SLP32_TST_INC 0x000FFFFF + +#define AR_SLP_MIB_CLEAR 0x00000001 /* clear pending */ +#define AR_SLP_MIB_PENDING 0x00000002 /* clear counters */ + +#define AR_TIMER_MODE_TBTT 0x00000001 +#define AR_TIMER_MODE_DBA 0x00000002 +#define AR_TIMER_MODE_SWBA 0x00000004 +#define AR_TIMER_MODE_HCF 0x00000008 +#define AR_TIMER_MODE_TIM 0x00000010 +#define AR_TIMER_MODE_DTIM 0x00000020 +#define AR_TIMER_MODE_QUIET 0x00000040 +#define AR_TIMER_MODE_NDP 0x00000080 +#define AR_TIMER_MODE_OVERFLOW_INDEX 0x00000700 +#define AR_TIMER_MODE_OVERFLOW_INDEX_S 8 +#define AR_TIMER_MODE_THRESH 0xFFFFF000 +#define AR_TIMER_MODE_THRESH_S 12 + +/* PCU Misc modes */ +#define AR_PCU_FORCE_BSSID_MATCH 0x00000001 /* force bssid to match */ +#define AR_PCU_MIC_NEW_LOC_ENA 0x00000004 /* tx/rx mic keys together */ +#define AR_PCU_TX_ADD_TSF 0x00000008 /* add tx_tsf + int_tsf */ +#define AR_PCU_CCK_SIFS_MODE 0x00000010 /* assume 11b sifs */ +#define AR_PCU_RX_ANT_UPDT 0x00000800 /* KC_RX_ANT_UPDATE */ +#define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000 /* enforce txop / tbtt */ +#define AR_PCU_MISS_BCN_IN_SLEEP 0x00004000 /* count bmiss's when sleeping */ +#define AR_PCU_BUG_12306_FIX_ENA 0x00020000 /* use rx_clear to count sifs */ +#define AR_PCU_FORCE_QUIET_COLL 0x00040000 /* kill xmit for channel change */ +#define AR_PCU_BT_ANT_PREVENT_RX 0x00100000 +#define AR_PCU_BT_ANT_PREVENT_RX_S 20 +#define AR_PCU_TBTT_PROTECT 0x00200000 /* no xmit upto tbtt+20 uS */ +#define AR_PCU_CLEAR_VMF 0x01000000 /* clear vmf mode (fast cc)*/ +#define AR_PCU_CLEAR_BA_VALID 0x04000000 /* clear ba state */ +#define AR_PCU_SEL_EVM 0x08000000 /* select EVM data or PLCP header */ + +#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002 +#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004 +/* + * This bit enables the Multicast search based on both MAC Address and Key ID. + * If bit is 0, then Multicast search is based on MAC address only. + * For Merlin and above only. + */ +#define AR_PCU_MISC_MODE2_ADHOC_MCAST_KEYID_ENABLE 0x00000040 +#define AR_PCU_MISC_MODE2_ENABLE_AGGWEP 0x00020000 /* Kiwi or later? */ +#define AR_PCU_MISC_MODE2_HWWAR1 0x00100000 +#define AR_PCU_MISC_MODE2_HWWAR2 0x02000000 + +/* For Kiwi */ +#define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358 +#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400 +#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000 + +/* TSF2. For Kiwi only */ +#define AR_TSF2_L32 0x8390 +#define AR_TSF2_U32 0x8394 + +/* MAC Direct Connect Control. For Kiwi only */ +#define AR_DIRECT_CONNECT 0x83A0 +#define AR_DC_AP_STA_EN 0x00000001 + +/* GPIO Interrupt */ +#define AR_INTR_GPIO 0x3FF00000 /* gpio interrupted */ +#define AR_INTR_GPIO_S 20 + +#define AR_GPIO_OUT_CTRL 0x000003FF /* 0 = out, 1 = in */ +#define AR_GPIO_OUT_VAL 0x000FFC00 +#define AR_GPIO_OUT_VAL_S 10 +#define AR_GPIO_INTR_CTRL 0x3FF00000 +#define AR_GPIO_INTR_CTRL_S 20 + +#define AR_GPIO_IN_VAL 0x0FFFC000 /* pre-9280 */ +#define AR_GPIO_IN_VAL_S 14 +#define AR928X_GPIO_IN_VAL 0x000FFC00 +#define AR928X_GPIO_IN_VAL_S 10 +#define AR9285_GPIO_IN_VAL 0x00FFF000 +#define AR9285_GPIO_IN_VAL_S 12 +#define AR9287_GPIO_IN_VAL 0x003FF800 +#define AR9287_GPIO_IN_VAL_S 11 + +#define AR_GPIO_OE_OUT_DRV 0x3 /* 2 bit mask shifted by 2*bitpos */ +#define AR_GPIO_OE_OUT_DRV_NO 0x0 /* tristate */ +#define AR_GPIO_OE_OUT_DRV_LOW 0x1 /* drive if low */ +#define AR_GPIO_OE_OUT_DRV_HI 0x2 /* drive if high */ +#define AR_GPIO_OE_OUT_DRV_ALL 0x3 /* drive always */ + +#define AR_GPIO_INTR_POL_VAL 0x1FFF +#define AR_GPIO_INTR_POL_VAL_S 0 + +#define AR_GPIO_JTAG_DISABLE 0x00020000 + +#define AR_2040_JOINED_RX_CLEAR 0x00000001 /* use ctl + ext rx_clear for cca */ + +#define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF +#define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700 +#define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380 + +/* IFS, SIFS, slot, etc for Async FIFO mode (Kiwi) */ +#define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003AB +#define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR 0x16001D56 +#define AR_USEC_ASYNC_FIFO_DUR 0x12e00074 +#define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR 0x00000420 +#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR 0x0000A5EB + +/* Used by Kiwi Async FIFO */ +#define AR_MAC_PCU_LOGIC_ANALYZER 0x8264 +#define AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768 0x20000000 + +/* Eeprom defines */ +#define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff +#define AR_EEPROM_STATUS_DATA_VAL_S 0 +#define AR_EEPROM_STATUS_DATA_BUSY 0x00010000 +#define AR_EEPROM_STATUS_DATA_BUSY_ACCESS 0x00020000 +#define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 +#define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 + +/* K2 (9271) */ +#define AR9271_CLOCK_CONTROL 0x50040 +#define AR9271_CLOCK_SELECTION_22 0x0 +#define AR9271_CLOCK_SELECTION_88 0x1 +#define AR9271_CLOCK_SELECTION_44 0x2 +#define AR9271_CLOCK_SELECTION_117 0x4 +#define AR9271_CLOCK_SELECTION_OSC_40 0x6 +#define AR9271_CLOCK_SELECTION_RTC 0x7 +#define AR9271_SPI_SEL 0x100 +#define AR9271_UART_SEL 0x200 + +#define AR9271_RESET_POWER_DOWN_CONTROL 0x50044 +#define AR9271_RADIO_RF_RST 0x20 +#define AR9271_GATE_MAC_CTL 0x4000 +#define AR9271_MAIN_PLL_PWD_CTL 0x40000 + +#define AR9271_CLKMISC 0x4090 +#define AR9271_OSC_to_10M_EN 0x00000001 + +/* + * AR5212 defines the MAC revision mask as 0xF, but both ath9k and + * the Atheros HAL define it as 0x7. + * + * What this means however is AR5416 silicon revisions have + * changed. The below macros are for what is contained in the + * lower four bits; if the lower three bits are taken into account + * the revisions become 1.0 => 0x0, 2.0 => 0x1, 2.2 => 0x2. + */ + +/* These are the legacy revisions, with a four bit AR_SREV_REVISION mask */ +#define AR_SREV_REVISION_OWL_10 0x08 +#define AR_SREV_REVISION_OWL_20 0x09 +#define AR_SREV_REVISION_OWL_22 0x0a + +#define AR_RAD5133_SREV_MAJOR 0xc0 /* Fowl: 2+5G/3x3 */ +#define AR_RAD2133_SREV_MAJOR 0xd0 /* Fowl: 2G/3x3 */ +#define AR_RAD5122_SREV_MAJOR 0xe0 /* Fowl: 5G/2x2 */ +#define AR_RAD2122_SREV_MAJOR 0xf0 /* Fowl: 2+5G/2x2 */ + +/* Test macro for owl 1.0 */ +#define IS_5416V1(_ah) (AR_SREV_OWL((_ah)) && AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_OWL_10) +#define IS_5416V2(_ah) (AR_SREV_OWL((_ah)) && AH_PRIVATE((_ah))->ah_macRev >= AR_SREV_REVISION_OWL_20) +#define IS_5416V2_2(_ah) (AR_SREV_OWL((_ah)) && AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_OWL_22) + +/* Misc; compatibility with Atheros HAL */ +#define AR_SREV_5416_V20_OR_LATER(_ah) (AR_SREV_HOWL((_ah)) || AR_SREV_OWL_20_OR_LATER(_ah)) +#define AR_SREV_5416_V22_OR_LATER(_ah) (AR_SREV_HOWL((_ah)) || AR_SREV_OWL_22_OR_LATER(_ah)) + +/* Expanded Mac Silicon Rev (16 bits starting with Sowl) */ +#define AR_XSREV_ID 0xFFFFFFFF /* Chip ID */ +#define AR_XSREV_ID_S 0 +#define AR_XSREV_VERSION 0xFFFC0000 /* Chip version */ +#define AR_XSREV_VERSION_S 18 +#define AR_XSREV_TYPE 0x0003F000 /* Chip type */ +#define AR_XSREV_TYPE_S 12 +#define AR_XSREV_TYPE_CHAIN 0x00001000 /* Chain Mode (1:3 chains, + * 0:2 chains) */ +#define AR_XSREV_TYPE_HOST_MODE 0x00002000 /* Host Mode (1:PCI, 0:PCIe) */ +#define AR_XSREV_REVISION 0x00000F00 +#define AR_XSREV_REVISION_S 8 + +#define AR_XSREV_VERSION_OWL_PCI 0x0D +#define AR_XSREV_VERSION_OWL_PCIE 0x0C + + +/* + * These are from ath9k/Atheros and assume an AR_SREV version mask + * of 0x07, rather than 0x0F which is being used in the FreeBSD HAL. + * Thus, don't use these values as they're incorrect here; use + * AR_SREV_REVISION_OWL_{10,20,22}. + */ +#if 0 +#define AR_XSREV_REVISION_OWL_10 0 /* Owl 1.0 */ +#define AR_XSREV_REVISION_OWL_20 1 /* Owl 2.0/2.1 */ +#define AR_XSREV_REVISION_OWL_22 2 /* Owl 2.2 */ +#endif + +#define AR_XSREV_VERSION_HOWL 0x14 /* Howl (AR9130) */ +#define AR_XSREV_VERSION_SOWL 0x40 /* Sowl (AR9160) */ +#define AR_XSREV_REVISION_SOWL_10 0 /* Sowl 1.0 */ +#define AR_XSREV_REVISION_SOWL_11 1 /* Sowl 1.1 */ +#define AR_XSREV_VERSION_MERLIN 0x80 /* Merlin Version */ +#define AR_XSREV_REVISION_MERLIN_10 0 /* Merlin 1.0 */ +#define AR_XSREV_REVISION_MERLIN_20 1 /* Merlin 2.0 */ +#define AR_XSREV_REVISION_MERLIN_21 2 /* Merlin 2.1 */ +#define AR_XSREV_VERSION_KITE 0xC0 /* Kite Version */ +#define AR_XSREV_REVISION_KITE_10 0 /* Kite 1.0 */ +#define AR_XSREV_REVISION_KITE_11 1 /* Kite 1.1 */ +#define AR_XSREV_REVISION_KITE_12 2 /* Kite 1.2 */ +#define AR_XSREV_VERSION_KIWI 0x180 /* Kiwi (AR9287) */ +#define AR_XSREV_REVISION_KIWI_10 0 /* Kiwi 1.0 */ +#define AR_XSREV_REVISION_KIWI_11 1 /* Kiwi 1.1 */ +#define AR_XSREV_REVISION_KIWI_12 2 /* Kiwi 1.2 */ +#define AR_XSREV_REVISION_KIWI_13 3 /* Kiwi 1.3 */ + +/* Owl (AR5416) */ +#define AR_SREV_OWL(_ah) \ + ((AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) || \ + (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE)) + +#define AR_SREV_OWL_20_OR_LATER(_ah) \ + ((AR_SREV_OWL(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_SREV_REVISION_OWL_20) || \ + AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_HOWL) + +#define AR_SREV_OWL_22_OR_LATER(_ah) \ + ((AR_SREV_OWL(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_SREV_REVISION_OWL_22) || \ + AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_HOWL) + +/* Howl (AR9130) */ + +#define AR_SREV_HOWL(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_HOWL) + +#define AR_SREV_9100(_ah) AR_SREV_HOWL(_ah) + +/* Sowl (AR9160) */ + +#define AR_SREV_SOWL(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_SOWL) + +#define AR_SREV_SOWL_10_OR_LATER(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL) + +#define AR_SREV_SOWL_11(_ah) \ + (AR_SREV_SOWL(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_SOWL_11) + +/* Merlin (AR9280) */ + +#define AR_SREV_MERLIN(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_MERLIN) + +#define AR_SREV_MERLIN_10_OR_LATER(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_MERLIN) + +#define AR_SREV_MERLIN_20(_ah) \ + (AR_SREV_MERLIN(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_MERLIN_20) + +#define AR_SREV_MERLIN_20_OR_LATER(_ah) \ + ((AH_PRIVATE((_ah))->ah_macVersion > AR_XSREV_VERSION_MERLIN) || \ + (AR_SREV_MERLIN((_ah)) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_MERLIN_20)) + +/* Kite (AR9285) */ + +#define AR_SREV_KITE(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_KITE) + +#define AR_SREV_KITE_10_OR_LATER(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_KITE) + +#define AR_SREV_KITE_11(_ah) \ + (AR_SREV_KITE(ah) && \ + AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_KITE_11) + +#define AR_SREV_KITE_11_OR_LATER(_ah) \ + ((AH_PRIVATE((_ah))->ah_macVersion > AR_XSREV_VERSION_KITE) || \ + (AR_SREV_KITE((_ah)) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KITE_11)) + +#define AR_SREV_KITE_12(_ah) \ + (AR_SREV_KITE(ah) && \ + AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_KITE_12) + +#define AR_SREV_KITE_12_OR_LATER(_ah) \ + ((AH_PRIVATE((_ah))->ah_macVersion > AR_XSREV_VERSION_KITE) || \ + (AR_SREV_KITE((_ah)) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KITE_12)) + +#define AR_SREV_9285E_20(_ah) \ + (AR_SREV_KITE_12_OR_LATER(_ah) && \ + ((OS_REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) + +#define AR_SREV_KIWI(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_KIWI) + +#define AR_SREV_KIWI_10_OR_LATER(_ah) \ + (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_KIWI) + +/* XXX TODO: make these handle macVersion > Kiwi */ +#define AR_SREV_KIWI_11_OR_LATER(_ah) \ + (AR_SREV_KIWI(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KIWI_11) + +#define AR_SREV_KIWI_11(_ah) \ + (AR_SREV_KIWI(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_KIWI_11) + +#define AR_SREV_KIWI_12(_ah) \ + (AR_SREV_KIWI(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_KIWI_12) + +#define AR_SREV_KIWI_12_OR_LATER(_ah) \ + (AR_SREV_KIWI(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KIWI_12) + +#define AR_SREV_KIWI_13_OR_LATER(_ah) \ + (AR_SREV_KIWI(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KIWI_13) + + +/* Not yet implemented chips */ +#define AR_SREV_9271(_ah) 0 + +#endif /* _DEV_ATH_AR5416REG_H */ diff --git a/sys/external/isc/atheros_hal/dist/ar9001/ar9130.ini b/sys/external/isc/atheros_hal/dist/ar9001/ar9130.ini new file mode 100644 index 0000000..0bd9f8e --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9001/ar9130.ini @@ -0,0 +1,669 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +static const uint32_t ar5416Modes_9100[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, + { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, + { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, + { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2 }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, + { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, + { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 }, + { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, + { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e }, + { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff }, + { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, + { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, + { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, + { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, + { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 }, + { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, + { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, + { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, + { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, + { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, + { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, + { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, + { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, + { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const uint32_t ar5416Common_9100[][2] = { + /* Addr allmodes */ + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00020010, 0x00000003 }, + { 0x00020038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00004000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0x00000000 }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00000000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a01ae }, + { 0x0000984c, 0x1284233c }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x05100000 }, + { 0x0000a920, 0x05100000 }, + { 0x0000b920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280b212 }, + { 0x0000994c, 0x00020028 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x0000c968, 0x000003ce }, + { 0x00009970, 0x190fb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f0000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000200 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099fc, 0x00001042 }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, + { 0x0000a210, 0x40806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x001a0bb5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000e000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000001 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000c26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa33 }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, +}; + +static const uint32_t ar5416Bank0_9100[][2] = { + /* Addr allmodes */ + { 0x000098b0, 0x1e5795e5 }, + { 0x000098e0, 0x02008020 }, +}; + +static const uint32_t ar5416BB_RfGain_9100[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000141 }, + { 0x00009a10, 0x000001e1, 0x00000181 }, + { 0x00009a14, 0x00000021, 0x000001c1 }, + { 0x00009a18, 0x00000061, 0x00000001 }, + { 0x00009a1c, 0x00000168, 0x00000041 }, + { 0x00009a20, 0x000001a8, 0x000001a8 }, + { 0x00009a24, 0x000001e8, 0x000001e8 }, + { 0x00009a28, 0x00000028, 0x00000028 }, + { 0x00009a2c, 0x00000068, 0x00000068 }, + { 0x00009a30, 0x00000189, 0x000000a8 }, + { 0x00009a34, 0x000001c9, 0x00000169 }, + { 0x00009a38, 0x00000009, 0x000001a9 }, + { 0x00009a3c, 0x00000049, 0x000001e9 }, + { 0x00009a40, 0x00000089, 0x00000029 }, + { 0x00009a44, 0x00000170, 0x00000069 }, + { 0x00009a48, 0x000001b0, 0x00000190 }, + { 0x00009a4c, 0x000001f0, 0x000001d0 }, + { 0x00009a50, 0x00000030, 0x00000010 }, + { 0x00009a54, 0x00000070, 0x00000050 }, + { 0x00009a58, 0x00000191, 0x00000090 }, + { 0x00009a5c, 0x000001d1, 0x00000151 }, + { 0x00009a60, 0x00000011, 0x00000191 }, + { 0x00009a64, 0x00000051, 0x000001d1 }, + { 0x00009a68, 0x00000091, 0x00000011 }, + { 0x00009a6c, 0x000001b8, 0x00000051 }, + { 0x00009a70, 0x000001f8, 0x00000198 }, + { 0x00009a74, 0x00000038, 0x000001d8 }, + { 0x00009a78, 0x00000078, 0x00000018 }, + { 0x00009a7c, 0x00000199, 0x00000058 }, + { 0x00009a80, 0x000001d9, 0x00000098 }, + { 0x00009a84, 0x00000019, 0x00000159 }, + { 0x00009a88, 0x00000059, 0x00000199 }, + { 0x00009a8c, 0x00000099, 0x000001d9 }, + { 0x00009a90, 0x000000d9, 0x00000019 }, + { 0x00009a94, 0x000000f9, 0x00000059 }, + { 0x00009a98, 0x000000f9, 0x00000099 }, + { 0x00009a9c, 0x000000f9, 0x000000d9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const uint32_t ar5416Bank1_9100[][2] = { + /* Addr allmodes */ + { 0x000098b0, 0x02108421 }, + { 0x000098ec, 0x00000008 }, +}; + +static const uint32_t ar5416Bank2_9100[][2] = { + /* Addr allmodes */ + { 0x000098b0, 0x0e73ff17 }, + { 0x000098e0, 0x00000420 }, +}; + +static const uint32_t ar5416Bank3_9100[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +static const uint32_t ar5416Bank6_9100[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x004210a2, 0x004210a2 }, + { 0x0000989c, 0x0014000f, 0x0014000f }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x000180d6, 0x000180d6 }, + { 0x0000989c, 0x0000c0aa, 0x0000c0aa }, + { 0x0000989c, 0x000000b1, 0x000000b1 }, + { 0x0000989c, 0x00002000, 0x00002000 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const uint32_t ar5416Bank6TPC_9100[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x00423022, 0x00423022 }, + { 0x0000989c, 0x2014008f, 0x2014008f }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000e1, 0x000000e1 }, + { 0x0000989c, 0x00007080, 0x00007080 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const uint32_t ar5416Bank7_9100[][2] = { + /* Addr allmodes */ + { 0x0000989c, 0x00000500 }, + { 0x0000989c, 0x00000800 }, + { 0x000098cc, 0x0000000e }, +}; + +static const uint32_t ar5416Addac_9100[][2] = { + /* Addr allmodes */ + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000010 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x000000c0 }, + { 0x0000989c, 0x00000015 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x0000989c, 0x00000000 }, + { 0x000098cc, 0x00000000 }, +}; diff --git a/sys/external/isc/atheros_hal/dist/ar9001/ar9130_attach.c b/sys/external/isc/atheros_hal/dist/ar9001/ar9130_attach.c new file mode 100644 index 0000000..c270bab --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9001/ar9130_attach.c @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ar9001/ar9130reg.h" +#include "ar9001/ar9130_phy.h" +#include "ar9001/ar9130_eeprom.h" + +#include "ar9001/ar9130.ini" + +static const HAL_PERCAL_DATA ar9130_iq_cal = { /* multi sample */ + .calName = "IQ", .calType = IQ_MISMATCH_CAL, + .calNumSamples = MAX_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416IQCalCollect, + .calPostProc = ar5416IQCalibration +}; +static const HAL_PERCAL_DATA ar9130_adc_gain_cal = { /* multi sample */ + .calName = "ADC Gain", .calType = ADC_GAIN_CAL, + .calNumSamples = MAX_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcGainCalCollect, + .calPostProc = ar5416AdcGainCalibration +}; +static const HAL_PERCAL_DATA ar9130_adc_dc_cal = { /* multi sample */ + .calName = "ADC DC", .calType = ADC_DC_CAL, + .calNumSamples = MAX_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; +static const HAL_PERCAL_DATA ar9130_adc_init_dc_cal = { + .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = INIT_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; + +static HAL_BOOL ar9130FillCapabilityInfo(struct ath_hal *ah); + +/* + * Attach for an AR9130 part. + */ +static struct ath_hal * +ar9130Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_OPS_CONFIG *ah_config, + HAL_STATUS *status) +{ + struct ath_hal_5416 *ahp5416; + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + uint32_t val; + HAL_STATUS ecode; + HAL_BOOL rfStatus; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416)); + if (ahp5416 == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ar5416InitState(ahp5416, devid, sc, st, sh, status); + ahp = &ahp5416->ah_5212; + ah = &ahp->ah_priv.h; + + /* XXX override with 9100 specific state */ + AH5416(ah)->ah_initPLL = ar9130InitPLL; + /* XXX should force chainmasks to 0x7, as per ath9k calibration bugs */ + + /* override 5416 methods for our needs */ + + AH5416(ah)->ah_cal.iqCalData.calData = &ar9130_iq_cal; + AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9130_adc_gain_cal; + AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9130_adc_dc_cal; + AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9130_adc_init_dc_cal; + AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; + + /* + * This was hard-set because the initial ath9k port of this + * code kept their runtime conditional register #defines. + * AR_SREV and the RTC registers have shifted for Howl; + * they detected this and changed the values at runtime. + * The current port doesn't yet do this; it may do at a + * later stage, so this is set early so any routines which + * manipulate the registers have ah_macVersion set to base + * the above decision upon. + */ + AH_PRIVATE((ah))->ah_macVersion = AR_XSREV_VERSION_HOWL; + + /* + * Use the "local" EEPROM data given to us by the higher layers. + * This is a private copy out of system flash. + * By this stage the SoC SPI flash may have disabled the memory- + * mapping and rely purely on port-based SPI IO. + */ + AH_PRIVATE((ah))->ah_eepromRead = ath_hal_EepromDataRead; + AH_PRIVATE((ah))->ah_eepromWrite = NULL; + ah->ah_eepromdata = eepromdata; + + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { + /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + /* Read Revisions from Chips before taking out of reset */ + val = OS_REG_READ(ah, AR_SREV_CHIP_HOWL) & AR_SREV_CHIP_HOWL_ID; + + /* XXX are these values even valid for the mac/radio revision? -adrian */ + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", + __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), + MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); + AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); + AH_PRIVATE(ah)->ah_ispcie = 0; + + /* setup common ini data; rf backends handle remainder */ + HAL_INI_INIT(&ahp->ah_ini_modes, ar5416Modes_9100, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar5416Common_9100, 2); + + HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar5416BB_RfGain_9100, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar5416Bank0_9100, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar5416Bank1_9100, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar5416Bank2_9100, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar5416Bank3_9100, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar5416Bank6TPC_9100, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar5416Bank7_9100, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar5416Addac_9100, 2); + + ecode = ath_hal_v14EepromAttach(ah); + if (ecode != HAL_OK) + goto bad; + + if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + ecode = HAL_EIO; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); + switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { + case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ + case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ + break; + default: + if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5133_SREV_MAJOR; + break; + } +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; +#endif + } + rfStatus = ar2133RfAttach(ah, &ecode); + if (!rfStatus) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar9130FillCapabilityInfo(ah)) { + ecode = HAL_EEREAD; + goto bad; + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + /* XXX How about the serial number ? */ + /* Read Reg Domain */ + AH_PRIVATE(ah)->ah_currentRD = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + AH_PRIVATE(ah)->ah_currentRDext = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL); + + + /* + * ah_miscMode is populated by ar5416FillCapabilityInfo() + * starting from griffin. Set here to make sure that + * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is + * placed into hardware. + */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); + + /* XXX no ANI for AR9130 */ + AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ; + AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ; + AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ; + AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ; + AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ; + AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; + + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +bad: + if (ahp) + ar5416Detach((struct ath_hal *) ahp); + if (status) + *status = ecode; + return AH_NULL; +} + +/* + * Fill all software cached or static hardware state information. + * Return failure if capabilities are to come from EEPROM and + * cannot be read. + */ +static HAL_BOOL +ar9130FillCapabilityInfo(struct ath_hal *ah) +{ + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: begin\n", __func__); + if (!ar5416FillCapabilityInfo(ah)) + return AH_FALSE; + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: fill'ed; now setting\n", __func__); + pCap->halCSTSupport = AH_TRUE; + pCap->halRifsRxSupport = AH_TRUE; + pCap->halRifsTxSupport = AH_TRUE; + pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ + pCap->halExtChanDfsSupport = AH_TRUE; + pCap->halUseCombinedRadarRssi = AH_TRUE; + pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ + /* + * MBSSID aggregation is broken in Howl v1.1, v1.2, v1.3 + * and works fine in v1.4. + * XXX todo, enable it for v1.4. + */ + pCap->halMbssidAggrSupport = AH_FALSE; + pCap->hal4AddrAggrSupport = AH_TRUE; + /* BB Read WAR */ + pCap->halHasBBReadWar = AH_TRUE; + + /* + * Implement the PLL/config changes needed for half/quarter + * rates before re-enabling them here. + */ + pCap->halChanHalfRate = AH_FALSE; + pCap->halChanQuarterRate = AH_FALSE; + + return AH_TRUE; +} + +static const char* +ar9130Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID && devid == AR5416_AR9130_DEVID) + return "Atheros 9130"; + return AH_NULL; +} +AH_CHIP(AR9130, ar9130Probe, ar9130Attach); diff --git a/sys/external/isc/atheros_hal/dist/ar9001/ar9130_eeprom.c b/sys/external/isc/atheros_hal/dist/ar9001/ar9130_eeprom.c new file mode 100644 index 0000000..81bd0fe --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9001/ar9130_eeprom.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ diff --git a/sys/external/isc/atheros_hal/dist/ar9001/ar9130_eeprom.h b/sys/external/isc/atheros_hal/dist/ar9001/ar9130_eeprom.h new file mode 100644 index 0000000..5d1013b --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9001/ar9130_eeprom.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2010 Adrian Chadd, Xenion Pty Ltd + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef __AR9130_EEPROM_H__ +#define __AR9130_EEPROM_H__ + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ar9001/ar9130_phy.c b/sys/external/isc/atheros_hal/dist/ar9001/ar9130_phy.c new file mode 100644 index 0000000..a71fdfa --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9001/ar9130_phy.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9001/ar9130_phy.h" + +void +ar9130InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + + uint32_t pll; + + /* + * XXX TODO: support half/quarter rates + */ + if (chan && IEEE80211_IS_CHAN_5GHZ(chan)) + pll = 0x1450; + else + pll = 0x1458; + + OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); + OS_DELAY(RTC_PLL_SETTLE_DELAY); + OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK); +} diff --git a/sys/external/isc/atheros_hal/dist/ar9001/ar9130_phy.h b/sys/external/isc/atheros_hal/dist/ar9001/ar9130_phy.h new file mode 100644 index 0000000..516df92 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9001/ar9130_phy.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2010 Adrian Chadd, Xenion Pty Ltd + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef __AR9130_PHY_H__ +#define __AR9130_PHY_H__ + +extern void ar9130InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan); + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ar9001/ar9130reg.h b/sys/external/isc/atheros_hal/dist/ar9001/ar9130reg.h new file mode 100644 index 0000000..c289c32 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9001/ar9130reg.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2010 Adrian Chadd, Xenion Pty Ltd + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef __AR9130REG_H__ +#define __AR9130REG_H__ + +/* AR9130 shifts these registers */ +#define AR_SREV_CHIP_HOWL 0x0600 +#define AR_SREV_CHIP_HOWL_ID 0x00000FFF + +#endif /* __AR9130REG_H__ */ diff --git a/sys/external/isc/atheros_hal/dist/ar9001/ar9160.ini b/sys/external/isc/atheros_hal/dist/ar9001/ar9160.ini new file mode 100644 index 0000000..963b000 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9001/ar9160.ini @@ -0,0 +1,717 @@ +/* + * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2009 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +/* Auto Generated PCI Register Writes. Created: 05/22/08 */ + +static const uint32_t ar9160Modes[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, + { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, + { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, + { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, + { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, + { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, + { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, + { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, + { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, + { 0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, + { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, + { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, + { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, + { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, + { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, + { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, + { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, + { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, + { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, + { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const uint32_t ar9160Common[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00007010, 0x00000020 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00ff0000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a01ae }, + { 0x0000984c, 0x1284233c }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x05100000 }, + { 0x0000a920, 0x05100000 }, + { 0x0000b920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280b212 }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x2108ecff }, + { 0x00009940, 0x00750604 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x00009970, 0x190fb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f0000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000200 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, /* XXX adrian's addition: AR_PHY_CALMODE == 0 */ + { 0x000099fc, 0x00001042 }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, + { 0x0000a210, 0x40806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x001a0bb5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000e000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000001 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000c26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79bfaa03 }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, +}; + +static const uint32_t ar9160Bank0[][2] = { + { 0x000098b0, 0x1e5795e5 }, + { 0x000098e0, 0x02008020 }, +}; + +static const uint32_t ar9160BB_RfGain[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000141 }, + { 0x00009a10, 0x000001e1, 0x00000181 }, + { 0x00009a14, 0x00000021, 0x000001c1 }, + { 0x00009a18, 0x00000061, 0x00000001 }, + { 0x00009a1c, 0x00000168, 0x00000041 }, + { 0x00009a20, 0x000001a8, 0x000001a8 }, + { 0x00009a24, 0x000001e8, 0x000001e8 }, + { 0x00009a28, 0x00000028, 0x00000028 }, + { 0x00009a2c, 0x00000068, 0x00000068 }, + { 0x00009a30, 0x00000189, 0x000000a8 }, + { 0x00009a34, 0x000001c9, 0x00000169 }, + { 0x00009a38, 0x00000009, 0x000001a9 }, + { 0x00009a3c, 0x00000049, 0x000001e9 }, + { 0x00009a40, 0x00000089, 0x00000029 }, + { 0x00009a44, 0x00000170, 0x00000069 }, + { 0x00009a48, 0x000001b0, 0x00000190 }, + { 0x00009a4c, 0x000001f0, 0x000001d0 }, + { 0x00009a50, 0x00000030, 0x00000010 }, + { 0x00009a54, 0x00000070, 0x00000050 }, + { 0x00009a58, 0x00000191, 0x00000090 }, + { 0x00009a5c, 0x000001d1, 0x00000151 }, + { 0x00009a60, 0x00000011, 0x00000191 }, + { 0x00009a64, 0x00000051, 0x000001d1 }, + { 0x00009a68, 0x00000091, 0x00000011 }, + { 0x00009a6c, 0x000001b8, 0x00000051 }, + { 0x00009a70, 0x000001f8, 0x00000198 }, + { 0x00009a74, 0x00000038, 0x000001d8 }, + { 0x00009a78, 0x00000078, 0x00000018 }, + { 0x00009a7c, 0x00000199, 0x00000058 }, + { 0x00009a80, 0x000001d9, 0x00000098 }, + { 0x00009a84, 0x00000019, 0x00000159 }, + { 0x00009a88, 0x00000059, 0x00000199 }, + { 0x00009a8c, 0x00000099, 0x000001d9 }, + { 0x00009a90, 0x000000d9, 0x00000019 }, + { 0x00009a94, 0x000000f9, 0x00000059 }, + { 0x00009a98, 0x000000f9, 0x00000099 }, + { 0x00009a9c, 0x000000f9, 0x000000d9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const uint32_t ar9160Bank1[][2] = { + { 0x000098b0, 0x02108421 }, + { 0x000098ec, 0x00000008 }, +}; + +static const uint32_t ar9160Bank2[][2] = { + { 0x000098b0, 0x0e73ff17 }, + { 0x000098e0, 0x00000420 }, +}; + +static const uint32_t ar9160Bank3[][3] = { + { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +static const uint32_t ar9160Bank6[][3] = { +/* Reg A G */ + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x004210a2, 0x004210a2 }, + { 0x0000989c, 0x0014008f, 0x0014008f }, + { 0x0000989c, 0x00c40003, 0x00c40003 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000f1, 0x000000f1 }, + { 0x0000989c, 0x00002081, 0x00002081 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const uint32_t ar9160Bank6TPC[][3] = { + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x00423022, 0x00423022 }, + { 0x0000989c, 0x2014008f, 0x2014008f }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000e1, 0x000000e1 }, + { 0x0000989c, 0x00007080, 0x00007080 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const uint32_t ar9160Bank7[][2] = { + { 0x0000989c, 0x00000500 }, + { 0x0000989c, 0x00000800 }, + { 0x000098cc, 0x0000000e }, +}; + +/* Auto generated PCI Register Writes for SOWL1.0 ADDAC Shift Chain */ +static const uint32_t ar9160Addac[][2] = { + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000018 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000019 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000003 }, + {0x0000989c, 0x00000008 }, + {0x0000989c, 0x00000000 }, + {0x000098cc, 0x00000000 }, +}; + +/* Auto generated PCI Register Writes for SOWL1.1 ADDAC Shift Chain */ +static const uint32_t ar9160Addac_1_1[][2] = { + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000018 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000019 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x000098cc, 0x00000000 }, +}; + +/* hand-crafted from code that does explicit register writes */ +static const uint32_t ar9160PciePhy[][2] = { + { AR_PCIE_SERDES, 0x9248fc00 }, + { AR_PCIE_SERDES, 0x24924924 }, + { AR_PCIE_SERDES, 0x28000039 }, + { AR_PCIE_SERDES, 0x53160824 }, + { AR_PCIE_SERDES, 0xe5980579 }, + { AR_PCIE_SERDES, 0x001defff }, + { AR_PCIE_SERDES, 0x1aaabe40 }, + { AR_PCIE_SERDES, 0xbe105554 }, + { AR_PCIE_SERDES, 0x000e3007 }, + { AR_PCIE_SERDES2, 0x00000000 }, +}; diff --git a/sys/external/isc/atheros_hal/dist/ar9001/ar9160_attach.c b/sys/external/isc/atheros_hal/dist/ar9001/ar9160_attach.c new file mode 100644 index 0000000..5bda519 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9001/ar9160_attach.c @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2008 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ar9001/ar9160.ini" + +static const HAL_PERCAL_DATA ar9160_iq_cal = { /* multi sample */ + .calName = "IQ", .calType = IQ_MISMATCH_CAL, + .calNumSamples = MAX_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416IQCalCollect, + .calPostProc = ar5416IQCalibration +}; +static const HAL_PERCAL_DATA ar9160_adc_gain_cal = { /* multi sample */ + .calName = "ADC Gain", .calType = ADC_GAIN_CAL, + .calNumSamples = MAX_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcGainCalCollect, + .calPostProc = ar5416AdcGainCalibration +}; +static const HAL_PERCAL_DATA ar9160_adc_dc_cal = { /* multi sample */ + .calName = "ADC DC", .calType = ADC_DC_CAL, + .calNumSamples = MAX_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; +static const HAL_PERCAL_DATA ar9160_adc_init_dc_cal = { + .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = INIT_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; + +static HAL_BOOL ar9160FillCapabilityInfo(struct ath_hal *ah); + +static void +ar9160AniSetup(struct ath_hal *ah) +{ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -55, -55, -55, -55, -62 }, + .coarseHigh = { -14, -14, -14, -14, -12 }, + .coarseLow = { -64, -64, -64, -64, -70 }, + .firpwr = { -78, -78, -78, -78, -80 }, + .maxSpurImmunityLevel = 7, + .cycPwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + + /* NB: disable ANI noise immmunity for reliable RIFS rx */ + AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL); + ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE); +} + +static void +ar9160InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV); + if (chan != AH_NULL) { + if (IEEE80211_IS_CHAN_HALF(chan)) + pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL); + else if (IEEE80211_IS_CHAN_QUARTER(chan)) + pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL); + + if (IEEE80211_IS_CHAN_5GHZ(chan)) + pll |= SM(0x50, AR_RTC_SOWL_PLL_DIV); + else + pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV); + } else + pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV); + + OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); + OS_DELAY(RTC_PLL_SETTLE_DELAY); + OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK); +} + +/* + * Attach for an AR9160 part. + */ +static struct ath_hal * +ar9160Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_OPS_CONFIG *ah_config, + HAL_STATUS *status) +{ + struct ath_hal_5416 *ahp5416; + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + uint32_t val; + HAL_STATUS ecode; + HAL_BOOL rfStatus; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416)); + if (ahp5416 == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ar5416InitState(ahp5416, devid, sc, st, sh, status); + ahp = &ahp5416->ah_5212; + ah = &ahp->ah_priv.h; + + /* XXX override with 9160 specific state */ + /* override 5416 methods for our needs */ + AH5416(ah)->ah_initPLL = ar9160InitPLL; + + AH5416(ah)->ah_cal.iqCalData.calData = &ar9160_iq_cal; + AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9160_adc_gain_cal; + AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9160_adc_dc_cal; + AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9160_adc_init_dc_cal; + AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; + + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { + /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + /* Read Revisions from Chips before taking out of reset */ + val = OS_REG_READ(ah, AR_SREV); + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", + __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), + MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); + /* NB: include chip type to differentiate from pre-Sowl versions */ + AH_PRIVATE(ah)->ah_macVersion = + (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S; + AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); + AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0; + + /* setup common ini data; rf backends handle remainder */ + HAL_INI_INIT(&ahp->ah_ini_modes, ar9160Modes, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar9160Common, 2); + + HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar9160BB_RfGain, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar9160Bank0, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar9160Bank1, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar9160Bank2, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar9160Bank3, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar9160Bank6TPC, 3); + HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar9160Bank7, 2); + if (AR_SREV_SOWL_11(ah)) + HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar9160Addac_1_1, 2); + else + HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar9160Addac, 2); + + ecode = ath_hal_v14EepromAttach(ah); + if (ecode != HAL_OK) + goto bad; + + HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, ar9160PciePhy, 2); + ar5416AttachPCIE(ah); + + if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + ecode = HAL_EIO; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); + switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { + case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ + case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ + break; + default: + if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5133_SREV_MAJOR; + break; + } +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; +#endif + } + rfStatus = ar2133RfAttach(ah, &ecode); + if (!rfStatus) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar9160FillCapabilityInfo(ah)) { + ecode = HAL_EEREAD; + goto bad; + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + /* XXX How about the serial number ? */ + /* Read Reg Domain */ + AH_PRIVATE(ah)->ah_currentRD = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + AH_PRIVATE(ah)->ah_currentRDext = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL); + + /* + * ah_miscMode is populated by ar5416FillCapabilityInfo() + * starting from griffin. Set here to make sure that + * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is + * placed into hardware. + */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); + + ar9160AniSetup(ah); /* Anti Noise Immunity */ + + /* This just uses the AR5416 NF values */ + AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ; + AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ; + AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ; + AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ; + AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ; + AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; + + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +bad: + if (ahp) + ar5416Detach((struct ath_hal *) ahp); + if (status) + *status = ecode; + return AH_NULL; +} + +/* + * Fill all software cached or static hardware state information. + * Return failure if capabilities are to come from EEPROM and + * cannot be read. + */ +static HAL_BOOL +ar9160FillCapabilityInfo(struct ath_hal *ah) +{ + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + if (!ar5416FillCapabilityInfo(ah)) + return AH_FALSE; + pCap->halCSTSupport = AH_TRUE; + pCap->halRifsRxSupport = AH_TRUE; + pCap->halRifsTxSupport = AH_TRUE; + pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ + pCap->halExtChanDfsSupport = AH_TRUE; + pCap->halUseCombinedRadarRssi = AH_TRUE; + pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ + pCap->halMbssidAggrSupport = AH_TRUE; + pCap->hal4AddrAggrSupport = AH_TRUE; + /* BB Read WAR */ + pCap->halHasBBReadWar = AH_TRUE; + + /* AR9160 is a 2x2 stream device */ + pCap->halTxStreams = 2; + pCap->halRxStreams = 2; + + return AH_TRUE; +} + +static const char* +ar9160Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID && devid == AR9160_DEVID_PCI) + return "Atheros 9160"; + return AH_NULL; +} +AH_CHIP(AR9160, ar9160Probe, ar9160Attach); diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9002phy.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9002phy.h new file mode 100644 index 0000000..3d837cf --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9002phy.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __ATH_AR9002PHY_H__ +#define __ATH_AR9002PHY_H__ + +#define AR_PHY_TX_PWRCTRL4 0xa264 +#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001 +#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0 +#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE +#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1 + +#define AR_PHY_TX_PWRCTRL6_0 0xa270 +#define AR_PHY_TX_PWRCTRL6_1 0xb270 +#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000 +#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 + +#define AR_PHY_TX_PWRCTRL7 0xa274 +#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 +#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 + +#define AR_PHY_TX_PWRCTRL8 0xa278 +#define AR_PHY_TX_PWRCTRL10 0xa394 + +#define AR_PHY_TX_GAIN_TBL1 0xa300 +#define AR_PHY_TX_GAIN 0x0007F000 +#define AR_PHY_TX_GAIN_S 12 + +#define AR_PHY_CH0_TX_PWRCTRL11 0xa398 +#define AR_PHY_CH1_TX_PWRCTRL11 0xb398 +#define AR_PHY_CH0_TX_PWRCTRL12 0xa3dc +#define AR_PHY_CH0_TX_PWRCTRL13 0xa3e0 + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9280.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9280.c new file mode 100644 index 0000000..c9aabf0 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9280.c @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +/* + * NB: Merlin and later have a simpler RF backend. + */ +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v14.h" + +#include "ar9002/ar9280.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar9280State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[1]; /* XXX */ +}; +#define AR9280(ah) ((struct ar9280State *) AH5212(ah)->ah_rfHal) + +static HAL_BOOL ar9280GetChannelMaxMinPower(struct ath_hal *, + const struct ieee80211_channel *, int16_t *maxPow,int16_t *minPow); +int16_t ar9280GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c); + +static void +ar9280WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + (void) ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_bb_rfgain, + freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + * + * Actual Expression, + * + * For 2GHz channel, + * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) + * (freq_ref = 40MHz) + * + * For 5GHz channel, + * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) + * (freq_ref = 40MHz/(24>>amodeRefSel)) + * + * For 5GHz channels which are 5MHz spaced, + * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) + * (freq_ref = 40MHz) + */ +static HAL_BOOL +ar9280SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint16_t bMode, fracMode, aModeRefSel = 0; + uint32_t freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; + CHAN_CENTERS centers; + uint32_t refDivA = 24; + uint8_t frac_n_5g; + + OS_MARK(ah, AH_MARK_SETCHANNEL, chan->ic_freq); + + ar5416GetChannelCenters(ah, chan, ¢ers); + freq = centers.synth_center; + + reg32 = OS_REG_READ(ah, AR_PHY_SYNTH_CONTROL); + reg32 &= 0xc0000000; + + if (ath_hal_eepromGet(ah, AR_EEP_FRAC_N_5G, &frac_n_5g) != HAL_OK) + frac_n_5g = 0; + + if (freq < 4800) { /* 2 GHz, fractional mode */ + uint32_t txctl; + + bMode = 1; + fracMode = 1; + aModeRefSel = 0; + channelSel = (freq * 0x10000)/15; + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else { + bMode = 0; + fracMode = 0; + + switch (frac_n_5g) { + case 0: + /* + * Enable fractional mode for half/quarter rate + * channels. + * + * This is from the Linux ath9k code, rather than + * the Atheros HAL code. + */ + if (IEEE80211_IS_CHAN_QUARTER(chan) || + IEEE80211_IS_CHAN_HALF(chan)) + aModeRefSel = 0; + else if ((freq % 20) == 0) { + aModeRefSel = 3; + } else if ((freq % 10) == 0) { + aModeRefSel = 2; + } + if (aModeRefSel) break; + case 1: + default: + aModeRefSel = 0; + /* Enable 2G (fractional) mode for channels which are 5MHz spaced */ + + /* + * Workaround for talking on PSB non-5MHz channels; + * the pre-Merlin chips only had a 2.5MHz channel + * spacing so some channels aren't reachable. + + * + * This interoperates on the quarter rate channels + * with the AR5112 and later RF synths. Please note + * that the synthesiser isn't able to completely + * accurately represent these frequencies (as the + * resolution in this reference is 2.5MHz) and thus + * it will be slightly "off centre." This matches + * the same slightly incorrect centre frequency + * behaviour that the AR5112 and later channel + * selection code has. + * + * This also interoperates with the AR5416 + * synthesiser modification for programming + * fractional frequencies in 5GHz mode. However + * that modification is also disabled by default. + * + * This is disabled because it hasn't been tested for + * regulatory compliance and neither have the NICs + * which would use it. So if you enable this code, + * you must first ensure that you've re-certified the + * NICs in question beforehand or you will be + * violating your local regulatory rules and breaking + * the law. + */ +#if 0 + if (freq % 5 == 0) { +#endif + /* Normal */ + fracMode = 1; + refDivA = 1; + channelSel = (freq * 0x8000)/15; +#if 0 + } else { + /* Offset by 500KHz */ + uint32_t f, ch, ch2; + + fracMode = 1; + refDivA = 1; + + /* Calculate the "adjusted" frequency */ + f = freq - 2; + ch = (((f - 4800) * 10) / 25) + 1; + + ch2 = ((ch * 25) / 5) + 9600; + channelSel = (ch2 * 0x4000) / 15; + //ath_hal_printf(ah, + // "%s: freq=%d, ch=%d, ch2=%d, " + // "channelSel=%d\n", + // __func__, freq, ch, ch2, channelSel); + } +#endif + + /* RefDivA setting */ + OS_A_REG_RMW_FIELD(ah, AR_AN_SYNTH9, + AR_AN_SYNTH9_REFDIVA, refDivA); + } + + if (!fracMode) { + ndiv = (freq * (refDivA >> aModeRefSel))/60; + channelSel = ndiv & 0x1ff; + channelFrac = (ndiv & 0xfffffe00) * 2; + channelSel = (channelSel << 17) | channelFrac; + } + } + + reg32 = reg32 | (bMode << 29) | (fracMode << 28) | + (aModeRefSel << 26) | (channelSel); + + OS_REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); + + AH_PRIVATE(ah)->ah_curchan = chan; + + return AH_TRUE; +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar9280GetRfBank(struct ath_hal *ah, int bank) +{ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + */ +static HAL_BOOL +ar9280SetRfRegs(struct ath_hal *ah, const struct ieee80211_channel *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ + return AH_TRUE; /* nothing to do */ +} + +/* + * Read the transmit power levels from the structures taken from EEPROM + * Interpolate read transmit power values for this channel + * Organize the transmit power values into a table for writing into the hardware + */ + +static HAL_BOOL +ar9280SetPowerTable(struct ath_hal *ah, int16_t *pPowerMin, int16_t *pPowerMax, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain) +{ + return AH_TRUE; +} + +#if 0 +static int16_t +ar9280GetMinPower(struct ath_hal *ah, EXPN_DATA_PER_CHANNEL_5112 *data) +{ + int i, minIndex; + int16_t minGain,minPwr,minPcdac,retVal; + + /* Assume NUM_POINTS_XPD0 > 0 */ + minGain = data->pDataPerXPD[0].xpd_gain; + for (minIndex=0,i=1; ipDataPerXPD[i].xpd_gain < minGain) { + minIndex = i; + minGain = data->pDataPerXPD[i].xpd_gain; + } + } + minPwr = data->pDataPerXPD[minIndex].pwr_t4[0]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[0]; + for (i=1; ipDataPerXPD[minIndex].pwr_t4[i] < minPwr) { + minPwr = data->pDataPerXPD[minIndex].pwr_t4[i]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[i]; + } + } + retVal = minPwr - (minPcdac*2); + return(retVal); +} +#endif + +static HAL_BOOL +ar9280GetChannelMaxMinPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *maxPow, int16_t *minPow) +{ +#if 0 + struct ath_hal_5212 *ahp = AH5212(ah); + int numChannels=0,i,last; + int totalD, totalF,totalMin; + EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL; + EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL; + + *maxPow = 0; + if (IS_CHAN_A(chan)) { + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11A].pDataPerChannel; + numChannels = powerArray[headerInfo11A].numChannels; + } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) { + /* XXX - is this correct? Should we also use the same power for turbo G? */ + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11G].pDataPerChannel; + numChannels = powerArray[headerInfo11G].numChannels; + } else if (IS_CHAN_B(chan)) { + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11B].pDataPerChannel; + numChannels = powerArray[headerInfo11B].numChannels; + } else { + return (AH_TRUE); + } + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if ((numChannels < 1) || + (chan->channel < data[0].channelValue) || + (chan->channel > data[numChannels-1].channelValue)) + return(AH_FALSE); + + /* Linearly interpolate the power value now */ + for (last=0,i=0; + (ichannel > data[i].channelValue); + last=i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = data[i].maxPower_t4 - data[last].maxPower_t4; + *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD); + + totalMin = ar9280GetMinPower(ah,&data[i]) - ar9280GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar9280GetMinPower(ah, &data[last])*totalD)/totalD); + return (AH_TRUE); + } else { + if (chan->channel == data[i].channelValue) { + *maxPow = data[i].maxPower_t4; + *minPow = ar9280GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +#else + *maxPow = *minPow = 0; + return AH_FALSE; +#endif +} + +/* + * The ordering of nfarray is thus: + * + * nfarray[0]: Chain 0 ctl + * nfarray[1]: Chain 1 ctl + * nfarray[2]: Chain 2 ctl + * nfarray[3]: Chain 0 ext + * nfarray[4]: Chain 1 ext + * nfarray[5]: Chain 2 ext + */ +static void +ar9280GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) +{ + int16_t nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 0] is %d\n", nf); + nfarray[0] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 1] is %d\n", nf); + nfarray[1] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 0] is %d\n", nf); + nfarray[3] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 1] is %d\n", nf); + nfarray[4] = nf; + + /* Chain 2 - invalid */ + nfarray[2] = 0; + nfarray[5] = 0; + +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + * Stubbed:Not used by Fowl + */ +int16_t +ar9280GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + return 0; +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar9280RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +HAL_BOOL +ar9280RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar9280State *priv; + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: attach AR9280 radio\n", __func__); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar9280State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar9280RfDetach; + priv->base.writeRegs = ar9280WriteRegs; + priv->base.getRfBank = ar9280GetRfBank; + priv->base.setChannel = ar9280SetChannel; + priv->base.setRfRegs = ar9280SetRfRegs; + priv->base.setPowerTable = ar9280SetPowerTable; + priv->base.getChannelMaxMinPower = ar9280GetChannelMaxMinPower; + priv->base.getNfAdjust = ar9280GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + /* + * Set noise floor adjust method; we arrange a + * direct call instead of thunking. + */ + AH_PRIVATE(ah)->ah_getNfAdjust = priv->base.getNfAdjust; + AH_PRIVATE(ah)->ah_getNoiseFloor = ar9280GetNoiseFloor; + + return AH_TRUE; +} + +static HAL_BOOL +ar9280RfProbe(struct ath_hal *ah) +{ + return (AR_SREV_MERLIN(ah)); +} + +AH_RF(RF9280, ar9280RfProbe, ar9280RfAttach); diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9280.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9280.h new file mode 100644 index 0000000..e383918 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9280.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AR9280_H_ +#define _ATH_AR9280_H_ + +#include "ar5416/ar5416.h" + +/* + * This is a chip thing, but it's used here as part of the + * ath_hal_9280 struct; so it's convienent to locate the + * define here. + */ +#define AR9280_TX_GAIN_TABLE_SIZE 22 + +struct ath_hal_9280 { + struct ath_hal_5416 ah_5416; + + HAL_INI_ARRAY ah_ini_xmodes; + HAL_INI_ARRAY ah_ini_rxgain; + HAL_INI_ARRAY ah_ini_txgain; + + int PDADCdelta; + + uint32_t originalGain[AR9280_TX_GAIN_TABLE_SIZE]; +}; +#define AH9280(_ah) ((struct ath_hal_9280 *)(_ah)) + +#define AR9280_DEFAULT_RXCHAINMASK 3 +#define AR9285_DEFAULT_RXCHAINMASK 1 +#define AR9280_DEFAULT_TXCHAINMASK 1 +#define AR9285_DEFAULT_TXCHAINMASK 1 + +#define AR_PHY_CCA_NOM_VAL_9280_2GHZ -112 +#define AR_PHY_CCA_NOM_VAL_9280_5GHZ -112 +#define AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ -127 +#define AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ -122 +#define AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ -97 +#define AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ -102 + +HAL_BOOL ar9280RfAttach(struct ath_hal *, HAL_STATUS *); + +struct ath_hal; + +HAL_BOOL ar9280SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); +void ar9280SpurMitigate(struct ath_hal *, + const struct ieee80211_channel *); +void ar9280InitPLL(struct ath_hal *ah, + const struct ieee80211_channel *chan); +#endif /* _ATH_AR9280_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9280_attach.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9280_attach.c new file mode 100644 index 0000000..3be3e35 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9280_attach.c @@ -0,0 +1,976 @@ +/* + * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" /* XXX for tx/rx gain */ + +#include "ar9002/ar9280.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ar9002/ar9280v1.ini" +#include "ar9002/ar9280v2.ini" +#include "ar9002/ar9280_olc.h" + +static const HAL_PERCAL_DATA ar9280_iq_cal = { /* single sample */ + .calName = "IQ", .calType = IQ_MISMATCH_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = PER_MAX_LOG_COUNT, + .calCollect = ar5416IQCalCollect, + .calPostProc = ar5416IQCalibration +}; +static const HAL_PERCAL_DATA ar9280_adc_gain_cal = { /* single sample */ + .calName = "ADC Gain", .calType = ADC_GAIN_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = PER_MAX_LOG_COUNT, + .calCollect = ar5416AdcGainCalCollect, + .calPostProc = ar5416AdcGainCalibration +}; +static const HAL_PERCAL_DATA ar9280_adc_dc_cal = { /* single sample */ + .calName = "ADC DC", .calType = ADC_DC_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = PER_MAX_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; +static const HAL_PERCAL_DATA ar9280_adc_init_dc_cal = { + .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = INIT_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; + +static void ar9280ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, + HAL_BOOL power_off); +static void ar9280DisablePCIE(struct ath_hal *ah); +static HAL_BOOL ar9280FillCapabilityInfo(struct ath_hal *ah); +static void ar9280WriteIni(struct ath_hal *ah, + const struct ieee80211_channel *chan); + +static void +ar9280AniSetup(struct ath_hal *ah) +{ + /* + * These are the parameters from the AR5416 ANI code; + * they likely need quite a bit of adjustment for the + * AR9280. + */ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -55, -55, -55, -55, -62 }, + .coarseHigh = { -14, -14, -14, -14, -12 }, + .coarseLow = { -64, -64, -64, -64, -70 }, + .firpwr = { -78, -78, -78, -78, -80 }, + .maxSpurImmunityLevel = 7, + .cycPwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + /* NB: disable ANI noise immmunity for reliable RIFS rx */ + AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL); + + /* NB: ANI is not enabled yet */ + ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE); +} + +void +ar9280InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint32_t pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV); + + if (AR_SREV_MERLIN_20(ah) && + chan != AH_NULL && IEEE80211_IS_CHAN_5GHZ(chan)) { + /* + * PLL WAR for Merlin 2.0/2.1 + * When doing fast clock, set PLL to 0x142c + * Else, set PLL to 0x2850 to prevent reset-to-reset variation + */ + pll = IS_5GHZ_FAST_CLOCK_EN(ah, chan) ? 0x142c : 0x2850; + if (IEEE80211_IS_CHAN_HALF(chan)) + pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL); + else if (IEEE80211_IS_CHAN_QUARTER(chan)) + pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL); + } else if (AR_SREV_MERLIN_10_OR_LATER(ah)) { + pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV); + if (chan != AH_NULL) { + if (IEEE80211_IS_CHAN_HALF(chan)) + pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL); + else if (IEEE80211_IS_CHAN_QUARTER(chan)) + pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL); + if (IEEE80211_IS_CHAN_5GHZ(chan)) + pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV); + else + pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV); + } else + pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV); + } + + OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); + OS_DELAY(RTC_PLL_SETTLE_DELAY); + OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK); +} + +/* XXX shouldn't be here! */ +#define EEP_MINOR(_ah) \ + (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK) + +/* + * Attach for an AR9280 part. + */ +static struct ath_hal * +ar9280Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_OPS_CONFIG *ah_config, + HAL_STATUS *status) +{ + struct ath_hal_9280 *ahp9280; + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + uint32_t val; + HAL_STATUS ecode; + HAL_BOOL rfStatus; + int8_t pwr_table_offset; + uint8_t pwr; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp9280 = ath_hal_malloc(sizeof (struct ath_hal_9280)); + if (ahp9280 == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ahp = AH5212(ahp9280); + ah = &ahp->ah_priv.h; + + ar5416InitState(AH5416(ah), devid, sc, st, sh, status); + + /* + * Use the "local" EEPROM data given to us by the higher layers. + * This is a private copy out of system flash. The Linux ath9k + * commit for the initial AR9130 support mentions MMIO flash + * access is "unreliable." -adrian + */ + if (eepromdata != AH_NULL) { + AH_PRIVATE((ah))->ah_eepromRead = ath_hal_EepromDataRead; + AH_PRIVATE((ah))->ah_eepromWrite = NULL; + ah->ah_eepromdata = eepromdata; + } + + /* XXX override with 9280 specific state */ + /* override 5416 methods for our needs */ + AH5416(ah)->ah_initPLL = ar9280InitPLL; + + ah->ah_setAntennaSwitch = ar9280SetAntennaSwitch; + ah->ah_configPCIE = ar9280ConfigPCIE; + ah->ah_disablePCIE = ar9280DisablePCIE; + + AH5416(ah)->ah_cal.iqCalData.calData = &ar9280_iq_cal; + AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9280_adc_gain_cal; + AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9280_adc_dc_cal; + AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9280_adc_init_dc_cal; + AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; + + AH5416(ah)->ah_spurMitigate = ar9280SpurMitigate; + AH5416(ah)->ah_writeIni = ar9280WriteIni; + AH5416(ah)->ah_olcInit = ar9280olcInit; + AH5416(ah)->ah_olcTempCompensation = ar9280olcTemperatureCompensation; + AH5416(ah)->ah_setPowerCalTable = ar9280SetPowerCalTable; + + AH5416(ah)->ah_rx_chainmask = AR9280_DEFAULT_RXCHAINMASK; + AH5416(ah)->ah_tx_chainmask = AR9280_DEFAULT_TXCHAINMASK; + + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { + /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + /* Read Revisions from Chips before taking out of reset */ + val = OS_REG_READ(ah, AR_SREV); + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", + __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), + MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); + /* NB: include chip type to differentiate from pre-Sowl versions */ + AH_PRIVATE(ah)->ah_macVersion = + (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S; + AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); + AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0; + + /* setup common ini data; rf backends handle remainder */ + if (AR_SREV_MERLIN_20_OR_LATER(ah)) { + HAL_INI_INIT(&ahp->ah_ini_modes, ar9280Modes_v2, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar9280Common_v2, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, + ar9280PciePhy_clkreq_always_on_L1_v2, 2); + HAL_INI_INIT(&ahp9280->ah_ini_xmodes, + ar9280Modes_fast_clock_v2, 3); + } else { + HAL_INI_INIT(&ahp->ah_ini_modes, ar9280Modes_v1, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar9280Common_v1, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, + ar9280PciePhy_v1, 2); + } + ar5416AttachPCIE(ah); + + ecode = ath_hal_v14EepromAttach(ah); + if (ecode != HAL_OK) + goto bad; + + if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + ecode = HAL_EIO; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); + switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { + case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ + case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ + break; + default: + if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5133_SREV_MAJOR; + break; + } +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; +#endif + } + rfStatus = ar9280RfAttach(ah, &ecode); + if (!rfStatus) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + + /* Enable fixup for AR_AN_TOP2 if necessary */ + /* + * The v14 EEPROM layer returns HAL_EIO if PWDCLKIND isn't supported + * by the EEPROM version. + * + * ath9k checks the EEPROM minor version is >= 0x0a here, instead of + * the abstracted EEPROM access layer. + */ + ecode = ath_hal_eepromGet(ah, AR_EEP_PWDCLKIND, &pwr); + if (AR_SREV_MERLIN_20_OR_LATER(ah) && ecode == HAL_OK && pwr == 0) { + printf("[ath] enabling AN_TOP2_FIXUP\n"); + AH5416(ah)->ah_need_an_top2_fixup = 1; + } + + /* + * Check whether the power table offset isn't the default. + * This can occur with eeprom minor V21 or greater on Merlin. + */ + (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, &pwr_table_offset); + if (pwr_table_offset != AR5416_PWR_TABLE_OFFSET_DB) + ath_hal_printf(ah, "[ath]: default pwr offset: %d dBm != EEPROM pwr offset: %d dBm; curves will be adjusted.\n", + AR5416_PWR_TABLE_OFFSET_DB, (int) pwr_table_offset); + + /* XXX check for >= minor ver 17 */ + if (AR_SREV_MERLIN_20(ah)) { + /* setup rxgain table */ + switch (ath_hal_eepromGet(ah, AR_EEP_RXGAIN_TYPE, AH_NULL)) { + case AR5416_EEP_RXGAIN_13dB_BACKOFF: + HAL_INI_INIT(&ahp9280->ah_ini_rxgain, + ar9280Modes_backoff_13db_rxgain_v2, 6); + break; + case AR5416_EEP_RXGAIN_23dB_BACKOFF: + HAL_INI_INIT(&ahp9280->ah_ini_rxgain, + ar9280Modes_backoff_23db_rxgain_v2, 6); + break; + case AR5416_EEP_RXGAIN_ORIG: + HAL_INI_INIT(&ahp9280->ah_ini_rxgain, + ar9280Modes_original_rxgain_v2, 6); + break; + default: + HALASSERT(AH_FALSE); + goto bad; /* XXX ? try to continue */ + } + } + + /* XXX check for >= minor ver 19 */ + if (AR_SREV_MERLIN_20(ah)) { + /* setp txgain table */ + switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) { + case AR5416_EEP_TXGAIN_HIGH_POWER: + HAL_INI_INIT(&ahp9280->ah_ini_txgain, + ar9280Modes_high_power_tx_gain_v2, 6); + break; + case AR5416_EEP_TXGAIN_ORIG: + HAL_INI_INIT(&ahp9280->ah_ini_txgain, + ar9280Modes_original_tx_gain_v2, 6); + break; + default: + HALASSERT(AH_FALSE); + goto bad; /* XXX ? try to continue */ + } + } + + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar9280FillCapabilityInfo(ah)) { + ecode = HAL_EEREAD; + goto bad; + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + /* XXX How about the serial number ? */ + /* Read Reg Domain */ + AH_PRIVATE(ah)->ah_currentRD = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + AH_PRIVATE(ah)->ah_currentRDext = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL); + + /* + * ah_miscMode is populated by ar5416FillCapabilityInfo() + * starting from griffin. Set here to make sure that + * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is + * placed into hardware. + */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); + + ar9280AniSetup(ah); /* Anti Noise Immunity */ + + /* Setup noise floor min/max/nominal values */ + AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ; + AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ; + AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9280_2GHZ; + AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ; + AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ; + AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9280_5GHZ; + + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +bad: + if (ah != AH_NULL) + ah->ah_detach(ah); + if (status) + *status = ecode; + return AH_NULL; +} + +static void +ar9280ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) +{ + uint32_t val; + + if (AH_PRIVATE(ah)->ah_ispcie && !restore) { + ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0); + OS_DELAY(1000); + } + + + /* + * Set PCIe workaround bits + * + * NOTE: + * + * In Merlin and Kite, bit 14 in WA register (disable L1) should only + * be set when device enters D3 and be cleared when device comes back + * to D0. + */ + if (power_off) { /* Power-off */ + OS_REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + + val = OS_REG_READ(ah, AR_WA); + + /* + * Disable bit 6 and 7 before entering D3 to prevent + * system hang. + */ + val &= ~(AR_WA_BIT6 | AR_WA_BIT7); + + /* + * XXX Not sure, is specified in the reference HAL. + */ + val |= AR_WA_BIT22; + + /* + * See above: set AR_WA_D3_L1_DISABLE when entering D3 state. + * + * XXX The reference HAL does it this way - it only sets + * AR_WA_D3_L1_DISABLE if it's set in AR9280_WA_DEFAULT, + * which it (currently) isn't. So the following statement + * is currently a NOP. + */ + if (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE) + val |= AR_WA_D3_L1_DISABLE; + + OS_REG_WRITE(ah, AR_WA, val); + } else { /* Power-on */ + val = AR9280_WA_DEFAULT; + + /* + * See note above: make sure L1_DISABLE is not set. + */ + val &= (~AR_WA_D3_L1_DISABLE); + OS_REG_WRITE(ah, AR_WA, val); + + /* set bit 19 to allow forcing of pcie core into L1 state */ + OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + } +} + +static void +ar9280DisablePCIE(struct ath_hal *ah) +{ +} + +static void +ar9280WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + u_int modesIndex, freqIndex; + int regWrites = 0; + int i; + const HAL_INI_ARRAY *ia; + + /* Setup the indices for the next set of register array writes */ + /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + freqIndex = 2; + if (IEEE80211_IS_CHAN_HT40(chan)) + modesIndex = 3; + else if (IEEE80211_IS_CHAN_108G(chan)) + modesIndex = 5; + else + modesIndex = 4; + } else { + freqIndex = 1; + if (IEEE80211_IS_CHAN_HT40(chan) || + IEEE80211_IS_CHAN_TURBO(chan)) + modesIndex = 2; + else + modesIndex = 1; + } + + /* Set correct Baseband to analog shift setting to access analog chips. */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); + + /* + * This is unwound because at the moment, there's a requirement + * for Merlin (and later, perhaps) to have a specific bit fixed + * in the AR_AN_TOP2 register before writing it. + */ + ia = &AH5212(ah)->ah_ini_modes; +#if 0 + regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, + modesIndex, regWrites); +#endif + HALASSERT(modesIndex < ia->cols); + for (i = 0; i < ia->rows; i++) { + uint32_t reg = HAL_INI_VAL(ia, i, 0); + uint32_t val = HAL_INI_VAL(ia, i, modesIndex); + + if (reg == AR_AN_TOP2 && AH5416(ah)->ah_need_an_top2_fixup) + val &= ~AR_AN_TOP2_PWDCLKIND; + + OS_REG_WRITE(ah, reg, val); + + /* Analog shift register delay seems needed for Merlin - PR kern/154220 */ + if (reg >= 0x7800 && reg < 0x7900) + OS_DELAY(100); + + DMA_YIELD(regWrites); + } + + if (AR_SREV_MERLIN_20_OR_LATER(ah)) { + regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain, + modesIndex, regWrites); + regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain, + modesIndex, regWrites); + } + /* XXX Merlin 100us delay for shift registers */ + regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, + 1, regWrites); + + if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { + /* 5GHz channels w/ Fast Clock use different modal values */ + regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes, + modesIndex, regWrites); + } +} + +#define AR_BASE_FREQ_2GHZ 2300 +#define AR_BASE_FREQ_5GHZ 4900 +#define AR_SPUR_FEEQ_BOUND_HT40 19 +#define AR_SPUR_FEEQ_BOUND_HT20 10 + +void +ar9280SpurMitigate(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 }; + static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 }; + static int inc[4] = { 0, 100, 0, 0 }; + + int bb_spur = AR_NO_SPUR; + int freq; + int bin, cur_bin; + int bb_spur_off, spur_subchannel_sd; + int spur_freq_sd; + int spur_delta_phase; + int denominator; + int upper, lower, cur_vit_mask; + int tmp, newVal; + int i; + CHAN_CENTERS centers; + + int8_t mask_m[123]; + int8_t mask_p[123]; + int8_t mask_amt; + int tmp_mask; + int cur_bb_spur; + HAL_BOOL is2GHz = IEEE80211_IS_CHAN_2GHZ(chan); + + OS_MEMZERO(&mask_m, sizeof(int8_t) * 123); + OS_MEMZERO(&mask_p, sizeof(int8_t) * 123); + + ar5416GetChannelCenters(ah, chan, ¢ers); + freq = centers.synth_center; + + /* + * Need to verify range +/- 9.38 for static ht20 and +/- 18.75 for ht40, + * otherwise spur is out-of-band and can be ignored. + */ + for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { + cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz); + /* Get actual spur freq in MHz from EEPROM read value */ + if (is2GHz) { + cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; + } else { + cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; + } + + if (AR_NO_SPUR == cur_bb_spur) + break; + cur_bb_spur = cur_bb_spur - freq; + + if (IEEE80211_IS_CHAN_HT40(chan)) { + if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && + (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { + bb_spur = cur_bb_spur; + break; + } + } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && + (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { + bb_spur = cur_bb_spur; + break; + } + } + + if (AR_NO_SPUR == bb_spur) { +#if 1 + /* + * MRC CCK can interfere with beacon detection and cause deaf/mute. + * Disable MRC CCK for now. + */ + OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); +#else + /* Enable MRC CCK if no spur is found in this channel. */ + OS_REG_SET_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); +#endif + return; + } else { + /* + * For Merlin, spur can break CCK MRC algorithm. Disable CCK MRC if spur + * is found in this channel. + */ + OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); + } + + bin = bb_spur * 320; + + tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0)); + + newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | + AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), newVal); + + newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | + AR_PHY_SPUR_REG_ENABLE_MASK_PPM | + AR_PHY_SPUR_REG_MASK_RATE_SELECT | + AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | + SM(AR5416_SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); + OS_REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); + + /* Pick control or extn channel to cancel the spur */ + if (IEEE80211_IS_CHAN_HT40(chan)) { + if (bb_spur < 0) { + spur_subchannel_sd = 1; + bb_spur_off = bb_spur + 10; + } else { + spur_subchannel_sd = 0; + bb_spur_off = bb_spur - 10; + } + } else { + spur_subchannel_sd = 0; + bb_spur_off = bb_spur; + } + + /* + * spur_delta_phase = bb_spur/40 * 2**21 for static ht20, + * /80 for dyn2040. + */ + if (IEEE80211_IS_CHAN_HT40(chan)) + spur_delta_phase = ((bb_spur * 262144) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; + else + spur_delta_phase = ((bb_spur * 524288) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; + + /* + * in 11A mode the denominator of spur_freq_sd should be 40 and + * it should be 44 in 11G + */ + denominator = IEEE80211_IS_CHAN_2GHZ(chan) ? 44 : 40; + spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; + + newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + OS_REG_WRITE(ah, AR_PHY_TIMING11, newVal); + + /* Choose to cancel between control and extension channels */ + newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; + OS_REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); + + /* + * ============================================ + * Set Pilot and Channel Masks + * + * pilot mask 1 [31:0] = +6..-26, no 0 bin + * pilot mask 2 [19:0] = +26..+7 + * + * channel mask 1 [31:0] = +6..-26, no 0 bin + * channel mask 2 [19:0] = +26..+7 + */ + cur_bin = -6000; + upper = bin + 100; + lower = bin - 100; + + for (i = 0; i < 4; i++) { + int pilot_mask = 0; + int chan_mask = 0; + int bp = 0; + for (bp = 0; bp < 30; bp++) { + if ((cur_bin > lower) && (cur_bin < upper)) { + pilot_mask = pilot_mask | 0x1 << bp; + chan_mask = chan_mask | 0x1 << bp; + } + cur_bin += 100; + } + cur_bin += inc[i]; + OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); + OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask); + } + + /* ================================================= + * viterbi mask 1 based on channel magnitude + * four levels 0-3 + * - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c) + * [1 2 2 1] for -9.6 or [1 2 1] for +16 + * - enable_mask_ppm, all bins move with freq + * + * - mask_select, 8 bits for rates (reg 67,0x990c) + * - mask_rate_cntl, 8 bits for rates (reg 67,0x990c) + * choose which mask to use mask or mask2 + */ + + /* + * viterbi mask 2 2nd set for per data rate puncturing + * four levels 0-3 + * - mask_select, 8 bits for rates (reg 67) + * - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994) + * [1 2 2 1] for -9.6 or [1 2 1] for +16 + */ + cur_vit_mask = 6100; + upper = bin + 120; + lower = bin - 120; + + for (i = 0; i < 123; i++) { + if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + if ((abs(cur_vit_mask - bin)) < 75) { + mask_amt = 1; + } else { + mask_amt = 0; + } + if (cur_vit_mask < 0) { + mask_m[abs(cur_vit_mask / 100)] = mask_amt; + } else { + mask_p[cur_vit_mask / 100] = mask_amt; + } + } + cur_vit_mask -= 100; + } + + tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) + | (mask_m[48] << 26) | (mask_m[49] << 24) + | (mask_m[50] << 22) | (mask_m[51] << 20) + | (mask_m[52] << 18) | (mask_m[53] << 16) + | (mask_m[54] << 14) | (mask_m[55] << 12) + | (mask_m[56] << 10) | (mask_m[57] << 8) + | (mask_m[58] << 6) | (mask_m[59] << 4) + | (mask_m[60] << 2) | (mask_m[61] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + + tmp_mask = (mask_m[31] << 28) + | (mask_m[32] << 26) | (mask_m[33] << 24) + | (mask_m[34] << 22) | (mask_m[35] << 20) + | (mask_m[36] << 18) | (mask_m[37] << 16) + | (mask_m[48] << 14) | (mask_m[39] << 12) + | (mask_m[40] << 10) | (mask_m[41] << 8) + | (mask_m[42] << 6) | (mask_m[43] << 4) + | (mask_m[44] << 2) | (mask_m[45] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + + tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) + | (mask_m[18] << 26) | (mask_m[18] << 24) + | (mask_m[20] << 22) | (mask_m[20] << 20) + | (mask_m[22] << 18) | (mask_m[22] << 16) + | (mask_m[24] << 14) | (mask_m[24] << 12) + | (mask_m[25] << 10) | (mask_m[26] << 8) + | (mask_m[27] << 6) | (mask_m[28] << 4) + | (mask_m[29] << 2) | (mask_m[30] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + + tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28) + | (mask_m[ 2] << 26) | (mask_m[ 3] << 24) + | (mask_m[ 4] << 22) | (mask_m[ 5] << 20) + | (mask_m[ 6] << 18) | (mask_m[ 7] << 16) + | (mask_m[ 8] << 14) | (mask_m[ 9] << 12) + | (mask_m[10] << 10) | (mask_m[11] << 8) + | (mask_m[12] << 6) | (mask_m[13] << 4) + | (mask_m[14] << 2) | (mask_m[15] << 0); + OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + + tmp_mask = (mask_p[15] << 28) + | (mask_p[14] << 26) | (mask_p[13] << 24) + | (mask_p[12] << 22) | (mask_p[11] << 20) + | (mask_p[10] << 18) | (mask_p[ 9] << 16) + | (mask_p[ 8] << 14) | (mask_p[ 7] << 12) + | (mask_p[ 6] << 10) | (mask_p[ 5] << 8) + | (mask_p[ 4] << 6) | (mask_p[ 3] << 4) + | (mask_p[ 2] << 2) | (mask_p[ 1] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + + tmp_mask = (mask_p[30] << 28) + | (mask_p[29] << 26) | (mask_p[28] << 24) + | (mask_p[27] << 22) | (mask_p[26] << 20) + | (mask_p[25] << 18) | (mask_p[24] << 16) + | (mask_p[23] << 14) | (mask_p[22] << 12) + | (mask_p[21] << 10) | (mask_p[20] << 8) + | (mask_p[19] << 6) | (mask_p[18] << 4) + | (mask_p[17] << 2) | (mask_p[16] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + + tmp_mask = (mask_p[45] << 28) + | (mask_p[44] << 26) | (mask_p[43] << 24) + | (mask_p[42] << 22) | (mask_p[41] << 20) + | (mask_p[40] << 18) | (mask_p[39] << 16) + | (mask_p[38] << 14) | (mask_p[37] << 12) + | (mask_p[36] << 10) | (mask_p[35] << 8) + | (mask_p[34] << 6) | (mask_p[33] << 4) + | (mask_p[32] << 2) | (mask_p[31] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + + tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) + | (mask_p[59] << 26) | (mask_p[58] << 24) + | (mask_p[57] << 22) | (mask_p[56] << 20) + | (mask_p[55] << 18) | (mask_p[54] << 16) + | (mask_p[53] << 14) | (mask_p[52] << 12) + | (mask_p[51] << 10) | (mask_p[50] << 8) + | (mask_p[49] << 6) | (mask_p[48] << 4) + | (mask_p[47] << 2) | (mask_p[46] << 0); + OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); + OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); +} + +/* + * Fill all software cached or static hardware state information. + * Return failure if capabilities are to come from EEPROM and + * cannot be read. + */ +static HAL_BOOL +ar9280FillCapabilityInfo(struct ath_hal *ah) +{ + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + if (!ar5416FillCapabilityInfo(ah)) + return AH_FALSE; + pCap->halNumGpioPins = 10; + pCap->halWowSupport = AH_TRUE; + pCap->halWowMatchPatternExact = AH_TRUE; +#if 0 + pCap->halWowMatchPatternDword = AH_TRUE; +#endif + pCap->halCSTSupport = AH_TRUE; + pCap->halRifsRxSupport = AH_TRUE; + pCap->halRifsTxSupport = AH_TRUE; + pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ + pCap->halExtChanDfsSupport = AH_TRUE; + pCap->halUseCombinedRadarRssi = AH_TRUE; +#if 0 + /* XXX bluetooth */ + pCap->halBtCoexSupport = AH_TRUE; +#endif + pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ + pCap->hal4kbSplitTransSupport = AH_FALSE; + /* Disable this so Block-ACK works correctly */ + pCap->halHasRxSelfLinkedTail = AH_FALSE; + pCap->halMbssidAggrSupport = AH_TRUE; + pCap->hal4AddrAggrSupport = AH_TRUE; + pCap->halSpectralScanSupport = AH_TRUE; + + if (AR_SREV_MERLIN_20(ah)) { + pCap->halPSPollBroken = AH_FALSE; + /* + * This just enables the support; it doesn't + * state 5ghz fast clock will always be used. + */ + pCap->halSupportsFastClock5GHz = AH_TRUE; + } + pCap->halRxStbcSupport = 1; + pCap->halTxStbcSupport = 1; + pCap->halEnhancedDfsSupport = AH_TRUE; + + return AH_TRUE; +} + +/* + * This has been disabled - having the HAL flip chainmasks on/off + * when attempting to implement 11n disrupts things. For now, just + * leave this flipped off and worry about implementing TX diversity + * for legacy and MCS0-7 when 11n is fully functioning. + */ +HAL_BOOL +ar9280SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) +{ +#define ANTENNA0_CHAINMASK 0x1 +#define ANTENNA1_CHAINMASK 0x2 +#if 0 + struct ath_hal_5416 *ahp = AH5416(ah); + + /* Antenna selection is done by setting the tx/rx chainmasks approp. */ + switch (settings) { + case HAL_ANT_FIXED_A: + /* Enable first antenna only */ + ahp->ah_tx_chainmask = ANTENNA0_CHAINMASK; + ahp->ah_rx_chainmask = ANTENNA0_CHAINMASK; + break; + case HAL_ANT_FIXED_B: + /* Enable second antenna only, after checking capability */ + if (AH_PRIVATE(ah)->ah_caps.halTxChainMask > ANTENNA1_CHAINMASK) + ahp->ah_tx_chainmask = ANTENNA1_CHAINMASK; + ahp->ah_rx_chainmask = ANTENNA1_CHAINMASK; + break; + case HAL_ANT_VARIABLE: + /* Restore original chainmask settings */ + /* XXX */ + ahp->ah_tx_chainmask = AR9280_DEFAULT_TXCHAINMASK; + ahp->ah_rx_chainmask = AR9280_DEFAULT_RXCHAINMASK; + break; + } + + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: settings=%d, tx/rx chainmask=%d/%d\n", + __func__, settings, ahp->ah_tx_chainmask, ahp->ah_rx_chainmask); + +#endif + return AH_TRUE; +#undef ANTENNA0_CHAINMASK +#undef ANTENNA1_CHAINMASK +} + +static const char* +ar9280Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID) { + if (devid == AR9280_DEVID_PCI) + return "Atheros 9220"; + if (devid == AR9280_DEVID_PCIE) + return "Atheros 9280"; + } + return AH_NULL; +} +AH_CHIP(AR9280, ar9280Probe, ar9280Attach); diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9280_olc.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9280_olc.c new file mode 100644 index 0000000..361930b --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9280_olc.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v14.h" + +#include "ar9002/ar9280.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9002/ar9002phy.h" + +#include "ar9002/ar9280_olc.h" + +void +ar9280olcInit(struct ath_hal *ah) +{ + uint32_t i; + + /* Only do OLC if it's enabled for this chipset */ + if (! ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) + return; + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Setting up TX gain tables.\n", __func__); + + for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) + AH9280(ah)->originalGain[i] = MS(OS_REG_READ(ah, + AR_PHY_TX_GAIN_TBL1 + i * 4), AR_PHY_TX_GAIN); + + AH9280(ah)->PDADCdelta = 0; +} + +void +ar9280olcGetTxGainIndex(struct ath_hal *ah, + const struct ieee80211_channel *chan, + struct calDataPerFreqOpLoop *rawDatasetOpLoop, + uint8_t *calChans, uint16_t availPiers, uint8_t *pwr, uint8_t *pcdacIdx) +{ + uint8_t pcdac, i = 0; + uint16_t idxL = 0, idxR = 0, numPiers; + HAL_BOOL match; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + for (numPiers = 0; numPiers < availPiers; numPiers++) + if (calChans[numPiers] == AR5416_BCHAN_UNUSED) + break; + + match = ath_ee_getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, + IEEE80211_IS_CHAN_2GHZ(chan)), calChans, numPiers, + &idxL, &idxR); + if (match) { + pcdac = rawDatasetOpLoop[idxL].pcdac[0][0]; + *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0]; + } else { + pcdac = rawDatasetOpLoop[idxR].pcdac[0][0]; + *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] + + rawDatasetOpLoop[idxR].pwrPdg[0][0])/2; + } + while (pcdac > AH9280(ah)->originalGain[i] && + i < (AR9280_TX_GAIN_TABLE_SIZE - 1)) + i++; + + *pcdacIdx = i; +} + +/* + * XXX txPower here is likely not the target txPower in the traditional + * XXX sense, but is set by a call to ar9280olcGetTxGainIndex(). + * XXX Thus, be careful if you're trying to use this routine yourself. + */ +void +ar9280olcGetPDADCs(struct ath_hal *ah, uint32_t initTxGain, int txPower, + uint8_t *pPDADCValues) +{ + uint32_t i; + uint32_t offset; + + OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); + OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); + + OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7, AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain); + + offset = txPower; + for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++) + if (i < offset) + pPDADCValues[i] = 0x0; + else + pPDADCValues[i] = 0xFF; +} + +/* + * Run temperature compensation calibration. + * + * The TX gain table is adjusted depending upon the difference + * between the initial PDADC value and the currently read + * average TX power sample value. This value is only valid if + * frames have been transmitted, so currPDADC will be 0 if + * no frames have yet been transmitted. + */ +void +ar9280olcTemperatureCompensation(struct ath_hal *ah) +{ + uint32_t rddata, i; + int delta, currPDADC, regval; + uint8_t hpwr_5g = 0; + + if (! ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) + return; + + rddata = OS_REG_READ(ah, AR_PHY_TX_PWRCTRL4); + currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: called: initPDADC=%d, currPDADC=%d\n", + __func__, AH5416(ah)->initPDADC, currPDADC); + + if (AH5416(ah)->initPDADC == 0 || currPDADC == 0) + return; + + (void) (ath_hal_eepromGet(ah, AR_EEP_DAC_HPWR_5G, &hpwr_5g)); + + if (hpwr_5g) + delta = (currPDADC - AH5416(ah)->initPDADC + 4) / 8; + else + delta = (currPDADC - AH5416(ah)->initPDADC + 5) / 10; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, "%s: delta=%d, PDADCdelta=%d\n", + __func__, delta, AH9280(ah)->PDADCdelta); + + if (delta != AH9280(ah)->PDADCdelta) { + AH9280(ah)->PDADCdelta = delta; + for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { + regval = AH9280(ah)->originalGain[i] - delta; + if (regval < 0) + regval = 0; + + OS_REG_RMW_FIELD(ah, + AR_PHY_TX_GAIN_TBL1 + i * 4, + AR_PHY_TX_GAIN, regval); + } + } +} + + +static int16_t +ar9280ChangeGainBoundarySettings(struct ath_hal *ah, uint16_t *gb, + uint16_t numXpdGain, uint16_t pdGainOverlap_t2, int8_t pwr_table_offset, + int16_t *diff) +{ + uint16_t k; + + /* Prior to writing the boundaries or the pdadc vs. power table + * into the chip registers the default starting point on the pdadc + * vs. power table needs to be checked and the curve boundaries + * adjusted accordingly + */ + if (AR_SREV_MERLIN_20_OR_LATER(ah)) { + uint16_t gb_limit; + + if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { + /* get the difference in dB */ + *diff = (uint16_t)(pwr_table_offset - AR5416_PWR_TABLE_OFFSET_DB); + /* get the number of half dB steps */ + *diff *= 2; + /* change the original gain boundary settings + * by the number of half dB steps + */ + for (k = 0; k < numXpdGain; k++) + gb[k] = (uint16_t)(gb[k] - *diff); + } + /* Because of a hardware limitation, ensure the gain boundary + * is not larger than (63 - overlap) + */ + gb_limit = (uint16_t)(AR5416_MAX_RATE_POWER - pdGainOverlap_t2); + + for (k = 0; k < numXpdGain; k++) + gb[k] = (uint16_t)min(gb_limit, gb[k]); + } + + return *diff; +} + +static void +ar9280AdjustPDADCValues(struct ath_hal *ah, int8_t pwr_table_offset, + int16_t diff, uint8_t *pdadcValues) +{ +#define NUM_PDADC(diff) (AR5416_NUM_PDADC_VALUES - diff) + uint16_t k; + + /* If this is a board that has a pwrTableOffset that differs from + * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the + * pdadc vs pwr table needs to be adjusted prior to writing to the + * chip. + */ + if (AR_SREV_MERLIN_20_OR_LATER(ah)) { + if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { + /* shift the table to start at the new offset */ + for (k = 0; k < (uint16_t)NUM_PDADC(diff); k++ ) { + pdadcValues[k] = pdadcValues[k + diff]; + } + + /* fill the back of the table */ + for (k = (uint16_t)NUM_PDADC(diff); k < NUM_PDADC(0); k++) { + pdadcValues[k] = pdadcValues[NUM_PDADC(diff)]; + } + } + } +#undef NUM_PDADC +} +/* + * This effectively disables the gain boundaries leaving it + * to the open-loop TX power control. + */ +static void +ar9280SetGainBoundariesOpenLoop(struct ath_hal *ah, int i, + uint16_t pdGainOverlap_t2, uint16_t gainBoundaries[]) +{ + int regChainOffset; + + regChainOffset = ar5416GetRegChainOffset(ah, i); + + /* These are unused for OLC */ + (void) pdGainOverlap_t2; + (void) gainBoundaries; + + HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: chain %d: writing closed loop values\n", + __func__, i); + + OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, + SM(0x6, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | + SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | + SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | + SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); +} + +/* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */ +/* XXX shouldn't be here! */ +#define EEP_MINOR(_ah) \ + (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK) +#define IS_EEP_MINOR_V2(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2) +#define IS_EEP_MINOR_V3(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_3) + +/************************************************************** + * ar9280SetPowerCalTable + * + * Pull the PDADC piers from cal data and interpolate them across the given + * points as well as from the nearest pier(s) to get a power detector + * linear voltage to power level table. + * + * Handle OLC for Merlin where required. + */ +HAL_BOOL +ar9280SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, + const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset) +{ + CAL_DATA_PER_FREQ *pRawDataset; + uint8_t *pCalBChans = AH_NULL; + uint16_t pdGainOverlap_t2; + static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES]; + uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK]; + uint16_t numPiers, i; + int16_t tMinCalPower; + uint16_t numXpdGain, xpdMask; + uint16_t xpdGainValues[AR5416_NUM_PD_GAINS]; + uint32_t regChainOffset; + int8_t pwr_table_offset; + + OS_MEMZERO(xpdGainValues, sizeof(xpdGainValues)); + + xpdMask = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].xpdGain; + + (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, &pwr_table_offset); + + + if (IS_EEP_MINOR_V2(ah)) { + pdGainOverlap_t2 = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].pdGainOverlap; + } else { + pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); + } + + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + pCalBChans = pEepData->calFreqPier2G; + numPiers = AR5416_NUM_2G_CAL_PIERS; + } else { + pCalBChans = pEepData->calFreqPier5G; + numPiers = AR5416_NUM_5G_CAL_PIERS; + } + + /* If OLC is being done, set the init PDADC value appropriately */ + if (IEEE80211_IS_CHAN_2GHZ(chan) && AR_SREV_MERLIN_20_OR_LATER(ah) && + ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + struct calDataPerFreq *pRawDataset = pEepData->calPierData2G[0]; + AH5416(ah)->initPDADC = ((struct calDataPerFreqOpLoop *) pRawDataset)->vpdPdg[0][0]; + } else { + /* + * XXX ath9k doesn't clear this for 5ghz mode if + * it were set in 2ghz mode before! + * The Merlin OLC temperature compensation code + * uses this to calculate the PDADC delta during + * calibration ; 0 here effectively stops the + * temperature compensation calibration from + * occuring. + */ + AH5416(ah)->initPDADC = 0; + } + + /* Calculate the value of xpdgains from the xpdGain Mask */ + numXpdGain = ar5416GetXpdGainValues(ah, xpdMask, xpdGainValues); + + /* Write the detector gain biases and their number */ + ar5416WriteDetectorGainBiases(ah, numXpdGain, xpdGainValues); + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + regChainOffset = ar5416GetRegChainOffset(ah, i); + if (pEepData->baseEepHeader.txMask & (1 << i)) { + uint16_t diff; + + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + pRawDataset = pEepData->calPierData2G[i]; + } else { + pRawDataset = pEepData->calPierData5G[i]; + } + + /* Fetch the gain boundaries and the PDADC values */ + if (AR_SREV_MERLIN_20_OR_LATER(ah) && + ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + uint8_t pcdacIdx; + uint8_t txPower; + + ar9280olcGetTxGainIndex(ah, chan, + (struct calDataPerFreqOpLoop *) pRawDataset, + pCalBChans, numPiers, &txPower, &pcdacIdx); + ar9280olcGetPDADCs(ah, pcdacIdx, txPower / 2, pdadcValues); + } else { + ar5416GetGainBoundariesAndPdadcs(ah, chan, + pRawDataset, pCalBChans, numPiers, + pdGainOverlap_t2, &tMinCalPower, + gainBoundaries, pdadcValues, numXpdGain); + } + + /* + * Prior to writing the boundaries or the pdadc vs. power table + * into the chip registers the default starting point on the pdadc + * vs. power table needs to be checked and the curve boundaries + * adjusted accordingly + */ + diff = ar9280ChangeGainBoundarySettings(ah, + gainBoundaries, numXpdGain, pdGainOverlap_t2, + pwr_table_offset, &diff); + + if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { + /* Set gain boundaries for either open- or closed-loop TPC */ + if (AR_SREV_MERLIN_20_OR_LATER(ah) && + ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) + ar9280SetGainBoundariesOpenLoop(ah, + i, pdGainOverlap_t2, + gainBoundaries); + else + ar5416SetGainBoundariesClosedLoop(ah, + i, pdGainOverlap_t2, + gainBoundaries); + } + + /* + * If this is a board that has a pwrTableOffset that differs from + * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the + * pdadc vs pwr table needs to be adjusted prior to writing to the + * chip. + */ + ar9280AdjustPDADCValues(ah, pwr_table_offset, diff, pdadcValues); + + /* Write the power values into the baseband power table */ + ar5416WritePdadcValues(ah, i, pdadcValues); + } + } + *pTxPowerIndexOffset = 0; + + return AH_TRUE; +} diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9280_olc.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9280_olc.h new file mode 100644 index 0000000..e08639c --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9280_olc.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __ATH_AR9280_OLC_H__ +#define __ATH_AR9280_OLC_H__ + +extern void ar9280olcInit(struct ath_hal *ah); + +/* OLC TX power control */ +extern void ar9280olcGetPDADCs(struct ath_hal *ah, uint32_t initTxGain, + int txPower, uint8_t *pPDADCValues); +extern void ar9280olcGetTxGainIndex(struct ath_hal *ah, + const struct ieee80211_channel *chan, + struct calDataPerFreqOpLoop *rawDatasetOpLoop, + uint8_t *calChans, uint16_t availPiers, uint8_t *pwr, uint8_t *pcdacIdx); +extern void ar9280GetGainBoundariesAndPdadcs(struct ath_hal *ah, + const struct ieee80211_channel *chan, CAL_DATA_PER_FREQ *pRawDataSet, + uint8_t * bChans, uint16_t availPiers, + uint16_t tPdGainOverlap, int16_t *pMinCalPower, + uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues, + uint16_t numXpdGains); +extern HAL_BOOL ar9280SetPowerCalTable(struct ath_hal *ah, + struct ar5416eeprom *pEepData, const struct ieee80211_channel *chan, + int16_t *pTxPowerIndexOffset); + +/* OLC calibration */ +extern void ar9280olcTemperatureCompensation(struct ath_hal *ah); + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9280v1.ini b/sys/external/isc/atheros_hal/dist/ar9002/ar9280v1.ini new file mode 100644 index 0000000..96e0f44 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9280v1.ini @@ -0,0 +1,582 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +/* Auto Generated PCI Register Writes. Created: 10/12/07 */ + +static const uint32_t ar9280Modes_v1[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 }, + { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, + { 0x00009848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, + { 0x0000a848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, + { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, + { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d20, 0x00049d20, 0x00049d18 }, + { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190 }, + { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 }, + { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, + { 0x0000c9b8, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a }, + { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009a00, 0x00008184, 0x00008184, 0x00000214, 0x00000214, 0x00000214 }, + { 0x00009a04, 0x00008188, 0x00008188, 0x00000218, 0x00000218, 0x00000218 }, + { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000224, 0x00000224, 0x00000224 }, + { 0x00009a0c, 0x00008190, 0x00008190, 0x00000228, 0x00000228, 0x00000228 }, + { 0x00009a10, 0x00008194, 0x00008194, 0x0000022c, 0x0000022c, 0x0000022c }, + { 0x00009a14, 0x00008200, 0x00008200, 0x00000230, 0x00000230, 0x00000230 }, + { 0x00009a18, 0x00008204, 0x00008204, 0x000002a4, 0x000002a4, 0x000002a4 }, + { 0x00009a1c, 0x00008208, 0x00008208, 0x000002a8, 0x000002a8, 0x000002a8 }, + { 0x00009a20, 0x0000820c, 0x0000820c, 0x000002ac, 0x000002ac, 0x000002ac }, + { 0x00009a24, 0x00008210, 0x00008210, 0x000002b0, 0x000002b0, 0x000002b0 }, + { 0x00009a28, 0x00008214, 0x00008214, 0x000002b4, 0x000002b4, 0x000002b4 }, + { 0x00009a2c, 0x00008280, 0x00008280, 0x000002b8, 0x000002b8, 0x000002b8 }, + { 0x00009a30, 0x00008284, 0x00008284, 0x00000390, 0x00000390, 0x00000390 }, + { 0x00009a34, 0x00008288, 0x00008288, 0x00000394, 0x00000394, 0x00000394 }, + { 0x00009a38, 0x0000828c, 0x0000828c, 0x00000398, 0x00000398, 0x00000398 }, + { 0x00009a3c, 0x00008290, 0x00008290, 0x00000334, 0x00000334, 0x00000334 }, + { 0x00009a40, 0x00008300, 0x00008300, 0x00000338, 0x00000338, 0x00000338 }, + { 0x00009a44, 0x00008304, 0x00008304, 0x000003ac, 0x000003ac, 0x000003ac }, + { 0x00009a48, 0x00008308, 0x00008308, 0x000003b0, 0x000003b0, 0x000003b0 }, + { 0x00009a4c, 0x0000830c, 0x0000830c, 0x000003b4, 0x000003b4, 0x000003b4 }, + { 0x00009a50, 0x00008310, 0x00008310, 0x000003b8, 0x000003b8, 0x000003b8 }, + { 0x00009a54, 0x00008314, 0x00008314, 0x000003a5, 0x000003a5, 0x000003a5 }, + { 0x00009a58, 0x00008380, 0x00008380, 0x000003a9, 0x000003a9, 0x000003a9 }, + { 0x00009a5c, 0x00008384, 0x00008384, 0x000003ad, 0x000003ad, 0x000003ad }, + { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, + { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, + { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, + { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, + { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, + { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, + { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, + { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, + { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, + { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, + { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, + { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, + { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, + { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, + { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, + { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, + { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, + { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, + { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, + { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, + { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, + { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, + { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, + { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, + { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, + { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, + { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, + { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, + { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, + { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, + { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, + { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, + { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, + { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, + { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, + { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, + { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, + { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, + { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, + { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, + { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, + { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, + { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, + { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, + { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, + { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, + { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, + { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, + { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, + { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, + { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, + { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, + { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, + { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, + { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, + { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, + { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, + { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, + { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, + { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, + { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, + { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, + { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, + { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, + { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, + { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, + { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, + { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, + { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, + { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, + { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, + { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, + { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, + { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, + { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, + { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, + { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 }, + { 0x0000a20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, + { 0x0000b20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, + { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, + { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, + { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, + { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, + { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, + { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, + { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, + { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, + { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, + { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, + { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, + { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, + { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, + { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, + { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, + { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, + { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, + { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, + { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, + { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, + { 0x0000784c, 0x0e4f048c, 0x0e4f048c, 0x0e4d048c, 0x0e4d048c, 0x0e4d048c }, + { 0x00007854, 0x12031828, 0x12031828, 0x12035828, 0x12035828, 0x12035828 }, + { 0x00007870, 0x807ec400, 0x807ec400, 0x807ec000, 0x807ec000, 0x807ec000 }, + { 0x0000788c, 0x00010000, 0x00010000, 0x00110000, 0x00110000, 0x00110000 }, +}; + +static const uint32_t ar9280Common_v1[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00007010, 0x00000033 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0x00000000 }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00000000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00008344, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xaf268e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a01ae }, + { 0x0000984c, 0x0040233c }, + { 0x0000a84c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x0000a920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0xe250a51e }, + { 0x00009958, 0x3388ffff }, + { 0x00009940, 0x00781204 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x0000c968, 0x000003ce }, + { 0x00009970, 0x190fb514 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f00c4 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099fc, 0x00001042 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x40206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x23277200 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x001da000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cdbd380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce }, + { 0x0000a358, 0x7999aa0f }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f38081 }, + { 0x00007800, 0x00040000 }, + { 0x00007804, 0xdb005012 }, + { 0x00007808, 0x04924914 }, + { 0x0000780c, 0x21084210 }, + { 0x00007810, 0x6d801300 }, + { 0x00007814, 0x0019beff }, + { 0x00007818, 0x07e40000 }, + { 0x0000781c, 0x00492000 }, + { 0x00007820, 0x92492480 }, + { 0x00007824, 0x00040000 }, + { 0x00007828, 0xdb005012 }, + { 0x0000782c, 0x04924914 }, + { 0x00007830, 0x21084210 }, + { 0x00007834, 0x6d801300 }, + { 0x00007838, 0x0019beff }, + { 0x0000783c, 0x07e40000 }, + { 0x00007840, 0x00492000 }, + { 0x00007844, 0x92492480 }, + { 0x00007848, 0x00120000 }, + { 0x00007850, 0x54214514 }, + { 0x00007858, 0x92592692 }, + { 0x00007860, 0x52802000 }, + { 0x00007864, 0x0a8e370e }, + { 0x00007868, 0xc0102850 }, + { 0x0000786c, 0x812d4000 }, + { 0x00007874, 0x001b6db0 }, + { 0x00007878, 0x00376b63 }, + { 0x0000787c, 0x06db6db6 }, + { 0x00007880, 0x006d8000 }, + { 0x00007884, 0xffeffffe }, + { 0x00007888, 0xffeffffe }, + { 0x00007890, 0x00060aeb }, + { 0x00007894, 0x5a108000 }, + { 0x00007898, 0x2a850160 }, +}; + +/* hand-crafted from code that does explicit register writes */ +static const uint32_t ar9280PciePhy_v1[][2] = { + { AR_PCIE_SERDES, 0x9248fd00 }, + { AR_PCIE_SERDES, 0x24924924 }, + { AR_PCIE_SERDES, 0xa8000019 }, + { AR_PCIE_SERDES, 0x13160820 }, + { AR_PCIE_SERDES, 0xe5980560 }, + { AR_PCIE_SERDES, 0x401deffd }, + { AR_PCIE_SERDES, 0x1aaabe40 }, + { AR_PCIE_SERDES, 0xbe105554 }, + { AR_PCIE_SERDES, 0x00043007 }, + { AR_PCIE_SERDES2, 0x00000000 }, +}; diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9280v2.ini b/sys/external/isc/atheros_hal/dist/ar9002/ar9280v2.ini new file mode 100644 index 0000000..60286ec --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9280v2.ini @@ -0,0 +1,929 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +static const uint32_t ar9280Modes_v2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, + { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, + { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, + { 0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, + { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, + { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 }, + { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, + { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, + { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c }, + { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, + { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, + { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000, 0x13c88000 }, + { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 }, + { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, + { 0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000, 0x0c000000 }, + { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 }, +}; + +static const uint32_t ar9280Common_v2[][2] = { + /* Addr allmodes */ + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00004060, 0x00000000 }, + { 0x00004064, 0x00000000 }, + { 0x00007010, 0x00000033 }, + { 0x00007034, 0x00000002 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a80001a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c0, 0x00000000 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0x88a00010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x0000829c, 0x00000000 }, + { 0x00008300, 0x00000040 }, + { 0x00008314, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00ff0000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00008344, 0x00481043 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xafa68e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x0040233c }, + { 0x0000a84c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x00009910, 0x01002310 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x0000a920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x2108ecff }, + { 0x00009940, 0x14750604 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x00009970, 0x190fb514 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f0000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099c4, 0x06336f77 }, + { 0x000099c8, 0x6af6532f }, + { 0x000099cc, 0x08f186c8 }, + { 0x000099d0, 0x00046384 }, + { 0x000099d4, 0x00000000 }, + { 0x000099d8, 0x00000000 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, + { 0x000099fc, 0x00001042 }, + { 0x0000a208, 0x803e4788 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x40206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x233f7180 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cdbd380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0e79e5c6 }, + { 0x0000b26c, 0x0e79e5c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x00007800, 0x00040000 }, + { 0x00007804, 0xdb005012 }, + { 0x00007808, 0x04924914 }, + { 0x0000780c, 0x21084210 }, + { 0x00007810, 0x6d801300 }, + { 0x00007818, 0x07e41000 }, + { 0x00007824, 0x00040000 }, + { 0x00007828, 0xdb005012 }, + { 0x0000782c, 0x04924914 }, + { 0x00007830, 0x21084210 }, + { 0x00007834, 0x6d801300 }, + { 0x0000783c, 0x07e40000 }, + { 0x00007848, 0x00100000 }, + { 0x0000784c, 0x773f0567 }, + { 0x00007850, 0x54214514 }, + { 0x00007854, 0x12035828 }, + { 0x00007858, 0x9259269a }, + { 0x00007860, 0x52802000 }, + { 0x00007864, 0x0a8e370e }, + { 0x00007868, 0xc0102850 }, + { 0x0000786c, 0x812d4000 }, + { 0x00007870, 0x807ec400 }, + { 0x00007874, 0x001b6db0 }, + { 0x00007878, 0x00376b63 }, + { 0x0000787c, 0x06db6db6 }, + { 0x00007880, 0x006d8000 }, + { 0x00007884, 0xffeffffe }, + { 0x00007888, 0xffeffffe }, + { 0x0000788c, 0x00010000 }, + { 0x00007890, 0x02060aeb }, + { 0x00007898, 0x2a850160 }, +}; + +static const uint32_t ar9280Modes_fast_clock_v2[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + { 0x00001030, 0x00000268, 0x000004d0 }, + { 0x00001070, 0x0000018c, 0x00000318 }, + { 0x000010b0, 0x00000fd0, 0x00001fa0 }, + { 0x00008014, 0x044c044c, 0x08980898 }, + { 0x0000801c, 0x148ec02b, 0x148ec057 }, + { 0x00008318, 0x000044c0, 0x00008980 }, + { 0x00009820, 0x02020200, 0x02020200 }, + { 0x00009824, 0x01000f0f, 0x01000f0f }, + { 0x00009828, 0x0b020001, 0x0b020001 }, + { 0x00009834, 0x00000f0f, 0x00000f0f }, + { 0x00009844, 0x03721821, 0x03721821 }, + { 0x00009914, 0x00000898, 0x00001130 }, + { 0x00009918, 0x0000000b, 0x00000016 }, +}; + +static const uint32_t ar9280Modes_backoff_23db_rxgain_v2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, + { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, + { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, + { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, + { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, + { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, + { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, + { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, + { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, + { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, + { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, + { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, + { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, + { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, + { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, + { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, + { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, + { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, + { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, + { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, + { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, + { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, + { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, + { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, + { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, + { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, + { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, + { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, + { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, + { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, + { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, + { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, + { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, + { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, + { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, + { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, + { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, + { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, + { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, + { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, + { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, + { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, + { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, + { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, + { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, + { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, + { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, + { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 }, + { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b80, 0x00008b80, 0x00008b80 }, + { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b84, 0x00008b84, 0x00008b84 }, + { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b88, 0x00008b88, 0x00008b88 }, + { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b8c, 0x00008b8c, 0x00008b8c }, + { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b90, 0x00008b90, 0x00008b90 }, + { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b94, 0x00008b94, 0x00008b94 }, + { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b98, 0x00008b98, 0x00008b98 }, + { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008ba4, 0x00008ba4, 0x00008ba4 }, + { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008ba8, 0x00008ba8, 0x00008ba8 }, + { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008bac, 0x00008bac, 0x00008bac }, + { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008bb0, 0x00008bb0, 0x00008bb0 }, + { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008bb4, 0x00008bb4, 0x00008bb4 }, + { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008ba1, 0x00008ba1, 0x00008ba1 }, + { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008ba5, 0x00008ba5, 0x00008ba5 }, + { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008ba9, 0x00008ba9, 0x00008ba9 }, + { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008bad, 0x00008bad, 0x00008bad }, + { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008bb1, 0x00008bb1, 0x00008bb1 }, + { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008bb5, 0x00008bb5, 0x00008bb5 }, + { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008ba2, 0x00008ba2, 0x00008ba2 }, + { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008ba6, 0x00008ba6, 0x00008ba6 }, + { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008baa, 0x00008baa, 0x00008baa }, + { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008bae, 0x00008bae, 0x00008bae }, + { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008bb2, 0x00008bb2, 0x00008bb2 }, + { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008bb6, 0x00008bb6, 0x00008bb6 }, + { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008ba3, 0x00008ba3, 0x00008ba3 }, + { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008ba7, 0x00008ba7, 0x00008ba7 }, + { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008bab, 0x00008bab, 0x00008bab }, + { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008baf, 0x00008baf, 0x00008baf }, + { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008bb3, 0x00008bb3, 0x00008bb3 }, + { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008bb7, 0x00008bb7, 0x00008bb7 }, + { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008bc3, 0x00008bc3, 0x00008bc3 }, + { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008bc7, 0x00008bc7, 0x00008bc7 }, + { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008bcb, 0x00008bcb, 0x00008bcb }, + { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008bcf, 0x00008bcf, 0x00008bcf }, + { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008bd3, 0x00008bd3, 0x00008bd3 }, + { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008bd7, 0x00008bd7, 0x00008bd7 }, + { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb }, + { 0x00009848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055 }, + { 0x0000a848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055 }, +}; + +static const uint32_t ar9280Modes_original_rxgain_v2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x00009a00, 0x00008184, 0x00008184, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a04, 0x00008188, 0x00008188, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a08, 0x0000818c, 0x0000818c, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a0c, 0x00008190, 0x00008190, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a10, 0x00008194, 0x00008194, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, + { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, + { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, + { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, + { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, + { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, + { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, + { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, + { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, + { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, + { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, + { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, + { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, + { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, + { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, + { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, + { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, + { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, + { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, + { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, + { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, + { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, + { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, + { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, + { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, + { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, + { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, + { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, + { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, + { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, + { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, + { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, + { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, + { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, + { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, + { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, + { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, + { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, + { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, + { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, + { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, + { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, + { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, + { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, + { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, + { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, + { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, + { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, + { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, + { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, + { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, + { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, + { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, + { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, + { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, + { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, + { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, + { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, + { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, + { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, + { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, + { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, + { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, + { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, + { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, + { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, + { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, + { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, + { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, + { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, + { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, + { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, + { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, + { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, + { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, + { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, + { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, + { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, + { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, + { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, + { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, + { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, + { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, + { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, + { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, + { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, + { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, + { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, + { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, + { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, + { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, + { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, + { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, + { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, + { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, +}; + +static const uint32_t ar9280Modes_backoff_13db_rxgain_v2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, + { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, + { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, + { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, + { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, + { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, + { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, + { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, + { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, + { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, + { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, + { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, + { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, + { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, + { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, + { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, + { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, + { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, + { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, + { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, + { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, + { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, + { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, + { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, + { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, + { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, + { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, + { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, + { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, + { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, + { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, + { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, + { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, + { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, + { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, + { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, + { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, + { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, + { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, + { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, + { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, + { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, + { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, + { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, + { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, + { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, + { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, + { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, + { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, + { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, + { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, + { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, + { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, + { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, + { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, + { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, + { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, + { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310 }, + { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314 }, + { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320 }, + { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324 }, + { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328 }, + { 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c }, + { 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330 }, + { 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334 }, + { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321 }, + { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325 }, + { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329 }, + { 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d }, + { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331 }, + { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335 }, + { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322 }, + { 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326 }, + { 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a }, + { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e }, + { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332 }, + { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336 }, + { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323 }, + { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327 }, + { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b }, + { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f }, + { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333 }, + { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337 }, + { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343 }, + { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347 }, + { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b }, + { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f }, + { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353 }, + { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357 }, + { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, + { 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, +}; + +static const uint32_t ar9280Modes_high_power_tx_gain_v2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, + { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce }, + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 }, + { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 }, + { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010 }, + { 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012 }, + { 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014 }, + { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a }, + { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 }, + { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, + { 0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411 }, + { 0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413 }, + { 0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811 }, + { 0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813 }, + { 0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14 }, + { 0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50 }, + { 0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c }, + { 0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a }, + { 0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92 }, + { 0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 }, + { 0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 }, + { 0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 }, + { 0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5 }, + { 0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081 }, + { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, + { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, + { 0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, + { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, + { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, + { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, +}; + +static const uint32_t ar9280Modes_original_tx_gain_v2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, + { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, + { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, + { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, + { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, + { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, + { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, + { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, + { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, + { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, + { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, + { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, + { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, + { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, + { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, + { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, + { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, + { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, + { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, + { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, + { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, + { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, + { 0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081 }, + { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, + { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, + { 0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, + { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, + { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, + { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, +}; + +static const uint32_t ar9280PciePhy_clkreq_off_L1_merlin[][2] = { + /* Addr allmodes */ + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffc }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +static const uint32_t ar9280PciePhy_clkreq_always_on_L1_v2[][2] = { + /* Addr allmodes */ + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffd }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9285.c new file mode 100644 index 0000000..9e9f95c --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v14.h" + +#include "ar9002/ar9280.h" +#include "ar9002/ar9285.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* + * The ordering of nfarray is thus: + * + * nfarray[0]: Chain 0 ctl + * nfarray[1]: Chain 1 ctl + * nfarray[2]: Chain 2 ctl + * nfarray[3]: Chain 0 ext + * nfarray[4]: Chain 1 ext + * nfarray[5]: Chain 2 ext + */ +static void +ar9285GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) +{ + int16_t nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 0] is %d\n", nf); + nfarray[0] = nf; + + + nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 0] is %d\n", nf); + nfarray[3] = nf; + + /* Chain 1 - invalid */ + nfarray[1] = 0; + nfarray[4] = 0; + + /* Chain 2 - invalid */ + nfarray[2] = 0; + nfarray[5] = 0; +} + +HAL_BOOL +ar9285RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + if (ar9280RfAttach(ah, status) == AH_FALSE) + return AH_FALSE; + + AH_PRIVATE(ah)->ah_getNoiseFloor = ar9285GetNoiseFloor; + + return AH_TRUE; +} + +static HAL_BOOL +ar9285RfProbe(struct ath_hal *ah) +{ + return (AR_SREV_KITE(ah)); +} + +AH_RF(RF9285, ar9285RfProbe, ar9285RfAttach); diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9285.h new file mode 100644 index 0000000..b37b297 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef _ATH_AR9285_H_ +#define _ATH_AR9285_H_ + +#include "ar5416/ar5416.h" + +struct ath_hal_9285 { + struct ath_hal_5416 ah_5416; + + HAL_INI_ARRAY ah_ini_txgain; + HAL_INI_ARRAY ah_ini_rxgain; + + struct { + int32_t prev_offset; /* Previous value of PA offset value */ + int8_t max_skipcount; /* Max No. of times PACAL can be skipped */ + int8_t skipcount; /* No. of times the PACAL to be skipped */ + } pacal_info; +}; +#define AH9285(_ah) ((struct ath_hal_9285 *)(_ah)) + +#define AR9285_DEFAULT_RXCHAINMASK 1 +#define AR9285_DEFAULT_TXCHAINMASK 1 + +#define AR_PHY_CCA_NOM_VAL_9285_2GHZ -118 +#define AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ -127 +#define AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ -108 + +HAL_BOOL ar9285RfAttach(struct ath_hal *, HAL_STATUS *); + +extern HAL_BOOL ar9285SetTransmitPower(struct ath_hal *, + const struct ieee80211_channel *, uint16_t *); +extern HAL_BOOL ar9285SetBoardValues(struct ath_hal *, + const struct ieee80211_channel *); + +/* ar9285_btcoex.h */ +extern void ar9285BTCoexAntennaDiversity(struct ath_hal *ah); +extern void ar9285BTCoexSetParameter(struct ath_hal *ah, + u_int32_t value, u_int32_t type); + +#endif /* _ATH_AR9285_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285.ini b/sys/external/isc/atheros_hal/dist/ar9002/ar9285.ini new file mode 100644 index 0000000..ef0ff2d --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285.ini @@ -0,0 +1,699 @@ +/* + * Copyright (c) 2008-2009 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +/* AR9285 Revsion 10 */ +static const u_int32_t ar9285Modes[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020, 0x037216a0 }, + { 0x00009848, 0x00001066, 0x00001066, 0x0000004e, 0x0000004e, 0x00001059 }, + { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, + { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e }, + { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 }, + { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, + { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1020, 0xdfbc1020, 0xdfbc1010 }, + { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099b8, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c }, + { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, + { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, + { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, + { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, + { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, + { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, + { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, + { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114, 0x00000000 }, + { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, + { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, + { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, + { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, + { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, + { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, + { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, + { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, + { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, + { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284, 0x00000000 }, + { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288, 0x00000000 }, + { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220, 0x00000000 }, + { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, + { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, + { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304, 0x00000000 }, + { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, + { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, + { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380, 0x00000000 }, + { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384, 0x00000000 }, + { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, + { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, + { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, + { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, + { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, + { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, + { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04, 0x00000000 }, + { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, + { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, + { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c, 0x00000000 }, + { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80, 0x00000000 }, + { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84, 0x00000000 }, + { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88, 0x00000000 }, + { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c, 0x00000000 }, + { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90, 0x00000000 }, + { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80, 0x00000000 }, + { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, + { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, + { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c, 0x00000000 }, + { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90, 0x00000000 }, + { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c, 0x00000000 }, + { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310, 0x00000000 }, + { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, + { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, + { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324, 0x00000000 }, + { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704, 0x00000000 }, + { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4, 0x00000000 }, + { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8, 0x00000000 }, + { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, + { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, + { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720, 0x00000000 }, + { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724, 0x00000000 }, + { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728, 0x00000000 }, + { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c, 0x00000000 }, + { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0, 0x00000000 }, + { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4, 0x00000000 }, + { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, + { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, + { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4, 0x00000000 }, + { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, + { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, + { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, + { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad, 0x00000000 }, + { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, + { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, + { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9, 0x00000000 }, + { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5, 0x00000000 }, + { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, + { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, + { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5, 0x00000000 }, + { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, + { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, + { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, + { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, + { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, + { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, + { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, + { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7, 0x00000000 }, + { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, + { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf, 0x00000000 }, + { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7, 0x00000000 }, + { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 }, + { 0x0000aa04, 0x00000000, 0x00000000, 0x00068080, 0x00068080, 0x00000000 }, + { 0x0000aa08, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, + { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, + { 0x0000aa10, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, + { 0x0000aa14, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, + { 0x0000aa18, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, + { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, + { 0x0000aa20, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, + { 0x0000aa24, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, + { 0x0000aa28, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, + { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, + { 0x0000aa30, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, + { 0x0000aa34, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, + { 0x0000aa38, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, + { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, + { 0x0000aa40, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, + { 0x0000aa44, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, + { 0x0000aa48, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, + { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, + { 0x0000aa50, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac, 0x00000000 }, + { 0x0000aa54, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c, 0x00000000 }, + { 0x0000aa58, 0x00000000, 0x00000000, 0x00068224, 0x00068224, 0x00000000 }, + { 0x0000aa5c, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, + { 0x0000aa60, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, + { 0x0000aa64, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, + { 0x0000aa68, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, + { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068310, 0x00068310, 0x00000000 }, + { 0x0000aa70, 0x00000000, 0x00000000, 0x00068788, 0x00068788, 0x00000000 }, + { 0x0000aa74, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c, 0x00000000 }, + { 0x0000aa78, 0x00000000, 0x00000000, 0x00068790, 0x00068790, 0x00000000 }, + { 0x0000aa7c, 0x00000000, 0x00000000, 0x00068794, 0x00068794, 0x00000000 }, + { 0x0000aa80, 0x00000000, 0x00000000, 0x00068798, 0x00068798, 0x00000000 }, + { 0x0000aa84, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c, 0x00000000 }, + { 0x0000aa88, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89, 0x00000000 }, + { 0x0000aa8c, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d, 0x00000000 }, + { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91, 0x00000000 }, + { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95, 0x00000000 }, + { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99, 0x00000000 }, + { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5, 0x00000000 }, + { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9, 0x00000000 }, + { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad, 0x00000000 }, + { 0x0000aaa8, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c, 0x00000000 }, + { 0x0000aaac, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10, 0x00000000 }, + { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14, 0x00000000 }, + { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, + { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, + { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, + { 0x0000aac0, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380, 0x00000000 }, + { 0x0000aac4, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, + { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, + { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c, 0x00000000 }, + { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394, 0x00000000 }, + { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798, 0x00000000 }, + { 0x0000aad8, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c, 0x00000000 }, + { 0x0000aadc, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, + { 0x0000aae0, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, + { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718, 0x00000000 }, + { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705, 0x00000000 }, + { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709, 0x00000000 }, + { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d, 0x00000000 }, + { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711, 0x00000000 }, + { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715, 0x00000000 }, + { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719, 0x00000000 }, + { 0x0000ab00, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4, 0x00000000 }, + { 0x0000ab04, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, + { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, + { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, + { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, + { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, + { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc, 0x00000000 }, + { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1, 0x00000000 }, + { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, + { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, + { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, + { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, + { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd, 0x00000000 }, + { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, + { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd, 0x00000000 }, + { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, + { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, + { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2, 0x00000000 }, + { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, + { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, + { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, + { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, + { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, + { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, + { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, + { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, + { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a250, 0x001ff000, 0x001ff000, 0x001ca000, 0x001ca000, 0x001da000 }, + { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652 }, + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0002c89a, 0x0002c89a, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0002e89b, 0x0002e89b, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0003089c, 0x0003089c, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0003289d, 0x0003289d, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0003489e, 0x0003489e, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x000388de, 0x000388de, 0x00000000 }, + { 0x0000a338, 0x00000000, 0x00000000, 0x0003b91e, 0x0003b91e, 0x00000000 }, + { 0x0000a33c, 0x00000000, 0x00000000, 0x0003d95e, 0x0003d95e, 0x00000000 }, + { 0x0000a340, 0x00000000, 0x00000000, 0x000419df, 0x000419df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, +}; + +static const u_int32_t ar9285Common[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020045 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00004060, 0x00000000 }, + { 0x00004064, 0x00000000 }, + { 0x00007010, 0x00000031 }, + { 0x00007034, 0x00000002 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x00000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a80001a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0x00000000 }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c0, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0xa8a00010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x0000829c, 0x00000000 }, + { 0x00008300, 0x00000040 }, + { 0x00008314, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000001 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00000000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x00010380 }, + { 0x00008344, 0x00481043 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xafe68e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x00009910, 0x01002310 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009940, 0x14750604 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x2108ecff }, + { 0x00009968, 0x000003ce }, + { 0x00009970, 0x1927b515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x2def0a00 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, + { 0x0000a208, 0x803e6788 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x00206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a244, 0x00000000 }, + { 0x0000a248, 0xfffffffc }, + { 0x0000a24c, 0x00000000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0ccb5380 }, + { 0x0000a25c, 0x15151501 }, + { 0x0000a260, 0xdfa90f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0ebae9e6 }, + { 0x0000d270, 0x0d820820 }, + { 0x0000a278, 0x39ce739c }, + { 0x0000a27c, 0x050e039c }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x39ce739c }, + { 0x0000a398, 0x0000039c }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x39ce739c }, + { 0x0000a3e0, 0x0000039c }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f70081 }, + { 0x00007800, 0x00140000 }, + { 0x00007804, 0x0e4548d8 }, + { 0x00007808, 0x54214514 }, + { 0x0000780c, 0x02025820 }, + { 0x00007810, 0x71c0d388 }, + { 0x00007814, 0x924934a8 }, + { 0x0000781c, 0x00000000 }, + { 0x00007820, 0x00000c04 }, + { 0x00007824, 0x00d86fff }, + { 0x00007828, 0x26d2491b }, + { 0x0000782c, 0x6e36d97b }, + { 0x00007830, 0xedb6d96c }, + { 0x00007834, 0x71400086 }, + { 0x00007838, 0xfac68800 }, + { 0x0000783c, 0x0001fffe }, + { 0x00007840, 0xffeb1a20 }, + { 0x00007844, 0x000c0db6 }, + { 0x00007848, 0x6db61b6f }, + { 0x0000784c, 0x6d9b66db }, + { 0x00007850, 0x6d8c6dba }, + { 0x00007854, 0x00040000 }, + { 0x00007858, 0xdb003012 }, + { 0x0000785c, 0x04924914 }, + { 0x00007860, 0x21084210 }, + { 0x00007864, 0xf7d7ffde }, + { 0x00007868, 0xc2034080 }, + { 0x0000786c, 0x48609eb4 }, + { 0x00007870, 0x10142c00 }, +}; + +static const u_int32_t ar9285PciePhy_clkreq_always_on_L1[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffd }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +static const u_int32_t ar9285PciePhy_clkreq_off_L1[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffc }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285_attach.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_attach.c new file mode 100644 index 0000000..eb3490a --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_attach.c @@ -0,0 +1,581 @@ +/* + * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v4k.h" /* XXX for tx/rx gain */ + +#include "ar9002/ar9280.h" +#include "ar9002/ar9285.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ar9002/ar9285.ini" +#include "ar9002/ar9285v2.ini" +#include "ar9002/ar9280v2.ini" /* XXX ini for tx/rx gain */ + +#include "ar9002/ar9285_cal.h" +#include "ar9002/ar9285_phy.h" +#include "ar9002/ar9285_diversity.h" + +static const HAL_PERCAL_DATA ar9280_iq_cal = { /* single sample */ + .calName = "IQ", .calType = IQ_MISMATCH_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = PER_MAX_LOG_COUNT, + .calCollect = ar5416IQCalCollect, + .calPostProc = ar5416IQCalibration +}; +static const HAL_PERCAL_DATA ar9280_adc_gain_cal = { /* single sample */ + .calName = "ADC Gain", .calType = ADC_GAIN_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcGainCalCollect, + .calPostProc = ar5416AdcGainCalibration +}; +static const HAL_PERCAL_DATA ar9280_adc_dc_cal = { /* single sample */ + .calName = "ADC DC", .calType = ADC_DC_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; +static const HAL_PERCAL_DATA ar9280_adc_init_dc_cal = { + .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = INIT_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; + +static void ar9285ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, + HAL_BOOL power_off); +static void ar9285DisablePCIE(struct ath_hal *ah); +static HAL_BOOL ar9285FillCapabilityInfo(struct ath_hal *ah); +static void ar9285WriteIni(struct ath_hal *ah, + const struct ieee80211_channel *chan); + +static void +ar9285AniSetup(struct ath_hal *ah) +{ + /* + * These are the parameters from the AR5416 ANI code; + * they likely need quite a bit of adjustment for the + * AR9285. + */ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -55, -55, -55, -55, -62 }, + .coarseHigh = { -14, -14, -14, -14, -12 }, + .coarseLow = { -64, -64, -64, -64, -70 }, + .firpwr = { -78, -78, -78, -78, -80 }, + .maxSpurImmunityLevel = 7, + .cycPwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + /* NB: disable ANI noise immmunity for reliable RIFS rx */ + AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL); + + ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE); +} + +static const char * ar9285_lna_conf[] = { + "LNA1-LNA2", + "LNA2", + "LNA1", + "LNA1+LNA2", +}; + +static void +ar9285_eeprom_print_diversity_settings(struct ath_hal *ah) +{ + const HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + const MODAL_EEP4K_HEADER *pModal = &ee->ee_base.modalHeader; + + ath_hal_printf(ah, "[ath] AR9285 Main LNA config: %s\n", + ar9285_lna_conf[(pModal->antdiv_ctl2 >> 2) & 0x3]); + ath_hal_printf(ah, "[ath] AR9285 Alt LNA config: %s\n", + ar9285_lna_conf[pModal->antdiv_ctl2 & 0x3]); + ath_hal_printf(ah, "[ath] LNA diversity %s, Diversity %s\n", + ((pModal->antdiv_ctl1 & 0x1) ? "enabled" : "disabled"), + ((pModal->antdiv_ctl1 & 0x8) ? "enabled" : "disabled")); +} + +/* + * Attach for an AR9285 part. + */ +static struct ath_hal * +ar9285Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_OPS_CONFIG *ah_config, + HAL_STATUS *status) +{ + struct ath_hal_9285 *ahp9285; + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + uint32_t val; + HAL_STATUS ecode; + HAL_BOOL rfStatus; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp9285 = ath_hal_malloc(sizeof (struct ath_hal_9285)); + if (ahp9285 == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ahp = AH5212(ahp9285); + ah = &ahp->ah_priv.h; + + ar5416InitState(AH5416(ah), devid, sc, st, sh, status); + + /* + * Use the "local" EEPROM data given to us by the higher layers. + * This is a private copy out of system flash. The Linux ath9k + * commit for the initial AR9130 support mentions MMIO flash + * access is "unreliable." -adrian + */ + if (eepromdata != AH_NULL) { + AH_PRIVATE(ah)->ah_eepromRead = ath_hal_EepromDataRead; + AH_PRIVATE(ah)->ah_eepromWrite = NULL; + ah->ah_eepromdata = eepromdata; + } + + /* override with 9285 specific state */ + AH5416(ah)->ah_initPLL = ar9280InitPLL; + AH5416(ah)->ah_btCoexSetDiversity = ar9285BTCoexAntennaDiversity; + + ah->ah_setAntennaSwitch = ar9285SetAntennaSwitch; + ah->ah_configPCIE = ar9285ConfigPCIE; + ah->ah_disablePCIE = ar9285DisablePCIE; + ah->ah_setTxPower = ar9285SetTransmitPower; + ah->ah_setBoardValues = ar9285SetBoardValues; + ah->ah_btCoexSetParameter = ar9285BTCoexSetParameter; + ah->ah_divLnaConfGet = ar9285_antdiv_comb_conf_get; + ah->ah_divLnaConfSet = ar9285_antdiv_comb_conf_set; + + AH5416(ah)->ah_cal.iqCalData.calData = &ar9280_iq_cal; + AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9280_adc_gain_cal; + AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9280_adc_dc_cal; + AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9280_adc_init_dc_cal; + AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; + + AH5416(ah)->ah_spurMitigate = ar9280SpurMitigate; + AH5416(ah)->ah_writeIni = ar9285WriteIni; + AH5416(ah)->ah_rx_chainmask = AR9285_DEFAULT_RXCHAINMASK; + AH5416(ah)->ah_tx_chainmask = AR9285_DEFAULT_TXCHAINMASK; + + ahp->ah_maxTxTrigLev = MAX_TX_FIFO_THRESHOLD >> 1; + + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { + /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + /* Read Revisions from Chips before taking out of reset */ + val = OS_REG_READ(ah, AR_SREV); + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", + __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), + MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); + /* NB: include chip type to differentiate from pre-Sowl versions */ + AH_PRIVATE(ah)->ah_macVersion = + (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S; + AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); + AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0; + + /* setup common ini data; rf backends handle remainder */ + if (AR_SREV_KITE_12_OR_LATER(ah)) { + HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes_v2, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common_v2, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, + ar9285PciePhy_clkreq_always_on_L1_v2, 2); + } else { + HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common, 2); + HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, + ar9285PciePhy_clkreq_always_on_L1, 2); + } + ar5416AttachPCIE(ah); + + /* Attach methods that require MAC version/revision info */ + if (AR_SREV_KITE_12_OR_LATER(ah)) + AH5416(ah)->ah_cal_initcal = ar9285InitCalHardware; + if (AR_SREV_KITE_11_OR_LATER(ah)) + AH5416(ah)->ah_cal_pacal = ar9002_hw_pa_cal; + + ecode = ath_hal_v4kEepromAttach(ah); + if (ecode != HAL_OK) + goto bad; + + if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); + switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { + case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ + case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ + break; + default: + if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5133_SREV_MAJOR; + break; + } +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; +#endif + } + rfStatus = ar9285RfAttach(ah, &ecode); + if (!rfStatus) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + + HAL_INI_INIT(&ahp9285->ah_ini_rxgain, ar9280Modes_original_rxgain_v2, + 6); + + if (AR_SREV_9285E_20(ah)) + ath_hal_printf(ah, "[ath] AR9285E_20 detected; using XE TX gain tables\n"); + + /* setup txgain table */ + switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) { + case AR5416_EEP_TXGAIN_HIGH_POWER: + if (AR_SREV_9285E_20(ah)) + HAL_INI_INIT(&ahp9285->ah_ini_txgain, + ar9285Modes_XE2_0_high_power, 6); + else + HAL_INI_INIT(&ahp9285->ah_ini_txgain, + ar9285Modes_high_power_tx_gain_v2, 6); + break; + case AR5416_EEP_TXGAIN_ORIG: + if (AR_SREV_9285E_20(ah)) + HAL_INI_INIT(&ahp9285->ah_ini_txgain, + ar9285Modes_XE2_0_normal_power, 6); + else + HAL_INI_INIT(&ahp9285->ah_ini_txgain, + ar9285Modes_original_tx_gain_v2, 6); + break; + default: + HALASSERT(AH_FALSE); + goto bad; /* XXX ? try to continue */ + } + + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar9285FillCapabilityInfo(ah)) { + ecode = HAL_EEREAD; + goto bad; + } + + /* + * Print out the EEPROM antenna configuration mapping. + * Some devices have a hard-coded LNA configuration profile; + * others enable diversity. + */ + ar9285_eeprom_print_diversity_settings(ah); + + /* Print out whether the EEPROM settings enable AR9285 diversity */ + if (ar9285_check_div_comb(ah)) { + ath_hal_printf(ah, "[ath] Enabling diversity for Kite\n"); + } + + /* Disable 11n for the AR2427 */ + if (devid == AR2427_DEVID_PCIE) + AH_PRIVATE(ah)->ah_caps.halHTSupport = AH_FALSE; + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + /* XXX How about the serial number ? */ + /* Read Reg Domain */ + AH_PRIVATE(ah)->ah_currentRD = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + /* + * For Kite and later chipsets, the following bits are not + * programmed in EEPROM and so are set as enabled always. + */ + AH_PRIVATE(ah)->ah_currentRDext = AR9285_RDEXT_DEFAULT; + + /* + * ah_miscMode is populated by ar5416FillCapabilityInfo() + * starting from griffin. Set here to make sure that + * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is + * placed into hardware. + */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); + + ar9285AniSetup(ah); /* Anti Noise Immunity */ + + /* Setup noise floor min/max/nominal values */ + AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ; + AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ; + AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ; + /* XXX no 5ghz values? */ + + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +bad: + if (ah != AH_NULL) + ah->ah_detach(ah); + if (status) + *status = ecode; + return AH_NULL; +} + +static void +ar9285ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) +{ + uint32_t val; + + /* + * This workaround needs some integration work with the HAL + * config parameters and the if_ath_pci.c glue. + * Specifically, read the value of the PCI register 0x70c + * (4 byte PCI config space register) and store it in ath_hal_war70c. + * Then if it's non-zero, the below WAR would override register + * 0x570c upon suspend/resume. + */ +#if 0 + if (AR_SREV_9285E_20(ah)) { + val = AH_PRIVATE(ah)->ah_config.ath_hal_war70c; + if (val) { + val &= 0xffff00ff; + val |= 0x6f00; + OS_REG_WRITE(ah, 0x570c, val); + } + } +#endif + + if (AH_PRIVATE(ah)->ah_ispcie && !restore) { + ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0); + OS_DELAY(1000); + } + + /* + * Set PCIe workaround bits + * + * NOTE: + * + * In Merlin and Kite, bit 14 in WA register (disable L1) should only + * be set when device enters D3 and be cleared when device comes back + * to D0. + */ + if (power_off) { /* Power-off */ + OS_REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + + val = OS_REG_READ(ah, AR_WA); + + /* + * Disable bit 6 and 7 before entering D3 to prevent + * system hang. + */ + val &= ~(AR_WA_BIT6 | AR_WA_BIT7); + + /* + * See above: set AR_WA_D3_L1_DISABLE when entering D3 state. + * + * XXX The reference HAL does it this way - it only sets + * AR_WA_D3_L1_DISABLE if it's set in AR9280_WA_DEFAULT, + * which it (currently) isn't. So the following statement + * is currently a NOP. + */ + if (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE) + val |= AR_WA_D3_L1_DISABLE; + + if (AR_SREV_9285E_20(ah)) + val |= AR_WA_BIT23; + + OS_REG_WRITE(ah, AR_WA, val); + } else { /* Power-on */ + val = AR9285_WA_DEFAULT; + /* + * See note above: make sure L1_DISABLE is not set. + */ + val &= (~AR_WA_D3_L1_DISABLE); + + /* Software workaroud for ASPM system hang. */ + val |= (AR_WA_BIT6 | AR_WA_BIT7); + + if (AR_SREV_9285E_20(ah)) + val |= AR_WA_BIT23; + + OS_REG_WRITE(ah, AR_WA, val); + + /* set bit 19 to allow forcing of pcie core into L1 state */ + OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + } +} + +static void +ar9285DisablePCIE(struct ath_hal *ah) +{ +} + +static void +ar9285WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + u_int modesIndex, freqIndex; + int regWrites = 0; + + /* Setup the indices for the next set of register array writes */ + /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */ + freqIndex = 2; + if (IEEE80211_IS_CHAN_HT40(chan)) + modesIndex = 3; + else if (IEEE80211_IS_CHAN_108G(chan)) + modesIndex = 5; + else + modesIndex = 4; + + /* Set correct Baseband to analog shift setting to access analog chips. */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); + regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, + modesIndex, regWrites); + if (AR_SREV_KITE_12_OR_LATER(ah)) { + regWrites = ath_hal_ini_write(ah, &AH9285(ah)->ah_ini_txgain, + modesIndex, regWrites); + } + regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, + 1, regWrites); +} + +/* + * Fill all software cached or static hardware state information. + * Return failure if capabilities are to come from EEPROM and + * cannot be read. + */ +static HAL_BOOL +ar9285FillCapabilityInfo(struct ath_hal *ah) +{ + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + if (!ar5416FillCapabilityInfo(ah)) + return AH_FALSE; + pCap->halNumGpioPins = 12; + pCap->halWowSupport = AH_TRUE; + pCap->halWowMatchPatternExact = AH_TRUE; +#if 0 + pCap->halWowMatchPatternDword = AH_TRUE; +#endif + /* AR9285 has 2 antennas but is a 1x1 stream device */ + pCap->halTxStreams = 1; + pCap->halRxStreams = 1; + + if (ar9285_check_div_comb(ah)) + pCap->halAntDivCombSupport = AH_TRUE; + + pCap->halCSTSupport = AH_TRUE; + pCap->halRifsRxSupport = AH_TRUE; + pCap->halRifsTxSupport = AH_TRUE; + pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ + pCap->halExtChanDfsSupport = AH_TRUE; + pCap->halUseCombinedRadarRssi = AH_TRUE; +#if 1 + /* XXX bluetooth */ + pCap->halBtCoexSupport = AH_TRUE; +#endif + pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ + pCap->hal4kbSplitTransSupport = AH_FALSE; + /* Disable this so Block-ACK works correctly */ + pCap->halHasRxSelfLinkedTail = AH_FALSE; + pCap->halMbssidAggrSupport = AH_TRUE; + pCap->hal4AddrAggrSupport = AH_TRUE; + pCap->halSpectralScanSupport = AH_TRUE; + pCap->halRxUsingLnaMixing = AH_TRUE; + + if (AR_SREV_KITE_12_OR_LATER(ah)) + pCap->halPSPollBroken = AH_FALSE; + + /* Only RX STBC supported */ + pCap->halRxStbcSupport = 1; + pCap->halTxStbcSupport = 0; + + return AH_TRUE; +} + +static const char* +ar9285Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID && devid == AR9285_DEVID_PCIE) + return "Atheros 9285"; + if (vendorid == ATHEROS_VENDOR_ID && (devid == AR2427_DEVID_PCIE)) + return "Atheros 2427"; + + return AH_NULL; +} +AH_CHIP(AR9285, ar9285Probe, ar9285Attach); diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285_btcoex.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_btcoex.c new file mode 100644 index 0000000..4d79a4f --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_btcoex.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2005 Atheros Communications, Inc. + * Copyright (c) 2008-2010, Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#ifdef AH_DEBUG +#include "ah_desc.h" /* NB: for HAL_PHYERR* */ +#endif + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar5416/ar5416desc.h" /* AR5416_CONTTXMODE */ + +#include "ar9002/ar9285phy.h" +#include "ar9002/ar9285.h" + +/* + * This is specific to Kite. + * + * Kiwi and others don't have antenna diversity like this. + */ +void +ar9285BTCoexAntennaDiversity(struct ath_hal *ah) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + u_int32_t regVal; + u_int8_t ant_div_control1, ant_div_control2; + + HALDEBUG(ah, HAL_DEBUG_BT_COEX, + "%s: btCoexFlag: ALLOW=%d, ENABLE=%d\n", + __func__, + !! (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW), + !! (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ENABLE)); + + if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW) || + (AH5212(ah)->ah_diversity != HAL_ANT_VARIABLE)) { + if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ENABLE) && + (AH5212(ah)->ah_antControl == HAL_ANT_VARIABLE)) { + /* Enable antenna diversity */ + ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_ENABLE; + ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_ENABLE; + + /* Don't disable BT ant to allow BB to control SWCOM */ + ahp->ah_btCoexMode2 &= (~(AR_BT_DISABLE_BT_ANT)); + OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); + + /* Program the correct SWCOM table */ + OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, + HAL_BT_COEX_ANT_DIV_SWITCH_COM); + OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000); + } else if (AH5212(ah)->ah_antControl == HAL_ANT_FIXED_B) { + /* Disable antenna diversity. Use antenna B(LNA2) only. */ + ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_B; + ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_B; + + /* Disable BT ant to allow concurrent BT and WLAN receive */ + ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT; + OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); + + /* + * Program SWCOM table to make sure RF switch always parks + * at WLAN side + */ + OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, + HAL_BT_COEX_ANT_DIV_SWITCH_COM); + OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0x60000000, 0xf0000000); + } else { + /* Disable antenna diversity. Use antenna A(LNA1) only */ + ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_A; + ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_A; + + /* Disable BT ant to allow concurrent BT and WLAN receive */ + ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT; + OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); + + /* + * Program SWCOM table to make sure RF switch always + * parks at BT side + */ + OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 0); + OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000); + } + + regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL)); + /* + * Clear ant_fast_div_bias [14:9] since for Janus the main LNA is + * always LNA1. + */ + regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS)); + + regVal |= SM(ant_div_control1, AR_PHY_9285_ANT_DIV_CTL); + regVal |= SM(ant_div_control2, AR_PHY_9285_ANT_DIV_ALT_LNACONF); + regVal |= SM((ant_div_control2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF); + regVal |= SM((ant_div_control1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB); + regVal |= SM((ant_div_control1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB); + OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); + + regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT); + regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + regVal |= SM((ant_div_control1 >> 3), + AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal); + } +} + +void +ar9285BTCoexSetParameter(struct ath_hal *ah, u_int32_t type, u_int32_t value) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + + switch (type) { + case HAL_BT_COEX_ANTENNA_DIVERSITY: + if (AR_SREV_KITE(ah)) { + ahp->ah_btCoexFlag |= HAL_BT_COEX_FLAG_ANT_DIV_ALLOW; + if (value) + ahp->ah_btCoexFlag |= + HAL_BT_COEX_FLAG_ANT_DIV_ENABLE; + else + ahp->ah_btCoexFlag &= + ~HAL_BT_COEX_FLAG_ANT_DIV_ENABLE; + ar9285BTCoexAntennaDiversity(ah); + } + break; + default: + ar5416BTCoexSetParameter(ah, type, value); + break; + } +} + + diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285_cal.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_cal.c new file mode 100644 index 0000000..a743e21 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_cal.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v4k.h" + +#include "ar9002/ar9285.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9002/ar9002phy.h" +#include "ar9002/ar9285phy.h" +#include "ar9002/ar9285an.h" + +#include "ar9002/ar9285_cal.h" + +#define AR9285_CLCAL_REDO_THRESH 1 +#define MAX_PACAL_SKIPCOUNT 8 + +#define N(a) (sizeof (a) / sizeof (a[0])) + +static void +ar9285_hw_pa_cal(struct ath_hal *ah, HAL_BOOL is_reset) +{ + uint32_t regVal; + int i, offset, offs_6_1, offs_0; + uint32_t ccomp_org, reg_field; + uint32_t regList[][2] = { + { 0x786c, 0 }, + { 0x7854, 0 }, + { 0x7820, 0 }, + { 0x7824, 0 }, + { 0x7868, 0 }, + { 0x783c, 0 }, + { 0x7838, 0 }, + }; + + /* PA CAL is not needed for high power solution */ + if (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL) == + AR5416_EEP_TXGAIN_HIGH_POWER) + return; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, "Running PA Calibration\n"); + + for (i = 0; i < N(regList); i++) + regList[i][1] = OS_REG_READ(ah, regList[i][0]); + + regVal = OS_REG_READ(ah, 0x7834); + regVal &= (~(0x1)); + OS_REG_WRITE(ah, 0x7834, regVal); + regVal = OS_REG_READ(ah, 0x9808); + regVal |= (0x1 << 27); + OS_REG_WRITE(ah, 0x9808, regVal); + + OS_REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); + OS_REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); + OS_REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); + OS_REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); + ccomp_org = MS(OS_REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf); + + OS_REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); + OS_DELAY(30); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); + + for (i = 6; i > 0; i--) { + regVal = OS_REG_READ(ah, 0x7834); + regVal |= (1 << (19 + i)); + OS_REG_WRITE(ah, 0x7834, regVal); + OS_DELAY(1); + regVal = OS_REG_READ(ah, 0x7834); + regVal &= (~(0x1 << (19 + i))); + reg_field = MS(OS_REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); + regVal |= (reg_field << (19 + i)); + OS_REG_WRITE(ah, 0x7834, regVal); + } + + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); + OS_DELAY(1); + reg_field = MS(OS_REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); + offs_6_1 = MS(OS_REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); + offs_0 = MS(OS_REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); + + offset = (offs_6_1<<1) | offs_0; + offset = offset - 0; + offs_6_1 = offset>>1; + offs_0 = offset & 1; + + if ((!is_reset) && (AH9285(ah)->pacal_info.prev_offset == offset)) { + if (AH9285(ah)->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) + AH9285(ah)->pacal_info.max_skipcount = + 2 * AH9285(ah)->pacal_info.max_skipcount; + AH9285(ah)->pacal_info.skipcount = AH9285(ah)->pacal_info.max_skipcount; + } else { + AH9285(ah)->pacal_info.max_skipcount = 1; + AH9285(ah)->pacal_info.skipcount = 0; + AH9285(ah)->pacal_info.prev_offset = offset; + } + + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); + + regVal = OS_REG_READ(ah, 0x7834); + regVal |= 0x1; + OS_REG_WRITE(ah, 0x7834, regVal); + regVal = OS_REG_READ(ah, 0x9808); + regVal &= (~(0x1 << 27)); + OS_REG_WRITE(ah, 0x9808, regVal); + + for (i = 0; i < N(regList); i++) + OS_REG_WRITE(ah, regList[i][0], regList[i][1]); + + OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); +} + +void +ar9002_hw_pa_cal(struct ath_hal *ah, HAL_BOOL is_reset) +{ + if (AR_SREV_KITE_11_OR_LATER(ah)) { + if (is_reset || !AH9285(ah)->pacal_info.skipcount) + ar9285_hw_pa_cal(ah, is_reset); + else + AH9285(ah)->pacal_info.skipcount--; + } +} + +/* Carrier leakage Calibration fix */ +static HAL_BOOL +ar9285_hw_cl_cal(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + if (IEEE80211_IS_CHAN_HT20(chan)) { + OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); + OS_REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_FLTR_CAL); + OS_REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "offset calibration failed to complete in 1ms; noisy environment?\n"); + return AH_FALSE; + } + OS_REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); + OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); + OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + } + OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + OS_REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, + 0)) { + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "offset calibration failed to complete in 1ms; noisy environment?\n"); + return AH_FALSE; + } + + OS_REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + + return AH_TRUE; +} + +static HAL_BOOL +ar9285_hw_clc(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + int i; + uint32_t txgain_max; + uint32_t clc_gain, gain_mask = 0, clc_num = 0; + uint32_t reg_clc_I0, reg_clc_Q0; + uint32_t i0_num = 0; + uint32_t q0_num = 0; + uint32_t total_num = 0; + uint32_t reg_rf2g5_org; + HAL_BOOL retv = AH_TRUE; + + if (!(ar9285_hw_cl_cal(ah, chan))) + return AH_FALSE; + + txgain_max = MS(OS_REG_READ(ah, AR_PHY_TX_PWRCTRL7), + AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX); + + for (i = 0; i < (txgain_max+1); i++) { + clc_gain = (OS_REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) & + AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S; + if (!(gain_mask & (1 << clc_gain))) { + gain_mask |= (1 << clc_gain); + clc_num++; + } + } + + for (i = 0; i < clc_num; i++) { + reg_clc_I0 = (OS_REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) + & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S; + reg_clc_Q0 = (OS_REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) + & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S; + if (reg_clc_I0 == 0) + i0_num++; + + if (reg_clc_Q0 == 0) + q0_num++; + } + total_num = i0_num + q0_num; + if (total_num > AR9285_CLCAL_REDO_THRESH) { + reg_rf2g5_org = OS_REG_READ(ah, AR9285_RF2G5); + if (AR_SREV_9285E_20(ah)) { + OS_REG_WRITE(ah, AR9285_RF2G5, + (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | + AR9285_RF2G5_IC50TX_XE_SET); + } else { + OS_REG_WRITE(ah, AR9285_RF2G5, + (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | + AR9285_RF2G5_IC50TX_SET); + } + retv = ar9285_hw_cl_cal(ah, chan); + OS_REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org); + } + return retv; +} + +HAL_BOOL +ar9285InitCalHardware(struct ath_hal *ah, + const struct ieee80211_channel *chan) +{ + if (AR_SREV_KITE(ah) && AR_SREV_KITE_10_OR_LATER(ah) && + (! ar9285_hw_clc(ah, chan))) + return AH_FALSE; + + return AH_TRUE; +} diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285_cal.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_cal.h new file mode 100644 index 0000000..c6ecc41 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_cal.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __AR9285_CAL_H__ +#define __AR9285_CAL_H__ + +extern void ar9002_hw_pa_cal(struct ath_hal *ah, HAL_BOOL is_reset); +extern HAL_BOOL ar9285InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan); + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285_diversity.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_diversity.c new file mode 100644 index 0000000..5fd01b7 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_diversity.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_desc.h" +#include "ah_internal.h" +#include "ah_eeprom_v4k.h" + +#include "ar9002/ar9280.h" +#include "ar9002/ar9285.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9002/ar9285phy.h" +#include "ar9002/ar9285_phy.h" + +#include "ar9002/ar9285_diversity.h" + +/* + * Set the antenna switch to control RX antenna diversity. + * + * If a fixed configuration is used, the LNA and div bias + * settings are fixed and the antenna diversity scanning routine + * is disabled. + * + * If a variable configuration is used, a default is programmed + * in and sampling commences per RXed packet. + * + * Since this is called from ar9285SetBoardValues() to setup + * diversity, it means that after a reset or scan, any current + * software diversity combining settings will be lost and won't + * re-appear until after the first successful sample run. + * Please keep this in mind if you're seeing weird performance + * that happens to relate to scan/diversity timing. + */ +HAL_BOOL +ar9285SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) +{ + int regVal; + const HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + const MODAL_EEP4K_HEADER *pModal = &ee->ee_base.modalHeader; + uint8_t ant_div_control1, ant_div_control2; + + if (pModal->version < 3) { + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: not supported\n", + __func__); + return AH_FALSE; /* Can't do diversity */ + } + + /* Store settings */ + AH5212(ah)->ah_antControl = settings; + AH5212(ah)->ah_diversity = (settings == HAL_ANT_VARIABLE); + + /* XXX don't fiddle if the PHY is in sleep mode or ! chan */ + + /* Begin setting the relevant registers */ + + ant_div_control1 = pModal->antdiv_ctl1; + ant_div_control2 = pModal->antdiv_ctl2; + + regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL)); + + /* enable antenna diversity only if diversityControl == HAL_ANT_VARIABLE */ + if (settings == HAL_ANT_VARIABLE) + regVal |= SM(ant_div_control1, AR_PHY_9285_ANT_DIV_CTL); + + if (settings == HAL_ANT_VARIABLE) { + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: HAL_ANT_VARIABLE\n", + __func__); + regVal |= SM(ant_div_control2, AR_PHY_9285_ANT_DIV_ALT_LNACONF); + regVal |= SM((ant_div_control2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF); + regVal |= SM((ant_div_control1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB); + regVal |= SM((ant_div_control1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB); + } else { + if (settings == HAL_ANT_FIXED_A) { + /* Diversity disabled, RX = LNA1 */ + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: HAL_ANT_FIXED_A\n", + __func__); + regVal |= SM(HAL_ANT_DIV_COMB_LNA2, AR_PHY_9285_ANT_DIV_ALT_LNACONF); + regVal |= SM(HAL_ANT_DIV_COMB_LNA1, AR_PHY_9285_ANT_DIV_MAIN_LNACONF); + regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_0, AR_PHY_9285_ANT_DIV_ALT_GAINTB); + regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_1, AR_PHY_9285_ANT_DIV_MAIN_GAINTB); + } + else if (settings == HAL_ANT_FIXED_B) { + /* Diversity disabled, RX = LNA2 */ + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: HAL_ANT_FIXED_B\n", + __func__); + regVal |= SM(HAL_ANT_DIV_COMB_LNA1, AR_PHY_9285_ANT_DIV_ALT_LNACONF); + regVal |= SM(HAL_ANT_DIV_COMB_LNA2, AR_PHY_9285_ANT_DIV_MAIN_LNACONF); + regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_1, AR_PHY_9285_ANT_DIV_ALT_GAINTB); + regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_0, AR_PHY_9285_ANT_DIV_MAIN_GAINTB); + } + } + + OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); + regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT); + regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + if (settings == HAL_ANT_VARIABLE) + regVal |= SM((ant_div_control1 >> 3), AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + + OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal); + regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT); + + /* + * If Diversity combining is available and the diversity setting + * is to allow variable diversity, enable it by default. + * + * This will be eventually overridden by the software antenna + * diversity logic. + * + * Note that yes, this following section overrides the above + * settings for the LNA configuration and fast-bias. + */ + if (ar9285_check_div_comb(ah) && AH5212(ah)->ah_diversity == AH_TRUE) { + // If support DivComb, set MAIN to LNA1 and ALT to LNA2 at the first beginning + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, + "%s: Enable initial settings for combined diversity\n", + __func__); + regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + regVal &= (~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF | AR_PHY_9285_ANT_DIV_ALT_LNACONF)); + regVal |= (HAL_ANT_DIV_COMB_LNA1 << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S); + regVal |= (HAL_ANT_DIV_COMB_LNA2 << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S); + regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS)); + regVal |= (0 << AR_PHY_9285_FAST_DIV_BIAS_S); + OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); + } + + return AH_TRUE; +} diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285_diversity.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_diversity.h new file mode 100644 index 0000000..59d53b6 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_diversity.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __AR9285_DIVERSITY_H__ +#define __AR9285_DIVERSITY_H__ + +extern HAL_BOOL ar9285SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285_phy.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_phy.c new file mode 100644 index 0000000..c91048a --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_phy.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" +#include "ah_eeprom_v4k.h" + +#include "ar9002/ar9280.h" +#include "ar9002/ar9285.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9002/ar9285phy.h" +#include "ar9002/ar9285_phy.h" + +void +ar9285_antdiv_comb_conf_get(struct ath_hal *ah, HAL_ANT_COMB_CONFIG *antconf) +{ + uint32_t regval; + + regval = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + antconf->main_lna_conf = (regval & AR_PHY_9285_ANT_DIV_MAIN_LNACONF) >> + AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S; + antconf->alt_lna_conf = (regval & AR_PHY_9285_ANT_DIV_ALT_LNACONF) >> + AR_PHY_9285_ANT_DIV_ALT_LNACONF_S; + antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >> + AR_PHY_9285_FAST_DIV_BIAS_S; + antconf->antdiv_configgroup = DEFAULT_ANTDIV_CONFIG_GROUP; +} + +void +ar9285_antdiv_comb_conf_set(struct ath_hal *ah, HAL_ANT_COMB_CONFIG *antconf) +{ + uint32_t regval; + + regval = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + regval &= ~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF | + AR_PHY_9285_ANT_DIV_ALT_LNACONF | + AR_PHY_9285_FAST_DIV_BIAS); + regval |= ((antconf->main_lna_conf << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S) + & AR_PHY_9285_ANT_DIV_MAIN_LNACONF); + regval |= ((antconf->alt_lna_conf << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S) + & AR_PHY_9285_ANT_DIV_ALT_LNACONF); + regval |= ((antconf->fast_div_bias << AR_PHY_9285_FAST_DIV_BIAS_S) + & AR_PHY_9285_FAST_DIV_BIAS); + + OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval); +} + +/* + * Check whether combined + fast antenna diversity should be enabled. + * + * This enables software-driven RX antenna diversity based on RX + * RSSI + antenna config packet sampling. + */ +HAL_BOOL +ar9285_check_div_comb(struct ath_hal *ah) +{ + uint8_t ant_div_ctl1; + HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + const MODAL_EEP4K_HEADER *pModal = &ee->ee_base.modalHeader; + +#if 0 + /* For now, simply disable this until it's better debugged. -adrian */ + return AH_FALSE; +#endif + + if (! AR_SREV_KITE(ah)) + return AH_FALSE; + + if (pModal->version < 3) + return AH_FALSE; + + ant_div_ctl1 = pModal->antdiv_ctl1; + if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) + return AH_TRUE; + + return AH_FALSE; +} diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285_phy.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_phy.h new file mode 100644 index 0000000..0255e17 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_phy.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __AR9285_PHY_H__ +#define __AR9285_PHY_H__ + +/* + * Manipulate AR9285 antenna diversity configuration + */ + +extern void ar9285_antdiv_comb_conf_set(struct ath_hal *ah, + HAL_ANT_COMB_CONFIG *antconf); +extern void ar9285_antdiv_comb_conf_get(struct ath_hal *ah, + HAL_ANT_COMB_CONFIG *antconf); +extern HAL_BOOL ar9285_check_div_comb(struct ath_hal *ah); + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285_reset.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_reset.c new file mode 100644 index 0000000..cb5940f --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285_reset.c @@ -0,0 +1,801 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +/* + * This is almost the same as ar5416_reset.c but uses the v4k EEPROM and + * supports only 2Ghz operation. + */ + +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" +#include "ah_eeprom_v4k.h" + +#include "ar9002/ar9285.h" +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9002/ar9002phy.h" +#include "ar9002/ar9285phy.h" +#include "ar9002/ar9285an.h" +#include "ar9002/ar9285_diversity.h" + +/* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */ +#define EEP_MINOR(_ah) \ + (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK) +#define IS_EEP_MINOR_V2(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2) +#define IS_EEP_MINOR_V3(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_3) + +/* Additional Time delay to wait after activiting the Base band */ +#define BASE_ACTIVATE_DELAY 100 /* 100 usec */ +#define PLL_SETTLE_DELAY 300 /* 300 usec */ +#define RTC_PLL_SETTLE_DELAY 1000 /* 1 ms */ + +static HAL_BOOL ar9285SetPowerPerRateTable(struct ath_hal *ah, + struct ar5416eeprom_4k *pEepData, + const struct ieee80211_channel *chan, int16_t *ratesArray, + uint16_t cfgCtl, uint16_t AntennaReduction, + uint16_t twiceMaxRegulatoryPower, + uint16_t powerLimit); +static HAL_BOOL ar9285SetPowerCalTable(struct ath_hal *ah, + struct ar5416eeprom_4k *pEepData, + const struct ieee80211_channel *chan, + int16_t *pTxPowerIndexOffset); +static void ar9285GetGainBoundariesAndPdadcs(struct ath_hal *ah, + const struct ieee80211_channel *chan, CAL_DATA_PER_FREQ_4K *pRawDataSet, + uint8_t * bChans, uint16_t availPiers, + uint16_t tPdGainOverlap, int16_t *pMinCalPower, + uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues, + uint16_t numXpdGains); + +HAL_BOOL +ar9285SetTransmitPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain) +{ +#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) +#define N(a) (sizeof (a) / sizeof (a[0])) + + MODAL_EEP4K_HEADER *pModal; + struct ath_hal_5212 *ahp = AH5212(ah); + int16_t txPowerIndexOffset = 0; + int i; + + uint16_t cfgCtl; + uint16_t powerLimit; + uint16_t twiceAntennaReduction; + uint16_t twiceMaxRegulatoryPower; + int16_t maxPower; + HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ar5416eeprom_4k *pEepData = &ee->ee_base; + + HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); + + AH5416(ah)->ah_ht40PowerIncForPdadc = 2; + + /* Setup info for the actual eeprom */ + OS_MEMZERO(AH5416(ah)->ah_ratesArray, sizeof(AH5416(ah)->ah_ratesArray)); + cfgCtl = ath_hal_getctl(ah, chan); + powerLimit = chan->ic_maxregpower * 2; + twiceAntennaReduction = chan->ic_maxantgain; + twiceMaxRegulatoryPower = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit); + pModal = &pEepData->modalHeader; + HALDEBUG(ah, HAL_DEBUG_RESET, "%s Channel=%u CfgCtl=%u\n", + __func__,chan->ic_freq, cfgCtl ); + + if (IS_EEP_MINOR_V2(ah)) { + AH5416(ah)->ah_ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; + } + + if (!ar9285SetPowerPerRateTable(ah, pEepData, chan, + &AH5416(ah)->ah_ratesArray[0],cfgCtl, + twiceAntennaReduction, + twiceMaxRegulatoryPower, powerLimit)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to set tx power per rate table\n", __func__); + return AH_FALSE; + } + + if (!ar9285SetPowerCalTable(ah, pEepData, chan, &txPowerIndexOffset)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n", + __func__); + return AH_FALSE; + } + + maxPower = AH_MAX(AH5416(ah)->ah_ratesArray[rate6mb], + AH5416(ah)->ah_ratesArray[rateHt20_0]); + maxPower = AH_MAX(maxPower, AH5416(ah)->ah_ratesArray[rate1l]); + + if (IEEE80211_IS_CHAN_HT40(chan)) { + maxPower = AH_MAX(maxPower, AH5416(ah)->ah_ratesArray[rateHt40_0]); + } + + ahp->ah_tx6PowerInHalfDbm = maxPower; + AH_PRIVATE(ah)->ah_maxPowerLevel = maxPower; + ahp->ah_txPowerIndexOffset = txPowerIndexOffset; + + /* + * txPowerIndexOffset is set by the SetPowerTable() call - + * adjust the rate table (0 offset if rates EEPROM not loaded) + */ + for (i = 0; i < N(AH5416(ah)->ah_ratesArray); i++) { + AH5416(ah)->ah_ratesArray[i] = (int16_t)(txPowerIndexOffset + AH5416(ah)->ah_ratesArray[i]); + /* -5 dBm offset for Merlin and later; this includes Kite */ + AH5416(ah)->ah_ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; + if (AH5416(ah)->ah_ratesArray[i] > AR5416_MAX_RATE_POWER) + AH5416(ah)->ah_ratesArray[i] = AR5416_MAX_RATE_POWER; + if (AH5416(ah)->ah_ratesArray[i] < 0) + AH5416(ah)->ah_ratesArray[i] = 0; + } + +#ifdef AH_EEPROM_DUMP + ar5416PrintPowerPerRate(ah, AH5416(ah)->ah_ratesArray); +#endif + + /* + * Adjust the HT40 power to meet the correct target TX power + * for 40MHz mode, based on TX power curves that are established + * for 20MHz mode. + * + * XXX handle overflow/too high power level? + */ + if (IEEE80211_IS_CHAN_HT40(chan)) { + AH5416(ah)->ah_ratesArray[rateHt40_0] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_1] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_2] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_3] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_4] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_5] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_6] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_7] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + } + + /* Write the TX power rate registers */ + ar5416WriteTxPowerRateRegisters(ah, chan, AH5416(ah)->ah_ratesArray); + + return AH_TRUE; +#undef POW_SM +#undef N +} + +static void +ar9285SetBoardGain(struct ath_hal *ah, const MODAL_EEP4K_HEADER *pModal, + const struct ar5416eeprom_4k *eep, uint8_t txRxAttenLocal) +{ + OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0, + pModal->antCtrlChain[0]); + + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), + (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0)) & + ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | + SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | + SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); + + if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= + AR5416_EEP_MINOR_VER_3) { + txRxAttenLocal = pModal->txRxAttenCh[0]; + + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, + AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, + AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, + AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, pModal->xatten2Margin[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, + AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); + + /* Set the block 1 value to block 0 value */ + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, + AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, + pModal->bswMargin[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, + AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, + AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, + pModal->xatten2Margin[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, + AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); + } + + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, + AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, + AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); + + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, + AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, + AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); +} + +/* + * Read EEPROM header info and program the device for correct operation + * given the channel value. + */ +HAL_BOOL +ar9285SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + const HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + const struct ar5416eeprom_4k *eep = &ee->ee_base; + const MODAL_EEP4K_HEADER *pModal; + uint8_t txRxAttenLocal; + uint8_t ob[5], db1[5], db2[5]; + + pModal = &eep->modalHeader; + txRxAttenLocal = 23; + + OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); + + /* Single chain for 4K EEPROM*/ + ar9285SetBoardGain(ah, pModal, eep, txRxAttenLocal); + + /* Initialize Ant Diversity settings if supported */ + (void) ar9285SetAntennaSwitch(ah, AH5212(ah)->ah_antControl); + + /* Configure TX power calibration */ + if (pModal->version >= 2) { + ob[0] = pModal->ob_0; + ob[1] = pModal->ob_1; + ob[2] = pModal->ob_2; + ob[3] = pModal->ob_3; + ob[4] = pModal->ob_4; + + db1[0] = pModal->db1_0; + db1[1] = pModal->db1_1; + db1[2] = pModal->db1_2; + db1[3] = pModal->db1_3; + db1[4] = pModal->db1_4; + + db2[0] = pModal->db2_0; + db2[1] = pModal->db2_1; + db2[2] = pModal->db2_2; + db2[3] = pModal->db2_3; + db2[4] = pModal->db2_4; + } else if (pModal->version == 1) { + ob[0] = pModal->ob_0; + ob[1] = ob[2] = ob[3] = ob[4] = pModal->ob_1; + db1[0] = pModal->db1_0; + db1[1] = db1[2] = db1[3] = db1[4] = pModal->db1_1; + db2[0] = pModal->db2_0; + db2[1] = db2[2] = db2[3] = db2[4] = pModal->db2_1; + } else { + int i; + + for (i = 0; i < 5; i++) { + ob[i] = pModal->ob_0; + db1[i] = pModal->db1_0; + db2[i] = pModal->db1_0; + } + } + + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_0, ob[0]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_1, ob[1]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_2, ob[2]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_3, ob[3]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_4, ob[4]); + + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_DB1_0, db1[0]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_DB1_1, db1[1]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_DB1_2, db1[2]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB1_3, db1[3]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB1_4, db1[4]); + + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_0, db2[0]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_1, db2[1]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_2, db2[2]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_3, db2[3]); + OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_4, db2[4]); + + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, + pModal->switchSettling); + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, + pModal->adcDesiredSize); + + OS_REG_WRITE(ah, AR_PHY_RF_CTL4, + SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | + SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | + SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | + SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); + + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, + pModal->txEndToRxOn); + + OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, + pModal->thresh62); + OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, + pModal->thresh62); + + if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= + AR5416_EEP_MINOR_VER_2) { + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_DATA_START, + pModal->txFrameToDataStart); + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_PA_ON, + pModal->txFrameToPaOn); + } + + if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= + AR5416_EEP_MINOR_VER_3) { + if (IEEE80211_IS_CHAN_HT40(chan)) + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, + AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); + } + + /* + * Program the CCK TX gain factor appropriately if needed. + * The AR9285/AR9271 has a non-constant PA tx gain behaviour + * for CCK versus OFDM rates; other chips deal with this + * differently. + * + * The mask/shift/multiply hackery is done so place the same + * value (bb_desired_scale) into multiple 5-bit fields. + * For example, AR_PHY_TX_PWRCTRL9 has bb_desired_scale written + * to three fields: (0..4), (5..9) and (10..14). + */ + if (AR_SREV_9271(ah) || AR_SREV_KITE(ah)) { + uint8_t bb_desired_scale = (pModal->bb_scale_smrt_antenna & EEP_4K_BB_DESIRED_SCALE_MASK); + if ((eep->baseEepHeader.txGainType == 0) && (bb_desired_scale != 0)) { + ath_hal_printf(ah, "[ath]: adjusting cck tx gain factor\n"); + uint32_t pwrctrl, mask, clr; + + mask = (1<<0) | (1<<5) | (1<<10) | (1<<15) | (1<<20) | (1<<25); + pwrctrl = mask * bb_desired_scale; + clr = mask * 0x1f; + OS_REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); + OS_REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); + OS_REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); + + mask = (1<<0) | (1<<5) | (1<<15); + pwrctrl = mask * bb_desired_scale; + clr = mask * 0x1f; + OS_REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr); + + mask = (1<<0) | (1<<5); + pwrctrl = mask * bb_desired_scale; + clr = mask * 0x1f; + OS_REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); + OS_REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); + } + } + + return AH_TRUE; +} + +/* + * Helper functions common for AP/CB/XB + */ + +static HAL_BOOL +ar9285SetPowerPerRateTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, + const struct ieee80211_channel *chan, + int16_t *ratesArray, uint16_t cfgCtl, + uint16_t AntennaReduction, + uint16_t twiceMaxRegulatoryPower, + uint16_t powerLimit) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) +/* Local defines to distinguish between extension and control CTL's */ +#define EXT_ADDITIVE (0x8000) +#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) +#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) + + uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + int i; + int16_t twiceLargestAntenna; + CAL_CTL_DATA_4K *rep; + CAL_TARGET_POWER_LEG targetPowerOfdm, targetPowerCck = {0, {0, 0, 0, 0}}; + CAL_TARGET_POWER_LEG targetPowerOfdmExt = {0, {0, 0, 0, 0}}, targetPowerCckExt = {0, {0, 0, 0, 0}}; + CAL_TARGET_POWER_HT targetPowerHt20, targetPowerHt40 = {0, {0, 0, 0, 0}}; + int16_t scaledPower, minCtlPower; + +#define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ + static const uint16_t ctlModesFor11g[] = { + CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 + }; + const uint16_t *pCtlMode; + uint16_t numCtlModes, ctlMode, freq; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + /* Compute TxPower reduction due to Antenna Gain */ + + twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0]; + twiceLargestAntenna = (int16_t)AH_MIN((AntennaReduction) - twiceLargestAntenna, 0); + + /* XXX setup for 5212 use (really used?) */ + ath_hal_eepromSet(ah, AR_EEP_ANTGAINMAX_2, twiceLargestAntenna); + + /* + * scaledPower is the minimum of the user input power level and + * the regulatory allowed power level + */ + scaledPower = AH_MIN(powerLimit, twiceMaxRegulatoryPower + twiceLargestAntenna); + + /* Get target powers from EEPROM - our baseline for TX Power */ + /* Setup for CTL modes */ + numCtlModes = N(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; /* CTL_11B, CTL_11G, CTL_2GHT20 */ + pCtlMode = ctlModesFor11g; + + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck, + AR5416_4K_NUM_2G_CCK_TARGET_POWERS, &targetPowerCck, 4, AH_FALSE); + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G, + AR5416_4K_NUM_2G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE); + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT20, + AR5416_4K_NUM_2G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE); + + if (IEEE80211_IS_CHAN_HT40(chan)) { + numCtlModes = N(ctlModesFor11g); /* All 2G CTL's */ + + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT40, + AR5416_4K_NUM_2G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE); + /* Get target powers for extension channels */ + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck, + AR5416_4K_NUM_2G_CCK_TARGET_POWERS, &targetPowerCckExt, 4, AH_TRUE); + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G, + AR5416_4K_NUM_2G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE); + } + + /* + * For MIMO, need to apply regulatory caps individually across dynamically + * running modes: CCK, OFDM, HT20, HT40 + * + * The outer loop walks through each possible applicable runtime mode. + * The inner loop walks through each ctlIndex entry in EEPROM. + * The ctl value is encoded as [7:4] == test group, [3:0] == test mode. + * + */ + for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { + HAL_BOOL isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || + (pCtlMode[ctlMode] == CTL_2GHT40); + if (isHt40CtlMode) { + freq = centers.ctl_center; + } else if (pCtlMode[ctlMode] & EXT_ADDITIVE) { + freq = centers.ext_center; + } else { + freq = centers.ctl_center; + } + + /* walk through each CTL index stored in EEPROM */ + for (i = 0; (i < AR5416_4K_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { + uint16_t twiceMinEdgePower; + + /* compare test group from regulatory channel list with test mode from pCtlMode list */ + if ((((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == pEepData->ctlIndex[i]) || + (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == + ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { + rep = &(pEepData->ctlData[i]); + twiceMinEdgePower = ar5416GetMaxEdgePower(freq, + rep->ctlEdges[ + owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask) - 1], AH_TRUE); + if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { + /* Find the minimum of all CTL edge powers that apply to this channel */ + twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower); + } else { + /* specific */ + twiceMaxEdgePower = twiceMinEdgePower; + break; + } + } + } + minCtlPower = (uint8_t)AH_MIN(twiceMaxEdgePower, scaledPower); + /* Apply ctl mode to correct target power set */ + switch(pCtlMode[ctlMode]) { + case CTL_11B: + for (i = 0; i < N(targetPowerCck.tPow2x); i++) { + targetPowerCck.tPow2x[i] = (uint8_t)AH_MIN(targetPowerCck.tPow2x[i], minCtlPower); + } + break; + case CTL_11A: + case CTL_11G: + for (i = 0; i < N(targetPowerOfdm.tPow2x); i++) { + targetPowerOfdm.tPow2x[i] = (uint8_t)AH_MIN(targetPowerOfdm.tPow2x[i], minCtlPower); + } + break; + case CTL_5GHT20: + case CTL_2GHT20: + for (i = 0; i < N(targetPowerHt20.tPow2x); i++) { + targetPowerHt20.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt20.tPow2x[i], minCtlPower); + } + break; + case CTL_11B_EXT: + targetPowerCckExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerCckExt.tPow2x[0], minCtlPower); + break; + case CTL_11G_EXT: + targetPowerOfdmExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerOfdmExt.tPow2x[0], minCtlPower); + break; + case CTL_5GHT40: + case CTL_2GHT40: + for (i = 0; i < N(targetPowerHt40.tPow2x); i++) { + targetPowerHt40.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt40.tPow2x[i], minCtlPower); + } + break; + default: + return AH_FALSE; + break; + } + } /* end ctl mode checking */ + + /* Set rates Array from collected data */ + ar5416SetRatesArrayFromTargetPower(ah, chan, ratesArray, + &targetPowerCck, + &targetPowerCckExt, + &targetPowerOfdm, + &targetPowerOfdmExt, + &targetPowerHt20, + &targetPowerHt40); + + return AH_TRUE; +#undef EXT_ADDITIVE +#undef CTL_11G_EXT +#undef CTL_11B_EXT +#undef SUB_NUM_CTL_MODES_AT_2G_40 +#undef N +} + +static HAL_BOOL +ar9285SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, + const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset) +{ + CAL_DATA_PER_FREQ_4K *pRawDataset; + uint8_t *pCalBChans = AH_NULL; + uint16_t pdGainOverlap_t2; + static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES]; + uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK]; + uint16_t numPiers, i; + int16_t tMinCalPower; + uint16_t numXpdGain, xpdMask; + uint16_t xpdGainValues[4]; /* v4k eeprom has 2; the other two stay 0 */ + uint32_t regChainOffset; + + OS_MEMZERO(xpdGainValues, sizeof(xpdGainValues)); + + xpdMask = pEepData->modalHeader.xpdGain; + + if (IS_EEP_MINOR_V2(ah)) { + pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; + } else { + pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); + } + + pCalBChans = pEepData->calFreqPier2G; + numPiers = AR5416_4K_NUM_2G_CAL_PIERS; + numXpdGain = 0; + + /* Calculate the value of xpdgains from the xpdGain Mask */ + for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { + if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { + if (numXpdGain >= AR5416_4K_NUM_PD_GAINS) { + HALASSERT(0); + break; + } + xpdGainValues[numXpdGain] = (uint16_t)(AR5416_PD_GAINS_IN_MASK - i); + numXpdGain++; + } + } + + /* Write the detector gain biases and their number */ + ar5416WriteDetectorGainBiases(ah, numXpdGain, xpdGainValues); + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + regChainOffset = ar5416GetRegChainOffset(ah, i); + if (pEepData->baseEepHeader.txMask & (1 << i)) { + pRawDataset = pEepData->calPierData2G[i]; + + ar9285GetGainBoundariesAndPdadcs(ah, chan, pRawDataset, + pCalBChans, numPiers, + pdGainOverlap_t2, + &tMinCalPower, gainBoundaries, + pdadcValues, numXpdGain); + + if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { + /* + * Note the pdadc table may not start at 0 dBm power, could be + * negative or greater than 0. Need to offset the power + * values by the amount of minPower for griffin + */ + ar5416SetGainBoundariesClosedLoop(ah, i, pdGainOverlap_t2, gainBoundaries); + } + + /* Write the power values into the baseband power table */ + ar5416WritePdadcValues(ah, i, pdadcValues); + } + } + *pTxPowerIndexOffset = 0; + + return AH_TRUE; +} + +static void +ar9285GetGainBoundariesAndPdadcs(struct ath_hal *ah, + const struct ieee80211_channel *chan, + CAL_DATA_PER_FREQ_4K *pRawDataSet, + uint8_t * bChans, uint16_t availPiers, + uint16_t tPdGainOverlap, int16_t *pMinCalPower, uint16_t * pPdGainBoundaries, + uint8_t * pPDADCValues, uint16_t numXpdGains) +{ + + int i, j, k; + int16_t ss; /* potentially -ve index for taking care of pdGainOverlap */ + uint16_t idxL, idxR, numPiers; /* Pier indexes */ + + /* filled out Vpd table for all pdGains (chanL) */ + static uint8_t vpdTableL[AR5416_4K_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + + /* filled out Vpd table for all pdGains (chanR) */ + static uint8_t vpdTableR[AR5416_4K_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + + /* filled out Vpd table for all pdGains (interpolated) */ + static uint8_t vpdTableI[AR5416_4K_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + + uint8_t *pVpdL, *pVpdR, *pPwrL, *pPwrR; + uint8_t minPwrT4[AR5416_4K_NUM_PD_GAINS]; + uint8_t maxPwrT4[AR5416_4K_NUM_PD_GAINS]; + int16_t vpdStep; + int16_t tmpVal; + uint16_t sizeCurrVpdTable, maxIndex, tgtIndex; + HAL_BOOL match; + int16_t minDelta = 0; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + /* Trim numPiers for the number of populated channel Piers */ + for (numPiers = 0; numPiers < availPiers; numPiers++) { + if (bChans[numPiers] == AR5416_BCHAN_UNUSED) { + break; + } + } + + /* Find pier indexes around the current channel */ + match = ath_ee_getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, + IEEE80211_IS_CHAN_2GHZ(chan)), bChans, numPiers, &idxL, &idxR); + + if (match) { + /* Directly fill both vpd tables from the matching index */ + for (i = 0; i < numXpdGains; i++) { + minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; + maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; + ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], + pRawDataSet[idxL].pwrPdg[i], + pRawDataSet[idxL].vpdPdg[i], + AR5416_PD_GAIN_ICEPTS, vpdTableI[i]); + } + } else { + for (i = 0; i < numXpdGains; i++) { + pVpdL = pRawDataSet[idxL].vpdPdg[i]; + pPwrL = pRawDataSet[idxL].pwrPdg[i]; + pVpdR = pRawDataSet[idxR].vpdPdg[i]; + pPwrR = pRawDataSet[idxR].pwrPdg[i]; + + /* Start Vpd interpolation from the max of the minimum powers */ + minPwrT4[i] = AH_MAX(pPwrL[0], pPwrR[0]); + + /* End Vpd interpolation from the min of the max powers */ + maxPwrT4[i] = AH_MIN(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); + HALASSERT(maxPwrT4[i] > minPwrT4[i]); + + /* Fill pier Vpds */ + ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrL, pVpdL, + AR5416_PD_GAIN_ICEPTS, vpdTableL[i]); + ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrR, pVpdR, + AR5416_PD_GAIN_ICEPTS, vpdTableR[i]); + + /* Interpolate the final vpd */ + for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { + vpdTableI[i][j] = (uint8_t)(ath_ee_interpolate((uint16_t)FREQ2FBIN(centers.synth_center, + IEEE80211_IS_CHAN_2GHZ(chan)), + bChans[idxL], bChans[idxR], vpdTableL[i][j], vpdTableR[i][j])); + } + } + } + *pMinCalPower = (int16_t)(minPwrT4[0] / 2); + + k = 0; /* index for the final table */ + for (i = 0; i < numXpdGains; i++) { + if (i == (numXpdGains - 1)) { + pPdGainBoundaries[i] = (uint16_t)(maxPwrT4[i] / 2); + } else { + pPdGainBoundaries[i] = (uint16_t)((maxPwrT4[i] + minPwrT4[i+1]) / 4); + } + + pPdGainBoundaries[i] = (uint16_t)AH_MIN(AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); + + /* NB: only applies to owl 1.0 */ + if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah) ) { + /* + * fix the gain delta, but get a delta that can be applied to min to + * keep the upper power values accurate, don't think max needs to + * be adjusted because should not be at that area of the table? + */ + minDelta = pPdGainBoundaries[0] - 23; + pPdGainBoundaries[0] = 23; + } + else { + minDelta = 0; + } + + /* Find starting index for this pdGain */ + if (i == 0) { + if (AR_SREV_MERLIN_20_OR_LATER(ah)) + ss = (int16_t)(0 - (minPwrT4[i] / 2)); + else + ss = 0; /* for the first pdGain, start from index 0 */ + } else { + /* need overlap entries extrapolated below. */ + ss = (int16_t)((pPdGainBoundaries[i-1] - (minPwrT4[i] / 2)) - tPdGainOverlap + 1 + minDelta); + } + vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); + vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); + /* + *-ve ss indicates need to extrapolate data below for this pdGain + */ + while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { + tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); + pPDADCValues[k++] = (uint8_t)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = (uint8_t)((maxPwrT4[i] - minPwrT4[i]) / 2 +1); + tgtIndex = (uint8_t)(pPdGainBoundaries[i] + tPdGainOverlap - (minPwrT4[i] / 2)); + maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; + + while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { + pPDADCValues[k++] = vpdTableI[i][ss++]; + } + + vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - vpdTableI[i][sizeCurrVpdTable - 2]); + vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); + /* + * for last gain, pdGainBoundary == Pmax_t2, so will + * have to extrapolate + */ + if (tgtIndex >= maxIndex) { /* need to extrapolate above */ + while ((ss <= tgtIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { + tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + + (ss - maxIndex +1) * vpdStep)); + pPDADCValues[k++] = (uint8_t)((tmpVal > 255) ? 255 : tmpVal); + ss++; + } + } /* extrapolated above */ + } /* for all pdGainUsed */ + + /* Fill out pdGainBoundaries - only up to 2 allowed here, but hardware allows up to 4 */ + while (i < AR5416_PD_GAINS_IN_MASK) { + pPdGainBoundaries[i] = AR5416_4K_EEP_PD_GAIN_BOUNDARY_DEFAULT; + i++; + } + + while (k < AR5416_NUM_PDADC_VALUES) { + pPDADCValues[k] = pPDADCValues[k-1]; + k++; + } + return; +} diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285an.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9285an.h new file mode 100644 index 0000000..3b80938 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285an.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AR9285_AN_H__ +#define __AR9285_AN_H__ + +/* AR9285 Analog register definitions */ + +#define AR9285_AN_RF2G1 0x7820 + +#define AR9285_AN_RF2G1_ENPACAL 0x00000800 +#define AR9285_AN_RF2G1_ENPACAL_S 11 +#define AR9285_AN_RF2G1_PDPADRV1 0x02000000 +#define AR9285_AN_RF2G1_PDPADRV1_S 25 +#define AR9285_AN_RF2G1_PDPADRV2 0x01000000 +#define AR9285_AN_RF2G1_PDPADRV2_S 24 +#define AR9285_AN_RF2G1_PDPAOUT 0x00800000 +#define AR9285_AN_RF2G1_PDPAOUT_S 23 + +#define AR9285_AN_RF2G2 0x7824 + +#define AR9285_AN_RF2G2_OFFCAL 0x00001000 +#define AR9285_AN_RF2G2_OFFCAL_S 12 + +#define AR9285_AN_RF2G3 0x7828 + +#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000 +#define AR9285_AN_RF2G3_PDVCCOMP_S 25 +#define AR9285_AN_RF2G3_OB_0 0x00E00000 +#define AR9285_AN_RF2G3_OB_0_S 21 +#define AR9285_AN_RF2G3_OB_1 0x001C0000 +#define AR9285_AN_RF2G3_OB_1_S 18 +#define AR9285_AN_RF2G3_OB_2 0x00038000 +#define AR9285_AN_RF2G3_OB_2_S 15 +#define AR9285_AN_RF2G3_OB_3 0x00007000 +#define AR9285_AN_RF2G3_OB_3_S 12 +#define AR9285_AN_RF2G3_OB_4 0x00000E00 +#define AR9285_AN_RF2G3_OB_4_S 9 +#define AR9285_AN_RF2G3_DB1_0 0x000001C0 +#define AR9285_AN_RF2G3_DB1_0_S 6 +#define AR9285_AN_RF2G3_DB1_1 0x00000038 +#define AR9285_AN_RF2G3_DB1_1_S 3 +#define AR9285_AN_RF2G3_DB1_2 0x00000007 +#define AR9285_AN_RF2G3_DB1_2_S 0 + +#define AR9285_AN_RF2G4 0x782C + +#define AR9285_AN_RF2G4_DB1_3 0xE0000000 +#define AR9285_AN_RF2G4_DB1_3_S 29 +#define AR9285_AN_RF2G4_DB1_4 0x1C000000 +#define AR9285_AN_RF2G4_DB1_4_S 26 + +#define AR9285_AN_RF2G4_DB2_0 0x03800000 +#define AR9285_AN_RF2G4_DB2_0_S 23 +#define AR9285_AN_RF2G4_DB2_1 0x00700000 +#define AR9285_AN_RF2G4_DB2_1_S 20 +#define AR9285_AN_RF2G4_DB2_2 0x000E0000 +#define AR9285_AN_RF2G4_DB2_2_S 17 +#define AR9285_AN_RF2G4_DB2_3 0x0001C000 +#define AR9285_AN_RF2G4_DB2_3_S 14 +#define AR9285_AN_RF2G4_DB2_4 0x00003800 +#define AR9285_AN_RF2G4_DB2_4_S 11 + +#define AR9285_AN_RF2G6 0x7834 + +#define AR9285_AN_RF2G6_CCOMP 0x00007800 +#define AR9285_AN_RF2G6_CCOMP_S 11 +#define AR9285_AN_RF2G6_OFFS 0x03f00000 +#define AR9285_AN_RF2G6_OFFS_S 20 + +#define AR9285_AN_RF2G7 0x7838 + +#define AR9285_AN_RF2G7_PWDDB 0x00000002 +#define AR9285_AN_RF2G7_PWDDB_S 1 +#define AR9285_AN_RF2G7_PADRVGN2TAB0 0xE0000000 +#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29 + +#define AR9285_AN_RF2G8 0x783C + +#define AR9285_AN_RF2G8_PADRVGN2TAB0 0x0001C000 +#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14 + +#define AR9285_AN_RF2G9 0x7840 + +#define AR9285_AN_RXTXBB1 0x7854 + +#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020 +#define AR9285_AN_RXTXBB1_PDRXTXBB1_S 5 +#define AR9285_AN_RXTXBB1_PDV2I 0x00000080 +#define AR9285_AN_RXTXBB1_PDV2I_S 7 +#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100 +#define AR9285_AN_RXTXBB1_PDDACIF_S 8 +#define AR9285_AN_RXTXBB1_SPARE9 0x00000001 +#define AR9285_AN_RXTXBB1_SPARE9_S 0 + +#define AR9285_AN_TOP2 0x7868 + +#define AR9285_AN_TOP3 0x786c + +#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C +#define AR9285_AN_TOP3_XPABIAS_LVL_S 2 +#define AR9285_AN_TOP3_PWDDAC 0x00800000 +#define AR9285_AN_TOP3_PWDDAC_S 23 + +#define AR9285_AN_TOP4 0x7870 +#define AR9285_AN_TOP4_DEFAULT 0x10142c00 + +#endif /* __AR9285_AN_H__ */ diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285phy.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9285phy.h new file mode 100644 index 0000000..f823053 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285phy.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __ATH_AR9285PHY_H__ +#define __ATH_AR9285PHY_H__ + +#define AR9285_AN_RF2G1 0x7820 +#define AR9285_AN_RF2G1_ENPACAL 0x00000800 +#define AR9285_AN_RF2G1_ENPACAL_S 11 +#define AR9285_AN_RF2G1_PDPADRV1 0x02000000 +#define AR9285_AN_RF2G1_PDPADRV1_S 25 +#define AR9285_AN_RF2G1_PDPADRV2 0x01000000 +#define AR9285_AN_RF2G1_PDPADRV2_S 24 +#define AR9285_AN_RF2G1_PDPAOUT 0x00800000 +#define AR9285_AN_RF2G1_PDPAOUT_S 23 + +#define AR9285_AN_RF2G2 0x7824 +#define AR9285_AN_RF2G2_OFFCAL 0x00001000 +#define AR9285_AN_RF2G2_OFFCAL_S 12 + +#define AR9285_AN_RF2G3 0x7828 +#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000 +#define AR9285_AN_RF2G3_PDVCCOMP_S 25 +#define AR9285_AN_RF2G3_OB_0 0x00E00000 +#define AR9285_AN_RF2G3_OB_0_S 21 +#define AR9285_AN_RF2G3_OB_1 0x001C0000 +#define AR9285_AN_RF2G3_OB_1_S 18 +#define AR9285_AN_RF2G3_OB_2 0x00038000 +#define AR9285_AN_RF2G3_OB_2_S 15 +#define AR9285_AN_RF2G3_OB_3 0x00007000 +#define AR9285_AN_RF2G3_OB_3_S 12 +#define AR9285_AN_RF2G3_OB_4 0x00000E00 +#define AR9285_AN_RF2G3_OB_4_S 9 + +#define AR9285_AN_RF2G3_DB1_0 0x000001C0 +#define AR9285_AN_RF2G3_DB1_0_S 6 +#define AR9285_AN_RF2G3_DB1_1 0x00000038 +#define AR9285_AN_RF2G3_DB1_1_S 3 +#define AR9285_AN_RF2G3_DB1_2 0x00000007 +#define AR9285_AN_RF2G3_DB1_2_S 0 + +#define AR9285_AN_RF2G4 0x782C +#define AR9285_AN_RF2G4_DB1_3 0xE0000000 +#define AR9285_AN_RF2G4_DB1_3_S 29 +#define AR9285_AN_RF2G4_DB1_4 0x1C000000 +#define AR9285_AN_RF2G4_DB1_4_S 26 + +#define AR9285_AN_RF2G4_DB2_0 0x03800000 +#define AR9285_AN_RF2G4_DB2_0_S 23 +#define AR9285_AN_RF2G4_DB2_1 0x00700000 +#define AR9285_AN_RF2G4_DB2_1_S 20 +#define AR9285_AN_RF2G4_DB2_2 0x000E0000 +#define AR9285_AN_RF2G4_DB2_2_S 17 +#define AR9285_AN_RF2G4_DB2_3 0x0001C000 +#define AR9285_AN_RF2G4_DB2_3_S 14 +#define AR9285_AN_RF2G4_DB2_4 0x00003800 +#define AR9285_AN_RF2G4_DB2_4_S 11 + +#define AR9285_RF2G5 0x7830 +#define AR9285_RF2G5_IC50TX 0xfffff8ff +#define AR9285_RF2G5_IC50TX_SET 0x00000400 +#define AR9285_RF2G5_IC50TX_XE_SET 0x00000500 +#define AR9285_RF2G5_IC50TX_CLEAR 0x00000700 +#define AR9285_RF2G5_IC50TX_CLEAR_S 8 + +#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX 0x0007E000 +#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX_S 13 +#define AR_PHY_TX_GAIN_CLC 0x0000001E +#define AR_PHY_TX_GAIN_CLC_S 1 +#define AR_PHY_TX_GAIN 0x0007F000 +#define AR_PHY_TX_GAIN_S 12 + +#define AR_PHY_CLC_TBL1 0xa35c +#define AR_PHY_CLC_I0 0x07ff0000 +#define AR_PHY_CLC_I0_S 16 +#define AR_PHY_CLC_Q0 0x0000ffd0 +#define AR_PHY_CLC_Q0_S 5 + +#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac +#define AR_PHY_9285_FAST_DIV_BIAS 0x00007E00 +#define AR_PHY_9285_FAST_DIV_BIAS_S 9 +#define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 +#define AR_PHY_9285_ANT_DIV_CTL 0x01000000 +#define AR_PHY_9285_ANT_DIV_CTL_S 24 +#define AR_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000 +#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S 25 +#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000 +#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27 +#define AR_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000 +#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29 +#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000 +#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30 +#define AR_PHY_9285_ANT_DIV_LNA1 2 +#define AR_PHY_9285_ANT_DIV_LNA2 1 +#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3 +#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0 +#define AR_PHY_9285_ANT_DIV_GAINTB_0 0 +#define AR_PHY_9285_ANT_DIV_GAINTB_1 1 + +/* for AR_PHY_CCK_DETECT */ +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 +#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 +#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13 + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9285v2.ini b/sys/external/isc/atheros_hal/dist/ar9002/ar9285v2.ini new file mode 100644 index 0000000..9126dc4 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9285v2.ini @@ -0,0 +1,835 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +static const u_int32_t ar9285Modes_v2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, + { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, + { 0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, + { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, + { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, + { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 }, + { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, + { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 }, + { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c }, + { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, + { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, + { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, + { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, + { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, + { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, + { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, + { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, + { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, + { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, + { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, + { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, + { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, + { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, + { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, + { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, + { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, + { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, + { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, + { 0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, + { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, + { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, + { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, + { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, + { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, + { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, + { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, + { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, + { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, + { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, + { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, + { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, + { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, + { 0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, + { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, + { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, + { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, + { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, + { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, + { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, + { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, + { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, + { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, + { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, + { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, + { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, + { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, + { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, + { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, + { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, + { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, + { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, + { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, + { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, + { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, + { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, + { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, + { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, + { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, + { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, + { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, + { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, + { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, + { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, + { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, + { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, + { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, + { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, + { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, + { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, + { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, + { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, + { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, + { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, + { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, + { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, + { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, + { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, + { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, + { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, + { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, + { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, + { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, + { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, + { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, + { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, + { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, + { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, + { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, + { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, + { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, + { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, + { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, + { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, + { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, + { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, + { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, + { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, + { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, + { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, + { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, + { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, + { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, + { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, + { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, + { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, + { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, + { 0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, + { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, + { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, + { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, + { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, + { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, + { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, + { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, + { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, + { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, + { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, + { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, + { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, + { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, + { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, + { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, + { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, + { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, + { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, + { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, + { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, + { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, + { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, + { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, + { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, + { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, + { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, + { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, + { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, + { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, + { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, + { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, + { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, + { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, + { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, + { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, + { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, + { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, + { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, + { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, + { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, + { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, + { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, + { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, + { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, + { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, + { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, + { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, + { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, + { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, + { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, + { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, + { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, + { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, + { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, + { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, + { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, + { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, + { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, + { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, + { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, + { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, + { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, + { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, + { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, + { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, + { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, + { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, + { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, + { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, + { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, + { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, +}; + +static const u_int32_t ar9285Common_v2[][2] = { + /* Addr allmodes */ + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020045 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00004060, 0x00000000 }, + { 0x00004064, 0x00000000 }, + { 0x00007010, 0x00000031 }, + { 0x00007034, 0x00000002 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x00000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a80001a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04810 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c0, 0x00000000 }, + { 0x000081d0, 0x0000320a }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0x88a00010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x0000829c, 0x00000000 }, + { 0x00008300, 0x00000040 }, + { 0x00008314, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000001 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00ff0000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x00010380 }, + { 0x00008344, 0x00481043 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xafe68e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x00009910, 0x01002310 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009940, 0x14750604 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x2108ecff }, + { 0x00009968, 0x000003ce }, + { 0x00009970, 0x192bb514 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x2def0400 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, + { 0x0000a208, 0x803e68c8 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x00206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a244, 0x00000000 }, + { 0x0000a248, 0xfffffffc }, + { 0x0000a24c, 0x00000000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0ccb5380 }, + { 0x0000a25c, 0x15151501 }, + { 0x0000a260, 0xdfa90f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0ebae9e6 }, + { 0x0000d270, 0x0d820820 }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f70081 }, + { 0x00007800, 0x00140000 }, + { 0x00007804, 0x0e4548d8 }, + { 0x00007808, 0x54214514 }, + { 0x0000780c, 0x02025830 }, + { 0x00007810, 0x71c0d388 }, + { 0x0000781c, 0x00000000 }, + { 0x00007824, 0x00d86fff }, + { 0x0000782c, 0x6e36d97b }, + { 0x00007834, 0x71400087 }, + { 0x00007844, 0x000c0db6 }, + { 0x00007848, 0x6db6246f }, + { 0x0000784c, 0x6d9b66db }, + { 0x00007850, 0x6d8c6dba }, + { 0x00007854, 0x00040000 }, + { 0x00007858, 0xdb003012 }, + { 0x0000785c, 0x04924914 }, + { 0x00007860, 0x21084210 }, + { 0x00007864, 0xf7d7ffde }, + { 0x00007868, 0xc2034080 }, + { 0x00007870, 0x10142c00 }, +}; + +static const u_int32_t ar9285Modes_high_power_tx_gain_v2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, + { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, + { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, + { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, + { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, + { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, + { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, + { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, + { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 }, + { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, + { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, +}; + +static const u_int32_t ar9285Modes_original_tx_gain_v2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, + { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, + { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, + { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, + { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, + { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, + { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, + { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, + { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, + { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, + { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, + { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, +}; + +static const u_int32_t ar9285Modes_XE2_0_normal_power[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, + { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, + { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6dbae }, + { 0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441 }, + { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, + { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, + { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, + { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, + { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, + { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, + { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, + { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, +}; + +static const u_int32_t ar9285Modes_XE2_0_high_power[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, + { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, + { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e }, + { 0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443 }, + { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, + { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, + { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, + { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, + { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 }, + { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, + { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, +}; + +static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_v2[][2] = { + /* Addr allmodes */ + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffd }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +static const u_int32_t ar9285PciePhy_clkreq_off_L1_v2[][2] = { + /* Addr allmodes */ + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffc }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9287.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9287.c new file mode 100644 index 0000000..724fb7c --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9287.c @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +/* + * NB: Merlin and later have a simpler RF backend. + */ +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v14.h" + +#include "ar9002/ar9287.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +struct ar9287State { + RF_HAL_FUNCS base; /* public state, must be first */ + uint16_t pcdacTable[1]; /* XXX */ +}; +#define AR9287(ah) ((struct ar9287State *) AH5212(ah)->ah_rfHal) + +static HAL_BOOL ar9287GetChannelMaxMinPower(struct ath_hal *, + const struct ieee80211_channel *, int16_t *maxPow,int16_t *minPow); +int16_t ar9287GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c); + +static void +ar9287WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, + int writes) +{ + (void) ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_bb_rfgain, + freqIndex, writes); +} + +/* + * Take the MHz channel value and set the Channel value + * + * ASSUMES: Writes enabled to analog bus + * + * Actual Expression, + * + * For 2GHz channel, + * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) + * (freq_ref = 40MHz) + * + * For 5GHz channel, + * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) + * (freq_ref = 40MHz/(24>>amodeRefSel)) + * + * For 5GHz channels which are 5MHz spaced, + * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) + * (freq_ref = 40MHz) + */ +static HAL_BOOL +ar9287SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + uint16_t bMode, fracMode, aModeRefSel = 0; + uint32_t freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; + CHAN_CENTERS centers; + uint32_t refDivA = 24; + + OS_MARK(ah, AH_MARK_SETCHANNEL, chan->ic_freq); + + ar5416GetChannelCenters(ah, chan, ¢ers); + freq = centers.synth_center; + + reg32 = OS_REG_READ(ah, AR_PHY_SYNTH_CONTROL); + reg32 &= 0xc0000000; + + if (freq < 4800) { /* 2 GHz, fractional mode */ + uint32_t txctl; + int regWrites = 0; + + bMode = 1; + fracMode = 1; + aModeRefSel = 0; + channelSel = (freq * 0x10000)/15; + + if (AR_SREV_KIWI_11_OR_LATER(ah)) { + if (freq == 2484) { + ath_hal_ini_write(ah, + &AH9287(ah)->ah_ini_cckFirJapan2484, 1, + regWrites); + } else { + ath_hal_ini_write(ah, + &AH9287(ah)->ah_ini_cckFirNormal, 1, + regWrites); + } + } + + txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + /* Enable channel spreading for channel 14 */ + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else { + bMode = 0; + fracMode = 0; + + if ((freq % 20) == 0) { + aModeRefSel = 3; + } else if ((freq % 10) == 0) { + aModeRefSel = 2; + } else { + aModeRefSel = 0; + /* + * Enable 2G (fractional) mode for channels which + * are 5MHz spaced + */ + fracMode = 1; + refDivA = 1; + channelSel = (freq * 0x8000)/15; + + /* RefDivA setting */ + OS_A_REG_RMW_FIELD(ah, AR_AN_SYNTH9, + AR_AN_SYNTH9_REFDIVA, refDivA); + } + if (!fracMode) { + ndiv = (freq * (refDivA >> aModeRefSel))/60; + channelSel = ndiv & 0x1ff; + channelFrac = (ndiv & 0xfffffe00) * 2; + channelSel = (channelSel << 17) | channelFrac; + } + } + + reg32 = reg32 | (bMode << 29) | (fracMode << 28) | + (aModeRefSel << 26) | (channelSel); + + OS_REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); + + AH_PRIVATE(ah)->ah_curchan = chan; + + return AH_TRUE; +} + +/* + * Return a reference to the requested RF Bank. + */ +static uint32_t * +ar9287GetRfBank(struct ath_hal *ah, int bank) +{ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", + __func__, bank); + return AH_NULL; +} + +/* + * Reads EEPROM header info from device structure and programs + * all rf registers + */ +static HAL_BOOL +ar9287SetRfRegs(struct ath_hal *ah, const struct ieee80211_channel *chan, + uint16_t modesIndex, uint16_t *rfXpdGain) +{ + return AH_TRUE; /* nothing to do */ +} + +/* + * Read the transmit power levels from the structures taken from EEPROM + * Interpolate read transmit power values for this channel + * Organize the transmit power values into a table for writing into the hardware + */ + +static HAL_BOOL +ar9287SetPowerTable(struct ath_hal *ah, int16_t *pPowerMin, int16_t *pPowerMax, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain) +{ + return AH_TRUE; +} + +#if 0 +static int16_t +ar9287GetMinPower(struct ath_hal *ah, EXPN_DATA_PER_CHANNEL_5112 *data) +{ + int i, minIndex; + int16_t minGain,minPwr,minPcdac,retVal; + + /* Assume NUM_POINTS_XPD0 > 0 */ + minGain = data->pDataPerXPD[0].xpd_gain; + for (minIndex=0,i=1; ipDataPerXPD[i].xpd_gain < minGain) { + minIndex = i; + minGain = data->pDataPerXPD[i].xpd_gain; + } + } + minPwr = data->pDataPerXPD[minIndex].pwr_t4[0]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[0]; + for (i=1; ipDataPerXPD[minIndex].pwr_t4[i] < minPwr) { + minPwr = data->pDataPerXPD[minIndex].pwr_t4[i]; + minPcdac = data->pDataPerXPD[minIndex].pcdac[i]; + } + } + retVal = minPwr - (minPcdac*2); + return(retVal); +} +#endif + +static HAL_BOOL +ar9287GetChannelMaxMinPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, + int16_t *maxPow, int16_t *minPow) +{ +#if 0 + struct ath_hal_5212 *ahp = AH5212(ah); + int numChannels=0,i,last; + int totalD, totalF,totalMin; + EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL; + EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL; + + *maxPow = 0; + if (IS_CHAN_A(chan)) { + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11A].pDataPerChannel; + numChannels = powerArray[headerInfo11A].numChannels; + } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) { + /* XXX - is this correct? Should we also use the same power for turbo G? */ + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11G].pDataPerChannel; + numChannels = powerArray[headerInfo11G].numChannels; + } else if (IS_CHAN_B(chan)) { + powerArray = ahp->ah_modePowerArray5112; + data = powerArray[headerInfo11B].pDataPerChannel; + numChannels = powerArray[headerInfo11B].numChannels; + } else { + return (AH_TRUE); + } + /* Make sure the channel is in the range of the TP values + * (freq piers) + */ + if ((numChannels < 1) || + (chan->channel < data[0].channelValue) || + (chan->channel > data[numChannels-1].channelValue)) + return(AH_FALSE); + + /* Linearly interpolate the power value now */ + for (last=0,i=0; + (ichannel > data[i].channelValue); + last=i++); + totalD = data[i].channelValue - data[last].channelValue; + if (totalD > 0) { + totalF = data[i].maxPower_t4 - data[last].maxPower_t4; + *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD); + + totalMin = ar9287GetMinPower(ah,&data[i]) - ar9287GetMinPower(ah, &data[last]); + *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar9287GetMinPower(ah, &data[last])*totalD)/totalD); + return (AH_TRUE); + } else { + if (chan->channel == data[i].channelValue) { + *maxPow = data[i].maxPower_t4; + *minPow = ar9287GetMinPower(ah, &data[i]); + return(AH_TRUE); + } else + return(AH_FALSE); + } +#else + *maxPow = *minPow = 0; + return AH_FALSE; +#endif +} + +/* + * The ordering of nfarray is thus: + * + * nfarray[0]: Chain 0 ctl + * nfarray[1]: Chain 1 ctl + * nfarray[2]: Chain 2 ctl + * nfarray[3]: Chain 0 ext + * nfarray[4]: Chain 1 ext + * nfarray[5]: Chain 2 ext + */ +static void +ar9287GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) +{ + int16_t nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 0] is %d\n", nf); + nfarray[0] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 1] is %d\n", nf); + nfarray[1] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 0] is %d\n", nf); + nfarray[3] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 1] is %d\n", nf); + nfarray[4] = nf; + + /* Chain 2 - invalid */ + nfarray[2] = 0; + nfarray[5] = 0; + +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + * Stubbed:Not used by Fowl + */ +int16_t +ar9287GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + return 0; +} + +/* + * Free memory for analog bank scratch buffers + */ +static void +ar9287RfDetach(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALASSERT(ahp->ah_rfHal != AH_NULL); + ath_hal_free(ahp->ah_rfHal); + ahp->ah_rfHal = AH_NULL; +} + +HAL_BOOL +ar9287RfAttach(struct ath_hal *ah, HAL_STATUS *status) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar9287State *priv; + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: attach AR9280 radio\n", __func__); + + HALASSERT(ahp->ah_rfHal == AH_NULL); + priv = ath_hal_malloc(sizeof(struct ar9287State)); + if (priv == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot allocate private state\n", __func__); + *status = HAL_ENOMEM; /* XXX */ + return AH_FALSE; + } + priv->base.rfDetach = ar9287RfDetach; + priv->base.writeRegs = ar9287WriteRegs; + priv->base.getRfBank = ar9287GetRfBank; + priv->base.setChannel = ar9287SetChannel; + priv->base.setRfRegs = ar9287SetRfRegs; + priv->base.setPowerTable = ar9287SetPowerTable; + priv->base.getChannelMaxMinPower = ar9287GetChannelMaxMinPower; + priv->base.getNfAdjust = ar9287GetNfAdjust; + + ahp->ah_pcdacTable = priv->pcdacTable; + ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); + ahp->ah_rfHal = &priv->base; + /* + * Set noise floor adjust method; we arrange a + * direct call instead of thunking. + */ + AH_PRIVATE(ah)->ah_getNfAdjust = priv->base.getNfAdjust; + AH_PRIVATE(ah)->ah_getNoiseFloor = ar9287GetNoiseFloor; + + return AH_TRUE; +} + +static HAL_BOOL +ar9287RfProbe(struct ath_hal *ah) +{ + return (AR_SREV_KIWI(ah)); +} + +AH_RF(RF9287, ar9287RfProbe, ar9287RfAttach); diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9287.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9287.h new file mode 100644 index 0000000..3122ea4 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9287.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef _ATH_AR9287_H_ +#define _ATH_AR9287_H_ + +#include "ar5416/ar5416.h" + +/* + * This is a chip thing, but it's used here as part of the + * ath_hal_9287 struct; so it's convienent to locate the + * define here. + */ +#define AR9287_TX_GAIN_TABLE_SIZE 22 + +struct ath_hal_9287 { + struct ath_hal_5416 ah_5416; + + HAL_INI_ARRAY ah_ini_xmodes; + HAL_INI_ARRAY ah_ini_rxgain; + HAL_INI_ARRAY ah_ini_txgain; + + HAL_INI_ARRAY ah_ini_cckFirNormal; + HAL_INI_ARRAY ah_ini_cckFirJapan2484; + + int PDADCdelta; + + uint32_t originalGain[AR9287_TX_GAIN_TABLE_SIZE]; +}; +#define AH9287(_ah) ((struct ath_hal_9287 *)(_ah)) + +#define AR9287_DEFAULT_RXCHAINMASK 3 +#define AR9287_DEFAULT_TXCHAINMASK 3 + +#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -112 +#define AR_PHY_CCA_NOM_VAL_9287_5GHZ -112 +#define AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ -127 +#define AR_PHY_CCA_MIN_GOOD_VAL_9287_5GHZ -122 +#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -97 +#define AR_PHY_CCA_MAX_GOOD_VAL_9287_5GHZ -102 + +extern HAL_BOOL ar9287RfAttach(struct ath_hal *, HAL_STATUS *); +extern HAL_BOOL ar9287SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); + +#endif /* _ATH_AR9287_H_ */ diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9287.ini b/sys/external/isc/atheros_hal/dist/ar9002/ar9287.ini new file mode 100644 index 0000000..7f4ca05 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9287.ini @@ -0,0 +1,783 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +static const uint32_t ar9287Modes_9287_1_1[][6] = { + {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0}, + {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0}, + {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180}, + {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008}, + {0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0}, + {0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a}, + {0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880}, + {0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303}, + {0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200}, + {0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001, 0x3a020001}, + {0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007}, + {0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e}, + {0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0}, + {0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2}, + {0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e}, + {0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e}, + {0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18}, + {0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, + {0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881}, + {0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0}, + {0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016}, + {0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d}, + {0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010}, + {0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010}, + {0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010}, + {0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210}, + {0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce}, + {0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c}, + {0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00}, + {0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444}, + {0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a}, + {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, + {0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000}, + {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e}, + {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +}; + +static const uint32_t ar9287Common_9287_1_1[][2] = { + /* Addr allmodes */ + {0x0000000c, 0x00000000}, + {0x00000030, 0x00020015}, + {0x00000034, 0x00000005}, + {0x00000040, 0x00000000}, + {0x00000044, 0x00000008}, + {0x00000048, 0x00000008}, + {0x0000004c, 0x00000010}, + {0x00000050, 0x00000000}, + {0x00000054, 0x0000001f}, + {0x00000800, 0x00000000}, + {0x00000804, 0x00000000}, + {0x00000808, 0x00000000}, + {0x0000080c, 0x00000000}, + {0x00000810, 0x00000000}, + {0x00000814, 0x00000000}, + {0x00000818, 0x00000000}, + {0x0000081c, 0x00000000}, + {0x00000820, 0x00000000}, + {0x00000824, 0x00000000}, + {0x00001040, 0x002ffc0f}, + {0x00001044, 0x002ffc0f}, + {0x00001048, 0x002ffc0f}, + {0x0000104c, 0x002ffc0f}, + {0x00001050, 0x002ffc0f}, + {0x00001054, 0x002ffc0f}, + {0x00001058, 0x002ffc0f}, + {0x0000105c, 0x002ffc0f}, + {0x00001060, 0x002ffc0f}, + {0x00001064, 0x002ffc0f}, + {0x00001230, 0x00000000}, + {0x00001270, 0x00000000}, + {0x00001038, 0x00000000}, + {0x00001078, 0x00000000}, + {0x000010b8, 0x00000000}, + {0x000010f8, 0x00000000}, + {0x00001138, 0x00000000}, + {0x00001178, 0x00000000}, + {0x000011b8, 0x00000000}, + {0x000011f8, 0x00000000}, + {0x00001238, 0x00000000}, + {0x00001278, 0x00000000}, + {0x000012b8, 0x00000000}, + {0x000012f8, 0x00000000}, + {0x00001338, 0x00000000}, + {0x00001378, 0x00000000}, + {0x000013b8, 0x00000000}, + {0x000013f8, 0x00000000}, + {0x00001438, 0x00000000}, + {0x00001478, 0x00000000}, + {0x000014b8, 0x00000000}, + {0x000014f8, 0x00000000}, + {0x00001538, 0x00000000}, + {0x00001578, 0x00000000}, + {0x000015b8, 0x00000000}, + {0x000015f8, 0x00000000}, + {0x00001638, 0x00000000}, + {0x00001678, 0x00000000}, + {0x000016b8, 0x00000000}, + {0x000016f8, 0x00000000}, + {0x00001738, 0x00000000}, + {0x00001778, 0x00000000}, + {0x000017b8, 0x00000000}, + {0x000017f8, 0x00000000}, + {0x0000103c, 0x00000000}, + {0x0000107c, 0x00000000}, + {0x000010bc, 0x00000000}, + {0x000010fc, 0x00000000}, + {0x0000113c, 0x00000000}, + {0x0000117c, 0x00000000}, + {0x000011bc, 0x00000000}, + {0x000011fc, 0x00000000}, + {0x0000123c, 0x00000000}, + {0x0000127c, 0x00000000}, + {0x000012bc, 0x00000000}, + {0x000012fc, 0x00000000}, + {0x0000133c, 0x00000000}, + {0x0000137c, 0x00000000}, + {0x000013bc, 0x00000000}, + {0x000013fc, 0x00000000}, + {0x0000143c, 0x00000000}, + {0x0000147c, 0x00000000}, + {0x00004030, 0x00000002}, + {0x0000403c, 0x00000002}, + {0x00004024, 0x0000001f}, + {0x00004060, 0x00000000}, + {0x00004064, 0x00000000}, + {0x00007010, 0x00000033}, + {0x00007020, 0x00000000}, + {0x00007034, 0x00000002}, + {0x00007038, 0x000004c2}, + {0x00008004, 0x00000000}, + {0x00008008, 0x00000000}, + {0x0000800c, 0x00000000}, + {0x00008018, 0x00000700}, + {0x00008020, 0x00000000}, + {0x00008038, 0x00000000}, + {0x0000803c, 0x00000000}, + {0x00008048, 0x40000000}, + {0x00008054, 0x00000000}, + {0x00008058, 0x00000000}, + {0x0000805c, 0x000fc78f}, + {0x00008060, 0x0000000f}, + {0x00008064, 0x00000000}, + {0x00008070, 0x00000000}, + {0x000080c0, 0x2a80001a}, + {0x000080c4, 0x05dc01e0}, + {0x000080c8, 0x1f402710}, + {0x000080cc, 0x01f40000}, + {0x000080d0, 0x00001e00}, + {0x000080d4, 0x00000000}, + {0x000080d8, 0x00400000}, + {0x000080e0, 0xffffffff}, + {0x000080e4, 0x0000ffff}, + {0x000080e8, 0x003f3f3f}, + {0x000080ec, 0x00000000}, + {0x000080f0, 0x00000000}, + {0x000080f4, 0x00000000}, + {0x000080f8, 0x00000000}, + {0x000080fc, 0x00020000}, + {0x00008100, 0x00020000}, + {0x00008104, 0x00000001}, + {0x00008108, 0x00000052}, + {0x0000810c, 0x00000000}, + {0x00008110, 0x00000168}, + {0x00008118, 0x000100aa}, + {0x0000811c, 0x00003210}, + {0x00008124, 0x00000000}, + {0x00008128, 0x00000000}, + {0x0000812c, 0x00000000}, + {0x00008130, 0x00000000}, + {0x00008134, 0x00000000}, + {0x00008138, 0x00000000}, + {0x0000813c, 0x00000000}, + {0x00008144, 0xffffffff}, + {0x00008168, 0x00000000}, + {0x0000816c, 0x00000000}, + {0x00008170, 0x18487320}, + {0x00008174, 0xfaa4fa50}, + {0x00008178, 0x00000100}, + {0x0000817c, 0x00000000}, + {0x000081c0, 0x00000000}, + {0x000081c4, 0x00000000}, + {0x000081d4, 0x00000000}, + {0x000081ec, 0x00000000}, + {0x000081f0, 0x00000000}, + {0x000081f4, 0x00000000}, + {0x000081f8, 0x00000000}, + {0x000081fc, 0x00000000}, + {0x00008200, 0x00000000}, + {0x00008204, 0x00000000}, + {0x00008208, 0x00000000}, + {0x0000820c, 0x00000000}, + {0x00008210, 0x00000000}, + {0x00008214, 0x00000000}, + {0x00008218, 0x00000000}, + {0x0000821c, 0x00000000}, + {0x00008220, 0x00000000}, + {0x00008224, 0x00000000}, + {0x00008228, 0x00000000}, + {0x0000822c, 0x00000000}, + {0x00008230, 0x00000000}, + {0x00008234, 0x00000000}, + {0x00008238, 0x00000000}, + {0x0000823c, 0x00000000}, + {0x00008240, 0x00100000}, + {0x00008244, 0x0010f400}, + {0x00008248, 0x00000100}, + {0x0000824c, 0x0001e800}, + {0x00008250, 0x00000000}, + {0x00008254, 0x00000000}, + {0x00008258, 0x00000000}, + {0x0000825c, 0x400000ff}, + {0x00008260, 0x00080922}, + {0x00008264, 0x88a00010}, + {0x00008270, 0x00000000}, + {0x00008274, 0x40000000}, + {0x00008278, 0x003e4180}, + {0x0000827c, 0x00000000}, + {0x00008284, 0x0000002c}, + {0x00008288, 0x0000002c}, + {0x0000828c, 0x000000ff}, + {0x00008294, 0x00000000}, + {0x00008298, 0x00000000}, + {0x0000829c, 0x00000000}, + {0x00008300, 0x00000040}, + {0x00008314, 0x00000000}, + {0x00008328, 0x00000000}, + {0x0000832c, 0x00000007}, + {0x00008330, 0x00000302}, + {0x00008334, 0x00000e00}, + {0x00008338, 0x00ff0000}, + {0x0000833c, 0x00000000}, + {0x00008340, 0x000107ff}, + {0x00008344, 0x01c81043}, + {0x00008360, 0xffffffff}, + {0x00008364, 0xffffffff}, + {0x00008368, 0x00000000}, + {0x00008370, 0x00000000}, + {0x00008374, 0x000000ff}, + {0x00008378, 0x00000000}, + {0x0000837c, 0x00000000}, + {0x00008380, 0xffffffff}, + {0x00008384, 0xffffffff}, + {0x00008390, 0x0fffffff}, + {0x00008394, 0x0fffffff}, + {0x00008398, 0x00000000}, + {0x0000839c, 0x00000000}, + {0x000083a0, 0x00000000}, + {0x00009808, 0x00000000}, + {0x0000980c, 0xafe68e30}, + {0x00009810, 0xfd14e000}, + {0x00009814, 0x9c0a9f6b}, + {0x0000981c, 0x00000000}, + {0x0000982c, 0x0000a000}, + {0x00009830, 0x00000000}, + {0x0000983c, 0x00200400}, + {0x0000984c, 0x0040233c}, + {0x0000a84c, 0x0040233c}, + {0x00009854, 0x00000044}, + {0x00009900, 0x00000000}, + {0x00009904, 0x00000000}, + {0x00009908, 0x00000000}, + {0x0000990c, 0x00000000}, + {0x00009910, 0x10002310}, + {0x0000991c, 0x10000fff}, + {0x00009920, 0x04900000}, + {0x0000a920, 0x04900000}, + {0x00009928, 0x00000001}, + {0x0000992c, 0x00000004}, + {0x00009930, 0x00000000}, + {0x0000a930, 0x00000000}, + {0x00009934, 0x1e1f2022}, + {0x00009938, 0x0a0b0c0d}, + {0x0000993c, 0x00000000}, + {0x00009948, 0x9280c00a}, + {0x0000994c, 0x00020028}, + {0x00009954, 0x5f3ca3de}, + {0x00009958, 0x0108ecff}, + {0x00009940, 0x14750604}, + {0x0000c95c, 0x004b6a8e}, + {0x00009970, 0x990bb514}, + {0x00009974, 0x00000000}, + {0x00009978, 0x00000001}, + {0x0000997c, 0x00000000}, + {0x000099a0, 0x00000000}, + {0x000099a4, 0x00000001}, + {0x000099a8, 0x201fff00}, + {0x000099ac, 0x0c6f0000}, + {0x000099b0, 0x03051000}, + {0x000099b4, 0x00000820}, + {0x000099c4, 0x06336f77}, + {0x000099c8, 0x6af6532f}, + {0x000099cc, 0x08f186c8}, + {0x000099d0, 0x00046384}, + {0x000099dc, 0x00000000}, + {0x000099e0, 0x00000000}, + {0x000099e4, 0xaaaaaaaa}, + {0x000099e8, 0x3c466478}, + {0x000099ec, 0x0cc80caa}, + {0x000099f0, 0x00000000}, + {0x000099fc, 0x00001042}, + {0x0000a208, 0x803e4788}, + {0x0000a210, 0x4080a333}, + {0x0000a214, 0x40206c10}, + {0x0000a218, 0x009c4060}, + {0x0000a220, 0x01834061}, + {0x0000a224, 0x00000400}, + {0x0000a228, 0x000003b5}, + {0x0000a22c, 0x233f7180}, + {0x0000a234, 0x20202020}, + {0x0000a238, 0x20202020}, + {0x0000a23c, 0x13c889af}, + {0x0000a240, 0x38490a20}, + {0x0000a244, 0x00000000}, + {0x0000a248, 0xfffffffc}, + {0x0000a24c, 0x00000000}, + {0x0000a254, 0x00000000}, + {0x0000a258, 0x0cdbd380}, + {0x0000a25c, 0x0f0f0f01}, + {0x0000a260, 0xdfa91f01}, + {0x0000a264, 0x00418a11}, + {0x0000b264, 0x00418a11}, + {0x0000a268, 0x00000000}, + {0x0000a26c, 0x0e79e5c6}, + {0x0000b26c, 0x0e79e5c6}, + {0x0000d270, 0x00820820}, + {0x0000a278, 0x1ce739ce}, + {0x0000a27c, 0x050701ce}, + {0x0000d35c, 0x07ffffef}, + {0x0000d360, 0x0fffffe7}, + {0x0000d364, 0x17ffffe5}, + {0x0000d368, 0x1fffffe4}, + {0x0000d36c, 0x37ffffe3}, + {0x0000d370, 0x3fffffe3}, + {0x0000d374, 0x57ffffe3}, + {0x0000d378, 0x5fffffe2}, + {0x0000d37c, 0x7fffffe2}, + {0x0000d380, 0x7f3c7bba}, + {0x0000d384, 0xf3307ff0}, + {0x0000a388, 0x0c000000}, + {0x0000a38c, 0x20202020}, + {0x0000a390, 0x20202020}, + {0x0000a394, 0x1ce739ce}, + {0x0000a398, 0x000001ce}, + {0x0000b398, 0x000001ce}, + {0x0000a39c, 0x00000001}, + {0x0000a3c8, 0x00000246}, + {0x0000a3cc, 0x20202020}, + {0x0000a3d0, 0x20202020}, + {0x0000a3d4, 0x20202020}, + {0x0000a3dc, 0x1ce739ce}, + {0x0000a3e0, 0x000001ce}, + {0x0000a3e4, 0x00000000}, + {0x0000a3e8, 0x18c43433}, + {0x0000a3ec, 0x00f70081}, + {0x0000a3f0, 0x01036a1e}, + {0x0000a3f4, 0x00000000}, + {0x0000b3f4, 0x00000000}, + {0x0000a7d8, 0x000003f1}, + {0x00007800, 0x00000800}, + {0x00007804, 0x6c35ffd2}, + {0x00007808, 0x6db6c000}, + {0x0000780c, 0x6db6cb30}, + {0x00007810, 0x6db6cb6c}, + {0x00007814, 0x0501e200}, + {0x00007818, 0x0094128d}, + {0x0000781c, 0x976ee392}, + {0x00007820, 0xf75ff6fc}, + {0x00007824, 0x00040000}, + {0x00007828, 0xdb003012}, + {0x0000782c, 0x04924914}, + {0x00007830, 0x21084210}, + {0x00007834, 0x00140000}, + {0x00007838, 0x0e4548d8}, + {0x0000783c, 0x54214514}, + {0x00007840, 0x02025830}, + {0x00007844, 0x71c0d388}, + {0x00007848, 0x934934a8}, + {0x00007850, 0x00000000}, + {0x00007854, 0x00000800}, + {0x00007858, 0x6c35ffd2}, + {0x0000785c, 0x6db6c000}, + {0x00007860, 0x6db6cb30}, + {0x00007864, 0x6db6cb6c}, + {0x00007868, 0x0501e200}, + {0x0000786c, 0x0094128d}, + {0x00007870, 0x976ee392}, + {0x00007874, 0xf75ff6fc}, + {0x00007878, 0x00040000}, + {0x0000787c, 0xdb003012}, + {0x00007880, 0x04924914}, + {0x00007884, 0x21084210}, + {0x00007888, 0x001b6db0}, + {0x0000788c, 0x00376b63}, + {0x00007890, 0x06db6db6}, + {0x00007894, 0x006d8000}, + {0x00007898, 0x48100000}, + {0x0000789c, 0x00000000}, + {0x000078a0, 0x08000000}, + {0x000078a4, 0x0007ffd8}, + {0x000078a8, 0x0007ffd8}, + {0x000078ac, 0x001c0020}, + {0x000078b0, 0x00060aeb}, + {0x000078b4, 0x40008080}, + {0x000078b8, 0x2a850160}, +}; + +static const uint32_t ar9287Common_normal_cck_fir_coeff_9287_1_1[][2] = { + /* Addr allmodes */ + {0x0000a1f4, 0x00fffeff}, + {0x0000a1f8, 0x00f5f9ff}, + {0x0000a1fc, 0xb79f6427}, +}; + +static const uint32_t ar9287Common_japan_2484_cck_fir_coeff_9287_1_1[][2] = { + /* Addr allmodes */ + {0x0000a1f4, 0x00000000}, + {0x0000a1f8, 0xefff0301}, + {0x0000a1fc, 0xca9228ee}, +}; + +static const uint32_t ar9287Modes_tx_gain_9287_1_1[][6] = { + {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002}, + {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004}, + {0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a}, + {0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c}, + {0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b}, + {0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a}, + {0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a}, + {0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a}, + {0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a}, + {0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a}, + {0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a}, + {0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a}, + {0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a}, + {0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c}, + {0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc}, + {0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4}, + {0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc}, + {0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede}, + {0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e}, + {0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e}, + {0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e}, + {0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062, 0x00000062}, + {0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064, 0x00004064}, + {0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4, 0x000080a4}, + {0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa, 0x0000c0aa}, + {0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac, 0x000100ac}, + {0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4, 0x000140b4}, + {0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4, 0x000180f4}, + {0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134, 0x0001c134}, + {0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174, 0x00020174}, + {0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c, 0x0002417c}, + {0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e, 0x0002817e}, + {0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be, 0x0002c1be}, + {0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000}, +}; + +static const uint32_t ar9287Modes_rx_gain_9287_1_1[][6] = { + {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120}, + {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124}, + {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128}, + {0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c}, + {0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130}, + {0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194}, + {0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198}, + {0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c}, + {0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210}, + {0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284}, + {0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288}, + {0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c}, + {0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290}, + {0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294}, + {0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0}, + {0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4}, + {0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8}, + {0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac}, + {0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0}, + {0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4}, + {0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8}, + {0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4}, + {0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708}, + {0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c}, + {0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710}, + {0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04}, + {0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08}, + {0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c}, + {0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10}, + {0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14}, + {0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18}, + {0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c}, + {0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90}, + {0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94}, + {0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98}, + {0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4}, + {0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8}, + {0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04}, + {0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08}, + {0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c}, + {0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10}, + {0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14}, + {0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18}, + {0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c}, + {0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90}, + {0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18}, + {0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24}, + {0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28}, + {0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314}, + {0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318}, + {0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c}, + {0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390}, + {0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394}, + {0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398}, + {0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4}, + {0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8}, + {0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac}, + {0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0}, + {0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380}, + {0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384}, + {0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388}, + {0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710}, + {0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714}, + {0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718}, + {0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10}, + {0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14}, + {0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18}, + {0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c}, + {0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90}, + {0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94}, + {0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c}, + {0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90}, + {0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94}, + {0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0}, + {0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4}, + {0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8}, + {0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac}, + {0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0}, + {0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4}, + {0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1}, + {0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5}, + {0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9}, + {0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad}, + {0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1}, + {0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5}, + {0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9}, + {0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5}, + {0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9}, + {0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd}, + {0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1}, + {0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5}, + {0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2}, + {0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6}, + {0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca}, + {0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce}, + {0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2}, + {0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6}, + {0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda}, + {0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7}, + {0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb}, + {0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf}, + {0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3}, + {0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7}, + {0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120}, + {0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124}, + {0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128}, + {0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c}, + {0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130}, + {0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194}, + {0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198}, + {0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c}, + {0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210}, + {0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284}, + {0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288}, + {0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c}, + {0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290}, + {0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294}, + {0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0}, + {0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4}, + {0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8}, + {0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac}, + {0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0}, + {0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4}, + {0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8}, + {0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4}, + {0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708}, + {0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c}, + {0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710}, + {0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04}, + {0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08}, + {0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c}, + {0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10}, + {0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14}, + {0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18}, + {0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c}, + {0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90}, + {0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94}, + {0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98}, + {0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4}, + {0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8}, + {0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04}, + {0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08}, + {0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c}, + {0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10}, + {0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14}, + {0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18}, + {0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c}, + {0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90}, + {0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18}, + {0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24}, + {0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28}, + {0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314}, + {0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318}, + {0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c}, + {0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390}, + {0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394}, + {0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398}, + {0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4}, + {0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8}, + {0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac}, + {0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0}, + {0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380}, + {0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384}, + {0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388}, + {0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710}, + {0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714}, + {0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718}, + {0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10}, + {0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14}, + {0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18}, + {0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c}, + {0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90}, + {0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94}, + {0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c}, + {0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90}, + {0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94}, + {0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0}, + {0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4}, + {0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8}, + {0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac}, + {0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0}, + {0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4}, + {0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1}, + {0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5}, + {0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9}, + {0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad}, + {0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1}, + {0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5}, + {0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9}, + {0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5}, + {0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9}, + {0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd}, + {0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1}, + {0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5}, + {0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2}, + {0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6}, + {0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca}, + {0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce}, + {0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2}, + {0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6}, + {0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda}, + {0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7}, + {0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb}, + {0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf}, + {0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3}, + {0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7}, + {0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067}, + {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067}, +}; + +static const uint32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = { + /* Addr allmodes */ + {0x00004040, 0x9248fd00}, + {0x00004040, 0x24924924}, + {0x00004040, 0xa8000019}, + {0x00004040, 0x13160820}, + {0x00004040, 0xe5980560}, + {0x00004040, 0xc01dcffd}, + {0x00004040, 0x1aaabe41}, + {0x00004040, 0xbe105554}, + {0x00004040, 0x00043007}, + {0x00004044, 0x00000000}, +}; + +static const uint32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { + /* Addr allmodes */ + {0x00004040, 0x9248fd00}, + {0x00004040, 0x24924924}, + {0x00004040, 0xa8000019}, + {0x00004040, 0x13160820}, + {0x00004040, 0xe5980560}, + {0x00004040, 0xc01dcffc}, + {0x00004040, 0x1aaabe41}, + {0x00004040, 0xbe105554}, + {0x00004040, 0x00043007}, + {0x00004044, 0x00000000}, +}; diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9287_attach.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_attach.c new file mode 100644 index 0000000..0ea565c --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_attach.c @@ -0,0 +1,494 @@ +/* + * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" /* XXX for tx/rx gain */ +#include "ah_eeprom_9287.h" + +#include "ar9002/ar9280.h" +#include "ar9002/ar9287.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ar9002/ar9287_cal.h" +#include "ar9002/ar9287_reset.h" +#include "ar9002/ar9287_olc.h" + +#include "ar9002/ar9287.ini" + +static const HAL_PERCAL_DATA ar9287_iq_cal = { /* single sample */ + .calName = "IQ", .calType = IQ_MISMATCH_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = PER_MAX_LOG_COUNT, + .calCollect = ar5416IQCalCollect, + .calPostProc = ar5416IQCalibration +}; +static const HAL_PERCAL_DATA ar9287_adc_gain_cal = { /* single sample */ + .calName = "ADC Gain", .calType = ADC_GAIN_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcGainCalCollect, + .calPostProc = ar5416AdcGainCalibration +}; +static const HAL_PERCAL_DATA ar9287_adc_dc_cal = { /* single sample */ + .calName = "ADC DC", .calType = ADC_DC_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = PER_MIN_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; +static const HAL_PERCAL_DATA ar9287_adc_init_dc_cal = { + .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, + .calNumSamples = MIN_CAL_SAMPLES, + .calCountMax = INIT_LOG_COUNT, + .calCollect = ar5416AdcDcCalCollect, + .calPostProc = ar5416AdcDcCalibration +}; + +static void ar9287ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, + HAL_BOOL power_off); +static void ar9287DisablePCIE(struct ath_hal *ah); +static HAL_BOOL ar9287FillCapabilityInfo(struct ath_hal *ah); +static void ar9287WriteIni(struct ath_hal *ah, + const struct ieee80211_channel *chan); + +static void +ar9287AniSetup(struct ath_hal *ah) +{ + /* + * These are the parameters from the AR5416 ANI code; + * they likely need quite a bit of adjustment for the + * AR9287. + */ + static const struct ar5212AniParams aniparams = { + .maxNoiseImmunityLevel = 4, /* levels 0..4 */ + .totalSizeDesired = { -55, -55, -55, -55, -62 }, + .coarseHigh = { -14, -14, -14, -14, -12 }, + .coarseLow = { -64, -64, -64, -64, -70 }, + .firpwr = { -78, -78, -78, -78, -80 }, + .maxSpurImmunityLevel = 7, + .cycPwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 }, + .maxFirstepLevel = 2, /* levels 0..2 */ + .firstep = { 0, 4, 8 }, + .ofdmTrigHigh = 500, + .ofdmTrigLow = 200, + .cckTrigHigh = 200, + .cckTrigLow = 100, + .rssiThrHigh = 40, + .rssiThrLow = 7, + .period = 100, + }; + /* NB: disable ANI noise immmunity for reliable RIFS rx */ + AH5416(ah)->ah_ani_function &= ~ HAL_ANI_NOISE_IMMUNITY_LEVEL; + + /* NB: ANI is not enabled yet */ + ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE); +} + +/* + * Attach for an AR9287 part. + */ +static struct ath_hal * +ar9287Attach(uint16_t devid, HAL_SOFTC sc, + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, + HAL_OPS_CONFIG *ah_config, + HAL_STATUS *status) +{ + struct ath_hal_9287 *ahp9287; + struct ath_hal_5212 *ahp; + struct ath_hal *ah; + uint32_t val; + HAL_STATUS ecode; + HAL_BOOL rfStatus; + int8_t pwr_table_offset; + + HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + __func__, sc, (void*) st, (void*) sh); + + /* NB: memory is returned zero'd */ + ahp9287 = ath_hal_malloc(sizeof (struct ath_hal_9287)); + if (ahp9287 == AH_NULL) { + HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + "%s: cannot allocate memory for state block\n", __func__); + *status = HAL_ENOMEM; + return AH_NULL; + } + ahp = AH5212(ahp9287); + ah = &ahp->ah_priv.h; + + ar5416InitState(AH5416(ah), devid, sc, st, sh, status); + + if (eepromdata != AH_NULL) { + AH_PRIVATE(ah)->ah_eepromRead = ath_hal_EepromDataRead; + AH_PRIVATE(ah)->ah_eepromWrite = NULL; + ah->ah_eepromdata = eepromdata; + } + + + /* XXX override with 9280 specific state */ + /* override 5416 methods for our needs */ + AH5416(ah)->ah_initPLL = ar9280InitPLL; + + ah->ah_setAntennaSwitch = ar9287SetAntennaSwitch; + ah->ah_configPCIE = ar9287ConfigPCIE; + ah->ah_disablePCIE = ar9287DisablePCIE; + + AH5416(ah)->ah_cal.iqCalData.calData = &ar9287_iq_cal; + AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9287_adc_gain_cal; + AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9287_adc_dc_cal; + AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9287_adc_init_dc_cal; + /* Better performance without ADC Gain Calibration */ + AH5416(ah)->ah_cal.suppCals = ADC_DC_CAL | IQ_MISMATCH_CAL; + + AH5416(ah)->ah_spurMitigate = ar9280SpurMitigate; + AH5416(ah)->ah_writeIni = ar9287WriteIni; + + ah->ah_setTxPower = ar9287SetTransmitPower; + ah->ah_setBoardValues = ar9287SetBoardValues; + + AH5416(ah)->ah_olcInit = ar9287olcInit; + AH5416(ah)->ah_olcTempCompensation = ar9287olcTemperatureCompensation; + //AH5416(ah)->ah_setPowerCalTable = ar9287SetPowerCalTable; + AH5416(ah)->ah_cal_initcal = ar9287InitCalHardware; + AH5416(ah)->ah_cal_pacal = ar9287PACal; + + /* XXX NF calibration */ + /* XXX Ini override? (IFS vars - since the kiwi mac clock is faster?) */ + /* XXX what else is kiwi-specific in the radio/calibration pathway? */ + + AH5416(ah)->ah_rx_chainmask = AR9287_DEFAULT_RXCHAINMASK; + AH5416(ah)->ah_tx_chainmask = AR9287_DEFAULT_TXCHAINMASK; + + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { + /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + + if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", + __func__); + ecode = HAL_EIO; + goto bad; + } + /* Read Revisions from Chips before taking out of reset */ + val = OS_REG_READ(ah, AR_SREV); + HALDEBUG(ah, HAL_DEBUG_ATTACH, + "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", + __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), + MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); + /* NB: include chip type to differentiate from pre-Sowl versions */ + AH_PRIVATE(ah)->ah_macVersion = + (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S; + AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); + AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0; + + /* Don't support Kiwi < 1.2; those are pre-release chips */ + if (! AR_SREV_KIWI_12_OR_LATER(ah)) { + ath_hal_printf(ah, "[ath]: Kiwi < 1.2 is not supported\n"); + ecode = HAL_EIO; + goto bad; + } + + /* setup common ini data; rf backends handle remainder */ + HAL_INI_INIT(&ahp->ah_ini_modes, ar9287Modes_9287_1_1, 6); + HAL_INI_INIT(&ahp->ah_ini_common, ar9287Common_9287_1_1, 2); + + /* If pcie_clock_req */ + HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, + ar9287PciePhy_clkreq_always_on_L1_9287_1_1, 2); + + /* XXX WoW ini values */ + + /* Else */ +#if 0 + HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, + ar9287PciePhy_clkreq_off_L1_9287_1_1, 2); +#endif + + /* Initialise Japan arrays */ + HAL_INI_INIT(&ahp9287->ah_ini_cckFirNormal, + ar9287Common_normal_cck_fir_coeff_9287_1_1, 2); + HAL_INI_INIT(&ahp9287->ah_ini_cckFirJapan2484, + ar9287Common_japan_2484_cck_fir_coeff_9287_1_1, 2); + + ar5416AttachPCIE(ah); + + ecode = ath_hal_9287EepromAttach(ah); + if (ecode != HAL_OK) + goto bad; + + if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); + ecode = HAL_EIO; + goto bad; + } + + AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); + + if (!ar5212ChipTest(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", + __func__); + ecode = HAL_ESELFTEST; + goto bad; + } + + /* + * Set correct Baseband to analog shift + * setting to access analog chips. + */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + + /* Read Radio Chip Rev Extract */ + AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); + switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { + case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ + case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ + break; + default: + if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5133_SREV_MAJOR; + break; + } +#ifdef AH_DEBUG + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 5G Radio Chip Rev 0x%02X is not supported by " + "this driver\n", __func__, + AH_PRIVATE(ah)->ah_analog5GhzRev); + ecode = HAL_ENOTSUPP; + goto bad; +#endif + } + rfStatus = ar9287RfAttach(ah, &ecode); + if (!rfStatus) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", + __func__, ecode); + goto bad; + } + + /* + * We only implement open-loop TX power control + * for the AR9287 in this codebase. + */ + if (! ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + ath_hal_printf(ah, "[ath] AR9287 w/ closed-loop TX power control" + " isn't supported.\n"); + ecode = HAL_ENOTSUPP; + goto bad; + } + + /* + * Check whether the power table offset isn't the default. + * This can occur with eeprom minor V21 or greater on Merlin. + */ + (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, &pwr_table_offset); + if (pwr_table_offset != AR5416_PWR_TABLE_OFFSET_DB) + ath_hal_printf(ah, "[ath]: default pwr offset: %d dBm != EEPROM pwr offset: %d dBm; curves will be adjusted.\n", + AR5416_PWR_TABLE_OFFSET_DB, (int) pwr_table_offset); + + /* setup rxgain table */ + HAL_INI_INIT(&ahp9287->ah_ini_rxgain, ar9287Modes_rx_gain_9287_1_1, 6); + + /* setup txgain table */ + HAL_INI_INIT(&ahp9287->ah_ini_txgain, ar9287Modes_tx_gain_9287_1_1, 6); + + /* + * Got everything we need now to setup the capabilities. + */ + if (!ar9287FillCapabilityInfo(ah)) { + ecode = HAL_EEREAD; + goto bad; + } + + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error getting mac address from EEPROM\n", __func__); + goto bad; + } + /* XXX How about the serial number ? */ + /* Read Reg Domain */ + AH_PRIVATE(ah)->ah_currentRD = + ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + AH_PRIVATE(ah)->ah_currentRDext = AR9287_RDEXT_DEFAULT; + + /* + * ah_miscMode is populated by ar5416FillCapabilityInfo() + * starting from griffin. Set here to make sure that + * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is + * placed into hardware. + */ + if (ahp->ah_miscMode != 0) + OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); + + ar9287AniSetup(ah); /* Anti Noise Immunity */ + + /* Setup noise floor min/max/nominal values */ + AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ; + AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ; + AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9287_2GHZ; + AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9287_5GHZ; + AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9287_5GHZ; + AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9287_5GHZ; + + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); + + HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); + + return ah; +bad: + if (ah != AH_NULL) + ah->ah_detach(ah); + if (status) + *status = ecode; + return AH_NULL; +} + +static void +ar9287ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) +{ + if (AH_PRIVATE(ah)->ah_ispcie && !restore) { + ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0); + OS_DELAY(1000); + OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + /* Yes, Kiwi uses the Kite PCIe PHY WA */ + OS_REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT); + } +} + +static void +ar9287DisablePCIE(struct ath_hal *ah) +{ + /* XXX TODO */ +} + +static void +ar9287WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + u_int modesIndex, freqIndex; + int regWrites = 0; + + /* Setup the indices for the next set of register array writes */ + /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + freqIndex = 2; + if (IEEE80211_IS_CHAN_HT40(chan)) + modesIndex = 3; + else if (IEEE80211_IS_CHAN_108G(chan)) + modesIndex = 5; + else + modesIndex = 4; + } else { + freqIndex = 1; + if (IEEE80211_IS_CHAN_HT40(chan) || + IEEE80211_IS_CHAN_TURBO(chan)) + modesIndex = 2; + else + modesIndex = 1; + } + + /* Set correct Baseband to analog shift setting to access analog chips. */ + OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); + OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); + + regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, modesIndex, regWrites); + regWrites = ath_hal_ini_write(ah, &AH9287(ah)->ah_ini_rxgain, modesIndex, regWrites); + regWrites = ath_hal_ini_write(ah, &AH9287(ah)->ah_ini_txgain, modesIndex, regWrites); + regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, 1, regWrites); +} + +/* + * Fill all software cached or static hardware state information. + * Return failure if capabilities are to come from EEPROM and + * cannot be read. + */ +static HAL_BOOL +ar9287FillCapabilityInfo(struct ath_hal *ah) +{ + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + if (!ar5416FillCapabilityInfo(ah)) + return AH_FALSE; + pCap->halNumGpioPins = 10; + pCap->halWowSupport = AH_TRUE; + pCap->halWowMatchPatternExact = AH_TRUE; +#if 0 + pCap->halWowMatchPatternDword = AH_TRUE; +#endif + + pCap->halCSTSupport = AH_TRUE; + pCap->halRifsRxSupport = AH_TRUE; + pCap->halRifsTxSupport = AH_TRUE; + pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ + pCap->halExtChanDfsSupport = AH_TRUE; + pCap->halUseCombinedRadarRssi = AH_TRUE; +#if 0 + /* XXX bluetooth */ + pCap->halBtCoexSupport = AH_TRUE; +#endif + pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ + pCap->hal4kbSplitTransSupport = AH_FALSE; + /* Disable this so Block-ACK works correctly */ + pCap->halHasRxSelfLinkedTail = AH_FALSE; + pCap->halPSPollBroken = AH_FALSE; + pCap->halSpectralScanSupport = AH_TRUE; + + /* Hardware supports (at least) single-stream STBC TX/RX */ + pCap->halRxStbcSupport = 1; + pCap->halTxStbcSupport = 1; + + /* Hardware supports short-GI w/ 20MHz */ + pCap->halHTSGI20Support = 1; + + pCap->halEnhancedDfsSupport = AH_TRUE; + + return AH_TRUE; +} + +/* + * This has been disabled - having the HAL flip chainmasks on/off + * when attempting to implement 11n disrupts things. For now, just + * leave this flipped off and worry about implementing TX diversity + * for legacy and MCS0-15 when 11n is fully functioning. + */ +HAL_BOOL +ar9287SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) +{ + return AH_TRUE; +} + +static const char* +ar9287Probe(uint16_t vendorid, uint16_t devid) +{ + if (vendorid == ATHEROS_VENDOR_ID) { + if (devid == AR9287_DEVID_PCI) + return "Atheros 9227"; + if (devid == AR9287_DEVID_PCIE) + return "Atheros 9287"; + } + return AH_NULL; +} +AH_CHIP(AR9287, ar9287Probe, ar9287Attach); diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9287_cal.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_cal.c new file mode 100644 index 0000000..d5024b0 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_cal.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v4k.h" + +#include "ar9002/ar9285.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9002/ar9002phy.h" +//#include "ar9002/ar9287phy.h" + +#include "ar9002/ar9287_cal.h" + + +void +ar9287PACal(struct ath_hal *ah, HAL_BOOL is_reset) +{ + /* XXX not required */ +} + +/* + * This is like Merlin but without ADC disable + */ +HAL_BOOL +ar9287InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + + /* Calibrate the AGC */ + OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, + OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL); + + /* Poll for offset calibration complete */ + if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: offset calibration failed to complete in 1ms; " + "noisy environment?\n", __func__); + return AH_FALSE; + } + + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + + return AH_TRUE; +} diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9287_cal.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_cal.h new file mode 100644 index 0000000..1a7cda2 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_cal.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __AR9287_CAL_H__ +#define __AR9287_CAL_H__ + +extern void ar9287PACal(struct ath_hal *ah, HAL_BOOL is_reset); +extern HAL_BOOL ar9287InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan); + +#endif /* __AR9287_CAL_H__ */ diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9287_olc.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_olc.c new file mode 100644 index 0000000..cbbe017 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_olc.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ah_eeprom_v14.h" +#include "ah_eeprom_9287.h" + +#include "ar9002/ar9280.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#include "ar9002/ar9002phy.h" + +#include "ar9002/ar9287phy.h" +#include "ar9002/ar9287an.h" +#include "ar9002/ar9287_olc.h" + +void +ar9287olcInit(struct ath_hal *ah) +{ + OS_REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9, + AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL); + OS_A_REG_RMW_FIELD(ah, AR9287_AN_TXPC0, + AR9287_AN_TXPC0_TXPCMODE, + AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE); + OS_DELAY(100); +} + +/* + * Run temperature compensation calibration. + * + * The TX gain table is adjusted depending upon the difference + * between the initial PDADC value and the currently read + * average TX power sample value. This value is only valid if + * frames have been transmitted, so currPDADC will be 0 if + * no frames have yet been transmitted. + */ +void +ar9287olcTemperatureCompensation(struct ath_hal *ah) +{ + uint32_t rddata; + int32_t delta, currPDADC, slope; + + rddata = OS_REG_READ(ah, AR_PHY_TX_PWRCTRL4); + currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, "%s: initPDADC=%d, currPDADC=%d\n", + __func__, AH5416(ah)->initPDADC, currPDADC); + + if (AH5416(ah)->initPDADC == 0 || currPDADC == 0) { + /* + * Zero value indicates that no frames have been transmitted + * yet, can't do temperature compensation until frames are + * transmitted. + */ + return; + } else { + int8_t val; + (void) (ath_hal_eepromGet(ah, AR_EEP_TEMPSENSE_SLOPE, &val)); + slope = val; + + if (slope == 0) { /* to avoid divide by zero case */ + delta = 0; + } else { + delta = ((currPDADC - AH5416(ah)->initPDADC)*4) / slope; + } + OS_REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, + AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); + OS_REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, + AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, "%s: delta=%d\n", __func__, delta); + } +} + +void +ar9287olcGetTxGainIndex(struct ath_hal *ah, + const struct ieee80211_channel *chan, + struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, + uint8_t *pCalChans, uint16_t availPiers, int8_t *pPwr) +{ + uint16_t idxL = 0, idxR = 0, numPiers; + HAL_BOOL match; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + for (numPiers = 0; numPiers < availPiers; numPiers++) { + if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED) + break; + } + + match = ath_ee_getLowerUpperIndex( + (uint8_t)FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)), + pCalChans, numPiers, &idxL, &idxR); + + if (match) { + *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0]; + } else { + *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] + + (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; + } +} + +void +ar9287olcSetPDADCs(struct ath_hal *ah, int32_t txPower, + uint16_t chain) +{ + uint32_t tmpVal; + uint32_t a; + + /* Enable OLPC for chain 0 */ + + tmpVal = OS_REG_READ(ah, 0xa270); + tmpVal = tmpVal & 0xFCFFFFFF; + tmpVal = tmpVal | (0x3 << 24); + OS_REG_WRITE(ah, 0xa270, tmpVal); + + /* Enable OLPC for chain 1 */ + + tmpVal = OS_REG_READ(ah, 0xb270); + tmpVal = tmpVal & 0xFCFFFFFF; + tmpVal = tmpVal | (0x3 << 24); + OS_REG_WRITE(ah, 0xb270, tmpVal); + + /* Write the OLPC ref power for chain 0 */ + + if (chain == 0) { + tmpVal = OS_REG_READ(ah, 0xa398); + tmpVal = tmpVal & 0xff00ffff; + a = (txPower)&0xff; + tmpVal = tmpVal | (a << 16); + OS_REG_WRITE(ah, 0xa398, tmpVal); + } + + /* Write the OLPC ref power for chain 1 */ + + if (chain == 1) { + tmpVal = OS_REG_READ(ah, 0xb398); + tmpVal = tmpVal & 0xff00ffff; + a = (txPower)&0xff; + tmpVal = tmpVal | (a << 16); + OS_REG_WRITE(ah, 0xb398, tmpVal); + } +} diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9287_olc.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_olc.h new file mode 100644 index 0000000..ff21ce6 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_olc.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AR9287_OLC_H__ +#define __AR9287_OLC_H__ + +extern void ar9287olcInit(struct ath_hal *ah); +extern void ar9287olcTemperatureCompensation(struct ath_hal *ah); +extern void ar9287olcGetTxGainIndex(struct ath_hal *ah, + const struct ieee80211_channel *chan, + struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, + uint8_t *pCalChans, uint16_t availPiers, int8_t *pPwr); +extern void ar9287olcSetPDADCs(struct ath_hal *ah, + int32_t txPower, uint16_t chain); + +#endif /* __AR9287_OLC_H__ */ diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9287_reset.c b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_reset.c new file mode 100644 index 0000000..5ed4af2 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_reset.c @@ -0,0 +1,586 @@ +/* + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" +#include "ah_eeprom_9287.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +#include "ar9002/ar9287phy.h" +#include "ar9002/ar9287an.h" + +#include "ar9002/ar9287_olc.h" +#include "ar9002/ar9287_reset.h" + +/* + * Set the TX power calibration table per-chain. + * + * This only supports open-loop TX power control for the AR9287. + */ +static void +ar9287SetPowerCalTable(struct ath_hal *ah, + const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset) +{ + struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; + uint8_t *pCalBChans = NULL; + uint16_t pdGainOverlap_t2; + uint16_t numPiers = 0, i; + uint16_t numXpdGain, xpdMask; + uint16_t xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0}; + uint32_t regChainOffset; + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ar9287_eeprom *pEepData = &ee->ee_base; + + xpdMask = pEepData->modalHeader.xpdGain; + + if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= + AR9287_EEP_MINOR_VER_2) + pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; + else + pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); + + /* Note: Kiwi should only be 2ghz.. */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + pCalBChans = pEepData->calFreqPier2G; + numPiers = AR9287_NUM_2G_CAL_PIERS; + pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[0]; + AH5416(ah)->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0]; + } + numXpdGain = 0; + + /* Calculate the value of xpdgains from the xpdGain Mask */ + for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { + if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { + if (numXpdGain >= AR5416_NUM_PD_GAINS) + break; + xpdGainValues[numXpdGain] = + (uint16_t)(AR5416_PD_GAINS_IN_MASK-i); + numXpdGain++; + } + } + + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (numXpdGain - 1) & 0x3); + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, + xpdGainValues[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, + xpdGainValues[1]); + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, + xpdGainValues[2]); + + for (i = 0; i < AR9287_MAX_CHAINS; i++) { + regChainOffset = i * 0x1000; + + if (pEepData->baseEepHeader.txMask & (1 << i)) { + int8_t txPower; + pRawDatasetOpenLoop = + (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[i]; + ar9287olcGetTxGainIndex(ah, chan, + pRawDatasetOpenLoop, + pCalBChans, numPiers, + &txPower); + ar9287olcSetPDADCs(ah, txPower, i); + } + } + + *pTxPowerIndexOffset = 0; +} + + +/* XXX hard-coded values? */ +#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 + +/* + * ar9287SetPowerPerRateTable + * + * Sets the transmit power in the baseband for the given + * operating channel and mode. + * + * This is like the v14 EEPROM table except the 5GHz code. + */ +static HAL_BOOL +ar9287SetPowerPerRateTable(struct ath_hal *ah, + struct ar9287_eeprom *pEepData, + const struct ieee80211_channel *chan, + int16_t *ratesArray, uint16_t cfgCtl, + uint16_t AntennaReduction, + uint16_t twiceMaxRegulatoryPower, + uint16_t powerLimit) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) +/* Local defines to distinguish between extension and control CTL's */ +#define EXT_ADDITIVE (0x8000) +#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) +#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) +#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) + + uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + int i; + int16_t twiceLargestAntenna; + struct cal_ctl_data_ar9287 *rep; + CAL_TARGET_POWER_LEG targetPowerOfdm; + CAL_TARGET_POWER_LEG targetPowerCck = {0, {0, 0, 0, 0}}; + CAL_TARGET_POWER_LEG targetPowerOfdmExt = {0, {0, 0, 0, 0}}; + CAL_TARGET_POWER_LEG targetPowerCckExt = {0, {0, 0, 0, 0}}; + CAL_TARGET_POWER_HT targetPowerHt20; + CAL_TARGET_POWER_HT targetPowerHt40 = {0, {0, 0, 0, 0}}; + int16_t scaledPower, minCtlPower; + +#define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ + static const uint16_t ctlModesFor11g[] = { + CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 + }; + const uint16_t *pCtlMode; + uint16_t numCtlModes, ctlMode, freq; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + /* Compute TxPower reduction due to Antenna Gain */ + + twiceLargestAntenna = AH_MAX( + pEepData->modalHeader.antennaGainCh[0], + pEepData->modalHeader.antennaGainCh[1]); + + twiceLargestAntenna = (int16_t)AH_MIN((AntennaReduction) - twiceLargestAntenna, 0); + + /* XXX setup for 5212 use (really used?) */ + ath_hal_eepromSet(ah, AR_EEP_ANTGAINMAX_2, twiceLargestAntenna); + + /* + * scaledPower is the minimum of the user input power level and + * the regulatory allowed power level + */ + scaledPower = AH_MIN(powerLimit, twiceMaxRegulatoryPower + twiceLargestAntenna); + + /* Reduce scaled Power by number of chains active to get to per chain tx power level */ + /* TODO: better value than these? */ + switch (owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask)) { + case 1: + break; + case 2: + scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; + break; + default: + return AH_FALSE; /* Unsupported number of chains */ + } + + scaledPower = AH_MAX(0, scaledPower); + + /* Get target powers from EEPROM - our baseline for TX Power */ + /* XXX assume channel is 2ghz */ + if (1) { + /* Setup for CTL modes */ + numCtlModes = N(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; /* CTL_11B, CTL_11G, CTL_2GHT20 */ + pCtlMode = ctlModesFor11g; + + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck, + AR9287_NUM_2G_CCK_TARGET_POWERS, &targetPowerCck, 4, AH_FALSE); + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G, + AR9287_NUM_2G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE); + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT20, + AR9287_NUM_2G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE); + + if (IEEE80211_IS_CHAN_HT40(chan)) { + numCtlModes = N(ctlModesFor11g); /* All 2G CTL's */ + + ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT40, + AR9287_NUM_2G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE); + /* Get target powers for extension channels */ + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck, + AR9287_NUM_2G_CCK_TARGET_POWERS, &targetPowerCckExt, 4, AH_TRUE); + ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G, + AR9287_NUM_2G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE); + } + } + + /* + * For MIMO, need to apply regulatory caps individually across dynamically + * running modes: CCK, OFDM, HT20, HT40 + * + * The outer loop walks through each possible applicable runtime mode. + * The inner loop walks through each ctlIndex entry in EEPROM. + * The ctl value is encoded as [7:4] == test group, [3:0] == test mode. + * + */ + for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { + HAL_BOOL isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || + (pCtlMode[ctlMode] == CTL_2GHT40); + if (isHt40CtlMode) { + freq = centers.ctl_center; + } else if (pCtlMode[ctlMode] & EXT_ADDITIVE) { + freq = centers.ext_center; + } else { + freq = centers.ctl_center; + } + + /* walk through each CTL index stored in EEPROM */ + for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { + uint16_t twiceMinEdgePower; + + /* compare test group from regulatory channel list with test mode from pCtlMode list */ + if ((((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == pEepData->ctlIndex[i]) || + (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == + ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { + rep = &(pEepData->ctlData[i]); + twiceMinEdgePower = ar5416GetMaxEdgePower(freq, + rep->ctlEdges[owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask) - 1], + IEEE80211_IS_CHAN_2GHZ(chan)); + if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { + /* Find the minimum of all CTL edge powers that apply to this channel */ + twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower); + } else { + /* specific */ + twiceMaxEdgePower = twiceMinEdgePower; + break; + } + } + } + minCtlPower = (uint8_t)AH_MIN(twiceMaxEdgePower, scaledPower); + /* Apply ctl mode to correct target power set */ + switch(pCtlMode[ctlMode]) { + case CTL_11B: + for (i = 0; i < N(targetPowerCck.tPow2x); i++) { + targetPowerCck.tPow2x[i] = (uint8_t)AH_MIN(targetPowerCck.tPow2x[i], minCtlPower); + } + break; + case CTL_11A: + case CTL_11G: + for (i = 0; i < N(targetPowerOfdm.tPow2x); i++) { + targetPowerOfdm.tPow2x[i] = (uint8_t)AH_MIN(targetPowerOfdm.tPow2x[i], minCtlPower); + } + break; + case CTL_5GHT20: + case CTL_2GHT20: + for (i = 0; i < N(targetPowerHt20.tPow2x); i++) { + targetPowerHt20.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt20.tPow2x[i], minCtlPower); + } + break; + case CTL_11B_EXT: + targetPowerCckExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerCckExt.tPow2x[0], minCtlPower); + break; + case CTL_11A_EXT: + case CTL_11G_EXT: + targetPowerOfdmExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerOfdmExt.tPow2x[0], minCtlPower); + break; + case CTL_5GHT40: + case CTL_2GHT40: + for (i = 0; i < N(targetPowerHt40.tPow2x); i++) { + targetPowerHt40.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt40.tPow2x[i], minCtlPower); + } + break; + default: + return AH_FALSE; + break; + } + } /* end ctl mode checking */ + + /* Set rates Array from collected data */ + ar5416SetRatesArrayFromTargetPower(ah, chan, ratesArray, + &targetPowerCck, + &targetPowerCckExt, + &targetPowerOfdm, + &targetPowerOfdmExt, + &targetPowerHt20, + &targetPowerHt40); + return AH_TRUE; +#undef EXT_ADDITIVE +#undef CTL_11A_EXT +#undef CTL_11G_EXT +#undef CTL_11B_EXT +#undef SUB_NUM_CTL_MODES_AT_5G_40 +#undef SUB_NUM_CTL_MODES_AT_2G_40 +#undef N +} + +#undef REDUCE_SCALED_POWER_BY_TWO_CHAIN + +/* + * This is based off of the AR5416/AR9285 code and likely could + * be unified in the future. + */ +HAL_BOOL +ar9287SetTransmitPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain) +{ +#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) +#define N(a) (sizeof (a) / sizeof (a[0])) + + const struct modal_eep_ar9287_header *pModal; + struct ath_hal_5212 *ahp = AH5212(ah); + int16_t txPowerIndexOffset = 0; + int i; + + uint16_t cfgCtl; + uint16_t powerLimit; + uint16_t twiceAntennaReduction; + uint16_t twiceMaxRegulatoryPower; + int16_t maxPower; + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ar9287_eeprom *pEepData = &ee->ee_base; + + AH5416(ah)->ah_ht40PowerIncForPdadc = 2; + + /* Setup info for the actual eeprom */ + OS_MEMZERO(AH5416(ah)->ah_ratesArray, + sizeof(AH5416(ah)->ah_ratesArray)); + cfgCtl = ath_hal_getctl(ah, chan); + powerLimit = chan->ic_maxregpower * 2; + twiceAntennaReduction = chan->ic_maxantgain; + twiceMaxRegulatoryPower = AH_MIN(MAX_RATE_POWER, + AH_PRIVATE(ah)->ah_powerLimit); + pModal = &pEepData->modalHeader; + HALDEBUG(ah, HAL_DEBUG_RESET, "%s Channel=%u CfgCtl=%u\n", + __func__,chan->ic_freq, cfgCtl ); + + /* XXX Assume Minor is v2 or later */ + AH5416(ah)->ah_ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; + + /* Fetch per-rate power table for the given channel */ + if (! ar9287SetPowerPerRateTable(ah, pEepData, chan, + &AH5416(ah)->ah_ratesArray[0], + cfgCtl, + twiceAntennaReduction, + twiceMaxRegulatoryPower, powerLimit)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to set tx power per rate table\n", __func__); + return AH_FALSE; + } + + /* Set TX power control calibration curves for each TX chain */ + ar9287SetPowerCalTable(ah, chan, &txPowerIndexOffset); + + /* Calculate maximum power level */ + maxPower = AH_MAX(AH5416(ah)->ah_ratesArray[rate6mb], + AH5416(ah)->ah_ratesArray[rateHt20_0]); + maxPower = AH_MAX(maxPower, + AH5416(ah)->ah_ratesArray[rate1l]); + + if (IEEE80211_IS_CHAN_HT40(chan)) + maxPower = AH_MAX(maxPower, + AH5416(ah)->ah_ratesArray[rateHt40_0]); + + ahp->ah_tx6PowerInHalfDbm = maxPower; + AH_PRIVATE(ah)->ah_maxPowerLevel = maxPower; + ahp->ah_txPowerIndexOffset = txPowerIndexOffset; + + /* + * txPowerIndexOffset is set by the SetPowerTable() call - + * adjust the rate table (0 offset if rates EEPROM not loaded) + */ + /* XXX what about the pwrTableOffset? */ + for (i = 0; i < N(AH5416(ah)->ah_ratesArray); i++) { + AH5416(ah)->ah_ratesArray[i] = + (int16_t)(txPowerIndexOffset + + AH5416(ah)->ah_ratesArray[i]); + /* -5 dBm offset for Merlin and later; this includes Kiwi */ + AH5416(ah)->ah_ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; + if (AH5416(ah)->ah_ratesArray[i] > AR5416_MAX_RATE_POWER) + AH5416(ah)->ah_ratesArray[i] = AR5416_MAX_RATE_POWER; + if (AH5416(ah)->ah_ratesArray[i] < 0) + AH5416(ah)->ah_ratesArray[i] = 0; + } + +#ifdef AH_EEPROM_DUMP + ar5416PrintPowerPerRate(ah, AH5416(ah)->ah_ratesArray); +#endif + + /* + * Adjust the HT40 power to meet the correct target TX power + * for 40MHz mode, based on TX power curves that are established + * for 20MHz mode. + * + * XXX handle overflow/too high power level? + */ + if (IEEE80211_IS_CHAN_HT40(chan)) { + AH5416(ah)->ah_ratesArray[rateHt40_0] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_1] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_2] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_3] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_4] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_5] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_6] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + AH5416(ah)->ah_ratesArray[rateHt40_7] += + AH5416(ah)->ah_ht40PowerIncForPdadc; + } + + /* Write the TX power rate registers */ + ar5416WriteTxPowerRateRegisters(ah, chan, AH5416(ah)->ah_ratesArray); + + return AH_TRUE; +#undef POW_SM +#undef N +} + +/* + * Read EEPROM header info and program the device for correct operation + * given the channel value. + */ +HAL_BOOL +ar9287SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + const HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + const struct ar9287_eeprom *eep = &ee->ee_base; + const struct modal_eep_ar9287_header *pModal = &eep->modalHeader; + uint16_t antWrites[AR9287_ANT_16S]; + uint32_t regChainOffset, regval; + uint8_t txRxAttenLocal; + int i, j, offset_num; + + pModal = &eep->modalHeader; + + antWrites[0] = (uint16_t)((pModal->antCtrlCommon >> 28) & 0xF); + antWrites[1] = (uint16_t)((pModal->antCtrlCommon >> 24) & 0xF); + antWrites[2] = (uint16_t)((pModal->antCtrlCommon >> 20) & 0xF); + antWrites[3] = (uint16_t)((pModal->antCtrlCommon >> 16) & 0xF); + antWrites[4] = (uint16_t)((pModal->antCtrlCommon >> 12) & 0xF); + antWrites[5] = (uint16_t)((pModal->antCtrlCommon >> 8) & 0xF); + antWrites[6] = (uint16_t)((pModal->antCtrlCommon >> 4) & 0xF); + antWrites[7] = (uint16_t)(pModal->antCtrlCommon & 0xF); + + offset_num = 8; + + for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) { + antWrites[j++] = (uint16_t)((pModal->antCtrlChain[i] >> 28) & 0xf); + antWrites[j++] = (uint16_t)((pModal->antCtrlChain[i] >> 10) & 0x3); + antWrites[j++] = (uint16_t)((pModal->antCtrlChain[i] >> 8) & 0x3); + antWrites[j++] = 0; + antWrites[j++] = (uint16_t)((pModal->antCtrlChain[i] >> 6) & 0x3); + antWrites[j++] = (uint16_t)((pModal->antCtrlChain[i] >> 4) & 0x3); + antWrites[j++] = (uint16_t)((pModal->antCtrlChain[i] >> 2) & 0x3); + antWrites[j++] = (uint16_t)(pModal->antCtrlChain[i] & 0x3); + } + + OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); + + for (i = 0; i < AR9287_MAX_CHAINS; i++) { + regChainOffset = i * 0x1000; + + OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, + pModal->antCtrlChain[i]); + + OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0) + regChainOffset, + (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0) + + regChainOffset) + & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | + SM(pModal->iqCalICh[i], + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | + SM(pModal->iqCalQCh[i], + AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); + + txRxAttenLocal = pModal->txRxAttenCh[i]; + + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, + pModal->bswMargin[i]); + OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_DB, + pModal->bswAtten[i]); + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_ATTEN, + txRxAttenLocal); + OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_MARGIN, + pModal->rxTxMarginCh[i]); + } + + if (IEEE80211_IS_CHAN_HT40(chan)) + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, + AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); + else + OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, + AR_PHY_SETTLING_SWITCH, pModal->switchSettling); + + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize); + + OS_REG_WRITE(ah, AR_PHY_RF_CTL4, + SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) + | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) + | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) + | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); + + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, + AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); + + OS_REG_RMW_FIELD(ah, AR_PHY_CCA, + AR9280_PHY_CCA_THRESH62, pModal->thresh62); + OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, + AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62); + + regval = OS_REG_READ(ah, AR9287_AN_RF2G3_CH0); + regval &= ~(AR9287_AN_RF2G3_DB1 | + AR9287_AN_RF2G3_DB2 | + AR9287_AN_RF2G3_OB_CCK | + AR9287_AN_RF2G3_OB_PSK | + AR9287_AN_RF2G3_OB_QAM | + AR9287_AN_RF2G3_OB_PAL_OFF); + regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) | + SM(pModal->db2, AR9287_AN_RF2G3_DB2) | + SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) | + SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) | + SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) | + SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF)); + + /* Analog write - requires a 100usec delay */ + OS_A_REG_WRITE(ah, AR9287_AN_RF2G3_CH0, regval); + + regval = OS_REG_READ(ah, AR9287_AN_RF2G3_CH1); + regval &= ~(AR9287_AN_RF2G3_DB1 | + AR9287_AN_RF2G3_DB2 | + AR9287_AN_RF2G3_OB_CCK | + AR9287_AN_RF2G3_OB_PSK | + AR9287_AN_RF2G3_OB_QAM | + AR9287_AN_RF2G3_OB_PAL_OFF); + regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) | + SM(pModal->db2, AR9287_AN_RF2G3_DB2) | + SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) | + SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) | + SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) | + SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF)); + + OS_A_REG_WRITE(ah, AR9287_AN_RF2G3_CH1, regval); + + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, + AR_PHY_TX_FRAME_TO_DATA_START, pModal->txFrameToDataStart); + OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, + AR_PHY_TX_FRAME_TO_PA_ON, pModal->txFrameToPaOn); + + OS_A_REG_RMW_FIELD(ah, AR9287_AN_TOP2, + AR9287_AN_TOP2_XPABIAS_LVL, pModal->xpaBiasLvl); + + return AH_TRUE; +} diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9287_reset.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_reset.h new file mode 100644 index 0000000..679fb8c --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9287_reset.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AR9287_RESET_H__ +#define __AR9287_RESET_H__ + +extern HAL_BOOL ar9287SetTransmitPower(struct ath_hal *ah, + const struct ieee80211_channel *chan, uint16_t *rfXpdGain); +extern HAL_BOOL ar9287SetBoardValues(struct ath_hal *ah, + const struct ieee80211_channel *chan); + +#endif /* __AR9287_RESET_H__ */ diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9287an.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9287an.h new file mode 100644 index 0000000..ba7a92c --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9287an.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AR9287AN_H__ +#define __AR9287AN_H__ + +#define AR9287_AN_RF2G3_CH0 0x7808 +#define AR9287_AN_RF2G3_CH1 0x785c +#define AR9287_AN_RF2G3_DB1 0xE0000000 +#define AR9287_AN_RF2G3_DB1_S 29 +#define AR9287_AN_RF2G3_DB2 0x1C000000 +#define AR9287_AN_RF2G3_DB2_S 26 +#define AR9287_AN_RF2G3_OB_CCK 0x03800000 +#define AR9287_AN_RF2G3_OB_CCK_S 23 +#define AR9287_AN_RF2G3_OB_PSK 0x00700000 +#define AR9287_AN_RF2G3_OB_PSK_S 20 +#define AR9287_AN_RF2G3_OB_QAM 0x000E0000 +#define AR9287_AN_RF2G3_OB_QAM_S 17 +#define AR9287_AN_RF2G3_OB_PAL_OFF 0x0001C000 +#define AR9287_AN_RF2G3_OB_PAL_OFF_S 14 + +#define AR9287_AN_TXPC0 0x7898 +#define AR9287_AN_TXPC0_TXPCMODE 0x0000C000 +#define AR9287_AN_TXPC0_TXPCMODE_S 14 +#define AR9287_AN_TXPC0_TXPCMODE_NORMAL 0 +#define AR9287_AN_TXPC0_TXPCMODE_TEST 1 +#define AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE 2 +#define AR9287_AN_TXPC0_TXPCMODE_ATBTEST 3 + +#define AR9287_AN_TOP2 0x78b4 +#define AR9287_AN_TOP2_XPABIAS_LVL 0xC0000000 +#define AR9287_AN_TOP2_XPABIAS_LVL_S 30 + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ar9002/ar9287phy.h b/sys/external/isc/atheros_hal/dist/ar9002/ar9287phy.h new file mode 100644 index 0000000..8f28194 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9002/ar9287phy.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AR9287PHY_H__ +#define __AR9287PHY_H__ + +/* AR_PHY_CH0_TX_PWRCTRL11, AR_PHY_CH1_TX_PWRCTRL11 */ +#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00 +#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 + +#endif diff --git a/sys/external/isc/atheros_hal/dist/ar9003/ar9300_btcoex.h b/sys/external/isc/atheros_hal/dist/ar9003/ar9300_btcoex.h new file mode 100644 index 0000000..583636e --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9003/ar9300_btcoex.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __ATH_AR9300_BTCOEX_H__ +#define __ATH_AR9300_BTCOEX_H__ +/* + * Weight table configurations. + */ +#define AR9300_BT_WGHT 0xcccc4444 +#define AR9300_STOMP_ALL_WLAN_WGHT0 0xfffffff0 +#define AR9300_STOMP_ALL_WLAN_WGHT1 0xfffffff0 +#define AR9300_STOMP_LOW_WLAN_WGHT0 0x88888880 +#define AR9300_STOMP_LOW_WLAN_WGHT1 0x88888880 +#define AR9300_STOMP_NONE_WLAN_WGHT0 0x00000000 +#define AR9300_STOMP_NONE_WLAN_WGHT1 0x00000000 +/* Stomp BT even when WLAN is idle */ +#define AR9300_STOMP_ALL_FORCE_WLAN_WGHT0 0xffffffff +#define AR9300_STOMP_ALL_FORCE_WLAN_WGHT1 0xffffffff +/* Stomp BT even when WLAN is idle */ +#define AR9300_STOMP_LOW_FORCE_WLAN_WGHT0 0x88888888 +#define AR9300_STOMP_LOW_FORCE_WLAN_WGHT1 0x88888888 + +#define JUPITER_STOMP_ALL_WLAN_WGHT0 0x00007d00 +#define JUPITER_STOMP_ALL_WLAN_WGHT1 0x7d7d7d00 +#define JUPITER_STOMP_ALL_WLAN_WGHT2 0x7d7d7d00 +#define JUPITER_STOMP_ALL_WLAN_WGHT3 0x7d7d7d7d +#define JUPITER_STOMP_LOW_WLAN_WGHT0 0x00007d00 +#define JUPITER_STOMP_LOW_WLAN_WGHT1 0x7d3b3b00 +#define JUPITER_STOMP_LOW_WLAN_WGHT2 0x3b3b3b00 +#define JUPITER_STOMP_LOW_WLAN_WGHT3 0x3b3b3b3b +#define JUPITER_STOMP_NONE_WLAN_WGHT0 0x00007d00 +#define JUPITER_STOMP_NONE_WLAN_WGHT1 0x7d000000 +#define JUPITER_STOMP_NONE_WLAN_WGHT2 0x00000000 +#define JUPITER_STOMP_NONE_WLAN_WGHT3 0x00000000 +#define JUPITER_STOMP_ALL_FORCE_WLAN_WGHT0 0x00007d7d +#define JUPITER_STOMP_ALL_FORCE_WLAN_WGHT1 0x7d7d7d00 +#define JUPITER_STOMP_ALL_FORCE_WLAN_WGHT2 0x7d7d7d7d +#define JUPITER_STOMP_ALL_FORCE_WLAN_WGHT3 0x7d7d7d7d +#define JUPITER_STOMP_LOW_FORCE_WLAN_WGHT0 0x00003b3b +#define JUPITER_STOMP_LOW_FORCE_WLAN_WGHT1 0x3b3b3b00 +#define JUPITER_STOMP_LOW_FORCE_WLAN_WGHT2 0x3b3b3b3b +#define JUPITER_STOMP_LOW_FORCE_WLAN_WGHT3 0x3b3b3b3b + +#endif /* __ATH_AR9300_BTCOEX_H__ */ diff --git a/sys/external/isc/atheros_hal/dist/ar9003/ar9300_devid.h b/sys/external/isc/atheros_hal/dist/ar9003/ar9300_devid.h new file mode 100644 index 0000000..00ceeb8 --- /dev/null +++ b/sys/external/isc/atheros_hal/dist/ar9003/ar9300_devid.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2012, Qualcomm Atheros, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the following conditions are met: + * 1. The materials contained herein are unmodified and are used + * unmodified. + * 2. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following NO + * ''WARRANTY'' disclaimer below (''Disclaimer''), without + * modification. + * 3. Redistributions in binary form must reproduce at minimum a + * disclaimer similar to the Disclaimer below and any redistribution + * must be conditioned upon including a substantially similar + * Disclaimer requirement for further binary redistribution. + * 4. Neither the names of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote + * product derived from this software without specific prior written + * permission. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + * FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + * + * $FreeBSD$ + * + */ +#ifndef __AR9300_DEVID_H__ +#define __AR9300_DEVID_H__ + +/* + * AR9380 HAL device IDs. + */ + +/* + * MAC Version and Revision + */ +#define AR_SREV_VERSION_AR9380 0x1C0 +#define AR_SREV_VERSION_AR9580 0x1C0 +#define AR_SREV_VERSION_AR9460 0x280 +#define AR_SREV_VERSION_QCA9565 0x2c0 + +#define AR_SREV_VERSION_AR9330 0x200 +#define AR_SREV_VERSION_AR9340 0x300 +#define AR_SREV_VERSION_QCA9550 0x400 +#define AR_SREV_VERSION_AR9485 0x240 +#define AR_SREV_VERSION_QCA9530 0x500 + +#define AR_SREV_REVISION_AR9380_10 0 /* AR9380 1.0 */ +#define AR_SREV_REVISION_AR9380_20 2 /* AR9380 2.0/2.1 */ +#define AR_SREV_REVISION_AR9380_22 3 /* AR9380 2.2 */ +#define AR_SREV_REVISION_AR9580_10 4 /* AR9580/Peacock 1.0 */ + +#define AR_SREV_REVISION_AR9330_10 0 /* AR9330 1.0 */ +#define AR_SREV_REVISION_AR9330_11 1 /* AR9330 1.1 */ +#define AR_SREV_REVISION_AR9330_12 2 /* AR9330 1.2 */ +#define AR_SREV_REVISION_AR9330_11_MASK 0xf /* AR9330 1.1 revision mask */ + +#define AR_SREV_REVISION_AR9485_10 0 /* AR9485 1.0 */ +#define AR_SREV_REVISION_AR9485_11 1 /* AR9485 1.1 */ + +#define AR_SREV_REVISION_AR9340_10 0 /* AR9340 1.0 */ +#define AR_SREV_REVISION_AR9340_11 1 /* AR9340 1.1 */ +#define AR_SREV_REVISION_AR9340_12 2 /* AR9340 1.2 */ +#define AR_SREV_REVISION_AR9340_MASK 0xf /* AR9340 revision mask */ + +#define AR_SREV_REVISION_AR9460_10 0 /* AR946x 1.0 */ + +#endif /* __AR9300_DEVID_H__ */ -- 2.9.3