diff options
Diffstat (limited to 'drivers/net/wireless')
327 files changed, 56118 insertions, 14095 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 4de4410cd38e..b4338f389394 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -279,6 +279,7 @@ source "drivers/net/wireless/libertas/Kconfig" source "drivers/net/wireless/orinoco/Kconfig" source "drivers/net/wireless/p54/Kconfig" source "drivers/net/wireless/rt2x00/Kconfig" +source "drivers/net/wireless/rtlwifi/Kconfig" source "drivers/net/wireless/wl1251/Kconfig" source "drivers/net/wireless/wl12xx/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 06f8ca26c5c1..9760561a27a5 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_B43LEGACY) += b43legacy/ obj-$(CONFIG_ZD1211RW) += zd1211rw/ obj-$(CONFIG_RTL8180) += rtl818x/ obj-$(CONFIG_RTL8187) += rtl818x/ +obj-$(CONFIG_RTL8192CE) += rtlwifi/ # 16-bit wireless PCMCIA client drivers obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index a36e7870b03e..57a79b0475f6 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -4652,24 +4652,18 @@ static ssize_t proc_write( struct file *file, size_t len, loff_t *offset ) { - loff_t pos = *offset; + ssize_t ret; struct proc_data *priv = file->private_data; if (!priv->wbuffer) return -EINVAL; - if (pos < 0) - return -EINVAL; - if (pos >= priv->maxwritelen) - return 0; - if (len > priv->maxwritelen - pos) - len = priv->maxwritelen - pos; - if (copy_from_user(priv->wbuffer + pos, buffer, len)) - return -EFAULT; - if ( pos + len > priv->writelen ) - priv->writelen = len + file->f_pos; - *offset = pos + len; - return len; + ret = simple_write_to_buffer(priv->wbuffer, priv->maxwritelen, offset, + buffer, len); + if (ret > 0) + priv->writelen = max_t(int, priv->writelen, *offset); + + return ret; } static int proc_status_open(struct inode *inode, struct file *file) diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c index 4604de09a8b2..6452c5055a63 100644 --- a/drivers/net/wireless/ath/ar9170/cmd.c +++ b/drivers/net/wireless/ath/ar9170/cmd.c @@ -54,7 +54,7 @@ int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len) int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) { - __le32 buf[2] = { + const __le32 buf[2] = { cpu_to_le32(reg), cpu_to_le32(val), }; diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 5dbb5361fd51..d3be6f9816b5 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -161,8 +161,7 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru) static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) { struct sk_buff *skb = urb->context; - struct ar9170_usb *aru = (struct ar9170_usb *) - usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); if (unlikely(!aru)) { dev_kfree_skb_irq(skb); @@ -219,8 +218,7 @@ free: static void ar9170_usb_rx_completed(struct urb *urb) { struct sk_buff *skb = urb->context; - struct ar9170_usb *aru = (struct ar9170_usb *) - usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); int err; if (!aru) diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 501050c0296f..e43210c8585c 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -126,6 +126,7 @@ struct ath_bus_ops { void (*read_cachesize)(struct ath_common *common, int *csz); bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); void (*bt_coex_prep)(struct ath_common *common); + void (*extn_synch_en)(struct ath_common *common); }; struct ath_common { @@ -162,6 +163,8 @@ struct ath_common { struct ath_regulatory regulatory; const struct ath_ops *ops; const struct ath_bus_ops *bus_ops; + + bool btcoex_enabled; }; struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, @@ -178,4 +181,112 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry); void ath_hw_cycle_counters_update(struct ath_common *common); int32_t ath_hw_get_listen_time(struct ath_common *common); +extern __attribute__ ((format (printf, 3, 4))) int +ath_printk(const char *level, struct ath_common *common, const char *fmt, ...); + +#define ath_emerg(common, fmt, ...) \ + ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__) +#define ath_alert(common, fmt, ...) \ + ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__) +#define ath_crit(common, fmt, ...) \ + ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__) +#define ath_err(common, fmt, ...) \ + ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__) +#define ath_warn(common, fmt, ...) \ + ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__) +#define ath_notice(common, fmt, ...) \ + ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__) +#define ath_info(common, fmt, ...) \ + ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__) + +/** + * enum ath_debug_level - atheros wireless debug level + * + * @ATH_DBG_RESET: reset processing + * @ATH_DBG_QUEUE: hardware queue management + * @ATH_DBG_EEPROM: eeprom processing + * @ATH_DBG_CALIBRATE: periodic calibration + * @ATH_DBG_INTERRUPT: interrupt processing + * @ATH_DBG_REGULATORY: regulatory processing + * @ATH_DBG_ANI: adaptive noise immunitive processing + * @ATH_DBG_XMIT: basic xmit operation + * @ATH_DBG_BEACON: beacon handling + * @ATH_DBG_CONFIG: configuration of the hardware + * @ATH_DBG_FATAL: fatal errors, this is the default, DBG_DEFAULT + * @ATH_DBG_PS: power save processing + * @ATH_DBG_HWTIMER: hardware timer handling + * @ATH_DBG_BTCOEX: bluetooth coexistance + * @ATH_DBG_BSTUCK: stuck beacons + * @ATH_DBG_ANY: enable all debugging + * + * The debug level is used to control the amount and type of debugging output + * we want to see. Each driver has its own method for enabling debugging and + * modifying debug level states -- but this is typically done through a + * module parameter 'debug' along with a respective 'debug' debugfs file + * entry. + */ +enum ATH_DEBUG { + ATH_DBG_RESET = 0x00000001, + ATH_DBG_QUEUE = 0x00000002, + ATH_DBG_EEPROM = 0x00000004, + ATH_DBG_CALIBRATE = 0x00000008, + ATH_DBG_INTERRUPT = 0x00000010, + ATH_DBG_REGULATORY = 0x00000020, + ATH_DBG_ANI = 0x00000040, + ATH_DBG_XMIT = 0x00000080, + ATH_DBG_BEACON = 0x00000100, + ATH_DBG_CONFIG = 0x00000200, + ATH_DBG_FATAL = 0x00000400, + ATH_DBG_PS = 0x00000800, + ATH_DBG_HWTIMER = 0x00001000, + ATH_DBG_BTCOEX = 0x00002000, + ATH_DBG_WMI = 0x00004000, + ATH_DBG_BSTUCK = 0x00008000, + ATH_DBG_ANY = 0xffffffff +}; + +#define ATH_DBG_DEFAULT (ATH_DBG_FATAL) + +#ifdef CONFIG_ATH_DEBUG + +#define ath_dbg(common, dbg_mask, fmt, ...) \ +({ \ + int rtn; \ + if ((common)->debug_mask & dbg_mask) \ + rtn = ath_printk(KERN_DEBUG, common, fmt, \ + ##__VA_ARGS__); \ + else \ + rtn = 0; \ + \ + rtn; \ +}) +#define ATH_DBG_WARN(foo, arg...) WARN(foo, arg) +#define ATH_DBG_WARN_ON_ONCE(foo) WARN_ON_ONCE(foo) + +#else + +static inline __attribute__ ((format (printf, 3, 4))) int +ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask, + const char *fmt, ...) +{ + return 0; +} +#define ATH_DBG_WARN(foo, arg...) do {} while (0) +#define ATH_DBG_WARN_ON_ONCE(foo) ({ \ + int __ret_warn_once = !!(foo); \ + unlikely(__ret_warn_once); \ +}) + +#endif /* CONFIG_ATH_DEBUG */ + +/** Returns string describing opmode, or NULL if unknown mode. */ +#ifdef CONFIG_ATH_DEBUG +const char *ath_opmode_to_string(enum nl80211_iftype opmode); +#else +static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode) +{ + return "UNKNOWN"; +} +#endif + #endif /* ATH_H */ diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig index eb83b7b4d0e3..e0793319389d 100644 --- a/drivers/net/wireless/ath/ath5k/Kconfig +++ b/drivers/net/wireless/ath/ath5k/Kconfig @@ -1,9 +1,12 @@ config ATH5K tristate "Atheros 5xxx wireless cards support" - depends on PCI && MAC80211 + depends on (PCI || ATHEROS_AR231X) && MAC80211 select MAC80211_LEDS select LEDS_CLASS select NEW_LEDS + select AVERAGE + select ATH5K_AHB if (ATHEROS_AR231X && !PCI) + select ATH5K_PCI if (!ATHEROS_AR231X && PCI) ---help--- This module adds support for wireless adapters based on Atheros 5xxx chipset. @@ -37,3 +40,16 @@ config ATH5K_DEBUG modprobe ath5k debug=0x00000400 +config ATH5K_AHB + bool "Atheros 5xxx AHB bus support" + depends on (ATHEROS_AR231X && !PCI) + ---help--- + This adds support for WiSoC type chipsets of the 5xxx Atheros + family. + +config ATH5K_PCI + bool "Atheros 5xxx PCI bus support" + depends on (!ATHEROS_AR231X && PCI) + ---help--- + This adds support for PCI type chipsets of the 5xxx Atheros + family. diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile index 2242a140e4fe..f60b3899afc4 100644 --- a/drivers/net/wireless/ath/ath5k/Makefile +++ b/drivers/net/wireless/ath/ath5k/Makefile @@ -14,5 +14,8 @@ ath5k-y += led.o ath5k-y += rfkill.o ath5k-y += ani.o ath5k-y += sysfs.o +ath5k-y += mac80211-ops.o ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o +ath5k-$(CONFIG_ATH5K_AHB) += ahb.o +ath5k-$(CONFIG_ATH5K_PCI) += pci.o obj-$(CONFIG_ATH5K) += ath5k.o diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c new file mode 100644 index 000000000000..707cde149248 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/ahb.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org> + * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org> + * + * 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. + */ + +#include <linux/nl80211.h> +#include <linux/platform_device.h> +#include <ar231x_platform.h> +#include "ath5k.h" +#include "debug.h" +#include "base.h" +#include "reg.h" +#include "debug.h" + +/* return bus cachesize in 4B word units */ +static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz) +{ + *csz = L1_CACHE_BYTES >> 2; +} + +bool ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) +{ + struct ath5k_softc *sc = common->priv; + struct platform_device *pdev = to_platform_device(sc->dev); + struct ar231x_board_config *bcfg = pdev->dev.platform_data; + u16 *eeprom, *eeprom_end; + + + + bcfg = pdev->dev.platform_data; + eeprom = (u16 *) bcfg->radio; + eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ; + + eeprom += off; + if (eeprom > eeprom_end) + return -EINVAL; + + *data = *eeprom; + return 0; +} + +int ath5k_hw_read_srev(struct ath5k_hw *ah) +{ + struct ath5k_softc *sc = ah->ah_sc; + struct platform_device *pdev = to_platform_device(sc->dev); + struct ar231x_board_config *bcfg = pdev->dev.platform_data; + ah->ah_mac_srev = bcfg->devid; + return 0; +} + +static const struct ath_bus_ops ath_ahb_bus_ops = { + .ath_bus_type = ATH_AHB, + .read_cachesize = ath5k_ahb_read_cachesize, + .eeprom_read = ath5k_ahb_eeprom_read, +}; + +/*Initialization*/ +static int ath_ahb_probe(struct platform_device *pdev) +{ + struct ar231x_board_config *bcfg = pdev->dev.platform_data; + struct ath5k_softc *sc; + struct ieee80211_hw *hw; + struct resource *res; + void __iomem *mem; + int irq; + int ret = 0; + u32 reg; + + if (!pdev->dev.platform_data) { + dev_err(&pdev->dev, "no platform data specified\n"); + ret = -EINVAL; + goto err_out; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no memory resource found\n"); + ret = -ENXIO; + goto err_out; + } + + mem = ioremap_nocache(res->start, res->end - res->start + 1); + if (mem == NULL) { + dev_err(&pdev->dev, "ioremap failed\n"); + ret = -ENOMEM; + goto err_out; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no IRQ resource found\n"); + ret = -ENXIO; + goto err_out; + } + + irq = res->start; + + hw = ieee80211_alloc_hw(sizeof(struct ath5k_softc), &ath5k_hw_ops); + if (hw == NULL) { + dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); + ret = -ENOMEM; + goto err_out; + } + + sc = hw->priv; + sc->hw = hw; + sc->dev = &pdev->dev; + sc->iobase = mem; + sc->irq = irq; + sc->devid = bcfg->devid; + + if (bcfg->devid >= AR5K_SREV_AR2315_R6) { + /* Enable WMAC AHB arbitration */ + reg = __raw_readl((void __iomem *) AR5K_AR2315_AHB_ARB_CTL); + reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN; + __raw_writel(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL); + + /* Enable global WMAC swapping */ + reg = __raw_readl((void __iomem *) AR5K_AR2315_BYTESWAP); + reg |= AR5K_AR2315_BYTESWAP_WMAC; + __raw_writel(reg, (void __iomem *) AR5K_AR2315_BYTESWAP); + } else { + /* Enable WMAC DMA access (assuming 5312 or 231x*/ + /* TODO: check other platforms */ + reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE); + if (to_platform_device(sc->dev)->id == 0) + reg |= AR5K_AR5312_ENABLE_WLAN0; + else + reg |= AR5K_AR5312_ENABLE_WLAN1; + __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); + } + + ret = ath5k_init_softc(sc, &ath_ahb_bus_ops); + if (ret != 0) { + dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret); + ret = -ENODEV; + goto err_free_hw; + } + + platform_set_drvdata(pdev, hw); + + return 0; + + err_free_hw: + ieee80211_free_hw(hw); + platform_set_drvdata(pdev, NULL); + err_out: + return ret; +} + +static int ath_ahb_remove(struct platform_device *pdev) +{ + struct ar231x_board_config *bcfg = pdev->dev.platform_data; + struct ieee80211_hw *hw = platform_get_drvdata(pdev); + struct ath5k_softc *sc; + u32 reg; + + if (!hw) + return 0; + + sc = hw->priv; + + if (bcfg->devid >= AR5K_SREV_AR2315_R6) { + /* Disable WMAC AHB arbitration */ + reg = __raw_readl((void __iomem *) AR5K_AR2315_AHB_ARB_CTL); + reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN; + __raw_writel(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL); + } else { + /*Stop DMA access */ + reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE); + if (to_platform_device(sc->dev)->id == 0) + reg &= ~AR5K_AR5312_ENABLE_WLAN0; + else + reg &= ~AR5K_AR5312_ENABLE_WLAN1; + __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); + } + + ath5k_deinit_softc(sc); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver ath_ahb_driver = { + .probe = ath_ahb_probe, + .remove = ath_ahb_remove, + .driver = { + .name = "ar231x-wmac", + .owner = THIS_MODULE, + }, +}; + +static int __init +ath5k_ahb_init(void) +{ + return platform_driver_register(&ath_ahb_driver); +} + +static void __exit +ath5k_ahb_exit(void) +{ + platform_driver_unregister(&ath_ahb_driver); +} + +module_init(ath5k_ahb_init); +module_exit(ath5k_ahb_exit); diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index f1419198a479..f915f404302d 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c @@ -58,20 +58,20 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) { /* TODO: * ANI documents suggest the following five levels to use, but the HAL - * and ath9k use only use the last two levels, making this + * and ath9k use only the last two levels, making this * essentially an on/off option. There *may* be a reason for this (???), * so i stick with the HAL version for now... */ #if 0 - const s8 hi[] = { -18, -18, -16, -14, -12 }; - const s8 lo[] = { -52, -56, -60, -64, -70 }; - const s8 sz[] = { -34, -41, -48, -55, -62 }; - const s8 fr[] = { -70, -72, -75, -78, -80 }; + static const s8 lo[] = { -52, -56, -60, -64, -70 }; + static const s8 hi[] = { -18, -18, -16, -14, -12 }; + static const s8 sz[] = { -34, -41, -48, -55, -62 }; + static const s8 fr[] = { -70, -72, -75, -78, -80 }; #else - const s8 sz[] = { -55, -62 }; - const s8 lo[] = { -64, -70 }; - const s8 hi[] = { -14, -12 }; - const s8 fr[] = { -78, -80 }; + static const s8 lo[] = { -64, -70 }; + static const s8 hi[] = { -14, -12 }; + static const s8 sz[] = { -55, -62 }; + static const s8 fr[] = { -78, -80 }; #endif if (level < 0 || level >= ARRAY_SIZE(sz)) { ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range", @@ -102,7 +102,7 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) void ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) { - const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; + static const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; if (level < 0 || level >= ARRAY_SIZE(val) || level > ah->ah_sc->ani_state.max_spur_level) { @@ -127,7 +127,7 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) void ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) { - const int val[] = { 0, 4, 8 }; + static const int val[] = { 0, 4, 8 }; if (level < 0 || level >= ARRAY_SIZE(val)) { ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level); @@ -151,12 +151,12 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) void ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) { - const int m1l[] = { 127, 50 }; - const int m2l[] = { 127, 40 }; - const int m1[] = { 127, 0x4d }; - const int m2[] = { 127, 0x40 }; - const int m2cnt[] = { 31, 16 }; - const int m2lcnt[] = { 63, 48 }; + static const int m1l[] = { 127, 50 }; + static const int m2l[] = { 127, 40 }; + static const int m1[] = { 127, 0x4d }; + static const int m2[] = { 127, 0x40 }; + static const int m2cnt[] = { 31, 16 }; + static const int m2lcnt[] = { 63, 48 }; AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, AR5K_PHY_WEAK_OFDM_LOW_THR_M1, m1l[on]); @@ -192,7 +192,7 @@ ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) void ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on) { - const int val[] = { 8, 6 }; + static const int val[] = { 8, 6 }; AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR, AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]); ah->ah_sc->ani_state.cck_weak_sig = on; @@ -216,7 +216,7 @@ static void ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, bool ofdm_trigger) { - int rssi = ah->ah_beacon_rssi_avg.avg; + int rssi = ewma_read(&ah->ah_beacon_rssi_avg); ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)", ofdm_trigger ? "ODFM" : "CCK"); @@ -301,7 +301,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, static void ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as) { - int rssi = ah->ah_beacon_rssi_avg.avg; + int rssi = ewma_read(&ah->ah_beacon_rssi_avg); ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity"); diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 308b79e1ff08..407e39c2b10b 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -25,6 +25,7 @@ #include <linux/io.h> #include <linux/types.h> +#include <linux/average.h> #include <net/mac80211.h> /* RX/TX descriptor hw structs @@ -153,19 +154,6 @@ udelay(1); \ } while (0) -/* Register dumps are done per operation mode */ -#define AR5K_INI_RFGAIN_5GHZ 0 -#define AR5K_INI_RFGAIN_2GHZ 1 - -/* TODO: Clean this up */ -#define AR5K_INI_VAL_11A 0 -#define AR5K_INI_VAL_11A_TURBO 1 -#define AR5K_INI_VAL_11B 2 -#define AR5K_INI_VAL_11G 3 -#define AR5K_INI_VAL_11G_TURBO 4 -#define AR5K_INI_VAL_XR 0 -#define AR5K_INI_VAL_MAX 5 - /* * Some tuneable values (these should be changeable by the user) * TODO: Make use of them and add more options OR use debug/configfs @@ -221,42 +209,66 @@ /* Initial values */ #define AR5K_INIT_CYCRSSI_THR1 2 -#define AR5K_INIT_TX_LATENCY 502 -#define AR5K_INIT_USEC 39 -#define AR5K_INIT_USEC_TURBO 79 -#define AR5K_INIT_USEC_32 31 -#define AR5K_INIT_SLOT_TIME 396 -#define AR5K_INIT_SLOT_TIME_TURBO 480 -#define AR5K_INIT_ACK_CTS_TIMEOUT 1024 -#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800 -#define AR5K_INIT_PROG_IFS 920 -#define AR5K_INIT_PROG_IFS_TURBO 960 -#define AR5K_INIT_EIFS 3440 -#define AR5K_INIT_EIFS_TURBO 6880 -#define AR5K_INIT_SIFS 560 -#define AR5K_INIT_SIFS_TURBO 480 + +/* Tx retry limits */ #define AR5K_INIT_SH_RETRY 10 #define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY +/* For station mode */ #define AR5K_INIT_SSH_RETRY 32 #define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY #define AR5K_INIT_TX_RETRY 10 -#define AR5K_INIT_TRANSMIT_LATENCY ( \ - (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ - (AR5K_INIT_USEC) \ -) -#define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \ - (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ - (AR5K_INIT_USEC_TURBO) \ -) -#define AR5K_INIT_PROTO_TIME_CNTRL ( \ - (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \ - (AR5K_INIT_PROG_IFS) \ -) -#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \ - (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \ - (AR5K_INIT_PROG_IFS_TURBO) \ -) + +/* Slot time */ +#define AR5K_INIT_SLOT_TIME_TURBO 6 +#define AR5K_INIT_SLOT_TIME_DEFAULT 9 +#define AR5K_INIT_SLOT_TIME_HALF_RATE 13 +#define AR5K_INIT_SLOT_TIME_QUARTER_RATE 21 +#define AR5K_INIT_SLOT_TIME_B 20 +#define AR5K_SLOT_TIME_MAX 0xffff + +/* SIFS */ +#define AR5K_INIT_SIFS_TURBO 6 +/* XXX: 8 from initvals 10 from standard */ +#define AR5K_INIT_SIFS_DEFAULT_BG 8 +#define AR5K_INIT_SIFS_DEFAULT_A 16 +#define AR5K_INIT_SIFS_HALF_RATE 32 +#define AR5K_INIT_SIFS_QUARTER_RATE 64 + +/* Used to calculate tx time for non 5/10/40MHz + * operation */ +/* It's preamble time + signal time (16 + 4) */ +#define AR5K_INIT_OFDM_PREAMPLE_TIME 20 +/* Preamble time for 40MHz (turbo) operation (min ?) */ +#define AR5K_INIT_OFDM_PREAMBLE_TIME_MIN 14 +#define AR5K_INIT_OFDM_SYMBOL_TIME 4 +#define AR5K_INIT_OFDM_PLCP_BITS 22 + +/* Rx latency for 5 and 10MHz operation (max ?) */ +#define AR5K_INIT_RX_LAT_MAX 63 +/* Tx latencies from initvals (5212 only but no problem + * because we only tweak them on 5212) */ +#define AR5K_INIT_TX_LAT_A 54 +#define AR5K_INIT_TX_LAT_BG 384 +/* Tx latency for 40MHz (turbo) operation (min ?) */ +#define AR5K_INIT_TX_LAT_MIN 32 +/* Default Tx/Rx latencies (same for 5211)*/ +#define AR5K_INIT_TX_LATENCY_5210 54 +#define AR5K_INIT_RX_LATENCY_5210 29 + +/* Tx frame to Tx data start delay */ +#define AR5K_INIT_TXF2TXD_START_DEFAULT 14 +#define AR5K_INIT_TXF2TXD_START_DELAY_10MHZ 12 +#define AR5K_INIT_TXF2TXD_START_DELAY_5MHZ 13 + +/* We need to increase PHY switch and agc settling time + * on turbo mode */ +#define AR5K_SWITCH_SETTLING 5760 +#define AR5K_SWITCH_SETTLING_TURBO 7168 + +#define AR5K_AGC_SETTLING 28 +/* 38 on 5210 but shouldn't matter */ +#define AR5K_AGC_SETTLING_TURBO 37 /* GENERIC CHIPSET DEFINITIONS */ @@ -303,12 +315,19 @@ struct ath5k_srev_name { #define AR5K_SREV_AR5311B 0x30 /* Spirit */ #define AR5K_SREV_AR5211 0x40 /* Oahu */ #define AR5K_SREV_AR5212 0x50 /* Venice */ +#define AR5K_SREV_AR5312_R2 0x52 /* AP31 */ #define AR5K_SREV_AR5212_V4 0x54 /* ??? */ #define AR5K_SREV_AR5213 0x55 /* ??? */ +#define AR5K_SREV_AR5312_R7 0x57 /* AP30 */ +#define AR5K_SREV_AR2313_R8 0x58 /* AP43 */ #define AR5K_SREV_AR5213A 0x59 /* Hainan */ #define AR5K_SREV_AR2413 0x78 /* Griffin lite */ #define AR5K_SREV_AR2414 0x70 /* Griffin */ +#define AR5K_SREV_AR2315_R6 0x86 /* AP51-Light */ +#define AR5K_SREV_AR2315_R7 0x87 /* AP51-Full */ #define AR5K_SREV_AR5424 0x90 /* Condor */ +#define AR5K_SREV_AR2317_R1 0x90 /* AP61-Light */ +#define AR5K_SREV_AR2317_R2 0x91 /* AP61-Full */ #define AR5K_SREV_AR5413 0xa4 /* Eagle lite */ #define AR5K_SREV_AR5414 0xa0 /* Eagle */ #define AR5K_SREV_AR2415 0xb0 /* Talon */ @@ -404,12 +423,10 @@ struct ath5k_srev_name { enum ath5k_driver_mode { AR5K_MODE_11A = 0, - AR5K_MODE_11A_TURBO = 1, - AR5K_MODE_11B = 2, - AR5K_MODE_11G = 3, - AR5K_MODE_11G_TURBO = 4, + AR5K_MODE_11B = 1, + AR5K_MODE_11G = 2, AR5K_MODE_XR = 0, - AR5K_MODE_MAX = 5 + AR5K_MODE_MAX = 3 }; enum ath5k_ant_mode { @@ -423,6 +440,12 @@ enum ath5k_ant_mode { AR5K_ANTMODE_MAX, }; +enum ath5k_bw_mode { + AR5K_BWMODE_DEFAULT = 0, /* 20MHz, default operation */ + AR5K_BWMODE_5MHZ = 1, /* Quarter rate */ + AR5K_BWMODE_10MHZ = 2, /* Half rate */ + AR5K_BWMODE_40MHZ = 3 /* Turbo */ +}; /****************\ TX DEFINITIONS @@ -655,7 +678,6 @@ struct ath5k_gain { /* channel_flags */ #define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */ -#define CHANNEL_TURBO 0x0010 /* Turbo Channel */ #define CHANNEL_CCK 0x0020 /* CCK channel */ #define CHANNEL_OFDM 0x0040 /* OFDM channel */ #define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */ @@ -667,16 +689,10 @@ struct ath5k_gain { #define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) #define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) #define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) -#define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO) -#define CHANNEL_TG (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO) -#define CHANNEL_108A CHANNEL_T -#define CHANNEL_108G CHANNEL_TG #define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR) -#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \ - CHANNEL_TURBO) +#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ) -#define CHANNEL_ALL_NOTURBO (CHANNEL_ALL & ~CHANNEL_TURBO) #define CHANNEL_MODES CHANNEL_ALL /* @@ -1025,7 +1041,6 @@ struct ath5k_hw { enum ath5k_int ah_imr; struct ieee80211_channel *ah_current_channel; - bool ah_turbo; bool ah_calibration; bool ah_single_chip; @@ -1034,6 +1049,7 @@ struct ath5k_hw { u32 ah_phy; u32 ah_mac_srev; u16 ah_mac_version; + u16 ah_mac_revision; u16 ah_phy_revision; u16 ah_radio_5ghz_revision; u16 ah_radio_2ghz_revision; @@ -1043,6 +1059,8 @@ struct ath5k_hw { u32 ah_limit_tx_retries; u8 ah_coverage_class; + bool ah_ack_bitrate_high; + u8 ah_bwmode; /* Antenna Control */ u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; @@ -1085,12 +1103,14 @@ struct ath5k_hw { /* Values in 0.25dB units */ s16 txp_min_pwr; s16 txp_max_pwr; + s16 txp_cur_pwr; /* Values in 0.5dB units */ s16 txp_offset; s16 txp_ofdm; s16 txp_cck_ofdm_gainf_delta; /* Value in dB units */ s16 txp_cck_ofdm_pwr_delta; + bool txp_setup; } ah_txpower; struct { @@ -1102,7 +1122,7 @@ struct ath5k_hw { struct ath5k_nfcal_hist ah_nfcal_hist; /* average beacon RSSI in our BSS (used by ANI) */ - struct ath5k_avg_val ah_beacon_rssi_avg; + struct ewma ah_beacon_rssi_avg; /* noise floor from last periodic calibration */ s32 ah_noise_floor; @@ -1131,36 +1151,50 @@ struct ath5k_hw { /* * Prototypes */ +extern const struct ieee80211_ops ath5k_hw_ops; -/* Attach/Detach Functions */ -int ath5k_hw_attach(struct ath5k_softc *sc); -void ath5k_hw_detach(struct ath5k_hw *ah); +/* Initialization and detach functions */ +int ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops); +void ath5k_deinit_softc(struct ath5k_softc *sc); +int ath5k_hw_init(struct ath5k_softc *sc); +void ath5k_hw_deinit(struct ath5k_hw *ah); int ath5k_sysfs_register(struct ath5k_softc *sc); void ath5k_sysfs_unregister(struct ath5k_softc *sc); +/*Chip id helper functions */ +const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val); +int ath5k_hw_read_srev(struct ath5k_hw *ah); + /* LED functions */ int ath5k_init_leds(struct ath5k_softc *sc); void ath5k_led_enable(struct ath5k_softc *sc); void ath5k_led_off(struct ath5k_softc *sc); void ath5k_unregister_leds(struct ath5k_softc *sc); + /* Reset Functions */ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); int ath5k_hw_on_hold(struct ath5k_hw *ah); int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, - struct ieee80211_channel *channel, bool change_channel); + struct ieee80211_channel *channel, bool fast, bool skip_pcu); int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, bool is_set); /* Power management functions */ + +/* Clock rate related functions */ +unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); +unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); +void ath5k_hw_set_clockrate(struct ath5k_hw *ah); + + /* DMA Related Functions */ void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); -int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); -void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); +int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); -int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); +int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue); u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr); @@ -1170,38 +1204,43 @@ bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask); void ath5k_hw_update_mib_counters(struct ath5k_hw *ah); +/* Init/Stop functions */ +void ath5k_hw_dma_init(struct ath5k_hw *ah); +int ath5k_hw_dma_stop(struct ath5k_hw *ah); /* EEPROM access functions */ int ath5k_eeprom_init(struct ath5k_hw *ah); void ath5k_eeprom_detach(struct ath5k_hw *ah); int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); + /* Protocol Control Unit Functions */ +/* Helpers */ +int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, + int len, struct ieee80211_rate *rate); +unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah); +unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah); extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); -/* BSSID Functions */ +/* RX filter control*/ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); void ath5k_hw_set_bssid(struct ath5k_hw *ah); void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); -/* Receive start/stop functions */ -void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); -void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); -/* RX Filter functions */ void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); +/* Receive (DRU) start/stop functions */ +void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); +void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); /* Beacon control functions */ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); void ath5k_hw_reset_tsf(struct ath5k_hw *ah); void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval); -/* ACK bit rate */ -void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); -/* Clock rate related functions */ -unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); -unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); -void ath5k_hw_set_clockrate(struct ath5k_hw *ah); +/* Init function */ +void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, + u8 mode); /* Queue Control Unit, DFS Control Unit Functions */ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, @@ -1214,7 +1253,9 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); -int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); +int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time); +/* Init function */ +int ath5k_hw_init_queues(struct ath5k_hw *ah); /* Hardware Descriptor Functions */ int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); @@ -1224,6 +1265,7 @@ int ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3); + /* GPIO Functions */ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); @@ -1233,11 +1275,13 @@ int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level); -/* rfkill Functions */ + +/* RFkill Functions */ void ath5k_rfkill_hw_start(struct ath5k_hw *ah); void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); -/* Misc functions */ + +/* Misc functions TODO: Cleanup */ int ath5k_hw_set_capabilities(struct ath5k_hw *ah); int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, @@ -1245,19 +1289,20 @@ int ath5k_hw_get_capability(struct ath5k_hw *ah, int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); + /* Initial register settings functions */ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); -/* Initialize RF */ -int ath5k_hw_rfregs_init(struct ath5k_hw *ah, - struct ieee80211_channel *channel, - unsigned int mode); -int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq); + +/* PHY functions */ +/* Misc PHY functions */ +u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); +int ath5k_hw_phy_disable(struct ath5k_hw *ah); +/* Gain_F optimization */ enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); /* PHY/RF channel functions */ bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); -int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); /* PHY calibration */ void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, @@ -1266,18 +1311,14 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah); /* Spur mitigation */ bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, struct ieee80211_channel *channel); -void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, - struct ieee80211_channel *channel); -/* Misc PHY functions */ -u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); -int ath5k_hw_phy_disable(struct ath5k_hw *ah); /* Antenna control */ void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode); /* TX power setup */ -int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, - u8 ee_mode, u8 txpower); int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); +/* Init function */ +int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, + u8 mode, bool fast); /* * Functions used internaly @@ -1293,6 +1334,32 @@ static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah) return &(ath5k_hw_common(ah)->regulatory); } +#ifdef CONFIG_ATHEROS_AR231X +#define AR5K_AR2315_PCI_BASE ((void __iomem *)0xb0100000) + +static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg) +{ + /* On AR2315 and AR2317 the PCI clock domain registers + * are outside of the WMAC register space */ + if (unlikely((reg >= 0x4000) && (reg < 0x5000) && + (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6))) + return AR5K_AR2315_PCI_BASE + reg; + + return ah->ah_iobase + reg; +} + +static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) +{ + return __raw_readl(ath5k_ahb_reg(ah, reg)); +} + +static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) +{ + __raw_writel(val, ath5k_ahb_reg(ah, reg)); +} + +#else + static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) { return ioread32(ah->ah_iobase + reg); @@ -1303,6 +1370,24 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) iowrite32(val, ah->ah_iobase + reg); } +#endif + +static inline enum ath_bus_type ath5k_get_bus_type(struct ath5k_hw *ah) +{ + return ath5k_hw_common(ah)->bus_ops->ath_bus_type; +} + +static inline void ath5k_read_cachesize(struct ath_common *common, int *csz) +{ + common->bus_ops->read_cachesize(common, csz); +} + +static inline bool ath5k_hw_nvram_read(struct ath5k_hw *ah, u32 off, u16 *data) +{ + struct ath_common *common = ath5k_hw_common(ah); + return common->bus_ops->eeprom_read(common, off, data); +} + static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) { u32 retval = 0, bit, i; @@ -1315,27 +1400,4 @@ static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) return retval; } -#define AVG_SAMPLES 8 -#define AVG_FACTOR 1000 - -/** - * ath5k_moving_average - Exponentially weighted moving average - * @avg: average structure - * @val: current value - * - * This implementation make use of a struct ath5k_avg_val to prevent rounding - * errors. - */ -static inline struct ath5k_avg_val -ath5k_moving_average(const struct ath5k_avg_val avg, const int val) -{ - struct ath5k_avg_val new; - new.avg_weight = avg.avg_weight ? - (((avg.avg_weight * ((AVG_SAMPLES) - 1)) + - (val * (AVG_FACTOR))) / (AVG_SAMPLES)) : - (val * (AVG_FACTOR)); - new.avg = new.avg_weight / (AVG_FACTOR); - return new; -} - #endif diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index fbe8aca975d8..cdac5cff0177 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -93,16 +93,16 @@ static int ath5k_hw_post(struct ath5k_hw *ah) } /** - * ath5k_hw_attach - Check if hw is supported and init the needed structs + * ath5k_hw_init - Check if hw is supported and init the needed structs * - * @sc: The &struct ath5k_softc we got from the driver's attach function + * @sc: The &struct ath5k_softc we got from the driver's init_softc function * * Check if the device is supported, perform a POST and initialize the needed * structs. Returns -ENOMEM if we don't have memory for the needed structs, * -ENODEV if the device is not supported or prints an error msg if something * else went wrong. */ -int ath5k_hw_attach(struct ath5k_softc *sc) +int ath5k_hw_init(struct ath5k_softc *sc) { struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); @@ -115,7 +115,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) * HW information */ ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; - ah->ah_turbo = false; + ah->ah_bwmode = AR5K_BWMODE_DEFAULT; ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; ah->ah_imr = 0; ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; @@ -128,7 +128,8 @@ int ath5k_hw_attach(struct ath5k_softc *sc) /* * Find the mac version */ - srev = ath5k_hw_reg_read(ah, AR5K_SREV); + ath5k_hw_read_srev(ah); + srev = ah->ah_mac_srev; if (srev < AR5K_SREV_AR5311) ah->ah_version = AR5K_AR5210; else if (srev < AR5K_SREV_AR5212) @@ -136,6 +137,10 @@ int ath5k_hw_attach(struct ath5k_softc *sc) else ah->ah_version = AR5K_AR5212; + /* Get the MAC revision */ + ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); + ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV); + /* Fill the ath5k_hw struct with the needed functions */ ret = ath5k_hw_init_desc_functions(ah); if (ret) @@ -146,9 +151,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) if (ret) goto err; - /* Get MAC, PHY and RADIO revisions */ - ah->ah_mac_srev = srev; - ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); + /* Get PHY and RADIO revisions */ ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & 0xffffffff; ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, @@ -273,7 +276,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) /* * Write PCI-E power save settings */ - if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { + if ((ah->ah_version == AR5K_AR5212) && pdev && (pci_is_pcie(pdev))) { ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); @@ -305,8 +308,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) /* Get misc capabilities */ ret = ath5k_hw_set_capabilities(ah); if (ret) { - ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n", - sc->pdev->device); + ATH5K_ERR(sc, "unable to get device capabilities\n"); goto err; } @@ -346,11 +348,11 @@ err: } /** - * ath5k_hw_detach - Free the ath5k_hw struct + * ath5k_hw_deinit - Free the ath5k_hw struct * * @ah: The &struct ath5k_hw */ -void ath5k_hw_detach(struct ath5k_hw *ah) +void ath5k_hw_deinit(struct ath5k_hw *ah) { __set_bit(ATH_STAT_INVALID, ah->ah_sc->status); diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 42ed923cdb1a..019a74d533a6 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -47,8 +47,6 @@ #include <linux/io.h> #include <linux/netdevice.h> #include <linux/cache.h> -#include <linux/pci.h> -#include <linux/pci-aspm.h> #include <linux/ethtool.h> #include <linux/uaccess.h> #include <linux/slab.h> @@ -62,10 +60,9 @@ #include "reg.h" #include "debug.h" #include "ani.h" -#include "../debug.h" -static int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); +int ath5k_modparam_nohwcrypt; +module_param_named(nohwcrypt, ath5k_modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); static int modparam_all_channels; @@ -78,39 +75,24 @@ MODULE_AUTHOR("Nick Kossifidis"); MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards."); MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); - -static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); -static int ath5k_beacon_update(struct ieee80211_hw *hw, - struct ieee80211_vif *vif); -static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); - -/* Known PCI ids */ -static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { - { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ - { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ - { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ - { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */ - { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */ - { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */ - { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */ - { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */ - { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */ - { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ - { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ - { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); + +static int ath5k_init(struct ieee80211_hw *hw); +static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, + bool skip_pcu); +int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); /* Known SREVs */ static const struct ath5k_srev_name srev_names[] = { +#ifdef CONFIG_ATHEROS_AR231X + { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R2 }, + { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R7 }, + { "2313", AR5K_VERSION_MAC, AR5K_SREV_AR2313_R8 }, + { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R6 }, + { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R7 }, + { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R1 }, + { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R2 }, +#else { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, @@ -129,6 +111,7 @@ static const struct ath5k_srev_name srev_names[] = { { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 }, { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 }, { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 }, +#endif { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN }, { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, @@ -142,10 +125,12 @@ static const struct ath5k_srev_name srev_names[] = { { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B }, { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 }, { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 }, - { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, - { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 }, { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, +#ifdef CONFIG_ATHEROS_AR231X + { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, + { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, +#endif { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, }; @@ -191,38 +176,6 @@ static const struct ieee80211_rate ath5k_rates[] = { /* XR missing */ }; -static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc, - struct ath5k_buf *bf) -{ - BUG_ON(!bf); - if (!bf->skb) - return; - pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len, - PCI_DMA_TODEVICE); - dev_kfree_skb_any(bf->skb); - bf->skb = NULL; - bf->skbaddr = 0; - bf->desc->ds_data = 0; -} - -static inline void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, - struct ath5k_buf *bf) -{ - struct ath5k_hw *ah = sc->ah; - struct ath_common *common = ath5k_hw_common(ah); - - BUG_ON(!bf); - if (!bf->skb) - return; - pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(bf->skb); - bf->skb = NULL; - bf->skbaddr = 0; - bf->desc->ds_data = 0; -} - - static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) { u64 tsf = ath5k_hw_get_tsf64(ah); @@ -233,7 +186,7 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) return (tsf & ~0x7fff) | rstamp; } -static const char * +const char * ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) { const char *name = "xxxxx"; @@ -327,14 +280,12 @@ ath5k_copy_channels(struct ath5k_hw *ah, switch (mode) { case AR5K_MODE_11A: - case AR5K_MODE_11A_TURBO: /* 1..220, but 2GHz frequencies are filtered by check_channel */ size = 220 ; chfreq = CHANNEL_5GHZ; break; case AR5K_MODE_11B: case AR5K_MODE_11G: - case AR5K_MODE_11G_TURBO: size = 26; chfreq = CHANNEL_2GHZ; break; @@ -363,11 +314,6 @@ ath5k_copy_channels(struct ath5k_hw *ah, case AR5K_MODE_11G: channels[count].hw_value = chfreq | CHANNEL_OFDM; break; - case AR5K_MODE_11A_TURBO: - case AR5K_MODE_11G_TURBO: - channels[count].hw_value = chfreq | - CHANNEL_OFDM | CHANNEL_TURBO; - break; case AR5K_MODE_11B: channels[count].hw_value = CHANNEL_B; } @@ -483,7 +429,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw) * * Called with sc->lock. */ -static int +int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) { ATH5K_DBG(sc, ATH5K_DEBUG_RESET, @@ -496,7 +442,7 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) * hardware at the new frequency, and then re-enable * the relevant bits of the h/w. */ - return ath5k_reset(sc, chan); + return ath5k_reset(sc, chan, true); } static void @@ -549,7 +495,7 @@ static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) /* Calculate combined mode - when APs are active, operate in AP mode. * Otherwise use the mode of the new interface. This can currently * only deal with combinations of APs and STAs. Only one ad-hoc - * interfaces is allowed above. + * interfaces is allowed. */ if (avf->opmode == NL80211_IFTYPE_AP) iter_data->opmode = NL80211_IFTYPE_AP; @@ -558,16 +504,9 @@ static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) iter_data->opmode = avf->opmode; } -static void ath_do_set_opmode(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - ath5k_hw_set_opmode(ah, sc->opmode); - ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n", - sc->opmode, ath_opmode_to_string(sc->opmode)); -} - -void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, - struct ieee80211_vif *vif) +void +ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, + struct ieee80211_vif *vif) { struct ath_common *common = ath5k_hw_common(sc->ah); struct ath_vif_iter_data iter_data; @@ -595,7 +534,9 @@ void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, /* Nothing active, default to station mode */ sc->opmode = NL80211_IFTYPE_STATION; - ath_do_set_opmode(sc); + ath5k_hw_set_opmode(sc->ah, sc->opmode); + ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n", + sc->opmode, ath_opmode_to_string(sc->opmode)); if (iter_data.need_set_hw_addr && iter_data.found_active) ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac); @@ -604,7 +545,7 @@ void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); } -static void +void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif) { struct ath5k_hw *ah = sc->ah; @@ -659,10 +600,11 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) return NULL; } - *skb_addr = pci_map_single(sc->pdev, + *skb_addr = dma_map_single(sc->dev, skb->data, common->rx_bufsize, - PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { + DMA_FROM_DEVICE); + + if (unlikely(dma_mapping_error(sc->dev, *skb_addr))) { ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); dev_kfree_skb(skb); return NULL; @@ -758,8 +700,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; /* XXX endianness */ - bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); + bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len, + DMA_TO_DEVICE); rate = ieee80211_get_tx_rate(sc->hw, info); if (!rate) { @@ -839,7 +781,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, return 0; err_unmap: - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); return ret; } @@ -848,7 +790,7 @@ err_unmap: \*******************/ static int -ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) +ath5k_desc_alloc(struct ath5k_softc *sc) { struct ath5k_desc *ds; struct ath5k_buf *bf; @@ -859,7 +801,9 @@ ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) /* allocate descriptors */ sc->desc_len = sizeof(struct ath5k_desc) * (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1); - sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr); + + sc->desc = dma_alloc_coherent(sc->dev, sc->desc_len, + &sc->desc_daddr, GFP_KERNEL); if (sc->desc == NULL) { ATH5K_ERR(sc, "can't allocate descriptors\n"); ret = -ENOMEM; @@ -905,14 +849,45 @@ ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) return 0; err_free: - pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); + dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr); err: sc->desc = NULL; return ret; } +void +ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf) +{ + BUG_ON(!bf); + if (!bf->skb) + return; + dma_unmap_single(sc->dev, bf->skbaddr, bf->skb->len, + DMA_TO_DEVICE); + dev_kfree_skb_any(bf->skb); + bf->skb = NULL; + bf->skbaddr = 0; + bf->desc->ds_data = 0; +} + +void +ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf) +{ + struct ath5k_hw *ah = sc->ah; + struct ath_common *common = ath5k_hw_common(ah); + + BUG_ON(!bf); + if (!bf->skb) + return; + dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize, + DMA_FROM_DEVICE); + dev_kfree_skb_any(bf->skb); + bf->skb = NULL; + bf->skbaddr = 0; + bf->desc->ds_data = 0; +} + static void -ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) +ath5k_desc_free(struct ath5k_softc *sc) { struct ath5k_buf *bf; @@ -924,7 +899,7 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) ath5k_txbuf_free_skb(sc, bf); /* Free memory associated with all descriptors */ - pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); + dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr); sc->desc = NULL; sc->desc_daddr = 0; @@ -1069,62 +1044,44 @@ err: return ret; } +/** + * ath5k_drain_tx_buffs - Empty tx buffers + * + * @sc The &struct ath5k_softc + * + * Empty tx buffers from all queues in preparation + * of a reset or during shutdown. + * + * NB: this assumes output has been stopped and + * we do not need to block ath5k_tx_tasklet + */ static void -ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) +ath5k_drain_tx_buffs(struct ath5k_softc *sc) { + struct ath5k_txq *txq; struct ath5k_buf *bf, *bf0; + int i; - /* - * NB: this assumes output has been stopped and - * we do not need to block ath5k_tx_tasklet - */ - spin_lock_bh(&txq->lock); - list_for_each_entry_safe(bf, bf0, &txq->q, list) { - ath5k_debug_printtxbuf(sc, bf); - - ath5k_txbuf_free_skb(sc, bf); - - spin_lock_bh(&sc->txbuflock); - list_move_tail(&bf->list, &sc->txbuf); - sc->txbuf_len++; - txq->txq_len--; - spin_unlock_bh(&sc->txbuflock); - } - txq->link = NULL; - txq->txq_poll_mark = false; - spin_unlock_bh(&txq->lock); -} + for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) { + if (sc->txqs[i].setup) { + txq = &sc->txqs[i]; + spin_lock_bh(&txq->lock); + list_for_each_entry_safe(bf, bf0, &txq->q, list) { + ath5k_debug_printtxbuf(sc, bf); -/* - * Drain the transmit queues and reclaim resources. - */ -static void -ath5k_txq_cleanup(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - unsigned int i; + ath5k_txbuf_free_skb(sc, bf); - /* XXX return value */ - if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) { - /* don't touch the hardware if marked invalid */ - ath5k_hw_stop_tx_dma(ah, sc->bhalq); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n", - ath5k_hw_get_txdp(ah, sc->bhalq)); - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) - if (sc->txqs[i].setup) { - ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, " - "link %p\n", - sc->txqs[i].qnum, - ath5k_hw_get_txdp(ah, - sc->txqs[i].qnum), - sc->txqs[i].link); + spin_lock_bh(&sc->txbuflock); + list_move_tail(&bf->list, &sc->txbuf); + sc->txbuf_len++; + txq->txq_len--; + spin_unlock_bh(&sc->txbuflock); } + txq->link = NULL; + txq->txq_poll_mark = false; + spin_unlock_bh(&txq->lock); + } } - - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) - if (sc->txqs[i].setup) - ath5k_txq_drainq(sc, &sc->txqs[i]); } static void @@ -1184,16 +1141,19 @@ err: } /* - * Disable the receive h/w in preparation for a reset. + * Disable the receive logic on PCU (DRU) + * In preparation for a shutdown. + * + * Note: Doesn't stop rx DMA, ath5k_hw_dma_stop + * does. */ static void ath5k_rx_stop(struct ath5k_softc *sc) { struct ath5k_hw *ah = sc->ah; - ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ - ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ + ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ ath5k_debug_printrxbuffs(sc, ah); } @@ -1307,8 +1267,7 @@ ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi) memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0) return; - ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg, - rssi); + ewma_add(&ah->ah_beacon_rssi_avg, rssi); /* in IBSS mode we should keep RSSI statistics per neighbour */ /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */ @@ -1551,9 +1510,9 @@ ath5k_tasklet_rx(unsigned long data) if (!next_skb) goto next; - pci_unmap_single(sc->pdev, bf->skbaddr, + dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); skb_put(skb, rs.rs_datalen); @@ -1574,8 +1533,9 @@ unlock: * TX Handling * \*************/ -static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ath5k_txq *txq) +int +ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ath5k_txq *txq) { struct ath5k_softc *sc = hw->priv; struct ath5k_buf *bf; @@ -1716,8 +1676,9 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) skb = bf->skb; bf->skb = NULL; - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, - PCI_DMA_TODEVICE); + + dma_unmap_single(sc->dev, bf->skbaddr, skb->len, + DMA_TO_DEVICE); ath5k_tx_frame_completed(sc, skb, &ts); } @@ -1771,12 +1732,13 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) u32 flags; const int padsize = 0; - bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); + bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len, + DMA_TO_DEVICE); ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] " "skbaddr %llx\n", skb, skb->data, skb->len, (unsigned long long)bf->skbaddr); - if (pci_dma_mapping_error(sc->pdev, bf->skbaddr)) { + + if (dma_mapping_error(sc->dev, bf->skbaddr)) { ATH5K_ERR(sc, "beacon DMA mapping failed\n"); return -EIO; } @@ -1828,7 +1790,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) return 0; err_unmap: - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); return ret; } @@ -1839,7 +1801,7 @@ err_unmap: * * Called with the beacon lock. */ -static int +int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { int ret; @@ -1945,7 +1907,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) * This should never fail since we check above that no frames * are still pending on the queue. */ - if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) { + if (unlikely(ath5k_hw_stop_beacon_queue(ah, sc->bhalq))) { ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq); /* NB: hw still stops DMA, so proceed */ } @@ -1985,7 +1947,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) * when we otherwise know we have to update the timers, but we keep it in this * function to have it all together in one place. */ -static void +void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) { struct ath5k_hw *ah = sc->ah; @@ -2087,7 +2049,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA * interrupts to detect TSF updates only. */ -static void +void ath5k_beacon_config(struct ath5k_softc *sc) { struct ath5k_hw *ah = sc->ah; @@ -2115,7 +2077,7 @@ ath5k_beacon_config(struct ath5k_softc *sc) } else ath5k_beacon_update_timers(sc, -1); } else { - ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq); + ath5k_hw_stop_beacon_queue(sc->ah, sc->bhalq); } ath5k_hw_set_imr(ah, sc->imask); @@ -2177,7 +2139,7 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah) * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ } -static irqreturn_t +irqreturn_t ath5k_intr(int irq, void *dev_id) { struct ath5k_softc *sc = dev_id; @@ -2186,7 +2148,8 @@ ath5k_intr(int irq, void *dev_id) unsigned int counter = 1000; if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) || - !ath5k_hw_is_intr_pending(ah))) + ((ath5k_get_bus_type(ah) != ATH_AHB) && + !ath5k_hw_is_intr_pending(ah)))) return IRQ_NONE; do { @@ -2252,6 +2215,10 @@ ath5k_intr(int irq, void *dev_id) tasklet_schedule(&sc->rf_kill.toggleq); } + + if (ath5k_get_bus_type(ah) == ATH_AHB) + break; + } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); if (unlikely(!counter)) @@ -2351,7 +2318,7 @@ ath5k_tx_complete_poll_work(struct work_struct *work) if (needreset) { ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "TX queues stuck, resetting\n"); - ath5k_reset(sc, sc->curchan); + ath5k_reset(sc, NULL, true); } ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, @@ -2363,6 +2330,163 @@ ath5k_tx_complete_poll_work(struct work_struct *work) * Initialization routines * \*************************/ +int +ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops) +{ + struct ieee80211_hw *hw = sc->hw; + struct ath_common *common; + int ret; + int csz; + + /* Initialize driver private data */ + SET_IEEE80211_DEV(hw, sc->dev); + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_REPORTS_TX_ACK_STATUS; + + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_MESH_POINT); + + /* both antennas can be configured as RX or TX */ + hw->wiphy->available_antennas_tx = 0x3; + hw->wiphy->available_antennas_rx = 0x3; + + hw->extra_tx_headroom = 2; + hw->channel_change_time = 5000; + + /* + * Mark the device as detached to avoid processing + * interrupts until setup is complete. + */ + __set_bit(ATH_STAT_INVALID, sc->status); + + sc->opmode = NL80211_IFTYPE_STATION; + sc->bintval = 1000; + mutex_init(&sc->lock); + spin_lock_init(&sc->rxbuflock); + spin_lock_init(&sc->txbuflock); + spin_lock_init(&sc->block); + + + /* Setup interrupt handler */ + ret = request_irq(sc->irq, ath5k_intr, IRQF_SHARED, "ath", sc); + if (ret) { + ATH5K_ERR(sc, "request_irq failed\n"); + goto err; + } + + /* If we passed the test, malloc an ath5k_hw struct */ + sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); + if (!sc->ah) { + ret = -ENOMEM; + ATH5K_ERR(sc, "out of memory\n"); + goto err_irq; + } + + sc->ah->ah_sc = sc; + sc->ah->ah_iobase = sc->iobase; + common = ath5k_hw_common(sc->ah); + common->ops = &ath5k_common_ops; + common->bus_ops = bus_ops; + common->ah = sc->ah; + common->hw = hw; + common->priv = sc; + + /* + * Cache line size is used to size and align various + * structures used to communicate with the hardware. + */ + ath5k_read_cachesize(common, &csz); + common->cachelsz = csz << 2; /* convert to bytes */ + + spin_lock_init(&common->cc_lock); + + /* Initialize device */ + ret = ath5k_hw_init(sc); + if (ret) + goto err_free_ah; + + /* set up multi-rate retry capabilities */ + if (sc->ah->ah_version == AR5K_AR5212) { + hw->max_rates = 4; + hw->max_rate_tries = 11; + } + + hw->vif_data_size = sizeof(struct ath5k_vif); + + /* Finish private driver data initialization */ + ret = ath5k_init(hw); + if (ret) + goto err_ah; + + ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", + ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), + sc->ah->ah_mac_srev, + sc->ah->ah_phy_revision); + + if (!sc->ah->ah_single_chip) { + /* Single chip radio (!RF5111) */ + if (sc->ah->ah_radio_5ghz_revision && + !sc->ah->ah_radio_2ghz_revision) { + /* No 5GHz support -> report 2GHz radio */ + if (!test_bit(AR5K_MODE_11A, + sc->ah->ah_capabilities.cap_mode)) { + ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + /* No 2GHz support (5110 and some + * 5Ghz only cards) -> report 5Ghz radio */ + } else if (!test_bit(AR5K_MODE_11B, + sc->ah->ah_capabilities.cap_mode)) { + ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + /* Multiband radio */ + } else { + ATH5K_INFO(sc, "RF%s multiband radio found" + " (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + } + } + /* Multi chip radio (RF5111 - RF2111) -> + * report both 2GHz/5GHz radios */ + else if (sc->ah->ah_radio_5ghz_revision && + sc->ah->ah_radio_2ghz_revision){ + ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_2ghz_revision), + sc->ah->ah_radio_2ghz_revision); + } + } + + ath5k_debug_init_device(sc); + + /* ready to process interrupts */ + __clear_bit(ATH_STAT_INVALID, sc->status); + + return 0; +err_ah: + ath5k_hw_deinit(sc->ah); +err_free_ah: + kfree(sc->ah); +err_irq: + free_irq(sc->irq, sc); +err: + return ret; +} + static int ath5k_stop_locked(struct ath5k_softc *sc) { @@ -2391,19 +2515,18 @@ ath5k_stop_locked(struct ath5k_softc *sc) if (!test_bit(ATH_STAT_INVALID, sc->status)) { ath5k_led_off(sc); ath5k_hw_set_imr(ah, 0); - synchronize_irq(sc->pdev->irq); - } - ath5k_txq_cleanup(sc); - if (!test_bit(ATH_STAT_INVALID, sc->status)) { + synchronize_irq(sc->irq); ath5k_rx_stop(sc); + ath5k_hw_dma_stop(ah); + ath5k_drain_tx_buffs(sc); ath5k_hw_phy_disable(ah); } return 0; } -static int -ath5k_init(struct ath5k_softc *sc) +int +ath5k_init_hw(struct ath5k_softc *sc) { struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); @@ -2432,7 +2555,7 @@ ath5k_init(struct ath5k_softc *sc) AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; - ret = ath5k_reset(sc, NULL); + ret = ath5k_reset(sc, NULL, false); if (ret) goto done; @@ -2445,7 +2568,9 @@ ath5k_init(struct ath5k_softc *sc) for (i = 0; i < common->keymax; i++) ath_hw_keyreset(common, (u16) i); - ath5k_hw_set_ack_bitrate_high(ah, true); + /* Use higher rates for acks instead of base + * rate */ + ah->ah_ack_bitrate_high = true; for (i = 0; i < ARRAY_SIZE(sc->bslot); i++) sc->bslot[i] = NULL; @@ -2476,7 +2601,7 @@ static void stop_tasklets(struct ath5k_softc *sc) * if another thread does a system call and the thread doing the * stop is preempted). */ -static int +int ath5k_stop_hw(struct ath5k_softc *sc) { int ret; @@ -2529,25 +2654,35 @@ ath5k_stop_hw(struct ath5k_softc *sc) * This should be called with sc->lock. */ static int -ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) +ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, + bool skip_pcu) { struct ath5k_hw *ah = sc->ah; - int ret; + struct ath_common *common = ath5k_hw_common(ah); + int ret, ani_mode; ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); ath5k_hw_set_imr(ah, 0); - synchronize_irq(sc->pdev->irq); + synchronize_irq(sc->irq); stop_tasklets(sc); - if (chan) { - ath5k_txq_cleanup(sc); - ath5k_rx_stop(sc); + /* Save ani mode and disable ANI durring + * reset. If we don't we might get false + * PHY error interrupts. */ + ani_mode = ah->ah_sc->ani_state.ani_mode; + ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF); + /* We are going to empty hw queues + * so we should also free any remaining + * tx buffers */ + ath5k_drain_tx_buffs(sc); + if (chan) { sc->curchan = chan; sc->curband = &sc->sbands[chan->band]; } - ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL); + ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL, + skip_pcu); if (ret) { ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); goto err; @@ -2559,11 +2694,20 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) goto err; } - ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode); + ath5k_ani_init(ah, ani_mode); ah->ah_cal_next_full = jiffies; ah->ah_cal_next_ani = jiffies; ah->ah_cal_next_nf = jiffies; + ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8); + + /* clear survey data and cycle counters */ + memset(&sc->survey, 0, sizeof(sc->survey)); + spin_lock_bh(&common->cc_lock); + ath_hw_cycle_counters_update(common); + memset(&common->cc_survey, 0, sizeof(common->cc_survey)); + memset(&common->cc_ani, 0, sizeof(common->cc_ani)); + spin_unlock_bh(&common->cc_lock); /* * Change channels and update the h/w rate map if we're switching; @@ -2592,13 +2736,14 @@ static void ath5k_reset_work(struct work_struct *work) reset_work); mutex_lock(&sc->lock); - ath5k_reset(sc, sc->curchan); + ath5k_reset(sc, NULL, true); mutex_unlock(&sc->lock); } static int -ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) +ath5k_init(struct ieee80211_hw *hw) { + struct ath5k_softc *sc = hw->priv; struct ath5k_hw *ah = sc->ah; struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); @@ -2606,7 +2751,6 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) u8 mac[ETH_ALEN] = {}; int ret; - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); /* * Check if the MAC has multi-rate retry support. @@ -2643,7 +2787,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) /* * Allocate tx+rx descriptors and populate the lists. */ - ret = ath5k_desc_alloc(sc, pdev); + ret = ath5k_desc_alloc(sc); if (ret) { ATH5K_ERR(sc, "can't allocate descriptors\n"); goto err; @@ -2668,33 +2812,46 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) goto err_bhal; } - /* This order matches mac80211's queue priority, so we can - * directly use the mac80211 queue number without any mapping */ - txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO); - if (IS_ERR(txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); - ret = PTR_ERR(txq); - goto err_queues; - } - txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI); - if (IS_ERR(txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); - ret = PTR_ERR(txq); - goto err_queues; - } - txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); - if (IS_ERR(txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); - ret = PTR_ERR(txq); - goto err_queues; - } - txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); - if (IS_ERR(txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); - ret = PTR_ERR(txq); - goto err_queues; + /* 5211 and 5212 usually support 10 queues but we better rely on the + * capability information */ + if (ah->ah_capabilities.cap_queues.q_tx_num >= 6) { + /* This order matches mac80211's queue priority, so we can + * directly use the mac80211 queue number without any mapping */ + txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO); + if (IS_ERR(txq)) { + ATH5K_ERR(sc, "can't setup xmit queue\n"); + ret = PTR_ERR(txq); + goto err_queues; + } + txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI); + if (IS_ERR(txq)) { + ATH5K_ERR(sc, "can't setup xmit queue\n"); + ret = PTR_ERR(txq); + goto err_queues; + } + txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); + if (IS_ERR(txq)) { + ATH5K_ERR(sc, "can't setup xmit queue\n"); + ret = PTR_ERR(txq); + goto err_queues; + } + txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); + if (IS_ERR(txq)) { + ATH5K_ERR(sc, "can't setup xmit queue\n"); + ret = PTR_ERR(txq); + goto err_queues; + } + hw->queues = 4; + } else { + /* older hardware (5210) can only support one data queue */ + txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); + if (IS_ERR(txq)) { + ATH5K_ERR(sc, "can't setup xmit queue\n"); + ret = PTR_ERR(txq); + goto err_queues; + } + hw->queues = 1; } - hw->queues = 4; tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); @@ -2707,8 +2864,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) ret = ath5k_eeprom_read_mac(ah, mac); if (ret) { - ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", - sc->pdev->device); + ATH5K_ERR(sc, "unable to read address from EEPROM\n"); goto err_queues; } @@ -2743,15 +2899,15 @@ err_queues: err_bhal: ath5k_hw_release_tx_queue(ah, sc->bhalq); err_desc: - ath5k_desc_free(sc, pdev); + ath5k_desc_free(sc); err: return ret; } -static void -ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) +void +ath5k_deinit_softc(struct ath5k_softc *sc) { - struct ath5k_softc *sc = hw->priv; + struct ieee80211_hw *hw = sc->hw; /* * NB: the order of these is important: @@ -2766,8 +2922,9 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) * XXX: ??? detach ath5k_hw ??? * Other than that, it's straightforward... */ + ath5k_debug_finish_device(sc); ieee80211_unregister_hw(hw); - ath5k_desc_free(sc, pdev); + ath5k_desc_free(sc); ath5k_txq_release(sc); ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); ath5k_unregister_leds(sc); @@ -2778,232 +2935,12 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) * returns because we'll get called back to reclaim node * state and potentially want to use them. */ + ath5k_hw_deinit(sc->ah); + free_irq(sc->irq, sc); } -/********************\ -* Mac80211 functions * -\********************/ - -static int -ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ath5k_softc *sc = hw->priv; - u16 qnum = skb_get_queue_mapping(skb); - - if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) { - dev_kfree_skb_any(skb); - return 0; - } - - return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]); -} - -static int ath5k_start(struct ieee80211_hw *hw) -{ - return ath5k_init(hw->priv); -} - -static void ath5k_stop(struct ieee80211_hw *hw) -{ - ath5k_stop_hw(hw->priv); -} - -static int ath5k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct ath5k_softc *sc = hw->priv; - int ret; - struct ath5k_vif *avf = (void *)vif->drv_priv; - - mutex_lock(&sc->lock); - - if ((vif->type == NL80211_IFTYPE_AP || - vif->type == NL80211_IFTYPE_ADHOC) - && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) { - ret = -ELNRNG; - goto end; - } - - /* Don't allow other interfaces if one ad-hoc is configured. - * TODO: Fix the problems with ad-hoc and multiple other interfaces. - * We would need to operate the HW in ad-hoc mode to allow TSF updates - * for the IBSS, but this breaks with additional AP or STA interfaces - * at the moment. */ - if (sc->num_adhoc_vifs || - (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { - ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n"); - ret = -ELNRNG; - goto end; - } - - switch (vif->type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - avf->opmode = vif->type; - break; - default: - ret = -EOPNOTSUPP; - goto end; - } - - sc->nvifs++; - ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode); - - /* Assign the vap/adhoc to a beacon xmit slot. */ - if ((avf->opmode == NL80211_IFTYPE_AP) || - (avf->opmode == NL80211_IFTYPE_ADHOC) || - (avf->opmode == NL80211_IFTYPE_MESH_POINT)) { - int slot; - - WARN_ON(list_empty(&sc->bcbuf)); - avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf, - list); - list_del(&avf->bbuf->list); - - avf->bslot = 0; - for (slot = 0; slot < ATH_BCBUF; slot++) { - if (!sc->bslot[slot]) { - avf->bslot = slot; - break; - } - } - BUG_ON(sc->bslot[avf->bslot] != NULL); - sc->bslot[avf->bslot] = vif; - if (avf->opmode == NL80211_IFTYPE_AP) - sc->num_ap_vifs++; - else if (avf->opmode == NL80211_IFTYPE_ADHOC) - sc->num_adhoc_vifs++; - } - - /* Any MAC address is fine, all others are included through the - * filter. - */ - memcpy(&sc->lladdr, vif->addr, ETH_ALEN); - ath5k_hw_set_lladdr(sc->ah, vif->addr); - - memcpy(&avf->lladdr, vif->addr, ETH_ALEN); - - ath5k_mode_setup(sc, vif); - - ret = 0; -end: - mutex_unlock(&sc->lock); - return ret; -} - -static void -ath5k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_vif *avf = (void *)vif->drv_priv; - unsigned int i; - - mutex_lock(&sc->lock); - sc->nvifs--; - - if (avf->bbuf) { - ath5k_txbuf_free_skb(sc, avf->bbuf); - list_add_tail(&avf->bbuf->list, &sc->bcbuf); - for (i = 0; i < ATH_BCBUF; i++) { - if (sc->bslot[i] == vif) { - sc->bslot[i] = NULL; - break; - } - } - avf->bbuf = NULL; - } - if (avf->opmode == NL80211_IFTYPE_AP) - sc->num_ap_vifs--; - else if (avf->opmode == NL80211_IFTYPE_ADHOC) - sc->num_adhoc_vifs--; - - ath5k_update_bssid_mask_and_opmode(sc, NULL); - mutex_unlock(&sc->lock); -} - -/* - * TODO: Phy disable/diversity etc - */ -static int -ath5k_config(struct ieee80211_hw *hw, u32 changed) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - struct ieee80211_conf *conf = &hw->conf; - int ret = 0; - - mutex_lock(&sc->lock); - - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - ret = ath5k_chan_set(sc, conf->channel); - if (ret < 0) - goto unlock; - } - - if ((changed & IEEE80211_CONF_CHANGE_POWER) && - (sc->power_level != conf->power_level)) { - sc->power_level = conf->power_level; - - /* Half dB steps */ - ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); - } - - /* TODO: - * 1) Move this on config_interface and handle each case - * separately eg. when we have only one STA vif, use - * AR5K_ANTMODE_SINGLE_AP - * - * 2) Allow the user to change antenna mode eg. when only - * one antenna is present - * - * 3) Allow the user to set default/tx antenna when possible - * - * 4) Default mode should handle 90% of the cases, together - * with fixed a/b and single AP modes we should be able to - * handle 99%. Sectored modes are extreme cases and i still - * haven't found a usage for them. If we decide to support them, - * then we must allow the user to set how many tx antennas we - * have available - */ - ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); - -unlock: - mutex_unlock(&sc->lock); - return ret; -} - -static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, - struct netdev_hw_addr_list *mc_list) -{ - u32 mfilt[2], val; - u8 pos; - struct netdev_hw_addr *ha; - - mfilt[0] = 0; - mfilt[1] = 1; - - netdev_hw_addr_list_for_each(ha, mc_list) { - /* calculate XOR of eight 6-bit values */ - val = get_unaligned_le32(ha->addr + 0); - pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - val = get_unaligned_le32(ha->addr + 3); - pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - pos &= 0x3f; - mfilt[pos / 32] |= (1 << (pos % 32)); - /* XXX: we might be able to just do this instead, - * but not sure, needs testing, if we do use this we'd - * neet to inform below to not reset the mcast */ - /* ath5k_hw_set_mcast_filterindex(ah, - * ha->addr[5]); */ - } - - return ((u64)(mfilt[1]) << 32) | mfilt[0]; -} - -static bool ath_any_vif_assoc(struct ath5k_softc *sc) +bool +ath_any_vif_assoc(struct ath5k_softc *sc) { struct ath_vif_iter_data iter_data; iter_data.hw_macaddr = NULL; @@ -3016,242 +2953,7 @@ static bool ath_any_vif_assoc(struct ath5k_softc *sc) return iter_data.any_assoc; } -#define SUPPORTED_FIF_FLAGS \ - FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ - FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ - FIF_BCN_PRBRESP_PROMISC -/* - * o always accept unicast, broadcast, and multicast traffic - * o multicast traffic for all BSSIDs will be enabled if mac80211 - * says it should be - * o maintain current state of phy ofdm or phy cck error reception. - * If the hardware detects any of these type of errors then - * ath5k_hw_get_rx_filter() will pass to us the respective - * hardware filters to be able to receive these type of frames. - * o probe request frames are accepted only when operating in - * hostap, adhoc, or monitor modes - * o enable promiscuous mode according to the interface state - * o accept beacons: - * - when operating in adhoc mode so the 802.11 layer creates - * node table entries for peers, - * - when operating in station mode for collecting rssi data when - * the station is otherwise quiet, or - * - when scanning - */ -static void ath5k_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *new_flags, - u64 multicast) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - u32 mfilt[2], rfilt; - - mutex_lock(&sc->lock); - - mfilt[0] = multicast; - mfilt[1] = multicast >> 32; - - /* Only deal with supported flags */ - changed_flags &= SUPPORTED_FIF_FLAGS; - *new_flags &= SUPPORTED_FIF_FLAGS; - - /* If HW detects any phy or radar errors, leave those filters on. - * Also, always enable Unicast, Broadcasts and Multicast - * XXX: move unicast, bssid broadcasts and multicast to mac80211 */ - rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) | - (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST | - AR5K_RX_FILTER_MCAST); - - if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { - if (*new_flags & FIF_PROMISC_IN_BSS) { - __set_bit(ATH_STAT_PROMISC, sc->status); - } else { - __clear_bit(ATH_STAT_PROMISC, sc->status); - } - } - - if (test_bit(ATH_STAT_PROMISC, sc->status)) - rfilt |= AR5K_RX_FILTER_PROM; - - /* Note, AR5K_RX_FILTER_MCAST is already enabled */ - if (*new_flags & FIF_ALLMULTI) { - mfilt[0] = ~0; - mfilt[1] = ~0; - } - - /* This is the best we can do */ - if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)) - rfilt |= AR5K_RX_FILTER_PHYERR; - - /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons - * and probes for any BSSID */ - if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1)) - rfilt |= AR5K_RX_FILTER_BEACON; - - /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not - * set we should only pass on control frames for this - * station. This needs testing. I believe right now this - * enables *all* control frames, which is OK.. but - * but we should see if we can improve on granularity */ - if (*new_flags & FIF_CONTROL) - rfilt |= AR5K_RX_FILTER_CONTROL; - - /* Additional settings per mode -- this is per ath5k */ - - /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */ - - switch (sc->opmode) { - case NL80211_IFTYPE_MESH_POINT: - rfilt |= AR5K_RX_FILTER_CONTROL | - AR5K_RX_FILTER_BEACON | - AR5K_RX_FILTER_PROBEREQ | - AR5K_RX_FILTER_PROM; - break; - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_ADHOC: - rfilt |= AR5K_RX_FILTER_PROBEREQ | - AR5K_RX_FILTER_BEACON; - break; - case NL80211_IFTYPE_STATION: - if (sc->assoc) - rfilt |= AR5K_RX_FILTER_BEACON; - default: - break; - } - - /* Set filters */ - ath5k_hw_set_rx_filter(ah, rfilt); - - /* Set multicast bits */ - ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); - /* Set the cached hw filter flags, this will later actually - * be set in HW */ - sc->filter_flags = rfilt; - - mutex_unlock(&sc->lock); -} - -static int -ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - struct ath_common *common = ath5k_hw_common(ah); - int ret = 0; - - if (modparam_nohwcrypt) - return -EOPNOTSUPP; - - switch (key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - case WLAN_CIPHER_SUITE_TKIP: - break; - case WLAN_CIPHER_SUITE_CCMP: - if (common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM) - break; - return -EOPNOTSUPP; - default: - WARN_ON(1); - return -EINVAL; - } - - mutex_lock(&sc->lock); - - switch (cmd) { - case SET_KEY: - ret = ath_key_config(common, vif, sta, key); - if (ret >= 0) { - key->hw_key_idx = ret; - /* push IV and Michael MIC generation to stack */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - if (key->cipher == WLAN_CIPHER_SUITE_TKIP) - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - if (key->cipher == WLAN_CIPHER_SUITE_CCMP) - key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; - ret = 0; - } - break; - case DISABLE_KEY: - ath_key_delete(common, key); - break; - default: - ret = -EINVAL; - } - - mmiowb(); - mutex_unlock(&sc->lock); - return ret; -} - -static int -ath5k_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct ath5k_softc *sc = hw->priv; - - /* Force update */ - ath5k_hw_update_mib_counters(sc->ah); - - stats->dot11ACKFailureCount = sc->stats.ack_fail; - stats->dot11RTSFailureCount = sc->stats.rts_fail; - stats->dot11RTSSuccessCount = sc->stats.rts_ok; - stats->dot11FCSErrorCount = sc->stats.fcs_error; - - return 0; -} - -static int ath5k_get_survey(struct ieee80211_hw *hw, int idx, - struct survey_info *survey) -{ - struct ath5k_softc *sc = hw->priv; - struct ieee80211_conf *conf = &hw->conf; - - if (idx != 0) - return -ENOENT; - - survey->channel = conf->channel; - survey->filled = SURVEY_INFO_NOISE_DBM; - survey->noise = sc->ah->ah_noise_floor; - - return 0; -} - -static u64 -ath5k_get_tsf(struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - - return ath5k_hw_get_tsf64(sc->ah); -} - -static void -ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) -{ - struct ath5k_softc *sc = hw->priv; - - ath5k_hw_set_tsf64(sc->ah, tsf); -} - -static void -ath5k_reset_tsf(struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - - /* - * in IBSS mode we need to update the beacon timers too. - * this will also reset the TSF if we call it with 0 - */ - if (sc->opmode == NL80211_IFTYPE_ADHOC) - ath5k_beacon_update_timers(sc, 0); - else - ath5k_hw_reset_tsf(sc->ah); -} - -static void +void set_beacon_filter(struct ieee80211_hw *hw, bool enable) { struct ath5k_softc *sc = hw->priv; @@ -3265,494 +2967,3 @@ set_beacon_filter(struct ieee80211_hw *hw, bool enable) ath5k_hw_set_rx_filter(ah, rfilt); sc->filter_flags = rfilt; } - -static void ath5k_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) -{ - struct ath5k_vif *avf = (void *)vif->drv_priv; - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - struct ath_common *common = ath5k_hw_common(ah); - unsigned long flags; - - mutex_lock(&sc->lock); - - if (changes & BSS_CHANGED_BSSID) { - /* Cache for later use during resets */ - memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); - common->curaid = 0; - ath5k_hw_set_bssid(ah); - mmiowb(); - } - - if (changes & BSS_CHANGED_BEACON_INT) - sc->bintval = bss_conf->beacon_int; - - if (changes & BSS_CHANGED_ASSOC) { - avf->assoc = bss_conf->assoc; - if (bss_conf->assoc) - sc->assoc = bss_conf->assoc; - else - sc->assoc = ath_any_vif_assoc(sc); - - if (sc->opmode == NL80211_IFTYPE_STATION) - set_beacon_filter(hw, sc->assoc); - ath5k_hw_set_ledstate(sc->ah, sc->assoc ? - AR5K_LED_ASSOC : AR5K_LED_INIT); - if (bss_conf->assoc) { - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, - "Bss Info ASSOC %d, bssid: %pM\n", - bss_conf->aid, common->curbssid); - common->curaid = bss_conf->aid; - ath5k_hw_set_bssid(ah); - /* Once ANI is available you would start it here */ - } - } - - if (changes & BSS_CHANGED_BEACON) { - spin_lock_irqsave(&sc->block, flags); - ath5k_beacon_update(hw, vif); - spin_unlock_irqrestore(&sc->block, flags); - } - - if (changes & BSS_CHANGED_BEACON_ENABLED) - sc->enable_beacon = bss_conf->enable_beacon; - - if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED | - BSS_CHANGED_BEACON_INT)) - ath5k_beacon_config(sc); - - mutex_unlock(&sc->lock); -} - -static void ath5k_sw_scan_start(struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - if (!sc->assoc) - ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN); -} - -static void ath5k_sw_scan_complete(struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - ath5k_hw_set_ledstate(sc->ah, sc->assoc ? - AR5K_LED_ASSOC : AR5K_LED_INIT); -} - -/** - * ath5k_set_coverage_class - Set IEEE 802.11 coverage class - * - * @hw: struct ieee80211_hw pointer - * @coverage_class: IEEE 802.11 coverage class number - * - * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given - * coverage class. The values are persistent, they are restored after device - * reset. - */ -static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) -{ - struct ath5k_softc *sc = hw->priv; - - mutex_lock(&sc->lock); - ath5k_hw_set_coverage_class(sc->ah, coverage_class); - mutex_unlock(&sc->lock); -} - -static int ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - struct ath5k_txq_info qi; - int ret = 0; - - if (queue >= ah->ah_capabilities.cap_queues.q_tx_num) - return 0; - - mutex_lock(&sc->lock); - - ath5k_hw_get_tx_queueprops(ah, queue, &qi); - - qi.tqi_aifs = params->aifs; - qi.tqi_cw_min = params->cw_min; - qi.tqi_cw_max = params->cw_max; - qi.tqi_burst_time = params->txop; - - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, - "Configure tx [queue %d], " - "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", - queue, params->aifs, params->cw_min, - params->cw_max, params->txop); - - if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) { - ATH5K_ERR(sc, - "Unable to update hardware queue %u!\n", queue); - ret = -EIO; - } else - ath5k_hw_reset_tx_queue(ah, queue); - - mutex_unlock(&sc->lock); - - return ret; -} - -static const struct ieee80211_ops ath5k_hw_ops = { - .tx = ath5k_tx, - .start = ath5k_start, - .stop = ath5k_stop, - .add_interface = ath5k_add_interface, - .remove_interface = ath5k_remove_interface, - .config = ath5k_config, - .prepare_multicast = ath5k_prepare_multicast, - .configure_filter = ath5k_configure_filter, - .set_key = ath5k_set_key, - .get_stats = ath5k_get_stats, - .get_survey = ath5k_get_survey, - .conf_tx = ath5k_conf_tx, - .get_tsf = ath5k_get_tsf, - .set_tsf = ath5k_set_tsf, - .reset_tsf = ath5k_reset_tsf, - .bss_info_changed = ath5k_bss_info_changed, - .sw_scan_start = ath5k_sw_scan_start, - .sw_scan_complete = ath5k_sw_scan_complete, - .set_coverage_class = ath5k_set_coverage_class, -}; - -/********************\ -* PCI Initialization * -\********************/ - -static int __devinit -ath5k_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - void __iomem *mem; - struct ath5k_softc *sc; - struct ath_common *common; - struct ieee80211_hw *hw; - int ret; - u8 csz; - - /* - * L0s needs to be disabled on all ath5k cards. - * - * For distributions shipping with CONFIG_PCIEASPM (this will be enabled - * by default in the future in 2.6.36) this will also mean both L1 and - * L0s will be disabled when a pre 1.1 PCIe device is detected. We do - * know L1 works correctly even for all ath5k pre 1.1 PCIe devices - * though but cannot currently undue the effect of a blacklist, for - * details you can read pcie_aspm_sanity_check() and see how it adjusts - * the device link capability. - * - * It may be possible in the future to implement some PCI API to allow - * drivers to override blacklists for pre 1.1 PCIe but for now it is - * best to accept that both L0s and L1 will be disabled completely for - * distributions shipping with CONFIG_PCIEASPM rather than having this - * issue present. Motivation for adding this new API will be to help - * with power consumption for some of these devices. - */ - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); - - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, "can't enable device\n"); - goto err; - } - - /* XXX 32-bit addressing only */ - ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (ret) { - dev_err(&pdev->dev, "32-bit DMA not available\n"); - goto err_dis; - } - - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); - if (csz == 0) { - /* - * Linux 2.4.18 (at least) writes the cache line size - * register as a 16-bit wide register which is wrong. - * We must have this setup properly for rx buffer - * DMA to work so force a reasonable value here if it - * comes up zero. - */ - csz = L1_CACHE_BYTES >> 2; - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); - } - /* - * The default setting of latency timer yields poor results, - * set it to the value used by other systems. It may be worth - * tweaking this setting more. - */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* - * Disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state. - */ - pci_write_config_byte(pdev, 0x41, 0); - - ret = pci_request_region(pdev, 0, "ath5k"); - if (ret) { - dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); - goto err_dis; - } - - mem = pci_iomap(pdev, 0, 0); - if (!mem) { - dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; - ret = -EIO; - goto err_reg; - } - - /* - * Allocate hw (mac80211 main struct) - * and hw->priv (driver private data) - */ - hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); - if (hw == NULL) { - dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); - ret = -ENOMEM; - goto err_map; - } - - dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); - - /* Initialize driver private data */ - SET_IEEE80211_DEV(hw, &pdev->dev); - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM; - - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_MESH_POINT); - - hw->extra_tx_headroom = 2; - hw->channel_change_time = 5000; - sc = hw->priv; - sc->hw = hw; - sc->pdev = pdev; - - /* - * Mark the device as detached to avoid processing - * interrupts until setup is complete. - */ - __set_bit(ATH_STAT_INVALID, sc->status); - - sc->iobase = mem; /* So we can unmap it on detach */ - sc->opmode = NL80211_IFTYPE_STATION; - sc->bintval = 1000; - mutex_init(&sc->lock); - spin_lock_init(&sc->rxbuflock); - spin_lock_init(&sc->txbuflock); - spin_lock_init(&sc->block); - - /* Set private data */ - pci_set_drvdata(pdev, sc); - - /* Setup interrupt handler */ - ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); - if (ret) { - ATH5K_ERR(sc, "request_irq failed\n"); - goto err_free; - } - - /* If we passed the test, malloc an ath5k_hw struct */ - sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); - if (!sc->ah) { - ret = -ENOMEM; - ATH5K_ERR(sc, "out of memory\n"); - goto err_irq; - } - - sc->ah->ah_sc = sc; - sc->ah->ah_iobase = sc->iobase; - common = ath5k_hw_common(sc->ah); - common->ops = &ath5k_common_ops; - common->ah = sc->ah; - common->hw = hw; - common->cachelsz = csz << 2; /* convert to bytes */ - spin_lock_init(&common->cc_lock); - - /* Initialize device */ - ret = ath5k_hw_attach(sc); - if (ret) { - goto err_free_ah; - } - - /* set up multi-rate retry capabilities */ - if (sc->ah->ah_version == AR5K_AR5212) { - hw->max_rates = 4; - hw->max_rate_tries = 11; - } - - hw->vif_data_size = sizeof(struct ath5k_vif); - - /* Finish private driver data initialization */ - ret = ath5k_attach(pdev, hw); - if (ret) - goto err_ah; - - ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", - ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), - sc->ah->ah_mac_srev, - sc->ah->ah_phy_revision); - - if (!sc->ah->ah_single_chip) { - /* Single chip radio (!RF5111) */ - if (sc->ah->ah_radio_5ghz_revision && - !sc->ah->ah_radio_2ghz_revision) { - /* No 5GHz support -> report 2GHz radio */ - if (!test_bit(AR5K_MODE_11A, - sc->ah->ah_capabilities.cap_mode)) { - ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - /* No 2GHz support (5110 and some - * 5Ghz only cards) -> report 5Ghz radio */ - } else if (!test_bit(AR5K_MODE_11B, - sc->ah->ah_capabilities.cap_mode)) { - ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - /* Multiband radio */ - } else { - ATH5K_INFO(sc, "RF%s multiband radio found" - " (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - } - } - /* Multi chip radio (RF5111 - RF2111) -> - * report both 2GHz/5GHz radios */ - else if (sc->ah->ah_radio_5ghz_revision && - sc->ah->ah_radio_2ghz_revision){ - ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_2ghz_revision), - sc->ah->ah_radio_2ghz_revision); - } - } - - ath5k_debug_init_device(sc); - - /* ready to process interrupts */ - __clear_bit(ATH_STAT_INVALID, sc->status); - - return 0; -err_ah: - ath5k_hw_detach(sc->ah); -err_free_ah: - kfree(sc->ah); -err_irq: - free_irq(pdev->irq, sc); -err_free: - ieee80211_free_hw(hw); -err_map: - pci_iounmap(pdev, mem); -err_reg: - pci_release_region(pdev, 0); -err_dis: - pci_disable_device(pdev); -err: - return ret; -} - -static void __devexit -ath5k_pci_remove(struct pci_dev *pdev) -{ - struct ath5k_softc *sc = pci_get_drvdata(pdev); - - ath5k_debug_finish_device(sc); - ath5k_detach(pdev, sc->hw); - ath5k_hw_detach(sc->ah); - kfree(sc->ah); - free_irq(pdev->irq, sc); - pci_iounmap(pdev, sc->iobase); - pci_release_region(pdev, 0); - pci_disable_device(pdev); - ieee80211_free_hw(sc->hw); -} - -#ifdef CONFIG_PM_SLEEP -static int ath5k_pci_suspend(struct device *dev) -{ - struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); - - ath5k_led_off(sc); - return 0; -} - -static int ath5k_pci_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct ath5k_softc *sc = pci_get_drvdata(pdev); - - /* - * Suspend/Resume resets the PCI configuration space, so we have to - * re-disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state - */ - pci_write_config_byte(pdev, 0x41, 0); - - ath5k_led_enable(sc); - return 0; -} - -static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); -#define ATH5K_PM_OPS (&ath5k_pm_ops) -#else -#define ATH5K_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ - -static struct pci_driver ath5k_pci_driver = { - .name = KBUILD_MODNAME, - .id_table = ath5k_pci_id_table, - .probe = ath5k_pci_probe, - .remove = __devexit_p(ath5k_pci_remove), - .driver.pm = ATH5K_PM_OPS, -}; - -/* - * Module init/exit functions - */ -static int __init -init_ath5k_pci(void) -{ - int ret; - - ret = pci_register_driver(&ath5k_pci_driver); - if (ret) { - printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); - return ret; - } - - return 0; -} - -static void __exit -exit_ath5k_pci(void) -{ - pci_unregister_driver(&ath5k_pci_driver); -} - -module_init(init_ath5k_pci); -module_exit(exit_ath5k_pci); diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 9a79773cdc2a..6d511476e4d2 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -169,7 +169,10 @@ struct ath5k_vif { /* Software Carrier, keeps track of the driver state * associated with an instance of a device */ struct ath5k_softc { - struct pci_dev *pdev; /* for dma mapping */ + struct pci_dev *pdev; + struct device *dev; /* for dma mapping */ + int irq; + u16 devid; void __iomem *iobase; /* address of the device */ struct mutex lock; /* dev-level lock */ struct ieee80211_hw *hw; /* IEEE 802.11 common */ @@ -255,6 +258,8 @@ struct ath5k_softc { struct tasklet_struct ani_tasklet; /* ANI calibration */ struct delayed_work tx_complete_work; + + struct survey_info survey; /* collected survey info */ }; #define ath5k_hw_hasbssidmask(_ah) \ diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index beae519aa735..31cad80e9b01 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c @@ -49,7 +49,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) /* Set supported modes */ __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode); - __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode); } else { /* * XXX The tranceiver supports frequencies from 4920 to 6100GHz @@ -74,11 +73,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) /* Set supported modes */ __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode); - __set_bit(AR5K_MODE_11A_TURBO, - ah->ah_capabilities.cap_mode); - if (ah->ah_version == AR5K_AR5212) - __set_bit(AR5K_MODE_11G_TURBO, - ah->ah_capabilities.cap_mode); } /* Enable 802.11b if a 2GHz capable radio (2111/5112) is diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index acda56ee521b..d2f84d76bb07 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -60,7 +60,6 @@ #include "base.h" #include "debug.h" -#include "../debug.h" static unsigned int ath5k_debug; module_param_named(debug, ath5k_debug, uint, 0); @@ -312,6 +311,7 @@ static const struct { { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, + { ATH5K_DEBUG_DMA, "dma", "dma start/stop" }, { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, { ATH5K_DEBUG_DESC, "desc", "descriptor chains" }, { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, @@ -554,63 +554,63 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, len += snprintf(buf+len, sizeof(buf)-len, "RX\n---------------------\n"); - len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%u\t(%u%%)\n", st->rxerr_crc, st->rx_all_count > 0 ? st->rxerr_crc*100/st->rx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%u\t(%u%%)\n", st->rxerr_phy, st->rx_all_count > 0 ? st->rxerr_phy*100/st->rx_all_count : 0); for (i = 0; i < 32; i++) { if (st->rxerr_phy_code[i]) len += snprintf(buf+len, sizeof(buf)-len, - " phy_err[%d]\t%d\n", + " phy_err[%u]\t%u\n", i, st->rxerr_phy_code[i]); } - len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n", st->rxerr_fifo, st->rx_all_count > 0 ? st->rxerr_fifo*100/st->rx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%u\t(%u%%)\n", st->rxerr_decrypt, st->rx_all_count > 0 ? st->rxerr_decrypt*100/st->rx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%u\t(%u%%)\n", st->rxerr_mic, st->rx_all_count > 0 ? st->rxerr_mic*100/st->rx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "process\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "process\t%u\t(%u%%)\n", st->rxerr_proc, st->rx_all_count > 0 ? st->rxerr_proc*100/st->rx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%u\t(%u%%)\n", st->rxerr_jumbo, st->rx_all_count > 0 ? st->rxerr_jumbo*100/st->rx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n", + len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%u]\n", st->rx_all_count); - len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%d\n", + len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%u\n", st->rx_bytes_count); len += snprintf(buf+len, sizeof(buf)-len, "\nTX\n---------------------\n"); - len += snprintf(buf+len, sizeof(buf)-len, "retry\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "retry\t%u\t(%u%%)\n", st->txerr_retry, st->tx_all_count > 0 ? st->txerr_retry*100/st->tx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n", st->txerr_fifo, st->tx_all_count > 0 ? st->txerr_fifo*100/st->tx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "filter\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "filter\t%u\t(%u%%)\n", st->txerr_filt, st->tx_all_count > 0 ? st->txerr_filt*100/st->tx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n", + len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%u]\n", st->tx_all_count); - len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%d\n", + len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%u\n", st->tx_bytes_count); if (len > sizeof(buf)) @@ -719,7 +719,7 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf, st->mib_intr); len += snprintf(buf+len, sizeof(buf)-len, "beacon RSSI average:\t%d\n", - sc->ah->ah_beacon_rssi_avg.avg); + (int)ewma_read(&sc->ah->ah_beacon_rssi_avg)); #define CC_PRINT(_struct, _field) \ _struct._field, \ diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index 236edbd2507d..3e34428d5126 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h @@ -95,6 +95,7 @@ struct ath5k_dbg_info { * @ATH5K_DEBUG_DUMP_RX: print received skb content * @ATH5K_DEBUG_DUMP_TX: print transmit skb content * @ATH5K_DEBUG_DUMPBANDS: dump bands + * @ATH5K_DEBUG_DMA: debug dma start/stop * @ATH5K_DEBUG_TRACE: trace function calls * @ATH5K_DEBUG_DESC: descriptor setup * @ATH5K_DEBUG_ANY: show at any debug level @@ -118,6 +119,7 @@ enum ath5k_debug_level { ATH5K_DEBUG_DUMP_RX = 0x00000100, ATH5K_DEBUG_DUMP_TX = 0x00000200, ATH5K_DEBUG_DUMPBANDS = 0x00000400, + ATH5K_DEBUG_DMA = 0x00000800, ATH5K_DEBUG_ANI = 0x00002000, ATH5K_DEBUG_DESC = 0x00004000, ATH5K_DEBUG_ANY = 0xffffffff diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 43244382f213..16b44ff7dd3e 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -26,9 +26,10 @@ #include "debug.h" #include "base.h" -/* - * TX Descriptors - */ + +/************************\ +* TX Control descriptors * +\************************/ /* * Initialize the 2-word tx control descriptor on 5210/5211 @@ -335,6 +336,11 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, return 0; } + +/***********************\ +* TX Status descriptors * +\***********************/ + /* * Proccess the tx status descriptor on 5210/5211 */ @@ -476,9 +482,10 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, return 0; } -/* - * RX Descriptors - */ + +/****************\ +* RX Descriptors * +\****************/ /* * Initialize an rx control descriptor @@ -666,6 +673,11 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, return 0; } + +/********\ +* Attach * +\********/ + /* * Init function pointers inside ath5k_hw struct */ diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h index b2adb2a281c2..2509d0bf037d 100644 --- a/drivers/net/wireless/ath/ath5k/desc.h +++ b/drivers/net/wireless/ath/ath5k/desc.h @@ -26,7 +26,7 @@ struct ath5k_hw_rx_ctl { u32 rx_control_0; /* RX control word 0 */ u32 rx_control_1; /* RX control word 1 */ -} __packed; +} __packed __aligned(4); /* RX control word 1 fields/flags */ #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */ @@ -39,7 +39,7 @@ struct ath5k_hw_rx_ctl { struct ath5k_hw_rx_status { u32 rx_status_0; /* RX status word 0 */ u32 rx_status_1; /* RX status word 1 */ -} __packed; +} __packed __aligned(4); /* 5210/5211 */ /* RX status word 0 fields/flags */ @@ -129,7 +129,7 @@ enum ath5k_phy_error_code { struct ath5k_hw_2w_tx_ctl { u32 tx_control_0; /* TX control word 0 */ u32 tx_control_1; /* TX control word 1 */ -} __packed; +} __packed __aligned(4); /* TX control word 0 fields/flags */ #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ @@ -185,7 +185,7 @@ struct ath5k_hw_4w_tx_ctl { u32 tx_control_1; /* TX control word 1 */ u32 tx_control_2; /* TX control word 2 */ u32 tx_control_3; /* TX control word 3 */ -} __packed; +} __packed __aligned(4); /* TX control word 0 fields/flags */ #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ @@ -244,7 +244,7 @@ struct ath5k_hw_4w_tx_ctl { struct ath5k_hw_tx_status { u32 tx_status_0; /* TX status word 0 */ u32 tx_status_1; /* TX status word 1 */ -} __packed; +} __packed __aligned(4); /* TX status word 0 fields/flags */ #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 /* TX success */ @@ -282,7 +282,7 @@ struct ath5k_hw_tx_status { struct ath5k_hw_5210_tx_desc { struct ath5k_hw_2w_tx_ctl tx_ctl; struct ath5k_hw_tx_status tx_stat; -} __packed; +} __packed __aligned(4); /* * 5212 hardware TX descriptor @@ -290,7 +290,7 @@ struct ath5k_hw_5210_tx_desc { struct ath5k_hw_5212_tx_desc { struct ath5k_hw_4w_tx_ctl tx_ctl; struct ath5k_hw_tx_status tx_stat; -} __packed; +} __packed __aligned(4); /* * Common hardware RX descriptor @@ -298,7 +298,7 @@ struct ath5k_hw_5212_tx_desc { struct ath5k_hw_all_rx_desc { struct ath5k_hw_rx_ctl rx_ctl; struct ath5k_hw_rx_status rx_stat; -} __packed; +} __packed __aligned(4); /* * Atheros hardware DMA descriptor @@ -313,7 +313,7 @@ struct ath5k_desc { struct ath5k_hw_5212_tx_desc ds_tx5212; struct ath5k_hw_all_rx_desc ds_rx; } ud; -} __packed; +} __packed __aligned(4); #define AR5K_RXDESC_INTREQ 0x0020 diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 923c9ca5c4f0..0064be7ce5c9 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c @@ -37,6 +37,7 @@ #include "debug.h" #include "base.h" + /*********\ * Receive * \*********/ @@ -57,7 +58,7 @@ void ath5k_hw_start_rx_dma(struct ath5k_hw *ah) * * @ah: The &struct ath5k_hw */ -int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) +static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) { unsigned int i; @@ -69,7 +70,11 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) for (i = 1000; i > 0 && (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; i--) - udelay(10); + udelay(100); + + if (!i) + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + "failed to stop RX DMA !\n"); return i ? 0 : -EBUSY; } @@ -90,11 +95,18 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) * @ah: The &struct ath5k_hw * @phys_addr: RX descriptor address * - * XXX: Should we check if rx is enabled before setting rxdp ? + * Returns -EIO if rx is active */ -void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) +int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) { + if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + "tried to set RXDP while rx was active !\n"); + return -EIO; + } + ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); + return 0; } @@ -125,7 +137,7 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) /* Return if queue is declared inactive */ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return -EIO; + return -EINVAL; if (ah->ah_version == AR5K_AR5210) { tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); @@ -173,10 +185,10 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) * * Stop DMA transmit on a specific hw queue and drain queue so we don't * have any pending frames. Returns -EBUSY if we still have pending frames, - * -EINVAL if queue number is out of range. + * -EINVAL if queue number is out of range or inactive. * */ -int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) +static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) { unsigned int i = 40; u32 tx_queue, pending; @@ -185,7 +197,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) /* Return if queue is declared inactive */ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return -EIO; + return -EINVAL; if (ah->ah_version == AR5K_AR5210) { tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); @@ -211,12 +223,31 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); ath5k_hw_reg_read(ah, AR5K_CR); } else { + + /* + * Enable DCU early termination to quickly + * flush any pending frames from QCU + */ + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_DCU_EARLY); + /* * Schedule TX disable and wait until queue is empty */ AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue); - /*Check for pending frames*/ + /* Wait for queue to stop */ + for (i = 1000; i > 0 && + (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue) != 0); + i--) + udelay(100); + + if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + "queue %i didn't stop !\n", queue); + + /* Check for pending frames */ + i = 1000; do { pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)) & @@ -247,12 +278,12 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) AR5K_DIAG_SW_CHANNEL_IDLE_HIGH); /* Wait a while and disable mechanism */ - udelay(200); + udelay(400); AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1, AR5K_QUIET_CTL1_QT_EN); /* Re-check for pending frames */ - i = 40; + i = 100; do { pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)) & @@ -262,12 +293,27 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, AR5K_DIAG_SW_CHANNEL_IDLE_HIGH); + + if (pending) + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + "quiet mechanism didn't work q:%i !\n", + queue); } + /* + * Disable DCU early termination + */ + AR5K_REG_DISABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_DCU_EARLY); + /* Clear register */ ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); - if (pending) + if (pending) { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + "tx dma didn't stop (q:%i, frm:%i) !\n", + queue, pending); return -EBUSY; + } } /* TODO: Check for success on 5210 else return error */ @@ -275,6 +321,26 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) } /** + * ath5k_hw_stop_beacon_queue - Stop beacon queue + * + * @ah The &struct ath5k_hw + * @queue The queue number + * + * Returns -EIO if queue didn't stop + */ +int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) +{ + int ret; + ret = ath5k_hw_stop_tx_dma(ah, queue); + if (ret) { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + "beacon queue didn't stop !\n"); + return -EIO; + } + return 0; +} + +/** * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue * * @ah: The &struct ath5k_hw @@ -427,6 +493,7 @@ done: return ret; } + /*******************\ * Interrupt masking * \*******************/ @@ -688,3 +755,92 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) return old_mask; } + +/********************\ + Init/Stop functions +\********************/ + +/** + * ath5k_hw_dma_init - Initialize DMA unit + * + * @ah: The &struct ath5k_hw + * + * Set DMA size and pre-enable interrupts + * (driver handles tx/rx buffer setup and + * dma start/stop) + * + * XXX: Save/restore RXDP/TXDP registers ? + */ +void ath5k_hw_dma_init(struct ath5k_hw *ah) +{ + /* + * Set Rx/Tx DMA Configuration + * + * Set standard DMA size (128). Note that + * a DMA size of 512 causes rx overruns and tx errors + * on pci-e cards (tested on 5424 but since rx overruns + * also occur on 5416/5418 with madwifi we set 128 + * for all PCI-E cards to be safe). + * + * XXX: need to check 5210 for this + * TODO: Check out tx triger level, it's always 64 on dumps but I + * guess we can tweak it and see how it goes ;-) + */ + if (ah->ah_version != AR5K_AR5210) { + AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); + AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, + AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); + } + + /* Pre-enable interrupts on 5211/5212*/ + if (ah->ah_version != AR5K_AR5210) + ath5k_hw_set_imr(ah, ah->ah_imr); + +} + +/** + * ath5k_hw_dma_stop - stop DMA unit + * + * @ah: The &struct ath5k_hw + * + * Stop tx/rx DMA and interrupts. Returns + * -EBUSY if tx or rx dma failed to stop. + * + * XXX: Sometimes DMA unit hangs and we have + * stuck frames on tx queues, only a reset + * can fix that. + */ +int ath5k_hw_dma_stop(struct ath5k_hw *ah) +{ + int i, qmax, err; + err = 0; + + /* Disable interrupts */ + ath5k_hw_set_imr(ah, 0); + + /* Stop rx dma */ + err = ath5k_hw_stop_rx_dma(ah); + if (err) + return err; + + /* Clear any pending interrupts + * and disable tx dma */ + if (ah->ah_version != AR5K_AR5210) { + ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); + qmax = AR5K_NUM_TX_QUEUES; + } else { + /* PISR/SISR Not available on 5210 */ + ath5k_hw_reg_read(ah, AR5K_ISR); + qmax = AR5K_NUM_TX_QUEUES_NOQCU; + } + + for (i = 0; i < qmax; i++) { + err = ath5k_hw_stop_tx_dma(ah, i); + /* -EINVAL -> queue inactive */ + if (err != -EINVAL) + return err; + } + + return err; +} diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 39722dd73e43..80e625608bac 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -28,45 +28,16 @@ #include "debug.h" #include "base.h" -/* - * Read from eeprom - */ -static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) -{ - u32 status, timeout; - - /* - * Initialize EEPROM access - */ - if (ah->ah_version == AR5K_AR5210) { - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); - (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); - } else { - ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); - AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, - AR5K_EEPROM_CMD_READ); - } - - for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { - status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); - if (status & AR5K_EEPROM_STAT_RDDONE) { - if (status & AR5K_EEPROM_STAT_RDERR) - return -EIO; - *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & - 0xffff); - return 0; - } - udelay(15); - } - return -ETIMEDOUT; -} +/******************\ +* Helper functions * +\******************/ /* * Translate binary channel representation in EEPROM to frequency */ static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, - unsigned int mode) + unsigned int mode) { u16 val; @@ -89,6 +60,11 @@ static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, return val; } + +/*********\ +* Parsers * +\*********/ + /* * Initialize eeprom & capabilities structs */ @@ -198,7 +174,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) * * XXX: Serdes values seem to be fixed so * no need to read them here, we write them - * during ath5k_hw_attach */ + * during ath5k_hw_init */ AR5K_EEPROM_READ(AR5K_EEPROM_PCIE_OFFSET, val); ee->ee_serdes = (val == AR5K_EEPROM_PCIE_SERDES_SECTION) ? true : false; @@ -647,6 +623,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) return 0; } + /* * Read power calibration for RF5111 chips * @@ -1514,6 +1491,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) return 0; } + /* * Read per channel calibration info from EEPROM * @@ -1607,15 +1585,6 @@ ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) return 0; } -void -ath5k_eeprom_detach(struct ath5k_hw *ah) -{ - u8 mode; - - for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) - ath5k_eeprom_free_pcal_info(ah, mode); -} - /* Read conformance test limits used for regulatory control */ static int ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) @@ -1757,6 +1726,44 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah) } /* + * Read the MAC address from eeprom + */ +int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) +{ + u8 mac_d[ETH_ALEN] = {}; + u32 total, offset; + u16 data; + int octet, ret; + + ret = ath5k_hw_nvram_read(ah, 0x20, &data); + if (ret) + return ret; + + for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { + ret = ath5k_hw_nvram_read(ah, offset, &data); + if (ret) + return ret; + + total += data; + mac_d[octet + 1] = data & 0xff; + mac_d[octet] = data >> 8; + octet += 2; + } + + if (!total || total == 3 * 0xffff) + return -EINVAL; + + memcpy(mac, mac_d, ETH_ALEN); + + return 0; +} + + +/***********************\ +* Init/Detach functions * +\***********************/ + +/* * Initialize eeprom data structure */ int @@ -1787,35 +1794,27 @@ ath5k_eeprom_init(struct ath5k_hw *ah) return 0; } -/* - * Read the MAC address from eeprom - */ -int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) +void +ath5k_eeprom_detach(struct ath5k_hw *ah) { - u8 mac_d[ETH_ALEN] = {}; - u32 total, offset; - u16 data; - int octet, ret; - - ret = ath5k_hw_eeprom_read(ah, 0x20, &data); - if (ret) - return ret; + u8 mode; - for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { - ret = ath5k_hw_eeprom_read(ah, offset, &data); - if (ret) - return ret; + for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) + ath5k_eeprom_free_pcal_info(ah, mode); +} - total += data; - mac_d[octet + 1] = data & 0xff; - mac_d[octet] = data >> 8; - octet += 2; +int +ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel) +{ + switch (channel->hw_value & CHANNEL_MODES) { + case CHANNEL_A: + case CHANNEL_XR: + return AR5K_EEPROM_MODE_11A; + case CHANNEL_G: + return AR5K_EEPROM_MODE_11G; + case CHANNEL_B: + return AR5K_EEPROM_MODE_11B; + default: + return -1; } - - if (!total || total == 3 * 0xffff) - return -EINVAL; - - memcpy(mac, mac_d, ETH_ALEN); - - return 0; } diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index c4a6d5f26af4..7c09e150dbdc 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -241,7 +241,7 @@ enum ath5k_eeprom_freq_bands{ #define AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz 6250 #define AR5K_EEPROM_READ(_o, _v) do { \ - ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \ + ret = ath5k_hw_nvram_read(ah, (_o), &(_v)); \ if (ret) \ return ret; \ } while (0) @@ -517,3 +517,5 @@ struct ath5k_eeprom_info { u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; }; +int +ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel); diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c index 8fa439308828..e49340d18df4 100644 --- a/drivers/net/wireless/ath/ath5k/initvals.c +++ b/drivers/net/wireless/ath/ath5k/initvals.c @@ -44,7 +44,7 @@ struct ath5k_ini { struct ath5k_ini_mode { u16 mode_register; - u32 mode_value[5]; + u32 mode_value[3]; }; /* Initial register settings for AR5210 */ @@ -391,76 +391,74 @@ static const struct ath5k_ini ar5211_ini[] = { */ static const struct ath5k_ini_mode ar5211_ini_mode[] = { { AR5K_TXCFG, - /* a aTurbo b g (OFDM) */ - { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } }, + /* A/XR B G */ + { 0x00000015, 0x0000001d, 0x00000015 } }, { AR5K_QUEUE_DFS_LOCAL_IFS(0), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(1), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(2), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(3), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(4), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(5), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(6), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(7), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(8), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(9), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_DCU_GBL_IFS_SLOT, - { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } }, + { 0x00000168, 0x000001b8, 0x00000168 } }, { AR5K_DCU_GBL_IFS_SIFS, - { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } }, + { 0x00000230, 0x000000b0, 0x00000230 } }, { AR5K_DCU_GBL_IFS_EIFS, - { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } }, + { 0x00000d98, 0x00001f48, 0x00000d98 } }, { AR5K_DCU_GBL_IFS_MISC, - { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } }, + { 0x0000a0e0, 0x00005880, 0x0000a0e0 } }, { AR5K_TIME_OUT, - { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } }, + { 0x04000400, 0x20003000, 0x04000400 } }, { AR5K_USEC_5211, - { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } }, - { AR5K_PHY_TURBO, - { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } }, + { 0x0e8d8fa7, 0x01608f95, 0x0e8d8fa7 } }, { AR5K_PHY(8), - { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } }, - { AR5K_PHY(9), - { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } }, - { AR5K_PHY(10), - { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } }, - { AR5K_PHY(13), - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY(14), - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } }, - { AR5K_PHY(17), - { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } }, - { AR5K_PHY(18), - { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } }, - { AR5K_PHY(20), - { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } }, + { 0x02020200, 0x02010200, 0x02020200 } }, + { AR5K_PHY_RF_CTL2, + { 0x00000e0e, 0x00000707, 0x00000e0e } }, + { AR5K_PHY_RF_CTL3, + { 0x0a020001, 0x05010000, 0x0a020001 } }, + { AR5K_PHY_RF_CTL4, + { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { AR5K_PHY_PA_CTL, + { 0x00000007, 0x0000000b, 0x0000000b } }, + { AR5K_PHY_SETTLING, + { 0x1372169c, 0x137216a8, 0x1372169c } }, + { AR5K_PHY_GAIN, + { 0x0018ba67, 0x0018ba69, 0x0018ba69 } }, + { AR5K_PHY_DESIRED_SIZE, + { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } }, { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } }, + { 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } }, { AR5K_PHY_AGCCOARSE, - { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } }, + { 0x31375d5e, 0x313a5d5e, 0x31375d5e } }, { AR5K_PHY_AGCCTL, - { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } }, + { 0x0000bd10, 0x0000bd38, 0x0000bd10 } }, { AR5K_PHY_NF, - { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, + { 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, { AR5K_PHY_RX_DELAY, - { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } }, + { 0x00002710, 0x0000157c, 0x00002710 } }, { AR5K_PHY(70), - { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } }, + { 0x00000190, 0x00000084, 0x00000190 } }, { AR5K_PHY_FRAME_CTL_5211, - { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } }, + { 0x6fe01020, 0x6fe00920, 0x6fe01020 } }, { AR5K_PHY_PCDAC_TXPOWER_BASE, - { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } }, + { 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } }, { AR5K_RF_BUFFER_CONTROL_4, - { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } }, + { 0x00000010, 0x00000010, 0x00000010 } }, }; /* Initial register settings for AR5212 */ @@ -677,89 +675,87 @@ static const struct ath5k_ini ar5212_ini_common_start[] = { /* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */ static const struct ath5k_ini_mode ar5212_ini_mode_start[] = { { AR5K_QUEUE_DFS_LOCAL_IFS(0), - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + /* A/XR B G */ + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(1), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(2), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(3), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(4), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(5), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(6), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(7), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(8), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(9), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_DCU_GBL_IFS_SIFS, - { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } }, + { 0x00000230, 0x000000b0, 0x00000160 } }, { AR5K_DCU_GBL_IFS_SLOT, - { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } }, + { 0x00000168, 0x000001b8, 0x0000018c } }, { AR5K_DCU_GBL_IFS_EIFS, - { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } }, + { 0x00000e60, 0x00001f1c, 0x00003e38 } }, { AR5K_DCU_GBL_IFS_MISC, - { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } }, + { 0x0000a0e0, 0x00005880, 0x0000b0e0 } }, { AR5K_TIME_OUT, - { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } }, - { AR5K_PHY_TURBO, - { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } }, + { 0x03e803e8, 0x04200420, 0x08400840 } }, { AR5K_PHY(8), - { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } }, + { 0x02020200, 0x02010200, 0x02020200 } }, { AR5K_PHY_RF_CTL2, - { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } }, + { 0x00000e0e, 0x00000707, 0x00000e0e } }, { AR5K_PHY_SETTLING, - { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } }, + { 0x1372161c, 0x13721722, 0x137216a2 } }, { AR5K_PHY_AGCCTL, - { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } }, + { 0x00009d10, 0x00009d18, 0x00009d18 } }, { AR5K_PHY_NF, - { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, + { 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, { AR5K_PHY_WEAK_OFDM_HIGH_THR, - { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } }, + { 0x409a4190, 0x409a4190, 0x409a4190 } }, { AR5K_PHY(70), - { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } }, + { 0x000001b8, 0x00000084, 0x00000108 } }, { AR5K_PHY_OFDM_SELFCORR, - { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } }, + { 0x10058a05, 0x10058a05, 0x10058a05 } }, { 0xa230, - { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } }, + { 0x00000000, 0x00000000, 0x00000108 } }, }; /* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */ static const struct ath5k_ini_mode rf5111_ini_mode_end[] = { { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, + /* A/XR B G */ + { 0x00008015, 0x00008015, 0x00008015 } }, { AR5K_USEC_5211, - { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } }, + { 0x128d8fa7, 0x04e00f95, 0x12e00fab } }, { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } }, + { 0x0a020001, 0x05010100, 0x0a020001 } }, { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, { AR5K_PHY_PA_CTL, - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, + { 0x00000007, 0x0000000b, 0x0000000b } }, { AR5K_PHY_GAIN, - { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } }, + { 0x0018da5a, 0x0018ca69, 0x0018ca69 } }, { AR5K_PHY_DESIRED_SIZE, - { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, + { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } }, + { 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e } }, { AR5K_PHY_AGCCOARSE, - { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } }, + { 0x3137665e, 0x3137665e, 0x3137665e } }, { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } }, + { 0x050cb081, 0x050cb081, 0x050cb080 } }, { AR5K_PHY_RX_DELAY, - { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } }, + { 0x00002710, 0x0000157c, 0x00002af8 } }, { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } }, + { 0xf7b81020, 0xf7b80d20, 0xf7b81020 } }, { AR5K_PHY_GAIN_2GHZ, - { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } }, + { 0x642c416a, 0x6440416a, 0x6440416a } }, { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, + { 0x1883800a, 0x1873800a, 0x1883800a } }, }; static const struct ath5k_ini rf5111_ini_common_end[] = { @@ -782,38 +778,38 @@ static const struct ath5k_ini rf5111_ini_common_end[] = { /* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */ static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, + /* A/XR B G */ + { 0x00008015, 0x00008015, 0x00008015 } }, { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, + { 0x128d93a7, 0x04e01395, 0x12e013ab } }, { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, + { 0x0a020001, 0x05020100, 0x0a020001 } }, { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, { AR5K_PHY_PA_CTL, - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, + { 0x00000007, 0x0000000b, 0x0000000b } }, { AR5K_PHY_GAIN, - { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } }, + { 0x0018da6d, 0x0018ca75, 0x0018ca75 } }, { AR5K_PHY_DESIRED_SIZE, - { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, + { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } }, + { 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e } }, { AR5K_PHY_AGCCOARSE, - { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } }, + { 0x3137665e, 0x3137665e, 0x3137665e } }, { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, + { 0x050cb081, 0x050cb081, 0x050cb081 } }, { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, + { 0x000007d0, 0x0000044c, 0x00000898 } }, { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } }, + { 0xf7b81020, 0xf7b80d10, 0xf7b81010 } }, { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } }, + { 0x00000000, 0x00000008, 0x00000008 } }, { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { 0xd6be6788, 0xd03e6788, 0xd03e6788 } }, { AR5K_PHY_GAIN_2GHZ, - { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } }, + { 0x642c0140, 0x6442c160, 0x6442c160 } }, { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, + { 0x1883800a, 0x1873800a, 0x1883800a } }, }; static const struct ath5k_ini rf5112_ini_common_end[] = { @@ -833,66 +829,66 @@ static const struct ath5k_ini rf5112_ini_common_end[] = { /* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */ static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, + /* A/XR B G */ + { 0x00000015, 0x00000015, 0x00000015 } }, { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, + { 0x128d93a7, 0x04e01395, 0x12e013ab } }, { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, + { 0x0a020001, 0x05020100, 0x0a020001 } }, { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, { AR5K_PHY_PA_CTL, - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, + { 0x00000007, 0x0000000b, 0x0000000b } }, { AR5K_PHY_GAIN, - { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } }, + { 0x0018fa61, 0x001a1a63, 0x001a1a63 } }, { AR5K_PHY_DESIRED_SIZE, - { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } }, + { 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da } }, { AR5K_PHY_SIG, - { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, + { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, { AR5K_PHY_AGCCOARSE, - { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } }, + { 0x3139605e, 0x3139605e, 0x3139605e } }, { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, + { 0x050cb081, 0x050cb081, 0x050cb081 } }, { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, + { 0x000007d0, 0x0000044c, 0x00000898 } }, { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, + { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } }, { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0x00000000, 0x00000000, 0x00000000 } }, { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { 0xd6be6788, 0xd03e6788, 0xd03e6788 } }, { AR5K_PHY_GAIN_2GHZ, - { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } }, + { 0x002ec1e0, 0x002ac120, 0x002ac120 } }, { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, + { 0x1883800a, 0x1863800a, 0x1883800a } }, { 0xa300, - { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } }, + { 0x18010000, 0x18010000, 0x18010000 } }, { 0xa304, - { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } }, + { 0x30032602, 0x30032602, 0x30032602 } }, { 0xa308, - { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } }, + { 0x48073e06, 0x48073e06, 0x48073e06 } }, { 0xa30c, - { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } }, + { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } }, { 0xa310, - { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } }, + { 0x641a600f, 0x641a600f, 0x641a600f } }, { 0xa314, - { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } }, + { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } }, { 0xa318, - { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } }, + { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } }, { 0xa31c, - { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } }, + { 0x90cf865b, 0x8ecf865b, 0x8ecf865b } }, { 0xa320, - { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } }, + { 0x9d4f970f, 0x9b4f970f, 0x9b4f970f } }, { 0xa324, - { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } }, + { 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f } }, { 0xa328, - { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } }, + { 0xb55faf1f, 0xb35faf1f, 0xb35faf1f } }, { 0xa32c, - { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } }, + { 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f } }, { 0xa330, - { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } }, + { 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f } }, { 0xa334, - { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } }, + { 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } }, }; static const struct ath5k_ini rf5413_ini_common_end[] = { @@ -972,38 +968,38 @@ static const struct ath5k_ini rf5413_ini_common_end[] = { /* XXX: a mode ? */ static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, + /* A/XR B G */ + { 0x00000015, 0x00000015, 0x00000015 } }, { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, + { 0x128d93a7, 0x04e01395, 0x12e013ab } }, { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 } }, + { 0x0a020001, 0x05020000, 0x0a020001 } }, { AR5K_PHY_RF_CTL4, - { 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 } }, + { 0x00000e00, 0x00000e00, 0x00000e00 } }, { AR5K_PHY_PA_CTL, - { 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a } }, + { 0x00000002, 0x0000000a, 0x0000000a } }, { AR5K_PHY_GAIN, - { 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 } }, + { 0x0018da6d, 0x001a6a64, 0x001a6a64 } }, { AR5K_PHY_DESIRED_SIZE, - { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da } }, + { 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da } }, { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e } }, + { 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e } }, { AR5K_PHY_AGCCOARSE, - { 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e } }, + { 0x3137665e, 0x3137665e, 0x3139605e } }, { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, + { 0x050cb081, 0x050cb081, 0x050cb081 } }, { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, + { 0x000007d0, 0x0000044c, 0x00000898 } }, { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, + { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } }, { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0x00000000, 0x00000000, 0x00000000 } }, { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { 0xd6be6788, 0xd03e6788, 0xd03e6788 } }, { AR5K_PHY_GAIN_2GHZ, - { 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 } }, + { 0x002c0140, 0x0042c140, 0x0042c140 } }, { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, + { 0x1883800a, 0x1863800a, 0x1883800a } }, }; static const struct ath5k_ini rf2413_ini_common_end[] = { @@ -1094,52 +1090,50 @@ static const struct ath5k_ini rf2413_ini_common_end[] = { /* XXX: a mode ? */ static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, + /* A/XR B G */ + { 0x00000015, 0x00000015, 0x00000015 } }, { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, - { AR5K_PHY_TURBO, - { 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 } }, + { 0x128d93a7, 0x04e01395, 0x12e013ab } }, { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, + { 0x0a020001, 0x05020100, 0x0a020001 } }, { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, { AR5K_PHY_PA_CTL, - { 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b } }, + { 0x00000003, 0x0000000b, 0x0000000b } }, { AR5K_PHY_SETTLING, - { 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 } }, + { 0x1372161c, 0x13721722, 0x13721422 } }, { AR5K_PHY_GAIN, - { 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 } }, + { 0x0018fa61, 0x00199a65, 0x00199a65 } }, { AR5K_PHY_DESIRED_SIZE, - { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } }, + { 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da } }, { AR5K_PHY_SIG, - { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, + { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, { AR5K_PHY_AGCCOARSE, - { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } }, + { 0x3139605e, 0x3139605e, 0x3139605e } }, { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, + { 0x050cb081, 0x050cb081, 0x050cb081 } }, { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, + { 0x000007d0, 0x0000044c, 0x00000898 } }, { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, + { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } }, { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0x00000000, 0x00000000, 0x00000000 } }, { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { 0xd6be6788, 0xd03e6788, 0xd03e6788 } }, { AR5K_PHY_GAIN_2GHZ, - { 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 } }, + { 0x00000140, 0x0052c140, 0x0052c140 } }, { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, + { 0x1883800a, 0x1863800a, 0x1883800a } }, { 0xa324, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, { 0xa328, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, { 0xa32c, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, { 0xa330, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, { 0xa334, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, }; static const struct ath5k_ini rf2425_ini_common_end[] = { @@ -1368,15 +1362,15 @@ static const struct ath5k_ini rf5112_ini_bbgain[] = { * Write initial register dump */ static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, - const struct ath5k_ini *ini_regs, bool change_channel) + const struct ath5k_ini *ini_regs, bool skip_pcu) { unsigned int i; /* Write initial registers */ for (i = 0; i < size; i++) { - /* On channel change there is - * no need to mess with PCU */ - if (change_channel && + /* Skip PCU registers if + * requested */ + if (skip_pcu && ini_regs[i].ini_register >= AR5K_PCU_MIN && ini_regs[i].ini_register <= AR5K_PCU_MAX) continue; @@ -1409,7 +1403,7 @@ static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, } -int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) +int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu) { /* * Write initial register settings @@ -1427,7 +1421,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) * Write initial settings common for all modes */ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start), - ar5212_ini_common_start, change_channel); + ar5212_ini_common_start, skip_pcu); /* Second set of mode-specific settings */ switch (ah->ah_radio) { @@ -1439,12 +1433,12 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_common_end), - rf5111_ini_common_end, change_channel); + rf5111_ini_common_end, skip_pcu); /* Baseband gain table */ ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain), - rf5111_ini_bbgain, change_channel); + rf5111_ini_bbgain, skip_pcu); break; case AR5K_RF5112: @@ -1455,11 +1449,11 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5112_ini_common_end), - rf5112_ini_common_end, change_channel); + rf5112_ini_common_end, skip_pcu); ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); + rf5112_ini_bbgain, skip_pcu); break; case AR5K_RF5413: @@ -1470,11 +1464,11 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5413_ini_common_end), - rf5413_ini_common_end, change_channel); + rf5413_ini_common_end, skip_pcu); ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); + rf5112_ini_bbgain, skip_pcu); break; case AR5K_RF2316: @@ -1486,7 +1480,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf2413_ini_common_end), - rf2413_ini_common_end, change_channel); + rf2413_ini_common_end, skip_pcu); /* Override settings from rf2413_ini_common_end */ if (ah->ah_radio == AR5K_RF2316) { @@ -1498,9 +1492,32 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); + rf5112_ini_bbgain, skip_pcu); break; case AR5K_RF2317: + + ath5k_hw_ini_mode_registers(ah, + ARRAY_SIZE(rf2413_ini_mode_end), + rf2413_ini_mode_end, mode); + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf2425_ini_common_end), + rf2425_ini_common_end, skip_pcu); + + /* Override settings from rf2413_ini_mode_end */ + ath5k_hw_reg_write(ah, 0x00180a65, AR5K_PHY_GAIN); + + /* Override settings from rf2413_ini_common_end */ + ath5k_hw_reg_write(ah, 0x00004000, AR5K_PHY_AGC); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TPC_RG5, + AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP, 0xa); + ath5k_hw_reg_write(ah, 0x800000a8, 0x8140); + ath5k_hw_reg_write(ah, 0x000000ff, 0x9958); + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf5112_ini_bbgain), + rf5112_ini_bbgain, skip_pcu); + break; case AR5K_RF2425: ath5k_hw_ini_mode_registers(ah, @@ -1509,11 +1526,11 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf2425_ini_common_end), - rf2425_ini_common_end, change_channel); + rf2425_ini_common_end, skip_pcu); ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); + rf5112_ini_bbgain, skip_pcu); break; default: return -EINVAL; @@ -1538,17 +1555,17 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) * Write initial settings common for all modes */ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini), - ar5211_ini, change_channel); + ar5211_ini, skip_pcu); /* AR5211 only comes with 5111 */ /* Baseband gain table */ ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain), - rf5111_ini_bbgain, change_channel); + rf5111_ini_bbgain, skip_pcu); /* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */ } else if (ah->ah_version == AR5K_AR5210) { ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini), - ar5210_ini, change_channel); + ar5210_ini, skip_pcu); } return 0; diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index 67aa52e9bf94..576edf2965dc 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -133,7 +133,7 @@ ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, led->led_dev.default_trigger = trigger; led->led_dev.brightness_set = ath5k_led_brightness_set; - err = led_classdev_register(&sc->pdev->dev, &led->led_dev); + err = led_classdev_register(sc->dev, &led->led_dev); if (err) { ATH5K_WARN(sc, "could not register LED %s\n", name); led->sc = NULL; @@ -161,11 +161,20 @@ int ath5k_init_leds(struct ath5k_softc *sc) { int ret = 0; struct ieee80211_hw *hw = sc->hw; +#ifndef CONFIG_ATHEROS_AR231X struct pci_dev *pdev = sc->pdev; +#endif char name[ATH5K_LED_MAX_NAME_LEN + 1]; const struct pci_device_id *match; + if (!sc->pdev) + return 0; + +#ifdef CONFIG_ATHEROS_AR231X + match = NULL; +#else match = pci_match_id(&ath5k_led_devices[0], pdev); +#endif if (match) { __set_bit(ATH_STAT_LEDSOFT, sc->status); sc->led_pin = ATH_PIN(match->driver_data); diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c new file mode 100644 index 000000000000..d76d68c99f72 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -0,0 +1,774 @@ +/*- + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * Copyright (c) 2004-2005 Atheros Communications, Inc. + * Copyright (c) 2006 Devicescape Software, Inc. + * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> + * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu> + * Copyright (c) 2010 Bruno Randolf <br1@einfach.org> + * + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * 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. + * + */ + +#include <asm/unaligned.h> + +#include "base.h" +#include "reg.h" + +extern int ath5k_modparam_nohwcrypt; + +/* functions used from base.c */ +void set_beacon_filter(struct ieee80211_hw *hw, bool enable); +bool ath_any_vif_assoc(struct ath5k_softc *sc); +int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ath5k_txq *txq); +int ath5k_init_hw(struct ath5k_softc *sc); +int ath5k_stop_hw(struct ath5k_softc *sc); +void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif); +void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, + struct ieee80211_vif *vif); +int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan); +void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); +int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +void ath5k_beacon_config(struct ath5k_softc *sc); +void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf); +void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf); + +/********************\ +* Mac80211 functions * +\********************/ + +static int +ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ath5k_softc *sc = hw->priv; + u16 qnum = skb_get_queue_mapping(skb); + + if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) { + dev_kfree_skb_any(skb); + return 0; + } + + return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]); +} + + +static int +ath5k_start(struct ieee80211_hw *hw) +{ + return ath5k_init_hw(hw->priv); +} + + +static void +ath5k_stop(struct ieee80211_hw *hw) +{ + ath5k_stop_hw(hw->priv); +} + + +static int +ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct ath5k_softc *sc = hw->priv; + int ret; + struct ath5k_vif *avf = (void *)vif->drv_priv; + + mutex_lock(&sc->lock); + + if ((vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_ADHOC) + && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) { + ret = -ELNRNG; + goto end; + } + + /* Don't allow other interfaces if one ad-hoc is configured. + * TODO: Fix the problems with ad-hoc and multiple other interfaces. + * We would need to operate the HW in ad-hoc mode to allow TSF updates + * for the IBSS, but this breaks with additional AP or STA interfaces + * at the moment. */ + if (sc->num_adhoc_vifs || + (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { + ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n"); + ret = -ELNRNG; + goto end; + } + + switch (vif->type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + avf->opmode = vif->type; + break; + default: + ret = -EOPNOTSUPP; + goto end; + } + + sc->nvifs++; + ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode); + + /* Assign the vap/adhoc to a beacon xmit slot. */ + if ((avf->opmode == NL80211_IFTYPE_AP) || + (avf->opmode == NL80211_IFTYPE_ADHOC) || + (avf->opmode == NL80211_IFTYPE_MESH_POINT)) { + int slot; + + WARN_ON(list_empty(&sc->bcbuf)); + avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf, + list); + list_del(&avf->bbuf->list); + + avf->bslot = 0; + for (slot = 0; slot < ATH_BCBUF; slot++) { + if (!sc->bslot[slot]) { + avf->bslot = slot; + break; + } + } + BUG_ON(sc->bslot[avf->bslot] != NULL); + sc->bslot[avf->bslot] = vif; + if (avf->opmode == NL80211_IFTYPE_AP) + sc->num_ap_vifs++; + else if (avf->opmode == NL80211_IFTYPE_ADHOC) + sc->num_adhoc_vifs++; + } + + /* Any MAC address is fine, all others are included through the + * filter. + */ + memcpy(&sc->lladdr, vif->addr, ETH_ALEN); + ath5k_hw_set_lladdr(sc->ah, vif->addr); + + memcpy(&avf->lladdr, vif->addr, ETH_ALEN); + + ath5k_mode_setup(sc, vif); + + ret = 0; +end: + mutex_unlock(&sc->lock); + return ret; +} + + +static void +ath5k_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ath5k_softc *sc = hw->priv; + struct ath5k_vif *avf = (void *)vif->drv_priv; + unsigned int i; + + mutex_lock(&sc->lock); + sc->nvifs--; + + if (avf->bbuf) { + ath5k_txbuf_free_skb(sc, avf->bbuf); + list_add_tail(&avf->bbuf->list, &sc->bcbuf); + for (i = 0; i < ATH_BCBUF; i++) { + if (sc->bslot[i] == vif) { + sc->bslot[i] = NULL; + break; + } + } + avf->bbuf = NULL; + } + if (avf->opmode == NL80211_IFTYPE_AP) + sc->num_ap_vifs--; + else if (avf->opmode == NL80211_IFTYPE_ADHOC) + sc->num_adhoc_vifs--; + + ath5k_update_bssid_mask_and_opmode(sc, NULL); + mutex_unlock(&sc->lock); +} + + +/* + * TODO: Phy disable/diversity etc + */ +static int +ath5k_config(struct ieee80211_hw *hw, u32 changed) +{ + struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + struct ieee80211_conf *conf = &hw->conf; + int ret = 0; + + mutex_lock(&sc->lock); + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + ret = ath5k_chan_set(sc, conf->channel); + if (ret < 0) + goto unlock; + } + + if ((changed & IEEE80211_CONF_CHANGE_POWER) && + (sc->power_level != conf->power_level)) { + sc->power_level = conf->power_level; + + /* Half dB steps */ + ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); + } + + /* TODO: + * 1) Move this on config_interface and handle each case + * separately eg. when we have only one STA vif, use + * AR5K_ANTMODE_SINGLE_AP + * + * 2) Allow the user to change antenna mode eg. when only + * one antenna is present + * + * 3) Allow the user to set default/tx antenna when possible + * + * 4) Default mode should handle 90% of the cases, together + * with fixed a/b and single AP modes we should be able to + * handle 99%. Sectored modes are extreme cases and i still + * haven't found a usage for them. If we decide to support them, + * then we must allow the user to set how many tx antennas we + * have available + */ + ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); + +unlock: + mutex_unlock(&sc->lock); + return ret; +} + + +static void +ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, u32 changes) +{ + struct ath5k_vif *avf = (void *)vif->drv_priv; + struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + struct ath_common *common = ath5k_hw_common(ah); + unsigned long flags; + + mutex_lock(&sc->lock); + + if (changes & BSS_CHANGED_BSSID) { + /* Cache for later use during resets */ + memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); + common->curaid = 0; + ath5k_hw_set_bssid(ah); + mmiowb(); + } + + if (changes & BSS_CHANGED_BEACON_INT) + sc->bintval = bss_conf->beacon_int; + + if (changes & BSS_CHANGED_ASSOC) { + avf->assoc = bss_conf->assoc; + if (bss_conf->assoc) + sc->assoc = bss_conf->assoc; + else + sc->assoc = ath_any_vif_assoc(sc); + + if (sc->opmode == NL80211_IFTYPE_STATION) + set_beacon_filter(hw, sc->assoc); + ath5k_hw_set_ledstate(sc->ah, sc->assoc ? + AR5K_LED_ASSOC : AR5K_LED_INIT); + if (bss_conf->assoc) { + ATH5K_DBG(sc, ATH5K_DEBUG_ANY, + "Bss Info ASSOC %d, bssid: %pM\n", + bss_conf->aid, common->curbssid); + common->curaid = bss_conf->aid; + ath5k_hw_set_bssid(ah); + /* Once ANI is available you would start it here */ + } + } + + if (changes & BSS_CHANGED_BEACON) { + spin_lock_irqsave(&sc->block, flags); + ath5k_beacon_update(hw, vif); + spin_unlock_irqrestore(&sc->block, flags); + } + + if (changes & BSS_CHANGED_BEACON_ENABLED) + sc->enable_beacon = bss_conf->enable_beacon; + + if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED | + BSS_CHANGED_BEACON_INT)) + ath5k_beacon_config(sc); + + mutex_unlock(&sc->lock); +} + + +static u64 +ath5k_prepare_multicast(struct ieee80211_hw *hw, + struct netdev_hw_addr_list *mc_list) +{ + u32 mfilt[2], val; + u8 pos; + struct netdev_hw_addr *ha; + + mfilt[0] = 0; + mfilt[1] = 1; + + netdev_hw_addr_list_for_each(ha, mc_list) { + /* calculate XOR of eight 6-bit values */ + val = get_unaligned_le32(ha->addr + 0); + pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; + val = get_unaligned_le32(ha->addr + 3); + pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; + pos &= 0x3f; + mfilt[pos / 32] |= (1 << (pos % 32)); + /* XXX: we might be able to just do this instead, + * but not sure, needs testing, if we do use this we'd + * neet to inform below to not reset the mcast */ + /* ath5k_hw_set_mcast_filterindex(ah, + * ha->addr[5]); */ + } + + return ((u64)(mfilt[1]) << 32) | mfilt[0]; +} + + +/* + * o always accept unicast, broadcast, and multicast traffic + * o multicast traffic for all BSSIDs will be enabled if mac80211 + * says it should be + * o maintain current state of phy ofdm or phy cck error reception. + * If the hardware detects any of these type of errors then + * ath5k_hw_get_rx_filter() will pass to us the respective + * hardware filters to be able to receive these type of frames. + * o probe request frames are accepted only when operating in + * hostap, adhoc, or monitor modes + * o enable promiscuous mode according to the interface state + * o accept beacons: + * - when operating in adhoc mode so the 802.11 layer creates + * node table entries for peers, + * - when operating in station mode for collecting rssi data when + * the station is otherwise quiet, or + * - when scanning + */ +static void +ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, + unsigned int *new_flags, u64 multicast) +{ +#define SUPPORTED_FIF_FLAGS \ + (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ + FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ + FIF_BCN_PRBRESP_PROMISC) + + struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + u32 mfilt[2], rfilt; + + mutex_lock(&sc->lock); + + mfilt[0] = multicast; + mfilt[1] = multicast >> 32; + + /* Only deal with supported flags */ + changed_flags &= SUPPORTED_FIF_FLAGS; + *new_flags &= SUPPORTED_FIF_FLAGS; + + /* If HW detects any phy or radar errors, leave those filters on. + * Also, always enable Unicast, Broadcasts and Multicast + * XXX: move unicast, bssid broadcasts and multicast to mac80211 */ + rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) | + (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST | + AR5K_RX_FILTER_MCAST); + + if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { + if (*new_flags & FIF_PROMISC_IN_BSS) + __set_bit(ATH_STAT_PROMISC, sc->status); + else + __clear_bit(ATH_STAT_PROMISC, sc->status); + } + + if (test_bit(ATH_STAT_PROMISC, sc->status)) + rfilt |= AR5K_RX_FILTER_PROM; + + /* Note, AR5K_RX_FILTER_MCAST is already enabled */ + if (*new_flags & FIF_ALLMULTI) { + mfilt[0] = ~0; + mfilt[1] = ~0; + } + + /* This is the best we can do */ + if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)) + rfilt |= AR5K_RX_FILTER_PHYERR; + + /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons + * and probes for any BSSID */ + if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1)) + rfilt |= AR5K_RX_FILTER_BEACON; + + /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not + * set we should only pass on control frames for this + * station. This needs testing. I believe right now this + * enables *all* control frames, which is OK.. but + * but we should see if we can improve on granularity */ + if (*new_flags & FIF_CONTROL) + rfilt |= AR5K_RX_FILTER_CONTROL; + + /* Additional settings per mode -- this is per ath5k */ + + /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */ + + switch (sc->opmode) { + case NL80211_IFTYPE_MESH_POINT: + rfilt |= AR5K_RX_FILTER_CONTROL | + AR5K_RX_FILTER_BEACON | + AR5K_RX_FILTER_PROBEREQ | + AR5K_RX_FILTER_PROM; + break; + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_ADHOC: + rfilt |= AR5K_RX_FILTER_PROBEREQ | + AR5K_RX_FILTER_BEACON; + break; + case NL80211_IFTYPE_STATION: + if (sc->assoc) + rfilt |= AR5K_RX_FILTER_BEACON; + default: + break; + } + + /* Set filters */ + ath5k_hw_set_rx_filter(ah, rfilt); + + /* Set multicast bits */ + ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); + /* Set the cached hw filter flags, this will later actually + * be set in HW */ + sc->filter_flags = rfilt; + + mutex_unlock(&sc->lock); +} + + +static int +ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + struct ath_common *common = ath5k_hw_common(ah); + int ret = 0; + + if (ath5k_modparam_nohwcrypt) + return -EOPNOTSUPP; + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + break; + case WLAN_CIPHER_SUITE_CCMP: + if (common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM) + break; + return -EOPNOTSUPP; + default: + WARN_ON(1); + return -EINVAL; + } + + mutex_lock(&sc->lock); + + switch (cmd) { + case SET_KEY: + ret = ath_key_config(common, vif, sta, key); + if (ret >= 0) { + key->hw_key_idx = ret; + /* push IV and Michael MIC generation to stack */ + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + if (key->cipher == WLAN_CIPHER_SUITE_TKIP) + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + if (key->cipher == WLAN_CIPHER_SUITE_CCMP) + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; + ret = 0; + } + break; + case DISABLE_KEY: + ath_key_delete(common, key); + break; + default: + ret = -EINVAL; + } + + mmiowb(); + mutex_unlock(&sc->lock); + return ret; +} + + +static void +ath5k_sw_scan_start(struct ieee80211_hw *hw) +{ + struct ath5k_softc *sc = hw->priv; + if (!sc->assoc) + ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN); +} + + +static void +ath5k_sw_scan_complete(struct ieee80211_hw *hw) +{ + struct ath5k_softc *sc = hw->priv; + ath5k_hw_set_ledstate(sc->ah, sc->assoc ? + AR5K_LED_ASSOC : AR5K_LED_INIT); +} + + +static int +ath5k_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct ath5k_softc *sc = hw->priv; + + /* Force update */ + ath5k_hw_update_mib_counters(sc->ah); + + stats->dot11ACKFailureCount = sc->stats.ack_fail; + stats->dot11RTSFailureCount = sc->stats.rts_fail; + stats->dot11RTSSuccessCount = sc->stats.rts_ok; + stats->dot11FCSErrorCount = sc->stats.fcs_error; + + return 0; +} + + +static int +ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + struct ath5k_txq_info qi; + int ret = 0; + + if (queue >= ah->ah_capabilities.cap_queues.q_tx_num) + return 0; + + mutex_lock(&sc->lock); + + ath5k_hw_get_tx_queueprops(ah, queue, &qi); + + qi.tqi_aifs = params->aifs; + qi.tqi_cw_min = params->cw_min; + qi.tqi_cw_max = params->cw_max; + qi.tqi_burst_time = params->txop; + + ATH5K_DBG(sc, ATH5K_DEBUG_ANY, + "Configure tx [queue %d], " + "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", + queue, params->aifs, params->cw_min, + params->cw_max, params->txop); + + if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) { + ATH5K_ERR(sc, + "Unable to update hardware queue %u!\n", queue); + ret = -EIO; + } else + ath5k_hw_reset_tx_queue(ah, queue); + + mutex_unlock(&sc->lock); + + return ret; +} + + +static u64 +ath5k_get_tsf(struct ieee80211_hw *hw) +{ + struct ath5k_softc *sc = hw->priv; + + return ath5k_hw_get_tsf64(sc->ah); +} + + +static void +ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) +{ + struct ath5k_softc *sc = hw->priv; + + ath5k_hw_set_tsf64(sc->ah, tsf); +} + + +static void +ath5k_reset_tsf(struct ieee80211_hw *hw) +{ + struct ath5k_softc *sc = hw->priv; + + /* + * in IBSS mode we need to update the beacon timers too. + * this will also reset the TSF if we call it with 0 + */ + if (sc->opmode == NL80211_IFTYPE_ADHOC) + ath5k_beacon_update_timers(sc, 0); + else + ath5k_hw_reset_tsf(sc->ah); +} + + +static int +ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) +{ + struct ath5k_softc *sc = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + struct ath_common *common = ath5k_hw_common(sc->ah); + struct ath_cycle_counters *cc = &common->cc_survey; + unsigned int div = common->clockrate * 1000; + + if (idx != 0) + return -ENOENT; + + spin_lock_bh(&common->cc_lock); + ath_hw_cycle_counters_update(common); + if (cc->cycles > 0) { + sc->survey.channel_time += cc->cycles / div; + sc->survey.channel_time_busy += cc->rx_busy / div; + sc->survey.channel_time_rx += cc->rx_frame / div; + sc->survey.channel_time_tx += cc->tx_frame / div; + } + memset(cc, 0, sizeof(*cc)); + spin_unlock_bh(&common->cc_lock); + + memcpy(survey, &sc->survey, sizeof(*survey)); + + survey->channel = conf->channel; + survey->noise = sc->ah->ah_noise_floor; + survey->filled = SURVEY_INFO_NOISE_DBM | + SURVEY_INFO_CHANNEL_TIME | + SURVEY_INFO_CHANNEL_TIME_BUSY | + SURVEY_INFO_CHANNEL_TIME_RX | + SURVEY_INFO_CHANNEL_TIME_TX; + + return 0; +} + + +/** + * ath5k_set_coverage_class - Set IEEE 802.11 coverage class + * + * @hw: struct ieee80211_hw pointer + * @coverage_class: IEEE 802.11 coverage class number + * + * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given + * coverage class. The values are persistent, they are restored after device + * reset. + */ +static void +ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) +{ + struct ath5k_softc *sc = hw->priv; + + mutex_lock(&sc->lock); + ath5k_hw_set_coverage_class(sc->ah, coverage_class); + mutex_unlock(&sc->lock); +} + + +static int +ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) +{ + struct ath5k_softc *sc = hw->priv; + + if (tx_ant == 1 && rx_ant == 1) + ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A); + else if (tx_ant == 2 && rx_ant == 2) + ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B); + else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) + ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT); + else + return -EINVAL; + return 0; +} + + +static int +ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) +{ + struct ath5k_softc *sc = hw->priv; + + switch (sc->ah->ah_ant_mode) { + case AR5K_ANTMODE_FIXED_A: + *tx_ant = 1; *rx_ant = 1; break; + case AR5K_ANTMODE_FIXED_B: + *tx_ant = 2; *rx_ant = 2; break; + case AR5K_ANTMODE_DEFAULT: + *tx_ant = 3; *rx_ant = 3; break; + } + return 0; +} + + +const struct ieee80211_ops ath5k_hw_ops = { + .tx = ath5k_tx, + .start = ath5k_start, + .stop = ath5k_stop, + .add_interface = ath5k_add_interface, + /* .change_interface = not implemented */ + .remove_interface = ath5k_remove_interface, + .config = ath5k_config, + .bss_info_changed = ath5k_bss_info_changed, + .prepare_multicast = ath5k_prepare_multicast, + .configure_filter = ath5k_configure_filter, + /* .set_tim = not implemented */ + .set_key = ath5k_set_key, + /* .update_tkip_key = not implemented */ + /* .hw_scan = not implemented */ + .sw_scan_start = ath5k_sw_scan_start, + .sw_scan_complete = ath5k_sw_scan_complete, + .get_stats = ath5k_get_stats, + /* .get_tkip_seq = not implemented */ + /* .set_frag_threshold = not implemented */ + /* .set_rts_threshold = not implemented */ + /* .sta_add = not implemented */ + /* .sta_remove = not implemented */ + /* .sta_notify = not implemented */ + .conf_tx = ath5k_conf_tx, + .get_tsf = ath5k_get_tsf, + .set_tsf = ath5k_set_tsf, + .reset_tsf = ath5k_reset_tsf, + /* .tx_last_beacon = not implemented */ + /* .ampdu_action = not needed */ + .get_survey = ath5k_get_survey, + .set_coverage_class = ath5k_set_coverage_class, + /* .rfkill_poll = not implemented */ + /* .flush = not implemented */ + /* .channel_switch = not implemented */ + /* .napi_poll = not implemented */ + .set_antenna = ath5k_set_antenna, + .get_antenna = ath5k_get_antenna, +}; diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c new file mode 100644 index 000000000000..7f8c5b0e9d2a --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/pci.c @@ -0,0 +1,327 @@ +/* + * 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. + */ + +#include <linux/nl80211.h> +#include <linux/pci.h> +#include <linux/pci-aspm.h> +#include "../ath.h" +#include "ath5k.h" +#include "debug.h" +#include "base.h" +#include "reg.h" + +/* Known PCI ids */ +static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { + { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ + { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ + { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ + { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */ + { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */ + { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */ + { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */ + { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */ + { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */ + { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ + { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ + { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ + { 0 } +}; +MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); + +/* return bus cachesize in 4B word units */ +static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz) +{ + struct ath5k_softc *sc = (struct ath5k_softc *) common->priv; + u8 u8tmp; + + pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, &u8tmp); + *csz = (int)u8tmp; + + /* + * This check was put in to avoid "unplesant" consequences if + * the bootrom has not fully initialized all PCI devices. + * Sometimes the cache line size register is not set + */ + + if (*csz == 0) + *csz = L1_CACHE_BYTES >> 2; /* Use the default size */ +} + +/* + * Read from eeprom + */ +bool ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data) +{ + struct ath5k_hw *ah = (struct ath5k_hw *) common->ah; + u32 status, timeout; + + /* + * Initialize EEPROM access + */ + if (ah->ah_version == AR5K_AR5210) { + AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); + (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); + } else { + ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); + AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, + AR5K_EEPROM_CMD_READ); + } + + for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { + status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); + if (status & AR5K_EEPROM_STAT_RDDONE) { + if (status & AR5K_EEPROM_STAT_RDERR) + return -EIO; + *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & + 0xffff); + return 0; + } + udelay(15); + } + + return -ETIMEDOUT; +} + +int ath5k_hw_read_srev(struct ath5k_hw *ah) +{ + ah->ah_mac_srev = ath5k_hw_reg_read(ah, AR5K_SREV); + return 0; +} + +/* Common ath_bus_opts structure */ +static const struct ath_bus_ops ath_pci_bus_ops = { + .ath_bus_type = ATH_PCI, + .read_cachesize = ath5k_pci_read_cachesize, + .eeprom_read = ath5k_pci_eeprom_read, +}; + +/********************\ +* PCI Initialization * +\********************/ + +static int __devinit +ath5k_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + void __iomem *mem; + struct ath5k_softc *sc; + struct ieee80211_hw *hw; + int ret; + u8 csz; + + /* + * L0s needs to be disabled on all ath5k cards. + * + * For distributions shipping with CONFIG_PCIEASPM (this will be enabled + * by default in the future in 2.6.36) this will also mean both L1 and + * L0s will be disabled when a pre 1.1 PCIe device is detected. We do + * know L1 works correctly even for all ath5k pre 1.1 PCIe devices + * though but cannot currently undue the effect of a blacklist, for + * details you can read pcie_aspm_sanity_check() and see how it adjusts + * the device link capability. + * + * It may be possible in the future to implement some PCI API to allow + * drivers to override blacklists for pre 1.1 PCIe but for now it is + * best to accept that both L0s and L1 will be disabled completely for + * distributions shipping with CONFIG_PCIEASPM rather than having this + * issue present. Motivation for adding this new API will be to help + * with power consumption for some of these devices. + */ + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); + + ret = pci_enable_device(pdev); + if (ret) { + dev_err(&pdev->dev, "can't enable device\n"); + goto err; + } + + /* XXX 32-bit addressing only */ + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, "32-bit DMA not available\n"); + goto err_dis; + } + + /* + * Cache line size is used to size and align various + * structures used to communicate with the hardware. + */ + pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); + if (csz == 0) { + /* + * Linux 2.4.18 (at least) writes the cache line size + * register as a 16-bit wide register which is wrong. + * We must have this setup properly for rx buffer + * DMA to work so force a reasonable value here if it + * comes up zero. + */ + csz = L1_CACHE_BYTES >> 2; + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); + } + /* + * The default setting of latency timer yields poor results, + * set it to the value used by other systems. It may be worth + * tweaking this setting more. + */ + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* + * Disable the RETRY_TIMEOUT register (0x41) to keep + * PCI Tx retries from interfering with C3 CPU state. + */ + pci_write_config_byte(pdev, 0x41, 0); + + ret = pci_request_region(pdev, 0, "ath5k"); + if (ret) { + dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); + goto err_dis; + } + + mem = pci_iomap(pdev, 0, 0); + if (!mem) { + dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; + ret = -EIO; + goto err_reg; + } + + /* + * Allocate hw (mac80211 main struct) + * and hw->priv (driver private data) + */ + hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); + if (hw == NULL) { + dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); + ret = -ENOMEM; + goto err_map; + } + + dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); + + sc = hw->priv; + sc->hw = hw; + sc->pdev = pdev; + sc->dev = &pdev->dev; + sc->irq = pdev->irq; + sc->devid = id->device; + sc->iobase = mem; /* So we can unmap it on detach */ + + /* Initialize */ + ret = ath5k_init_softc(sc, &ath_pci_bus_ops); + if (ret) + goto err_free; + + /* Set private data */ + pci_set_drvdata(pdev, hw); + + return 0; +err_free: + ieee80211_free_hw(hw); +err_map: + pci_iounmap(pdev, mem); +err_reg: + pci_release_region(pdev, 0); +err_dis: + pci_disable_device(pdev); +err: + return ret; +} + +static void __devexit +ath5k_pci_remove(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath5k_softc *sc = hw->priv; + + ath5k_deinit_softc(sc); + pci_iounmap(pdev, sc->iobase); + pci_release_region(pdev, 0); + pci_disable_device(pdev); + ieee80211_free_hw(hw); +} + +#ifdef CONFIG_PM_SLEEP +static int ath5k_pci_suspend(struct device *dev) +{ + struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); + + ath5k_led_off(sc); + return 0; +} + +static int ath5k_pci_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct ath5k_softc *sc = pci_get_drvdata(pdev); + + /* + * Suspend/Resume resets the PCI configuration space, so we have to + * re-disable the RETRY_TIMEOUT register (0x41) to keep + * PCI Tx retries from interfering with C3 CPU state + */ + pci_write_config_byte(pdev, 0x41, 0); + + ath5k_led_enable(sc); + return 0; +} + +static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); +#define ATH5K_PM_OPS (&ath5k_pm_ops) +#else +#define ATH5K_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ + +static struct pci_driver ath5k_pci_driver = { + .name = KBUILD_MODNAME, + .id_table = ath5k_pci_id_table, + .probe = ath5k_pci_probe, + .remove = __devexit_p(ath5k_pci_remove), + .driver.pm = ATH5K_PM_OPS, +}; + +/* + * Module init/exit functions + */ +static int __init +init_ath5k_pci(void) +{ + int ret; + + ret = pci_register_driver(&ath5k_pci_driver); + if (ret) { + printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); + return ret; + } + + return 0; +} + +static void __exit +exit_ath5k_pci(void) +{ + pci_unregister_driver(&ath5k_pci_driver); +} + +module_init(init_ath5k_pci); +module_exit(exit_ath5k_pci); diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 074b4c644399..e5f2b96a4c63 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -31,87 +31,163 @@ #include "debug.h" #include "base.h" +/* + * AR5212+ can use higher rates for ack transmition + * based on current tx rate instead of the base rate. + * It does this to better utilize channel usage. + * This is a mapping between G rates (that cover both + * CCK and OFDM) and ack rates that we use when setting + * rate -> duration table. This mapping is hw-based so + * don't change anything. + * + * To enable this functionality we must set + * ah->ah_ack_bitrate_high to true else base rate is + * used (1Mb for CCK, 6Mb for OFDM). + */ +static const unsigned int ack_rates_high[] = +/* Tx -> ACK */ +/* 1Mb -> 1Mb */ { 0, +/* 2MB -> 2Mb */ 1, +/* 5.5Mb -> 2Mb */ 1, +/* 11Mb -> 2Mb */ 1, +/* 6Mb -> 6Mb */ 4, +/* 9Mb -> 6Mb */ 4, +/* 12Mb -> 12Mb */ 6, +/* 18Mb -> 12Mb */ 6, +/* 24Mb -> 24Mb */ 8, +/* 36Mb -> 24Mb */ 8, +/* 48Mb -> 24Mb */ 8, +/* 54Mb -> 24Mb */ 8 }; + /*******************\ -* Generic functions * +* Helper functions * \*******************/ /** - * ath5k_hw_set_opmode - Set PCU operating mode + * ath5k_hw_get_frame_duration - Get tx time of a frame * * @ah: The &struct ath5k_hw - * @op_mode: &enum nl80211_iftype operating mode + * @len: Frame's length in bytes + * @rate: The @struct ieee80211_rate * - * Initialize PCU for the various operating modes (AP/STA etc) + * Calculate tx duration of a frame given it's rate and length + * It extends ieee80211_generic_frame_duration for non standard + * bwmodes. */ -int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) +int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, + int len, struct ieee80211_rate *rate) { - struct ath_common *common = ath5k_hw_common(ah); - u32 pcu_reg, beacon_reg, low_id, high_id; + struct ath5k_softc *sc = ah->ah_sc; + int sifs, preamble, plcp_bits, sym_time; + int bitrate, bits, symbols, symbol_bits; + int dur; + + /* Fallback */ + if (!ah->ah_bwmode) { + dur = ieee80211_generic_frame_duration(sc->hw, + NULL, len, rate); + return dur; + } - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); + bitrate = rate->bitrate; + preamble = AR5K_INIT_OFDM_PREAMPLE_TIME; + plcp_bits = AR5K_INIT_OFDM_PLCP_BITS; + sym_time = AR5K_INIT_OFDM_SYMBOL_TIME; - /* Preserve rest settings */ - pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; - pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP - | AR5K_STA_ID1_KEYSRCH_MODE - | (ah->ah_version == AR5K_AR5210 ? - (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); + switch (ah->ah_bwmode) { + case AR5K_BWMODE_40MHZ: + sifs = AR5K_INIT_SIFS_TURBO; + preamble = AR5K_INIT_OFDM_PREAMBLE_TIME_MIN; + break; + case AR5K_BWMODE_10MHZ: + sifs = AR5K_INIT_SIFS_HALF_RATE; + preamble *= 2; + sym_time *= 2; + break; + case AR5K_BWMODE_5MHZ: + sifs = AR5K_INIT_SIFS_QUARTER_RATE; + preamble *= 4; + sym_time *= 4; + break; + default: + sifs = AR5K_INIT_SIFS_DEFAULT_BG; + break; + } - beacon_reg = 0; + bits = plcp_bits + (len << 3); + /* Bit rate is in 100Kbits */ + symbol_bits = bitrate * sym_time; + symbols = DIV_ROUND_UP(bits * 10, symbol_bits); - switch (op_mode) { - case NL80211_IFTYPE_ADHOC: - pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; - beacon_reg |= AR5K_BCR_ADHOC; - if (ah->ah_version == AR5K_AR5210) - pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; - else - AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); - break; + dur = sifs + preamble + (sym_time * symbols); - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; - beacon_reg |= AR5K_BCR_AP; - if (ah->ah_version == AR5K_AR5210) - pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; - else - AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); - break; + return dur; +} - case NL80211_IFTYPE_STATION: - pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE - | (ah->ah_version == AR5K_AR5210 ? - AR5K_STA_ID1_PWR_SV : 0); - case NL80211_IFTYPE_MONITOR: - pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE - | (ah->ah_version == AR5K_AR5210 ? - AR5K_STA_ID1_NO_PSPOLL : 0); - break; +/** + * ath5k_hw_get_default_slottime - Get the default slot time for current mode + * + * @ah: The &struct ath5k_hw + */ +unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) +{ + struct ieee80211_channel *channel = ah->ah_current_channel; + unsigned int slot_time; + switch (ah->ah_bwmode) { + case AR5K_BWMODE_40MHZ: + slot_time = AR5K_INIT_SLOT_TIME_TURBO; + break; + case AR5K_BWMODE_10MHZ: + slot_time = AR5K_INIT_SLOT_TIME_HALF_RATE; + break; + case AR5K_BWMODE_5MHZ: + slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE; + break; + case AR5K_BWMODE_DEFAULT: + slot_time = AR5K_INIT_SLOT_TIME_DEFAULT; default: - return -EINVAL; + if (channel->hw_value & CHANNEL_CCK) + slot_time = AR5K_INIT_SLOT_TIME_B; + break; } - /* - * Set PCU registers - */ - low_id = get_unaligned_le32(common->macaddr); - high_id = get_unaligned_le16(common->macaddr + 4); - ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); - ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); + return slot_time; +} - /* - * Set Beacon Control Register on 5210 - */ - if (ah->ah_version == AR5K_AR5210) - ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); +/** + * ath5k_hw_get_default_sifs - Get the default SIFS for current mode + * + * @ah: The &struct ath5k_hw + */ +unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) +{ + struct ieee80211_channel *channel = ah->ah_current_channel; + unsigned int sifs; - return 0; + switch (ah->ah_bwmode) { + case AR5K_BWMODE_40MHZ: + sifs = AR5K_INIT_SIFS_TURBO; + break; + case AR5K_BWMODE_10MHZ: + sifs = AR5K_INIT_SIFS_HALF_RATE; + break; + case AR5K_BWMODE_5MHZ: + sifs = AR5K_INIT_SIFS_QUARTER_RATE; + break; + case AR5K_BWMODE_DEFAULT: + sifs = AR5K_INIT_SIFS_DEFAULT_BG; + default: + if (channel->hw_value & CHANNEL_5GHZ) + sifs = AR5K_INIT_SIFS_DEFAULT_A; + break; + } + + return sifs; } /** - * ath5k_hw_update - Update MIB counters (mac layer statistics) + * ath5k_hw_update_mib_counters - Update MIB counters (mac layer statistics) * * @ah: The &struct ath5k_hw * @@ -133,36 +209,88 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); } + +/******************\ +* ACK/CTS Timeouts * +\******************/ + /** - * ath5k_hw_set_ack_bitrate - set bitrate for ACKs + * ath5k_hw_write_rate_duration - fill rate code to duration table * - * @ah: The &struct ath5k_hw - * @high: Flag to determine if we want to use high transmission rate - * for ACKs or not + * @ah: the &struct ath5k_hw + * @mode: one of enum ath5k_driver_mode + * + * Write the rate code to duration table upon hw reset. This is a helper for + * ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on + * the hardware, based on current mode, for each rate. The rates which are + * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have + * different rate code so we write their value twice (one for long preamble + * and one for short). + * + * Note: Band doesn't matter here, if we set the values for OFDM it works + * on both a and g modes. So all we have to do is set values for all g rates + * that include all OFDM and CCK rates. * - * If high flag is set, we tell hw to use a set of control rates based on - * the current transmission rate (check out control_rates array inside reset.c). - * If not hw just uses the lowest rate available for the current modulation - * scheme being used (1Mbit for CCK and 6Mbits for OFDM). */ -void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) +static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) { - if (ah->ah_version != AR5K_AR5212) - return; - else { - u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; - if (high) - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); + struct ath5k_softc *sc = ah->ah_sc; + struct ieee80211_rate *rate; + unsigned int i; + /* 802.11g covers both OFDM and CCK */ + u8 band = IEEE80211_BAND_2GHZ; + + /* Write rate duration table */ + for (i = 0; i < sc->sbands[band].n_bitrates; i++) { + u32 reg; + u16 tx_time; + + if (ah->ah_ack_bitrate_high) + rate = &sc->sbands[band].bitrates[ack_rates_high[i]]; + /* CCK -> 1Mb */ + else if (i < 4) + rate = &sc->sbands[band].bitrates[0]; + /* OFDM -> 6Mb */ else - AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); + rate = &sc->sbands[band].bitrates[4]; + + /* Set ACK timeout */ + reg = AR5K_RATE_DUR(rate->hw_value); + + /* An ACK frame consists of 10 bytes. If you add the FCS, + * which ieee80211_generic_frame_duration() adds, + * its 14 bytes. Note we use the control rate and not the + * actual rate for this rate. See mac80211 tx.c + * ieee80211_duration() for a brief description of + * what rate we should choose to TX ACKs. */ + tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); + + tx_time = le16_to_cpu(tx_time); + + ath5k_hw_reg_write(ah, tx_time, reg); + + if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) + continue; + + /* + * We're not distinguishing short preamble here, + * This is true, all we'll get is a longer value here + * which is not necessarilly bad. We could use + * export ieee80211_frame_duration() but that needs to be + * fixed first to be properly used by mac802111 drivers: + * + * - remove erp stuff and let the routine figure ofdm + * erp rates + * - remove passing argument ieee80211_local as + * drivers don't have access to it + * - move drivers using ieee80211_generic_frame_duration() + * to this + */ + ath5k_hw_reg_write(ah, tx_time, + reg + (AR5K_SET_SHORT_PREAMBLE << 2)); } } - -/******************\ -* ACK/CTS Timeouts * -\******************/ - /** * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU * @@ -199,88 +327,10 @@ static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) return 0; } -/** - * ath5k_hw_htoclock - Translate usec to hw clock units - * - * @ah: The &struct ath5k_hw - * @usec: value in microseconds - */ -unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) -{ - struct ath_common *common = ath5k_hw_common(ah); - return usec * common->clockrate; -} - -/** - * ath5k_hw_clocktoh - Translate hw clock units to usec - * @clock: value in hw clock units - */ -unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) -{ - struct ath_common *common = ath5k_hw_common(ah); - return clock / common->clockrate; -} - -/** - * ath5k_hw_set_clockrate - Set common->clockrate for the current channel - * - * @ah: The &struct ath5k_hw - */ -void ath5k_hw_set_clockrate(struct ath5k_hw *ah) -{ - struct ieee80211_channel *channel = ah->ah_current_channel; - struct ath_common *common = ath5k_hw_common(ah); - int clock; - - if (channel->hw_value & CHANNEL_5GHZ) - clock = 40; /* 802.11a */ - else if (channel->hw_value & CHANNEL_CCK) - clock = 22; /* 802.11b */ - else - clock = 44; /* 802.11g */ - - /* Clock rate in turbo modes is twice the normal rate */ - if (channel->hw_value & CHANNEL_TURBO) - clock *= 2; - - common->clockrate = clock; -} - -/** - * ath5k_hw_get_default_slottime - Get the default slot time for current mode - * - * @ah: The &struct ath5k_hw - */ -static unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) -{ - struct ieee80211_channel *channel = ah->ah_current_channel; - - if (channel->hw_value & CHANNEL_TURBO) - return 6; /* both turbo modes */ - - if (channel->hw_value & CHANNEL_CCK) - return 20; /* 802.11b */ - - return 9; /* 802.11 a/g */ -} - -/** - * ath5k_hw_get_default_sifs - Get the default SIFS for current mode - * - * @ah: The &struct ath5k_hw - */ -static unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) -{ - struct ieee80211_channel *channel = ah->ah_current_channel; - - if (channel->hw_value & CHANNEL_TURBO) - return 8; /* both turbo modes */ - if (channel->hw_value & CHANNEL_5GHZ) - return 16; /* 802.11a */ - - return 10; /* 802.11 b/g */ -} +/*******************\ +* RX filter Control * +\*******************/ /** * ath5k_hw_set_lladdr - Set station id @@ -362,39 +412,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) ath_hw_setbssidmask(common); } -/************\ -* RX Control * -\************/ - -/** - * ath5k_hw_start_rx_pcu - Start RX engine - * - * @ah: The &struct ath5k_hw - * - * Starts RX engine on PCU so that hw can process RXed frames - * (ACK etc). - * - * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma - */ -void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) -{ - AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); -} - -/** - * at5k_hw_stop_rx_pcu - Stop RX engine - * - * @ah: The &struct ath5k_hw - * - * Stops RX engine on PCU - * - * TODO: Detach ANI here - */ -void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) -{ - AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); -} - /* * Set multicast filter */ @@ -746,7 +763,7 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval) * @ah: The &struct ath5k_hw * @coverage_class: IEEE 802.11 coverage class number * - * Sets slot time, ACK timeout and CTS timeout for given coverage class. + * Sets IFS intervals and ACK/CTS timeouts for given coverage class. */ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) { @@ -755,9 +772,175 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time; int cts_timeout = ack_timeout; - ath5k_hw_set_slot_time(ah, slot_time); + ath5k_hw_set_ifs_intervals(ah, slot_time); ath5k_hw_set_ack_timeout(ah, ack_timeout); ath5k_hw_set_cts_timeout(ah, cts_timeout); ah->ah_coverage_class = coverage_class; } + +/***************************\ +* Init/Start/Stop functions * +\***************************/ + +/** + * ath5k_hw_start_rx_pcu - Start RX engine + * + * @ah: The &struct ath5k_hw + * + * Starts RX engine on PCU so that hw can process RXed frames + * (ACK etc). + * + * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma + */ +void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) +{ + AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); +} + +/** + * at5k_hw_stop_rx_pcu - Stop RX engine + * + * @ah: The &struct ath5k_hw + * + * Stops RX engine on PCU + */ +void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) +{ + AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); +} + +/** + * ath5k_hw_set_opmode - Set PCU operating mode + * + * @ah: The &struct ath5k_hw + * @op_mode: &enum nl80211_iftype operating mode + * + * Configure PCU for the various operating modes (AP/STA etc) + */ +int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) +{ + struct ath_common *common = ath5k_hw_common(ah); + u32 pcu_reg, beacon_reg, low_id, high_id; + + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); + + /* Preserve rest settings */ + pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; + pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP + | AR5K_STA_ID1_KEYSRCH_MODE + | (ah->ah_version == AR5K_AR5210 ? + (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); + + beacon_reg = 0; + + switch (op_mode) { + case NL80211_IFTYPE_ADHOC: + pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; + beacon_reg |= AR5K_BCR_ADHOC; + if (ah->ah_version == AR5K_AR5210) + pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; + else + AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); + break; + + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; + beacon_reg |= AR5K_BCR_AP; + if (ah->ah_version == AR5K_AR5210) + pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; + else + AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); + break; + + case NL80211_IFTYPE_STATION: + pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE + | (ah->ah_version == AR5K_AR5210 ? + AR5K_STA_ID1_PWR_SV : 0); + case NL80211_IFTYPE_MONITOR: + pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE + | (ah->ah_version == AR5K_AR5210 ? + AR5K_STA_ID1_NO_PSPOLL : 0); + break; + + default: + return -EINVAL; + } + + /* + * Set PCU registers + */ + low_id = get_unaligned_le32(common->macaddr); + high_id = get_unaligned_le16(common->macaddr + 4); + ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); + ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); + + /* + * Set Beacon Control Register on 5210 + */ + if (ah->ah_version == AR5K_AR5210) + ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); + + return 0; +} + +void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, + u8 mode) +{ + /* Set bssid and bssid mask */ + ath5k_hw_set_bssid(ah); + + /* Set PCU config */ + ath5k_hw_set_opmode(ah, op_mode); + + /* Write rate duration table only on AR5212 and if + * virtual interface has already been brought up + * XXX: rethink this after new mode changes to + * mac80211 are integrated */ + if (ah->ah_version == AR5K_AR5212 && + ah->ah_sc->nvifs) + ath5k_hw_write_rate_duration(ah); + + /* Set RSSI/BRSSI thresholds + * + * Note: If we decide to set this value + * dynamicaly, have in mind that when AR5K_RSSI_THR + * register is read it might return 0x40 if we haven't + * wrote anything to it plus BMISS RSSI threshold is zeroed. + * So doing a save/restore procedure here isn't the right + * choice. Instead store it on ath5k_hw */ + ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | + AR5K_TUNE_BMISS_THRES << + AR5K_RSSI_THR_BMISS_S), + AR5K_RSSI_THR); + + /* MIC QoS support */ + if (ah->ah_mac_srev >= AR5K_SREV_AR2413) { + ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL); + ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL); + } + + /* QoS NOACK Policy */ + if (ah->ah_version == AR5K_AR5212) { + ath5k_hw_reg_write(ah, + AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) | + AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) | + AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET), + AR5K_QOS_NOACK); + } + + /* Restore slot time and ACK timeouts */ + if (ah->ah_coverage_class > 0) + ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); + + /* Set ACK bitrate mode (see ack_rates_high) */ + if (ah->ah_version == AR5K_AR5212) { + u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; + if (ah->ah_ack_bitrate_high) + AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); + else + AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); + } + return; +} diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 219367884e64..78c26fdccad1 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -29,6 +29,95 @@ #include "rfbuffer.h" #include "rfgain.h" + +/******************\ +* Helper functions * +\******************/ + +/* + * Get the PHY Chip revision + */ +u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) +{ + unsigned int i; + u32 srev; + u16 ret; + + /* + * Set the radio chip access register + */ + switch (chan) { + case CHANNEL_2GHZ: + ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); + break; + case CHANNEL_5GHZ: + ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); + break; + default: + return 0; + } + + mdelay(2); + + /* ...wait until PHY is ready and read the selected radio revision */ + ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); + + for (i = 0; i < 8; i++) + ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); + + if (ah->ah_version == AR5K_AR5210) { + srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; + ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; + } else { + srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; + ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | + ((srev & 0x0f) << 4), 8); + } + + /* Reset to the 5GHz mode */ + ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); + + return ret; +} + +/* + * Check if a channel is supported + */ +bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) +{ + /* Check if the channel is in our supported range */ + if (flags & CHANNEL_2GHZ) { + if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && + (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) + return true; + } else if (flags & CHANNEL_5GHZ) + if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && + (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) + return true; + + return false; +} + +bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + u8 refclk_freq; + + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) + refclk_freq = 40; + else + refclk_freq = 32; + + if ((channel->center_freq % refclk_freq != 0) && + ((channel->center_freq % refclk_freq < 10) || + (channel->center_freq % refclk_freq > 22))) + return true; + else + return false; +} + /* * Used to modify RF Banks before writing them to AR5K_RF_BUFFER */ @@ -110,6 +199,90 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, return data; } +/** + * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 + * + * @ah: the &struct ath5k_hw + * @channel: the currently set channel upon reset + * + * Write the delta slope coefficient (used on pilot tracking ?) for OFDM + * operation on the AR5212 upon reset. This is a helper for ath5k_hw_phy_init. + * + * Since delta slope is floating point we split it on its exponent and + * mantissa and provide these values on hw. + * + * For more infos i think this patent is related + * http://www.freepatentsonline.com/7184495.html + */ +static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + /* Get exponent and mantissa and set it */ + u32 coef_scaled, coef_exp, coef_man, + ds_coef_exp, ds_coef_man, clock; + + BUG_ON(!(ah->ah_version == AR5K_AR5212) || + !(channel->hw_value & CHANNEL_OFDM)); + + /* Get coefficient + * ALGO: coef = (5 * clock / carrier_freq) / 2 + * we scale coef by shifting clock value by 24 for + * better precision since we use integers */ + switch (ah->ah_bwmode) { + case AR5K_BWMODE_40MHZ: + clock = 40 * 2; + break; + case AR5K_BWMODE_10MHZ: + clock = 40 / 2; + break; + case AR5K_BWMODE_5MHZ: + clock = 40 / 4; + break; + default: + clock = 40; + break; + } + coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; + + /* Get exponent + * ALGO: coef_exp = 14 - highest set bit position */ + coef_exp = ilog2(coef_scaled); + + /* Doesn't make sense if it's zero*/ + if (!coef_scaled || !coef_exp) + return -EINVAL; + + /* Note: we've shifted coef_scaled by 24 */ + coef_exp = 14 - (coef_exp - 24); + + + /* Get mantissa (significant digits) + * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ + coef_man = coef_scaled + + (1 << (24 - coef_exp - 1)); + + /* Calculate delta slope coefficient exponent + * and mantissa (remove scaling) and set them on hw */ + ds_coef_man = coef_man >> (24 - coef_exp); + ds_coef_exp = coef_exp - 16; + + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, + AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, + AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); + + return 0; +} + +int ath5k_hw_phy_disable(struct ath5k_hw *ah) +{ + /*Just a try M.F.*/ + ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); + + return 0; +} + + /**********************\ * RF Gain optimization * \**********************/ @@ -436,10 +609,10 @@ done: /* Write initial RF gain table to set the RF sensitivity * this one works on all RF chips and has nothing to do * with gain_F calibration */ -int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) +static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band) { const struct ath5k_ini_rfgain *ath5k_rfg; - unsigned int i, size; + unsigned int i, size, index; switch (ah->ah_radio) { case AR5K_RF5111: @@ -471,17 +644,11 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) return -EINVAL; } - switch (freq) { - case AR5K_INI_RFGAIN_2GHZ: - case AR5K_INI_RFGAIN_5GHZ: - break; - default: - return -EINVAL; - } + index = (band == IEEE80211_BAND_2GHZ) ? 1 : 0; for (i = 0; i < size; i++) { AR5K_REG_WAIT(i); - ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq], + ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[index], (u32)ath5k_rfg[i].rfg_register); } @@ -494,12 +661,11 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) * RF Registers setup * \********************/ - /* * Setup RF registers by writing RF buffer on hw */ -int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, - unsigned int mode) +static int ath5k_hw_rfregs_init(struct ath5k_hw *ah, + struct ieee80211_channel *channel, unsigned int mode) { const struct ath5k_rf_reg *rf_regs; const struct ath5k_ini_rfbuffer *ini_rfb; @@ -652,6 +818,11 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, g_step = &go->go_step[ah->ah_gain.g_step_idx]; + /* Set turbo mode (N/A on RF5413) */ + if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) && + (ah->ah_radio != AR5K_RF5413)) + ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_TURBO, false); + /* Bank Modifications (chip-specific) */ if (ah->ah_radio == AR5K_RF5111) { @@ -691,7 +862,23 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], AR5K_RF_PLO_SEL, true); - /* TODO: Half/quarter channel support */ + /* Tweak power detectors for half/quarter rate support */ + if (ah->ah_bwmode == AR5K_BWMODE_5MHZ || + ah->ah_bwmode == AR5K_BWMODE_10MHZ) { + u8 wait_i; + + ath5k_hw_rfb_op(ah, rf_regs, 0x1f, + AR5K_RF_WAIT_S, true); + + wait_i = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ? + 0x1f : 0x10; + + ath5k_hw_rfb_op(ah, rf_regs, wait_i, + AR5K_RF_WAIT_I, true); + ath5k_hw_rfb_op(ah, rf_regs, 3, + AR5K_RF_MAX_TIME, true); + + } } if (ah->ah_radio == AR5K_RF5112) { @@ -789,8 +976,20 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], AR5K_RF_GAIN_I, true); - /* TODO: Half/quarter channel support */ + /* Tweak power detector for half/quarter rates */ + if (ah->ah_bwmode == AR5K_BWMODE_5MHZ || + ah->ah_bwmode == AR5K_BWMODE_10MHZ) { + u8 pd_delay; + pd_delay = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ? + 0xf : 0x8; + + ath5k_hw_rfb_op(ah, rf_regs, pd_delay, + AR5K_RF_PD_PERIOD_A, true); + ath5k_hw_rfb_op(ah, rf_regs, 0xf, + AR5K_RF_PD_DELAY_A, true); + + } } if (ah->ah_radio == AR5K_RF5413 && @@ -822,24 +1021,6 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, \**************************/ /* - * Check if a channel is supported - */ -bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) -{ - /* Check if the channel is in our supported range */ - if (flags & CHANNEL_2GHZ) { - if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && - (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) - return true; - } else if (flags & CHANNEL_5GHZ) - if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && - (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) - return true; - - return false; -} - -/* * Convertion needed for RF5110 */ static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) @@ -1045,7 +1226,8 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, /* * Set a channel on the radio chip */ -int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) +static int ath5k_hw_channel(struct ath5k_hw *ah, + struct ieee80211_channel *channel) { int ret; /* @@ -1092,8 +1274,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) } ah->ah_current_channel = channel; - ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; - ath5k_hw_set_clockrate(ah); return 0; } @@ -1102,18 +1282,12 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) PHY calibration \*****************/ -static int sign_extend(int val, const int nbits) -{ - int order = BIT(nbits-1); - return (val ^ order) - order; -} - static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) { s32 val; val = ath5k_hw_reg_read(ah, AR5K_PHY_NF); - return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9); + return sign_extend32(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 8); } void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) @@ -1181,22 +1355,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) return; } - switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) { - case CHANNEL_A: - case CHANNEL_T: - case CHANNEL_XR: - ee_mode = AR5K_EEPROM_MODE_11A; - break; - case CHANNEL_G: - case CHANNEL_TG: - ee_mode = AR5K_EEPROM_MODE_11G; - break; - default: - case CHANNEL_B: - ee_mode = AR5K_EEPROM_MODE_11B; - break; - } - + ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel); /* completed NF calibration, test threshold */ nf = ath5k_hw_read_measured_noise_floor(ah); @@ -1425,31 +1584,12 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, return ret; } + /***************************\ * Spur mitigation functions * \***************************/ -bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u8 refclk_freq; - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - refclk_freq = 40; - else - refclk_freq = 32; - - if ((channel->center_freq % refclk_freq != 0) && - ((channel->center_freq % refclk_freq < 10) || - (channel->center_freq % refclk_freq > 22))) - return true; - else - return false; -} - -void +static void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, struct ieee80211_channel *channel) { @@ -1478,7 +1618,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, spur_chan_fbin = AR5K_EEPROM_NO_SPUR; spur_detection_window = AR5K_SPUR_CHAN_WIDTH; /* XXX: Half/Quarter channels ?*/ - if (channel->hw_value & CHANNEL_TURBO) + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) spur_detection_window *= 2; for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { @@ -1507,32 +1647,43 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, * Calculate deltas: * spur_freq_sigma_delta -> spur_offset / sample_freq << 21 * spur_delta_phase -> spur_offset / chip_freq << 11 - * Note: Both values have 100KHz resolution + * Note: Both values have 100Hz resolution */ - /* XXX: Half/Quarter rate channels ? */ - switch (channel->hw_value) { - case CHANNEL_A: - /* Both sample_freq and chip_freq are 40MHz */ - spur_delta_phase = (spur_offset << 17) / 25; - spur_freq_sigma_delta = (spur_delta_phase >> 10); - symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; - break; - case CHANNEL_G: - /* sample_freq -> 40MHz chip_freq -> 44MHz - * (for b compatibility) */ - spur_freq_sigma_delta = (spur_offset << 8) / 55; - spur_delta_phase = (spur_offset << 17) / 25; - symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; - break; - case CHANNEL_T: - case CHANNEL_TG: + switch (ah->ah_bwmode) { + case AR5K_BWMODE_40MHZ: /* Both sample_freq and chip_freq are 80MHz */ spur_delta_phase = (spur_offset << 16) / 25; spur_freq_sigma_delta = (spur_delta_phase >> 10); - symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz; + symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz * 2; break; + case AR5K_BWMODE_10MHZ: + /* Both sample_freq and chip_freq are 20MHz (?) */ + spur_delta_phase = (spur_offset << 18) / 25; + spur_freq_sigma_delta = (spur_delta_phase >> 10); + symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 2; + case AR5K_BWMODE_5MHZ: + /* Both sample_freq and chip_freq are 10MHz (?) */ + spur_delta_phase = (spur_offset << 19) / 25; + spur_freq_sigma_delta = (spur_delta_phase >> 10); + symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4; default: - return; + if (channel->hw_value == CHANNEL_A) { + /* Both sample_freq and chip_freq are 40MHz */ + spur_delta_phase = (spur_offset << 17) / 25; + spur_freq_sigma_delta = + (spur_delta_phase >> 10); + symbol_width = + AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; + } else { + /* sample_freq -> 40MHz chip_freq -> 44MHz + * (for b compatibility) */ + spur_delta_phase = (spur_offset << 17) / 25; + spur_freq_sigma_delta = + (spur_offset << 8) / 55; + symbol_width = + AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; + } + break; } /* Calculate pilot and magnitude masks */ @@ -1672,63 +1823,6 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, } } -/********************\ - Misc PHY functions -\********************/ - -int ath5k_hw_phy_disable(struct ath5k_hw *ah) -{ - /*Just a try M.F.*/ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); - - return 0; -} - -/* - * Get the PHY Chip revision - */ -u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) -{ - unsigned int i; - u32 srev; - u16 ret; - - /* - * Set the radio chip access register - */ - switch (chan) { - case CHANNEL_2GHZ: - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); - break; - case CHANNEL_5GHZ: - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); - break; - default: - return 0; - } - - mdelay(2); - - /* ...wait until PHY is ready and read the selected radio revision */ - ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); - - for (i = 0; i < 8; i++) - ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); - - if (ah->ah_version == AR5K_AR5210) { - srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; - ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; - } else { - srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; - ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | - ((srev & 0x0f) << 4), 8); - } - - /* Reset to the 5GHz mode */ - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); - - return ret; -} /*****************\ * Antenna control * @@ -1822,7 +1916,8 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) struct ieee80211_channel *channel = ah->ah_current_channel; bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div; bool use_def_for_sg; - u8 def_ant, tx_ant, ee_mode; + int ee_mode; + u8 def_ant, tx_ant; u32 sta_id1 = 0; /* if channel is not initialized yet we can't set the antennas @@ -1834,20 +1929,8 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) def_ant = ah->ah_def_ant; - switch (channel->hw_value & CHANNEL_MODES) { - case CHANNEL_A: - case CHANNEL_T: - case CHANNEL_XR: - ee_mode = AR5K_EEPROM_MODE_11A; - break; - case CHANNEL_G: - case CHANNEL_TG: - ee_mode = AR5K_EEPROM_MODE_11G; - break; - case CHANNEL_B: - ee_mode = AR5K_EEPROM_MODE_11B; - break; - default: + ee_mode = ath5k_eeprom_mode_from_channel(channel); + if (ee_mode < 0) { ATH5K_ERR(ah->ah_sc, "invalid channel: %d\n", channel->center_freq); return; @@ -2275,20 +2358,20 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah, switch (channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: - ctl_mode |= AR5K_CTL_11A; + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) + ctl_mode |= AR5K_CTL_TURBO; + else + ctl_mode |= AR5K_CTL_11A; break; case CHANNEL_G: - ctl_mode |= AR5K_CTL_11G; + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) + ctl_mode |= AR5K_CTL_TURBOG; + else + ctl_mode |= AR5K_CTL_11G; break; case CHANNEL_B: ctl_mode |= AR5K_CTL_11B; break; - case CHANNEL_T: - ctl_mode |= AR5K_CTL_TURBO; - break; - case CHANNEL_TG: - ctl_mode |= AR5K_CTL_TURBOG; - break; case CHANNEL_XR: /* Fall through */ default: @@ -2482,7 +2565,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min, /* Write PCDAC values on hw */ static void -ath5k_setup_pcdac_table(struct ath5k_hw *ah) +ath5k_write_pcdac_table(struct ath5k_hw *ah) { u8 *pcdac_out = ah->ah_txpower.txp_pd_table; int i; @@ -2631,10 +2714,12 @@ ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah, /* Write PDADC values on hw */ static void -ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah, - u8 pdcurves, u8 *pdg_to_idx) +ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode) { + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; u8 *pdadc_out = ah->ah_txpower.txp_pd_table; + u8 *pdg_to_idx = ee->ee_pdc_to_idx[ee_mode]; + u8 pdcurves = ee->ee_pd_gains[ee_mode]; u32 reg; u8 i; @@ -2844,8 +2929,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, (s16) pcinfo_R->freq, pcinfo_L->max_pwr, pcinfo_R->max_pwr); - /* We are ready to go, fill PCDAC/PDADC - * table and write settings on hardware */ + /* Fill PCDAC/PDADC table */ switch (type) { case AR5K_PWRTABLE_LINEAR_PCDAC: /* For RF5112 we can have one or two curves @@ -2858,9 +2942,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, * match max power value with max * table index */ ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2); - - /* Write settings on hw */ - ath5k_setup_pcdac_table(ah); break; case AR5K_PWRTABLE_PWR_TO_PCDAC: /* We are done for RF5111 since it has only @@ -2870,9 +2951,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, /* No rate powertable adjustment for RF5111 */ ah->ah_txpower.txp_min_idx = 0; ah->ah_txpower.txp_offset = 0; - - /* Write settings on hw */ - ath5k_setup_pcdac_table(ah); break; case AR5K_PWRTABLE_PWR_TO_PDADC: /* Set PDADC boundaries and fill @@ -2880,9 +2958,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max, ee->ee_pd_gains[ee_mode]); - /* Write settings on hw */ - ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx); - /* Set txp.offset, note that table_min * can be negative */ ah->ah_txpower.txp_offset = table_min[0]; @@ -2891,9 +2966,20 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, return -EINVAL; } + ah->ah_txpower.txp_setup = true; + return 0; } +/* Write power table for current channel to hw */ +static void +ath5k_write_channel_powertable(struct ath5k_hw *ah, u8 ee_mode, u8 type) +{ + if (type == AR5K_PWRTABLE_PWR_TO_PDADC) + ath5k_write_pwr_to_pdadc_table(ah, ee_mode); + else + ath5k_write_pcdac_table(ah); +} /* * Per-rate tx power setting @@ -2982,7 +3068,7 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, /* Min/max in 0.25dB units */ ah->ah_txpower.txp_min_pwr = 2 * rates[7]; - ah->ah_txpower.txp_max_pwr = 2 * rates[0]; + ah->ah_txpower.txp_cur_pwr = 2 * rates[0]; ah->ah_txpower.txp_ofdm = rates[7]; } @@ -2990,11 +3076,13 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, /* * Set transmission power */ -int +static int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, - u8 ee_mode, u8 txpower) + u8 txpower) { struct ath5k_rate_pcal_info rate_info; + struct ieee80211_channel *curr_channel = ah->ah_current_channel; + int ee_mode; u8 type; int ret; @@ -3003,14 +3091,18 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, return -EINVAL; } - /* Reset TX power values */ - memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); - ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; - ah->ah_txpower.txp_min_pwr = 0; - ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER; + ee_mode = ath5k_eeprom_mode_from_channel(channel); + if (ee_mode < 0) { + ATH5K_ERR(ah->ah_sc, + "invalid channel: %d\n", channel->center_freq); + return -EINVAL; + } /* Initialize TX power table */ switch (ah->ah_radio) { + case AR5K_RF5110: + /* TODO */ + return 0; case AR5K_RF5111: type = AR5K_PWRTABLE_PWR_TO_PCDAC; break; @@ -3028,10 +3120,26 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, return -EINVAL; } - /* FIXME: Only on channel/mode change */ - ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type); - if (ret) - return ret; + /* + * If we don't change channel/mode skip tx powertable calculation + * and use the cached one. + */ + if (!ah->ah_txpower.txp_setup || + (channel->hw_value != curr_channel->hw_value) || + (channel->center_freq != curr_channel->center_freq)) { + /* Reset TX power values */ + memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); + ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; + + /* Calculate the powertable */ + ret = ath5k_setup_channel_powertable(ah, channel, + ee_mode, type); + if (ret) + return ret; + } + + /* Write table on hw */ + ath5k_write_channel_powertable(ah, ee_mode, type); /* Limit max power if we have a CTL available */ ath5k_get_max_ctl_power(ah, channel); @@ -3086,31 +3194,219 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) { - /*Just a try M.F.*/ - struct ieee80211_channel *channel = ah->ah_current_channel; - u8 ee_mode; + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, + "changing txpower to %d\n", txpower); - switch (channel->hw_value & CHANNEL_MODES) { - case CHANNEL_A: - case CHANNEL_T: - case CHANNEL_XR: - ee_mode = AR5K_EEPROM_MODE_11A; - break; - case CHANNEL_G: - case CHANNEL_TG: - ee_mode = AR5K_EEPROM_MODE_11G; - break; - case CHANNEL_B: - ee_mode = AR5K_EEPROM_MODE_11B; - break; - default: - ATH5K_ERR(ah->ah_sc, - "invalid channel: %d\n", channel->center_freq); + return ath5k_hw_txpower(ah, ah->ah_current_channel, txpower); +} + +/*************\ + Init function +\*************/ + +int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, + u8 mode, bool fast) +{ + struct ieee80211_channel *curr_channel; + int ret, i; + u32 phy_tst1; + ret = 0; + + /* + * Sanity check for fast flag + * Don't try fast channel change when changing modulation + * mode/band. We check for chip compatibility on + * ath5k_hw_reset. + */ + curr_channel = ah->ah_current_channel; + if (fast && (channel->hw_value != curr_channel->hw_value)) return -EINVAL; + + /* + * On fast channel change we only set the synth parameters + * while PHY is running, enable calibration and skip the rest. + */ + if (fast) { + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, + AR5K_PHY_RFBUS_REQ_REQUEST); + for (i = 0; i < 100; i++) { + if (ath5k_hw_reg_read(ah, AR5K_PHY_RFBUS_GRANT)) + break; + udelay(5); + } + /* Failed */ + if (i >= 100) + return -EIO; } - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, - "changing txpower to %d\n", txpower); + /* + * Set TX power + * + * Note: We need to do that before we set + * RF buffer settings on 5211/5212+ so that we + * properly set curve indices. + */ + ret = ath5k_hw_txpower(ah, channel, ah->ah_txpower.txp_cur_pwr ? + ah->ah_txpower.txp_cur_pwr / 2 : AR5K_TUNE_MAX_TXPOWER); + if (ret) + return ret; + + /* + * For 5210 we do all initialization using + * initvals, so we don't have to modify + * any settings (5210 also only supports + * a/aturbo modes) + */ + if ((ah->ah_version != AR5K_AR5210) && !fast) { + + /* + * Write initial RF gain settings + * This should work for both 5111/5112 + */ + ret = ath5k_hw_rfgain_init(ah, channel->band); + if (ret) + return ret; + + mdelay(1); + + /* + * Write RF buffer + */ + ret = ath5k_hw_rfregs_init(ah, channel, mode); + if (ret) + return ret; + + /* Write OFDM timings on 5212*/ + if (ah->ah_version == AR5K_AR5212 && + channel->hw_value & CHANNEL_OFDM) { + + ret = ath5k_hw_write_ofdm_timings(ah, channel); + if (ret) + return ret; + + /* Spur info is available only from EEPROM versions + * greater than 5.3, but the EEPROM routines will use + * static values for older versions */ + if (ah->ah_mac_srev >= AR5K_SREV_AR5424) + ath5k_hw_set_spur_mitigation_filter(ah, + channel); + } + + /*Enable/disable 802.11b mode on 5111 + (enable 2111 frequency converter + CCK)*/ + if (ah->ah_radio == AR5K_RF5111) { + if (mode == AR5K_MODE_11B) + AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_B_MODE); + else + AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_B_MODE); + } + + } else if (ah->ah_version == AR5K_AR5210) { + mdelay(1); + /* Disable phy and wait */ + ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); + mdelay(1); + } + + /* Set channel on PHY */ + ret = ath5k_hw_channel(ah, channel); + if (ret) + return ret; + + /* + * Enable the PHY and wait until completion + * This includes BaseBand and Synthesizer + * activation. + */ + ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); + + /* + * On 5211+ read activation -> rx delay + * and use it. + */ + if (ah->ah_version != AR5K_AR5210) { + u32 delay; + delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & + AR5K_PHY_RX_DELAY_M; + delay = (channel->hw_value & CHANNEL_CCK) ? + ((delay << 2) / 22) : (delay / 10); + if (ah->ah_bwmode == AR5K_BWMODE_10MHZ) + delay = delay << 1; + if (ah->ah_bwmode == AR5K_BWMODE_5MHZ) + delay = delay << 2; + /* XXX: /2 on turbo ? Let's be safe + * for now */ + udelay(100 + delay); + } else { + mdelay(1); + } + + if (fast) + /* + * Release RF Bus grant + */ + AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, + AR5K_PHY_RFBUS_REQ_REQUEST); + else { + /* + * Perform ADC test to see if baseband is ready + * Set tx hold and check adc test register + */ + phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); + ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); + for (i = 0; i <= 20; i++) { + if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) + break; + udelay(200); + } + ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); + } + + /* + * Start automatic gain control calibration + * + * During AGC calibration RX path is re-routed to + * a power detector so we don't receive anything. + * + * This method is used to calibrate some static offsets + * used together with on-the fly I/Q calibration (the + * one performed via ath5k_hw_phy_calibrate), which doesn't + * interrupt rx path. + * + * While rx path is re-routed to the power detector we also + * start a noise floor calibration to measure the + * card's noise floor (the noise we measure when we are not + * transmitting or receiving anything). + * + * If we are in a noisy environment, AGC calibration may time + * out and/or noise floor calibration might timeout. + */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); + + /* At the same time start I/Q calibration for QAM constellation + * -no need for CCK- */ + ah->ah_calibration = false; + if (!(mode == AR5K_MODE_11B)) { + ah->ah_calibration = true; + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_RUN); + } + + /* Wait for gain calibration to finish (we check for I/Q calibration + * during ath5k_phy_calibrate) */ + if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_CAL, 0, false)) { + ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", + channel->center_freq); + } + + /* Restore antenna mode */ + ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); - return ath5k_hw_txpower(ah, channel, ee_mode, txpower); + return ret; } diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 84c717ded1c5..2c9c9e793d4e 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -25,14 +25,52 @@ Queue Control Unit, DFS Control Unit Functions #include "debug.h" #include "base.h" + +/******************\ +* Helper functions * +\******************/ + /* - * Get properties for a transmit queue + * Get number of pending frames + * for a specific queue [5211+] */ -int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, - struct ath5k_txq_info *queue_info) +u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) { - memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); - return 0; + u32 pending; + AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); + + /* Return if queue is declared inactive */ + if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) + return false; + + /* XXX: How about AR5K_CFG_TXCNT ? */ + if (ah->ah_version == AR5K_AR5210) + return false; + + pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)); + pending &= AR5K_QCU_STS_FRMPENDCNT; + + /* It's possible to have no frames pending even if TXE + * is set. To indicate that q has not stopped return + * true */ + if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) + return true; + + return pending; +} + +/* + * Set a transmit queue inactive + */ +void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) +{ + if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) + return; + + /* This queue will be skipped in further operations */ + ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; + /*For SIMR setup*/ + AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); } /* @@ -50,6 +88,16 @@ static u16 ath5k_cw_validate(u16 cw_req) } /* + * Get properties for a transmit queue + */ +int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, + struct ath5k_txq_info *queue_info) +{ + memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); + return 0; +} + +/* * Set properties for a transmit queue */ int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, @@ -104,8 +152,8 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, /* * Get queue by type */ - /*5210 only has 2 queues*/ - if (ah->ah_version == AR5K_AR5210) { + /* 5210 only has 2 queues */ + if (ah->ah_capabilities.cap_queues.q_tx_num == 2) { switch (queue_type) { case AR5K_TX_QUEUE_DATA: queue = AR5K_TX_QUEUE_ID_NOQCU_DATA; @@ -172,113 +220,18 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, return queue; } -/* - * Get number of pending frames - * for a specific queue [5211+] - */ -u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) -{ - u32 pending; - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - /* Return if queue is declared inactive */ - if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return false; - - /* XXX: How about AR5K_CFG_TXCNT ? */ - if (ah->ah_version == AR5K_AR5210) - return false; - - pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)); - pending &= AR5K_QCU_STS_FRMPENDCNT; - - /* It's possible to have no frames pending even if TXE - * is set. To indicate that q has not stopped return - * true */ - if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) - return true; - - return pending; -} - -/* - * Set a transmit queue inactive - */ -void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) -{ - if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) - return; - /* This queue will be skipped in further operations */ - ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; - /*For SIMR setup*/ - AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); -} +/*******************************\ +* Single QCU/DCU initialization * +\*******************************/ /* - * Set DFS properties for a transmit queue on DCU + * Set tx retry limits on DCU */ -int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) +static void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, + unsigned int queue) { u32 retry_lg, retry_sh; - struct ath5k_txq_info *tq = &ah->ah_txq[queue]; - - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - tq = &ah->ah_txq[queue]; - - if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE) - return 0; - - if (ah->ah_version == AR5K_AR5210) { - /* Only handle data queues, others will be ignored */ - if (tq->tqi_type != AR5K_TX_QUEUE_DATA) - return 0; - - /* Set Slot time */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME, - AR5K_SLOT_TIME); - /* Set ACK_CTS timeout */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_ACK_CTS_TIMEOUT_TURBO : - AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME); - /* Set Transmit Latency */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_TRANSMIT_LATENCY_TURBO : - AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210); - - /* Set IFS0 */ - if (ah->ah_turbo) { - ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + - tq->tqi_aifs * AR5K_INIT_SLOT_TIME_TURBO) << - AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, - AR5K_IFS0); - } else { - ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + - tq->tqi_aifs * AR5K_INIT_SLOT_TIME) << - AR5K_IFS0_DIFS_S) | - AR5K_INIT_SIFS, AR5K_IFS0); - } - - /* Set IFS1 */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_PROTO_TIME_CNTRL_TURBO : - AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1); - /* Set AR5K_PHY_SETTLING */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) - | 0x38 : - (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) - | 0x1C, - AR5K_PHY_SETTLING); - /* Set Frame Control Register */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE | - AR5K_PHY_TURBO_SHORT | 0x2020) : - (AR5K_PHY_FRAME_CTL_INI | 0x1020), - AR5K_PHY_FRAME_CTL_5210); - } /* * Calculate and set retry limits @@ -293,8 +246,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) retry_sh = AR5K_INIT_SH_RETRY; } - /*No QCU/DCU [5210]*/ + /* Single data queue on AR5210 */ if (ah->ah_version == AR5K_AR5210) { + struct ath5k_txq_info *tq = &ah->ah_txq[queue]; + + if (queue > 0) + return; + ath5k_hw_reg_write(ah, (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, @@ -304,8 +262,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY) | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY), AR5K_NODCU_RETRY_LMT); + /* DCU on AR5211+ */ } else { - /*QCU/DCU [5211+]*/ ath5k_hw_reg_write(ah, AR5K_REG_SM(AR5K_INIT_SLG_RETRY, AR5K_DCU_RETRY_LMT_SLG_RETRY) | @@ -314,219 +272,393 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) | AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY), AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); + } + return; +} - /*===Rest is also for QCU/DCU only [5211+]===*/ +/** + * ath5k_hw_reset_tx_queue - Initialize a single hw queue + * + * @ah The &struct ath5k_hw + * @queue The hw queue number + * + * Set DFS properties for the given transmit queue on DCU + * and configures all queue-specific parameters. + */ +int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) +{ + struct ath5k_txq_info *tq = &ah->ah_txq[queue]; - /* - * Set contention window (cw_min/cw_max) - * and arbitrated interframe space (aifs)... - */ - ath5k_hw_reg_write(ah, - AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | - AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | - AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS), - AR5K_QUEUE_DFS_LOCAL_IFS(queue)); - - /* - * Set misc registers - */ - /* Enable DCU early termination for this queue */ - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_DCU_EARLY); + AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); + + tq = &ah->ah_txq[queue]; + + /* Skip if queue inactive or if we are on AR5210 + * that doesn't have QCU/DCU */ + if ((ah->ah_version == AR5K_AR5210) || + (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)) + return 0; + + /* + * Set contention window (cw_min/cw_max) + * and arbitrated interframe space (aifs)... + */ + ath5k_hw_reg_write(ah, + AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | + AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | + AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS), + AR5K_QUEUE_DFS_LOCAL_IFS(queue)); + + /* + * Set tx retry limits for this queue + */ + ath5k_hw_set_tx_retry_limits(ah, queue); + + + /* + * Set misc registers + */ + + /* Enable DCU to wait for next fragment from QCU */ + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), + AR5K_DCU_MISC_FRAG_WAIT); - /* Enable DCU to wait for next fragment from QCU */ + /* On Maui and Spirit use the global seqnum on DCU */ + if (ah->ah_mac_version < AR5K_SREV_AR5211) AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - AR5K_DCU_MISC_FRAG_WAIT); - - /* On Maui and Spirit use the global seqnum on DCU */ - if (ah->ah_mac_version < AR5K_SREV_AR5211) - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - AR5K_DCU_MISC_SEQNUM_CTL); - - if (tq->tqi_cbr_period) { - ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, - AR5K_QCU_CBRCFG_INTVAL) | - AR5K_REG_SM(tq->tqi_cbr_overflow_limit, - AR5K_QCU_CBRCFG_ORN_THRES), - AR5K_QUEUE_CBRCFG(queue)); + AR5K_DCU_MISC_SEQNUM_CTL); + + /* Constant bit rate period */ + if (tq->tqi_cbr_period) { + ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, + AR5K_QCU_CBRCFG_INTVAL) | + AR5K_REG_SM(tq->tqi_cbr_overflow_limit, + AR5K_QCU_CBRCFG_ORN_THRES), + AR5K_QUEUE_CBRCFG(queue)); + + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_FRSHED_CBR); + + if (tq->tqi_cbr_overflow_limit) AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_FRSHED_CBR); - if (tq->tqi_cbr_overflow_limit) - AR5K_REG_ENABLE_BITS(ah, - AR5K_QUEUE_MISC(queue), AR5K_QCU_MISC_CBR_THRES_ENABLE); - } + } - if (tq->tqi_ready_time && - (tq->tqi_type != AR5K_TX_QUEUE_CAB)) - ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, - AR5K_QCU_RDYTIMECFG_INTVAL) | - AR5K_QCU_RDYTIMECFG_ENABLE, - AR5K_QUEUE_RDYTIMECFG(queue)); - - if (tq->tqi_burst_time) { - ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, - AR5K_DCU_CHAN_TIME_DUR) | - AR5K_DCU_CHAN_TIME_ENABLE, - AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); - - if (tq->tqi_flags - & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) - AR5K_REG_ENABLE_BITS(ah, - AR5K_QUEUE_MISC(queue), + /* Ready time interval */ + if (tq->tqi_ready_time && (tq->tqi_type != AR5K_TX_QUEUE_CAB)) + ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, + AR5K_QCU_RDYTIMECFG_INTVAL) | + AR5K_QCU_RDYTIMECFG_ENABLE, + AR5K_QUEUE_RDYTIMECFG(queue)); + + if (tq->tqi_burst_time) { + ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, + AR5K_DCU_CHAN_TIME_DUR) | + AR5K_DCU_CHAN_TIME_ENABLE, + AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), AR5K_QCU_MISC_RDY_VEOL_POLICY); - } + } - if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) - ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, - AR5K_QUEUE_DFS_MISC(queue)); + /* Enable/disable Post frame backoff */ + if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) + ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, + AR5K_QUEUE_DFS_MISC(queue)); - if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) - ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, - AR5K_QUEUE_DFS_MISC(queue)); + /* Enable/disable fragmentation burst backoff */ + if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) + ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, + AR5K_QUEUE_DFS_MISC(queue)); - /* - * Set registers by queue type - */ - switch (tq->tqi_type) { - case AR5K_TX_QUEUE_BEACON: - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + /* + * Set registers by queue type + */ + switch (tq->tqi_type) { + case AR5K_TX_QUEUE_BEACON: + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), AR5K_QCU_MISC_FRSHED_DBA_GT | AR5K_QCU_MISC_CBREXP_BCN_DIS | AR5K_QCU_MISC_BCN_ENABLE); - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << AR5K_DCU_MISC_ARBLOCK_CTL_S) | AR5K_DCU_MISC_ARBLOCK_IGNORE | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | AR5K_DCU_MISC_BCN_ENABLE); - break; + break; - case AR5K_TX_QUEUE_CAB: - /* XXX: use BCN_SENT_GT, if we can figure out how */ - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_FRSHED_DBA_GT | - AR5K_QCU_MISC_CBREXP_DIS | - AR5K_QCU_MISC_CBREXP_BCN_DIS); + case AR5K_TX_QUEUE_CAB: + /* XXX: use BCN_SENT_GT, if we can figure out how */ + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_FRSHED_DBA_GT | + AR5K_QCU_MISC_CBREXP_DIS | + AR5K_QCU_MISC_CBREXP_BCN_DIS); - ath5k_hw_reg_write(ah, ((tq->tqi_ready_time - - (AR5K_TUNE_SW_BEACON_RESP - - AR5K_TUNE_DMA_BEACON_RESP) - + ath5k_hw_reg_write(ah, ((tq->tqi_ready_time - + (AR5K_TUNE_SW_BEACON_RESP - + AR5K_TUNE_DMA_BEACON_RESP) - AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | - AR5K_QCU_RDYTIMECFG_ENABLE, - AR5K_QUEUE_RDYTIMECFG(queue)); + AR5K_QCU_RDYTIMECFG_ENABLE, + AR5K_QUEUE_RDYTIMECFG(queue)); - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << - AR5K_DCU_MISC_ARBLOCK_CTL_S)); - break; + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), + (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << + AR5K_DCU_MISC_ARBLOCK_CTL_S)); + break; - case AR5K_TX_QUEUE_UAPSD: - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_CBREXP_DIS); - break; + case AR5K_TX_QUEUE_UAPSD: + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_CBREXP_DIS); + break; - case AR5K_TX_QUEUE_DATA: - default: + case AR5K_TX_QUEUE_DATA: + default: break; - } - - /* TODO: Handle frame compression */ - - /* - * Enable interrupts for this tx queue - * in the secondary interrupt mask registers - */ - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue); - - /* Update secondary interrupt mask registers */ - - /* Filter out inactive queues */ - ah->ah_txq_imr_txok &= ah->ah_txq_status; - ah->ah_txq_imr_txerr &= ah->ah_txq_status; - ah->ah_txq_imr_txurn &= ah->ah_txq_status; - ah->ah_txq_imr_txdesc &= ah->ah_txq_status; - ah->ah_txq_imr_txeol &= ah->ah_txq_status; - ah->ah_txq_imr_cbrorn &= ah->ah_txq_status; - ah->ah_txq_imr_cbrurn &= ah->ah_txq_status; - ah->ah_txq_imr_qtrig &= ah->ah_txq_status; - ah->ah_txq_imr_nofrm &= ah->ah_txq_status; - - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, - AR5K_SIMR0_QCU_TXOK) | - AR5K_REG_SM(ah->ah_txq_imr_txdesc, - AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0); - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, - AR5K_SIMR1_QCU_TXERR) | - AR5K_REG_SM(ah->ah_txq_imr_txeol, - AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1); - /* Update simr2 but don't overwrite rest simr2 settings */ - AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN); - AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, - AR5K_REG_SM(ah->ah_txq_imr_txurn, - AR5K_SIMR2_QCU_TXURN)); - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn, - AR5K_SIMR3_QCBRORN) | - AR5K_REG_SM(ah->ah_txq_imr_cbrurn, - AR5K_SIMR3_QCBRURN), AR5K_SIMR3); - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig, - AR5K_SIMR4_QTRIG), AR5K_SIMR4); - /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */ - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm, - AR5K_TXNOFRM_QCU), AR5K_TXNOFRM); - /* No queue has TXNOFRM enabled, disable the interrupt - * by setting AR5K_TXNOFRM to zero */ - if (ah->ah_txq_imr_nofrm == 0) - ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); - - /* Set QCU mask for this DCU to save power */ - AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); } + /* TODO: Handle frame compression */ + + /* + * Enable interrupts for this tx queue + * in the secondary interrupt mask registers + */ + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue); + + /* Update secondary interrupt mask registers */ + + /* Filter out inactive queues */ + ah->ah_txq_imr_txok &= ah->ah_txq_status; + ah->ah_txq_imr_txerr &= ah->ah_txq_status; + ah->ah_txq_imr_txurn &= ah->ah_txq_status; + ah->ah_txq_imr_txdesc &= ah->ah_txq_status; + ah->ah_txq_imr_txeol &= ah->ah_txq_status; + ah->ah_txq_imr_cbrorn &= ah->ah_txq_status; + ah->ah_txq_imr_cbrurn &= ah->ah_txq_status; + ah->ah_txq_imr_qtrig &= ah->ah_txq_status; + ah->ah_txq_imr_nofrm &= ah->ah_txq_status; + + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, + AR5K_SIMR0_QCU_TXOK) | + AR5K_REG_SM(ah->ah_txq_imr_txdesc, + AR5K_SIMR0_QCU_TXDESC), + AR5K_SIMR0); + + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, + AR5K_SIMR1_QCU_TXERR) | + AR5K_REG_SM(ah->ah_txq_imr_txeol, + AR5K_SIMR1_QCU_TXEOL), + AR5K_SIMR1); + + /* Update SIMR2 but don't overwrite rest simr2 settings */ + AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN); + AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, + AR5K_REG_SM(ah->ah_txq_imr_txurn, + AR5K_SIMR2_QCU_TXURN)); + + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn, + AR5K_SIMR3_QCBRORN) | + AR5K_REG_SM(ah->ah_txq_imr_cbrurn, + AR5K_SIMR3_QCBRURN), + AR5K_SIMR3); + + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig, + AR5K_SIMR4_QTRIG), AR5K_SIMR4); + + /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */ + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm, + AR5K_TXNOFRM_QCU), AR5K_TXNOFRM); + + /* No queue has TXNOFRM enabled, disable the interrupt + * by setting AR5K_TXNOFRM to zero */ + if (ah->ah_txq_imr_nofrm == 0) + ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); + + /* Set QCU mask for this DCU to save power */ + AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); + return 0; } -/* - * Set slot time on DCU + +/**************************\ +* Global QCU/DCU functions * +\**************************/ + +/** + * ath5k_hw_set_ifs_intervals - Set global inter-frame spaces on DCU + * + * @ah The &struct ath5k_hw + * @slot_time Slot time in us + * + * Sets the global IFS intervals on DCU (also works on AR5210) for + * the given slot time and the current bwmode. */ -int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) +int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) { + struct ieee80211_channel *channel = ah->ah_current_channel; + struct ath5k_softc *sc = ah->ah_sc; + struct ieee80211_rate *rate; + u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock; u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX) return -EINVAL; - if (ah->ah_version == AR5K_AR5210) - ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME); + sifs = ath5k_hw_get_default_sifs(ah); + sifs_clock = ath5k_hw_htoclock(ah, sifs); + + /* EIFS + * Txtime of ack at lowest rate + SIFS + DIFS + * (DIFS = SIFS + 2 * Slot time) + * + * Note: HAL has some predefined values for EIFS + * Turbo: (37 + 2 * 6) + * Default: (74 + 2 * 9) + * Half: (149 + 2 * 13) + * Quarter: (298 + 2 * 21) + * + * (74 + 2 * 6) for AR5210 default and turbo ! + * + * According to the formula we have + * ack_tx_time = 25 for turbo and + * ack_tx_time = 42.5 * clock multiplier + * for default/half/quarter. + * + * This can't be right, 42 is what we would get + * from ath5k_hw_get_frame_dur_for_bwmode or + * ieee80211_generic_frame_duration for zero frame + * length and without SIFS ! + * + * Also we have different lowest rate for 802.11a + */ + if (channel->hw_value & CHANNEL_5GHZ) + rate = &sc->sbands[IEEE80211_BAND_5GHZ].bitrates[0]; else - ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT); + rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; + + ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); + + /* ack_tx_time includes an SIFS already */ + eifs = ack_tx_time + sifs + 2 * slot_time; + eifs_clock = ath5k_hw_htoclock(ah, eifs); + + /* Set IFS settings on AR5210 */ + if (ah->ah_version == AR5K_AR5210) { + u32 pifs, pifs_clock, difs, difs_clock; + + /* Set slot time */ + ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME); + + /* Set EIFS */ + eifs_clock = AR5K_REG_SM(eifs_clock, AR5K_IFS1_EIFS); + + /* PIFS = Slot time + SIFS */ + pifs = slot_time + sifs; + pifs_clock = ath5k_hw_htoclock(ah, pifs); + pifs_clock = AR5K_REG_SM(pifs_clock, AR5K_IFS1_PIFS); + + /* DIFS = SIFS + 2 * Slot time */ + difs = sifs + 2 * slot_time; + difs_clock = ath5k_hw_htoclock(ah, difs); + + /* Set SIFS/DIFS */ + ath5k_hw_reg_write(ah, (difs_clock << + AR5K_IFS0_DIFS_S) | sifs_clock, + AR5K_IFS0); + + /* Set PIFS/EIFS and preserve AR5K_INIT_CARR_SENSE_EN */ + ath5k_hw_reg_write(ah, pifs_clock | eifs_clock | + (AR5K_INIT_CARR_SENSE_EN << AR5K_IFS1_CS_EN_S), + AR5K_IFS1); + + return 0; + } + + /* Set IFS slot time */ + ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT); + + /* Set EIFS interval */ + ath5k_hw_reg_write(ah, eifs_clock, AR5K_DCU_GBL_IFS_EIFS); + + /* Set SIFS interval in usecs */ + AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC, + AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC, + sifs); + + /* Set SIFS interval in clock cycles */ + ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS); return 0; } + +int ath5k_hw_init_queues(struct ath5k_hw *ah) +{ + int i, ret; + + /* TODO: HW Compression support for data queues */ + /* TODO: Burst prefetch for data queues */ + + /* + * Reset queues and start beacon timers at the end of the reset routine + * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping + * Note: If we want we can assign multiple qcus on one dcu. + */ + if (ah->ah_version != AR5K_AR5210) + for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { + ret = ath5k_hw_reset_tx_queue(ah, i); + if (ret) { + ATH5K_ERR(ah->ah_sc, + "failed to reset TX queue #%d\n", i); + return ret; + } + } + else + /* No QCU/DCU on AR5210, just set tx + * retry limits. We set IFS parameters + * on ath5k_hw_set_ifs_intervals */ + ath5k_hw_set_tx_retry_limits(ah, 0); + + /* Set the turbo flag when operating on 40MHz */ + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) + AR5K_REG_ENABLE_BITS(ah, AR5K_DCU_GBL_IFS_MISC, + AR5K_DCU_GBL_IFS_MISC_TURBO_MODE); + + /* If we didn't set IFS timings through + * ath5k_hw_set_coverage_class make sure + * we set them here */ + if (!ah->ah_coverage_class) { + unsigned int slot_time = ath5k_hw_get_default_slottime(ah); + ath5k_hw_set_ifs_intervals(ah, slot_time); + } + + return 0; +} diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index ca79ecd832fd..7ad05d401ab5 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -787,6 +787,7 @@ #define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 /* LFSR Slice Select */ #define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */ #define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */ +#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC_S 4 #define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */ #define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10 #define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */ @@ -1311,7 +1312,7 @@ #define AR5K_IFS1_EIFS 0x03fff000 #define AR5K_IFS1_EIFS_S 12 #define AR5K_IFS1_CS_EN 0x04000000 - +#define AR5K_IFS1_CS_EN_S 26 /* * CFP duration register @@ -2058,6 +2059,7 @@ #define AR5K_PHY_SCAL 0x9878 #define AR5K_PHY_SCAL_32MHZ 0x0000000e +#define AR5K_PHY_SCAL_32MHZ_5311 0x00000008 #define AR5K_PHY_SCAL_32MHZ_2417 0x0000000a #define AR5K_PHY_SCAL_32MHZ_HB63 0x00000032 @@ -2244,6 +2246,8 @@ #define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \ AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211) /*---[5111+]---*/ +#define AR5K_PHY_FRAME_CTL_WIN_LEN 0x00000003 /* Force window length (?) */ +#define AR5K_PHY_FRAME_CTL_WIN_LEN_S 0 #define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */ #define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3 #define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */ @@ -2558,3 +2562,28 @@ */ #define AR5K_PHY_PDADC_TXPOWER_BASE 0xa280 #define AR5K_PHY_PDADC_TXPOWER(_n) (AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2)) + +/* + * Platform registers for WiSoC + */ +#define AR5K_AR5312_RESET 0xbc003020 +#define AR5K_AR5312_RESET_BB0_COLD 0x00000004 +#define AR5K_AR5312_RESET_BB1_COLD 0x00000200 +#define AR5K_AR5312_RESET_WMAC0 0x00002000 +#define AR5K_AR5312_RESET_BB0_WARM 0x00004000 +#define AR5K_AR5312_RESET_WMAC1 0x00020000 +#define AR5K_AR5312_RESET_BB1_WARM 0x00040000 + +#define AR5K_AR5312_ENABLE 0xbc003080 +#define AR5K_AR5312_ENABLE_WLAN0 0x00000001 +#define AR5K_AR5312_ENABLE_WLAN1 0x00000008 + +#define AR5K_AR2315_RESET 0xb1000004 +#define AR5K_AR2315_RESET_WMAC 0x00000001 +#define AR5K_AR2315_RESET_BB_WARM 0x00000002 + +#define AR5K_AR2315_AHB_ARB_CTL 0xb1000008 +#define AR5K_AR2315_AHB_ARB_CTL_WLAN 0x00000002 + +#define AR5K_AR2315_BYTESWAP 0xb100000c +#define AR5K_AR2315_BYTESWAP_WMAC 0x00000002 diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 5b179d01f97d..84206898f77d 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -27,11 +27,17 @@ #include <linux/pci.h> /* To determine if a card is pci-e */ #include <linux/log2.h> +#include <linux/platform_device.h> #include "ath5k.h" #include "reg.h" #include "base.h" #include "debug.h" + +/******************\ +* Helper functions * +\******************/ + /* * Check if a register write has been completed */ @@ -53,146 +59,267 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, return (i <= 0) ? -EAGAIN : 0; } + +/*************************\ +* Clock related functions * +\*************************/ + /** - * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 + * ath5k_hw_htoclock - Translate usec to hw clock units * - * @ah: the &struct ath5k_hw - * @channel: the currently set channel upon reset - * - * Write the delta slope coefficient (used on pilot tracking ?) for OFDM - * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset(). + * @ah: The &struct ath5k_hw + * @usec: value in microseconds + */ +unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) +{ + struct ath_common *common = ath5k_hw_common(ah); + return usec * common->clockrate; +} + +/** + * ath5k_hw_clocktoh - Translate hw clock units to usec + * @clock: value in hw clock units + */ +unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) +{ + struct ath_common *common = ath5k_hw_common(ah); + return clock / common->clockrate; +} + +/** + * ath5k_hw_init_core_clock - Initialize core clock * - * Since delta slope is floating point we split it on its exponent and - * mantissa and provide these values on hw. + * @ah The &struct ath5k_hw * - * For more infos i think this patent is related - * http://www.freepatentsonline.com/7184495.html + * Initialize core clock parameters (usec, usec32, latencies etc). */ -static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, - struct ieee80211_channel *channel) +static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) { - /* Get exponent and mantissa and set it */ - u32 coef_scaled, coef_exp, coef_man, - ds_coef_exp, ds_coef_man, clock; - - BUG_ON(!(ah->ah_version == AR5K_AR5212) || - !(channel->hw_value & CHANNEL_OFDM)); - - /* Get coefficient - * ALGO: coef = (5 * clock / carrier_freq) / 2 - * we scale coef by shifting clock value by 24 for - * better precision since we use integers */ - /* TODO: Half/quarter rate */ - clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40; - coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; - - /* Get exponent - * ALGO: coef_exp = 14 - highest set bit position */ - coef_exp = ilog2(coef_scaled); - - /* Doesn't make sense if it's zero*/ - if (!coef_scaled || !coef_exp) - return -EINVAL; + struct ieee80211_channel *channel = ah->ah_current_channel; + struct ath_common *common = ath5k_hw_common(ah); + u32 usec_reg, txlat, rxlat, usec, clock, sclock, txf2txs; + + /* + * Set core clock frequency + */ + if (channel->hw_value & CHANNEL_5GHZ) + clock = 40; /* 802.11a */ + else if (channel->hw_value & CHANNEL_CCK) + clock = 22; /* 802.11b */ + else + clock = 44; /* 802.11g */ + + /* Use clock multiplier for non-default + * bwmode */ + switch (ah->ah_bwmode) { + case AR5K_BWMODE_40MHZ: + clock *= 2; + break; + case AR5K_BWMODE_10MHZ: + clock /= 2; + break; + case AR5K_BWMODE_5MHZ: + clock /= 4; + break; + default: + break; + } - /* Note: we've shifted coef_scaled by 24 */ - coef_exp = 14 - (coef_exp - 24); + common->clockrate = clock; + /* + * Set USEC parameters + */ + /* Set USEC counter on PCU*/ + usec = clock - 1; + usec = AR5K_REG_SM(usec, AR5K_USEC_1); - /* Get mantissa (significant digits) - * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ - coef_man = coef_scaled + - (1 << (24 - coef_exp - 1)); + /* Set usec duration on DCU */ + if (ah->ah_version != AR5K_AR5210) + AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC, + AR5K_DCU_GBL_IFS_MISC_USEC_DUR, + clock); - /* Calculate delta slope coefficient exponent - * and mantissa (remove scaling) and set them on hw */ - ds_coef_man = coef_man >> (24 - coef_exp); - ds_coef_exp = coef_exp - 16; + /* Set 32MHz USEC counter */ + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_radio == AR5K_RF2316) || + (ah->ah_radio == AR5K_RF2317)) + /* Remain on 40MHz clock ? */ + sclock = 40 - 1; + else + sclock = 32 - 1; + sclock = AR5K_REG_SM(sclock, AR5K_USEC_32); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, - AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, - AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); + /* + * Set tx/rx latencies + */ + usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211); + txlat = AR5K_REG_MS(usec_reg, AR5K_USEC_TX_LATENCY_5211); + rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211); - return 0; -} + /* + * 5210 initvals don't include usec settings + * so we need to use magic values here for + * tx/rx latencies + */ + if (ah->ah_version == AR5K_AR5210) { + /* same for turbo */ + txlat = AR5K_INIT_TX_LATENCY_5210; + rxlat = AR5K_INIT_RX_LATENCY_5210; + } + if (ah->ah_mac_srev < AR5K_SREV_AR5211) { + /* 5311 has different tx/rx latency masks + * from 5211, since we deal 5311 the same + * as 5211 when setting initvals, shift + * values here to their proper locations + * + * Note: Initvals indicate tx/rx/ latencies + * are the same for turbo mode */ + txlat = AR5K_REG_SM(txlat, AR5K_USEC_TX_LATENCY_5210); + rxlat = AR5K_REG_SM(rxlat, AR5K_USEC_RX_LATENCY_5210); + } else + switch (ah->ah_bwmode) { + case AR5K_BWMODE_10MHZ: + txlat = AR5K_REG_SM(txlat * 2, + AR5K_USEC_TX_LATENCY_5211); + rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX, + AR5K_USEC_RX_LATENCY_5211); + txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_10MHZ; + break; + case AR5K_BWMODE_5MHZ: + txlat = AR5K_REG_SM(txlat * 4, + AR5K_USEC_TX_LATENCY_5211); + rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX, + AR5K_USEC_RX_LATENCY_5211); + txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_5MHZ; + break; + case AR5K_BWMODE_40MHZ: + txlat = AR5K_INIT_TX_LAT_MIN; + rxlat = AR5K_REG_SM(rxlat / 2, + AR5K_USEC_RX_LATENCY_5211); + txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT; + break; + default: + break; + } -/* - * index into rates for control rates, we can set it up like this because - * this is only used for AR5212 and we know it supports G mode - */ -static const unsigned int control_rates[] = - { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; + usec_reg = (usec | sclock | txlat | rxlat); + ath5k_hw_reg_write(ah, usec_reg, AR5K_USEC); -/** - * ath5k_hw_write_rate_duration - fill rate code to duration table - * - * @ah: the &struct ath5k_hw - * @mode: one of enum ath5k_driver_mode - * - * Write the rate code to duration table upon hw reset. This is a helper for - * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on - * the hardware, based on current mode, for each rate. The rates which are - * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have - * different rate code so we write their value twice (one for long preample - * and one for short). + /* On 5112 set tx frane to tx data start delay */ + if (ah->ah_radio == AR5K_RF5112) { + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL2, + AR5K_PHY_RF_CTL2_TXF2TXD_START, + txf2txs); + } +} + +/* + * If there is an external 32KHz crystal available, use it + * as ref. clock instead of 32/40MHz clock and baseband clocks + * to save power during sleep or restore normal 32/40MHz + * operation. * - * Note: Band doesn't matter here, if we set the values for OFDM it works - * on both a and g modes. So all we have to do is set values for all g rates - * that include all OFDM and CCK rates. If we operate in turbo or xr/half/ - * quarter rate mode, we need to use another set of bitrates (that's why we - * need the mode parameter) but we don't handle these proprietary modes yet. + * XXX: When operating on 32KHz certain PHY registers (27 - 31, + * 123 - 127) require delay on access. */ -static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, - unsigned int mode) +static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) { - struct ath5k_softc *sc = ah->ah_sc; - struct ieee80211_rate *rate; - unsigned int i; + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u32 scal, spending; + + /* Only set 32KHz settings if we have an external + * 32KHz crystal present */ + if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) || + AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) && + enable) { - /* Write rate duration table */ - for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) { - u32 reg; - u16 tx_time; + /* 1 usec/cycle */ + AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1); + /* Set up tsf increment on each cycle */ + AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61); - rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]]; + /* Set baseband sleep control registers + * and sleep control rate */ + ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); + + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_radio == AR5K_RF2316) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) + spending = 0x14; + else + spending = 0x18; + ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); - /* Set ACK timeout */ - reg = AR5K_RATE_DUR(rate->hw_value); + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { + ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT); + ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL); + ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK); + ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY); + AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02); + } else { + ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT); + ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL); + ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK); + ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY); + AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03); + } - /* An ACK frame consists of 10 bytes. If you add the FCS, - * which ieee80211_generic_frame_duration() adds, - * its 14 bytes. Note we use the control rate and not the - * actual rate for this rate. See mac80211 tx.c - * ieee80211_duration() for a brief description of - * what rate we should choose to TX ACKs. */ - tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, - NULL, 10, rate)); + /* Enable sleep clock operation */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_EN); - ath5k_hw_reg_write(ah, tx_time, reg); + } else { - if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) - continue; + /* Disable sleep clock operation and + * restore default parameters */ + AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_EN); - /* - * We're not distinguishing short preamble here, - * This is true, all we'll get is a longer value here - * which is not necessarilly bad. We could use - * export ieee80211_frame_duration() but that needs to be - * fixed first to be properly used by mac802111 drivers: - * - * - remove erp stuff and let the routine figure ofdm - * erp rates - * - remove passing argument ieee80211_local as - * drivers don't have access to it - * - move drivers using ieee80211_generic_frame_duration() - * to this - */ - ath5k_hw_reg_write(ah, tx_time, - reg + (AR5K_SET_SHORT_PREAMBLE << 2)); + AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_RATE, 0); + + /* Set DAC/ADC delays */ + ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); + ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); + + if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) + scal = AR5K_PHY_SCAL_32MHZ_2417; + else if (ee->ee_is_hb63) + scal = AR5K_PHY_SCAL_32MHZ_HB63; + else + scal = AR5K_PHY_SCAL_32MHZ; + ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); + + ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); + ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); + + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_radio == AR5K_RF2316) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) + spending = 0x14; + else + spending = 0x18; + ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); + + /* Set up tsf increment on each cycle */ + AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); } } + +/*********************\ +* Reset/Sleep control * +\*********************/ + /* * Reset chipset */ @@ -236,6 +363,64 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) } /* + * Reset AHB chipset + * AR5K_RESET_CTL_PCU flag resets WMAC + * AR5K_RESET_CTL_BASEBAND flag resets WBB + */ +static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) +{ + u32 mask = flags ? flags : ~0U; + volatile u32 *reg; + u32 regval; + u32 val = 0; + + /* ah->ah_mac_srev is not available at this point yet */ + if (ah->ah_sc->devid >= AR5K_SREV_AR2315_R6) { + reg = (u32 *) AR5K_AR2315_RESET; + if (mask & AR5K_RESET_CTL_PCU) + val |= AR5K_AR2315_RESET_WMAC; + if (mask & AR5K_RESET_CTL_BASEBAND) + val |= AR5K_AR2315_RESET_BB_WARM; + } else { + reg = (u32 *) AR5K_AR5312_RESET; + if (to_platform_device(ah->ah_sc->dev)->id == 0) { + if (mask & AR5K_RESET_CTL_PCU) + val |= AR5K_AR5312_RESET_WMAC0; + if (mask & AR5K_RESET_CTL_BASEBAND) + val |= AR5K_AR5312_RESET_BB0_COLD | + AR5K_AR5312_RESET_BB0_WARM; + } else { + if (mask & AR5K_RESET_CTL_PCU) + val |= AR5K_AR5312_RESET_WMAC1; + if (mask & AR5K_RESET_CTL_BASEBAND) + val |= AR5K_AR5312_RESET_BB1_COLD | + AR5K_AR5312_RESET_BB1_WARM; + } + } + + /* Put BB/MAC into reset */ + regval = __raw_readl(reg); + __raw_writel(regval | val, reg); + regval = __raw_readl(reg); + udelay(100); + + /* Bring BB/MAC out of reset */ + __raw_writel(regval & ~val, reg); + regval = __raw_readl(reg); + + /* + * Reset configuration register (for hw byte-swap). Note that this + * is only set for big endian. We do the necessary magic in + * AR5K_INIT_CFG. + */ + if ((flags & AR5K_RESET_CTL_PCU) == 0) + ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG); + + return 0; +} + + +/* * Sleep control */ static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, @@ -334,6 +519,9 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) u32 bus_flags; int ret; + if (ath5k_get_bus_type(ah) == ATH_AHB) + return 0; + /* Make sure device is awake */ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); if (ret) { @@ -349,7 +537,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) * we ingore that flag for PCI-E cards. On PCI cards * this flag gets cleared after 64 PCI clocks. */ - bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; + bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI; if (ah->ah_version == AR5K_AR5210) { ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | @@ -378,7 +566,6 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) /* * Bring up MAC + PHY Chips and program PLL - * TODO: Half/Quarter rate support */ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) { @@ -390,11 +577,13 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) mode = 0; clock = 0; - /* Wakeup the device */ - ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); - if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); - return ret; + if ((ath5k_get_bus_type(ah) != ATH_AHB) || !initial) { + /* Wakeup the device */ + ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); + if (ret) { + ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); + return ret; + } } /* @@ -405,7 +594,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) * we ingore that flag for PCI-E cards. On PCI cards * this flag gets cleared after 64 PCI clocks. */ - bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; + bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI; if (ah->ah_version == AR5K_AR5210) { ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | @@ -413,8 +602,12 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); mdelay(2); } else { - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_BASEBAND | bus_flags); + if (ath5k_get_bus_type(ah) == ATH_AHB) + ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU | + AR5K_RESET_CTL_BASEBAND); + else + ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | + AR5K_RESET_CTL_BASEBAND | bus_flags); } if (ret) { @@ -429,9 +622,15 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) return ret; } - /* ...clear reset control register and pull device out of - * warm reset */ - if (ath5k_hw_nic_reset(ah, 0)) { + /* ...reset configuration regiter on Wisoc ... + * ...clear reset control register and pull device out of + * warm reset on others */ + if (ath5k_get_bus_type(ah) == ATH_AHB) + ret = ath5k_hw_wisoc_reset(ah, 0); + else + ret = ath5k_hw_nic_reset(ah, 0); + + if (ret) { ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); return -EIO; } @@ -466,7 +665,8 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) * CCK headers) operation. We need to test * this, 5211 might support ofdm-only g after * all, there are also initial register values - * in the code for g mode (see initvals.c). */ + * in the code for g mode (see initvals.c). + */ if (ah->ah_version == AR5K_AR5211) mode |= AR5K_PHY_MODE_MOD_OFDM; else @@ -479,6 +679,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) } else if (flags & CHANNEL_5GHZ) { mode |= AR5K_PHY_MODE_FREQ_5GHZ; + /* Different PLL setting for 5413 */ if (ah->ah_radio == AR5K_RF5413) clock = AR5K_PHY_PLL_40MHZ_5413; else @@ -496,12 +697,29 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) return -EINVAL; } - if (flags & CHANNEL_TURBO) - turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT; + /*XXX: Can bwmode be used with dynamic mode ? + * (I don't think it supports 44MHz) */ + /* On 2425 initvals TURBO_SHORT is not pressent */ + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) { + turbo = AR5K_PHY_TURBO_MODE | + (ah->ah_radio == AR5K_RF2425) ? 0 : + AR5K_PHY_TURBO_SHORT; + } else if (ah->ah_bwmode != AR5K_BWMODE_DEFAULT) { + if (ah->ah_radio == AR5K_RF5413) { + mode |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ? + AR5K_PHY_MODE_HALF_RATE : + AR5K_PHY_MODE_QUARTER_RATE; + } else if (ah->ah_version == AR5K_AR5212) { + clock |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ? + AR5K_PHY_PLL_HALF_RATE : + AR5K_PHY_PLL_QUARTER_RATE; + } + } + } else { /* Reset the device */ /* ...enable Atheros turbo mode if requested */ - if (flags & CHANNEL_TURBO) + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE, AR5K_PHY_TURBO); } @@ -522,107 +740,10 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) return 0; } -/* - * If there is an external 32KHz crystal available, use it - * as ref. clock instead of 32/40MHz clock and baseband clocks - * to save power during sleep or restore normal 32/40MHz - * operation. - * - * XXX: When operating on 32KHz certain PHY registers (27 - 31, - * 123 - 127) require delay on access. - */ -static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 scal, spending, usec32; - /* Only set 32KHz settings if we have an external - * 32KHz crystal present */ - if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) || - AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) && - enable) { - - /* 1 usec/cycle */ - AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1); - /* Set up tsf increment on each cycle */ - AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61); - - /* Set baseband sleep control registers - * and sleep control rate */ - ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - spending = 0x14; - else - spending = 0x18; - ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { - ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT); - ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL); - ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY); - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02); - } else { - ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT); - ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL); - ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY); - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03); - } - - /* Enable sleep clock operation */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_EN); - - } else { - - /* Disable sleep clock operation and - * restore default parameters */ - AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_EN); - - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0); - - ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); - ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); - - if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) - scal = AR5K_PHY_SCAL_32MHZ_2417; - else if (ee->ee_is_hb63) - scal = AR5K_PHY_SCAL_32MHZ_HB63; - else - scal = AR5K_PHY_SCAL_32MHZ; - ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); - - ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - spending = 0x14; - else - spending = 0x18; - ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413)) - usec32 = 39; - else - usec32 = 31; - AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32); - - AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); - } -} +/**************************************\ +* Post-initvals register modifications * +\**************************************/ /* TODO: Half/Quarter rate */ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, @@ -663,22 +784,10 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_DCU_DBL_BUF_DIS); - /* Set DAC/ADC delays */ - if (ah->ah_version == AR5K_AR5212) { - u32 scal; - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) - scal = AR5K_PHY_SCAL_32MHZ_2417; - else if (ee->ee_is_hb63) - scal = AR5K_PHY_SCAL_32MHZ_HB63; - else - scal = AR5K_PHY_SCAL_32MHZ; - ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); - } - /* Set fast ADC */ if ((ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { + (ah->ah_radio == AR5K_RF2317) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { u32 fast_adc = true; if (channel->center_freq == 2462 || @@ -706,33 +815,68 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, } if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - u32 usec_reg; - /* 5311 has different tx/rx latency masks - * from 5211, since we deal 5311 the same - * as 5211 when setting initvals, shift - * values here to their proper locations */ - usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211); - ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 | - AR5K_USEC_32 | - AR5K_USEC_TX_LATENCY_5211 | - AR5K_REG_SM(29, - AR5K_USEC_RX_LATENCY_5210)), - AR5K_USEC_5211); /* Clear QCU/DCU clock gating register */ ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT); /* Set DAC/ADC delays */ - ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL); + ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ_5311, + AR5K_PHY_SCAL); /* Enable PCU FIFO corruption ECO */ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, AR5K_DIAG_SW_ECO_ENABLE); } + + if (ah->ah_bwmode) { + /* Increase PHY switch and AGC settling time + * on turbo mode (ath5k_hw_commit_eeprom_settings + * will override settling time if available) */ + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) { + + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, + AR5K_PHY_SETTLING_AGC, + AR5K_AGC_SETTLING_TURBO); + + /* XXX: Initvals indicate we only increase + * switch time on AR5212, 5211 and 5210 + * only change agc time (bug?) */ + if (ah->ah_version == AR5K_AR5212) + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, + AR5K_PHY_SETTLING_SWITCH, + AR5K_SWITCH_SETTLING_TURBO); + + if (ah->ah_version == AR5K_AR5210) { + /* Set Frame Control Register */ + ath5k_hw_reg_write(ah, + (AR5K_PHY_FRAME_CTL_INI | + AR5K_PHY_TURBO_MODE | + AR5K_PHY_TURBO_SHORT | 0x2020), + AR5K_PHY_FRAME_CTL_5210); + } + /* On 5413 PHY force window length for half/quarter rate*/ + } else if ((ah->ah_mac_srev >= AR5K_SREV_AR5424) && + (ah->ah_mac_srev <= AR5K_SREV_AR5414)) { + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL_5211, + AR5K_PHY_FRAME_CTL_WIN_LEN, + 3); + } + } else if (ah->ah_version == AR5K_AR5210) { + /* Set Frame Control Register for normal operation */ + ath5k_hw_reg_write(ah, (AR5K_PHY_FRAME_CTL_INI | 0x1020), + AR5K_PHY_FRAME_CTL_5210); + } } static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, - struct ieee80211_channel *channel, u8 ee_mode) + struct ieee80211_channel *channel) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; s16 cck_ofdm_pwr_delta; + u8 ee_mode; + + /* TODO: Add support for AR5210 EEPROM */ + if (ah->ah_version == AR5K_AR5210) + return; + + ee_mode = ath5k_eeprom_mode_from_channel(channel); /* Adjust power delta for channel 14 */ if (channel->center_freq == 2484) @@ -772,7 +916,7 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), AR5K_PHY_NFTHRES); - if ((channel->hw_value & CHANNEL_TURBO) && + if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) && (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) { /* Switch settling time (Turbo) */ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, @@ -870,143 +1014,172 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE); } -/* - * Main reset function - */ + +/*********************\ +* Main reset function * +\*********************/ + int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, - struct ieee80211_channel *channel, bool change_channel) + struct ieee80211_channel *channel, bool fast, bool skip_pcu) { - struct ath_common *common = ath5k_hw_common(ah); - u32 s_seq[10], s_led[3], staid1_flags, tsf_up, tsf_lo; - u32 phy_tst1; - u8 mode, freq, ee_mode; + u32 s_seq[10], s_led[3], tsf_up, tsf_lo; + u8 mode; int i, ret; - ee_mode = 0; - staid1_flags = 0; tsf_up = 0; tsf_lo = 0; - freq = 0; mode = 0; /* - * Save some registers before a reset + * Sanity check for fast flag + * Fast channel change only available + * on AR2413/AR5413. */ - /*DCU/Antenna selection not available on 5210*/ - if (ah->ah_version != AR5K_AR5210) { + if (fast && (ah->ah_radio != AR5K_RF2413) && + (ah->ah_radio != AR5K_RF5413)) + fast = 0; - switch (channel->hw_value & CHANNEL_MODES) { - case CHANNEL_A: - mode = AR5K_MODE_11A; - freq = AR5K_INI_RFGAIN_5GHZ; - ee_mode = AR5K_EEPROM_MODE_11A; - break; - case CHANNEL_G: - mode = AR5K_MODE_11G; - freq = AR5K_INI_RFGAIN_2GHZ; - ee_mode = AR5K_EEPROM_MODE_11G; - break; - case CHANNEL_B: - mode = AR5K_MODE_11B; - freq = AR5K_INI_RFGAIN_2GHZ; - ee_mode = AR5K_EEPROM_MODE_11B; - break; - case CHANNEL_T: - mode = AR5K_MODE_11A_TURBO; - freq = AR5K_INI_RFGAIN_5GHZ; - ee_mode = AR5K_EEPROM_MODE_11A; - break; - case CHANNEL_TG: - if (ah->ah_version == AR5K_AR5211) { - ATH5K_ERR(ah->ah_sc, - "TurboG mode not available on 5211"); - return -EINVAL; - } - mode = AR5K_MODE_11G_TURBO; - freq = AR5K_INI_RFGAIN_2GHZ; - ee_mode = AR5K_EEPROM_MODE_11G; - break; - case CHANNEL_XR: - if (ah->ah_version == AR5K_AR5211) { - ATH5K_ERR(ah->ah_sc, - "XR mode not available on 5211"); - return -EINVAL; - } - mode = AR5K_MODE_XR; - freq = AR5K_INI_RFGAIN_5GHZ; - ee_mode = AR5K_EEPROM_MODE_11A; - break; - default: + /* Disable sleep clock operation + * to avoid register access delay on certain + * PHY registers */ + if (ah->ah_version == AR5K_AR5212) + ath5k_hw_set_sleep_clock(ah, false); + + /* + * Stop PCU + */ + ath5k_hw_stop_rx_pcu(ah); + + /* + * Stop DMA + * + * Note: If DMA didn't stop continue + * since only a reset will fix it. + */ + ret = ath5k_hw_dma_stop(ah); + + /* RF Bus grant won't work if we have pending + * frames */ + if (ret && fast) { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, + "DMA didn't stop, falling back to normal reset\n"); + fast = 0; + /* Non fatal, just continue with + * normal reset */ + ret = 0; + } + + switch (channel->hw_value & CHANNEL_MODES) { + case CHANNEL_A: + mode = AR5K_MODE_11A; + break; + case CHANNEL_G: + + if (ah->ah_version <= AR5K_AR5211) { ATH5K_ERR(ah->ah_sc, - "invalid channel: %d\n", channel->center_freq); + "G mode not available on 5210/5211"); return -EINVAL; } - if (change_channel) { - /* - * Save frame sequence count - * For revs. after Oahu, only save - * seq num for DCU 0 (Global seq num) - */ - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - - for (i = 0; i < 10; i++) - s_seq[i] = ath5k_hw_reg_read(ah, - AR5K_QUEUE_DCU_SEQNUM(i)); + mode = AR5K_MODE_11G; + break; + case CHANNEL_B: - } else { - s_seq[0] = ath5k_hw_reg_read(ah, - AR5K_QUEUE_DCU_SEQNUM(0)); - } + if (ah->ah_version < AR5K_AR5211) { + ATH5K_ERR(ah->ah_sc, + "B mode not available on 5210"); + return -EINVAL; + } - /* TSF accelerates on AR5211 during reset - * As a workaround save it here and restore - * it later so that it's back in time after - * reset. This way it'll get re-synced on the - * next beacon without breaking ad-hoc. - * - * On AR5212 TSF is almost preserved across a - * reset so it stays back in time anyway and - * we don't have to save/restore it. - * - * XXX: Since this breaks power saving we have - * to disable power saving until we receive the - * next beacon, so we can resync beacon timers */ - if (ah->ah_version == AR5K_AR5211) { - tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32); - tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32); - } + mode = AR5K_MODE_11B; + break; + case CHANNEL_XR: + if (ah->ah_version == AR5K_AR5211) { + ATH5K_ERR(ah->ah_sc, + "XR mode not available on 5211"); + return -EINVAL; } + mode = AR5K_MODE_XR; + break; + default: + ATH5K_ERR(ah->ah_sc, + "invalid channel: %d\n", channel->center_freq); + return -EINVAL; + } - if (ah->ah_version == AR5K_AR5212) { - /* Restore normal 32/40MHz clock operation - * to avoid register access delay on certain - * PHY registers */ - ath5k_hw_set_sleep_clock(ah, false); + /* + * If driver requested fast channel change and DMA has stopped + * go on. If it fails continue with a normal reset. + */ + if (fast) { + ret = ath5k_hw_phy_init(ah, channel, mode, true); + if (ret) { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, + "fast chan change failed, falling back to normal reset\n"); + /* Non fatal, can happen eg. + * on mode change */ + ret = 0; + } else + return 0; + } - /* Since we are going to write rf buffer - * check if we have any pending gain_F - * optimization settings */ - if (change_channel && ah->ah_rf_banks != NULL) - ath5k_hw_gainf_calibrate(ah); + /* + * Save some registers before a reset + */ + if (ah->ah_version != AR5K_AR5210) { + /* + * Save frame sequence count + * For revs. after Oahu, only save + * seq num for DCU 0 (Global seq num) + */ + if (ah->ah_mac_srev < AR5K_SREV_AR5211) { + + for (i = 0; i < 10; i++) + s_seq[i] = ath5k_hw_reg_read(ah, + AR5K_QUEUE_DCU_SEQNUM(i)); + + } else { + s_seq[0] = ath5k_hw_reg_read(ah, + AR5K_QUEUE_DCU_SEQNUM(0)); + } + + /* TSF accelerates on AR5211 during reset + * As a workaround save it here and restore + * it later so that it's back in time after + * reset. This way it'll get re-synced on the + * next beacon without breaking ad-hoc. + * + * On AR5212 TSF is almost preserved across a + * reset so it stays back in time anyway and + * we don't have to save/restore it. + * + * XXX: Since this breaks power saving we have + * to disable power saving until we receive the + * next beacon, so we can resync beacon timers */ + if (ah->ah_version == AR5K_AR5211) { + tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32); + tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32); } } + /*GPIOs*/ s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_LEDSTATE; s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR); s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); - /* AR5K_STA_ID1 flags, only preserve antenna - * settings and ack/cts rate mode */ - staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & - (AR5K_STA_ID1_DEFAULT_ANTENNA | - AR5K_STA_ID1_DESC_ANTENNA | - AR5K_STA_ID1_RTS_DEF_ANTENNA | - AR5K_STA_ID1_ACKCTS_6MB | - AR5K_STA_ID1_BASE_RATE_11B | - AR5K_STA_ID1_SELFGEN_DEF_ANT); + + /* + * Since we are going to write rf buffer + * check if we have any pending gain_F + * optimization settings + */ + if (ah->ah_version == AR5K_AR5212 && + (ah->ah_radio <= AR5K_RF5112)) { + if (!fast && ah->ah_rf_banks != NULL) + ath5k_hw_gainf_calibrate(ah); + } /* Wakeup the device */ ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); @@ -1021,121 +1194,42 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, AR5K_PHY(0)); /* Write initial settings */ - ret = ath5k_hw_write_initvals(ah, mode, change_channel); + ret = ath5k_hw_write_initvals(ah, mode, skip_pcu); if (ret) return ret; + /* Initialize core clock settings */ + ath5k_hw_init_core_clock(ah); + /* - * 5211/5212 Specific + * Tweak initval settings for revised + * chipsets and add some more config + * bits */ - if (ah->ah_version != AR5K_AR5210) { - - /* - * Write initial RF gain settings - * This should work for both 5111/5112 - */ - ret = ath5k_hw_rfgain_init(ah, freq); - if (ret) - return ret; - - mdelay(1); - - /* - * Tweak initval settings for revised - * chipsets and add some more config - * bits - */ - ath5k_hw_tweak_initval_settings(ah, channel); - - /* - * Set TX power - */ - ret = ath5k_hw_txpower(ah, channel, ee_mode, - ah->ah_txpower.txp_max_pwr / 2); - if (ret) - return ret; + ath5k_hw_tweak_initval_settings(ah, channel); - /* Write rate duration table only on AR5212 and if - * virtual interface has already been brought up - * XXX: rethink this after new mode changes to - * mac80211 are integrated */ - if (ah->ah_version == AR5K_AR5212 && - ah->ah_sc->nvifs) - ath5k_hw_write_rate_duration(ah, mode); + /* Commit values from EEPROM */ + ath5k_hw_commit_eeprom_settings(ah, channel); - /* - * Write RF buffer - */ - ret = ath5k_hw_rfregs_init(ah, channel, mode); - if (ret) - return ret; - - - /* Write OFDM timings on 5212*/ - if (ah->ah_version == AR5K_AR5212 && - channel->hw_value & CHANNEL_OFDM) { - - ret = ath5k_hw_write_ofdm_timings(ah, channel); - if (ret) - return ret; - - /* Spur info is available only from EEPROM versions - * greater than 5.3, but the EEPROM routines will use - * static values for older versions */ - if (ah->ah_mac_srev >= AR5K_SREV_AR5424) - ath5k_hw_set_spur_mitigation_filter(ah, - channel); - } - - /*Enable/disable 802.11b mode on 5111 - (enable 2111 frequency converter + CCK)*/ - if (ah->ah_radio == AR5K_RF5111) { - if (mode == AR5K_MODE_11B) - AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_B_MODE); - else - AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_B_MODE); - } - - /* Commit values from EEPROM */ - ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode); - - } else { - /* - * For 5210 we do all initialization using - * initvals, so we don't have to modify - * any settings (5210 also only supports - * a/aturbo modes) - */ - mdelay(1); - /* Disable phy and wait */ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); - mdelay(1); - } /* * Restore saved values */ - /*DCU/Antenna selection not available on 5210*/ + /* Seqnum, TSF */ if (ah->ah_version != AR5K_AR5210) { + if (ah->ah_mac_srev < AR5K_SREV_AR5211) { + for (i = 0; i < 10; i++) + ath5k_hw_reg_write(ah, s_seq[i], + AR5K_QUEUE_DCU_SEQNUM(i)); + } else { + ath5k_hw_reg_write(ah, s_seq[0], + AR5K_QUEUE_DCU_SEQNUM(0)); + } - if (change_channel) { - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - for (i = 0; i < 10; i++) - ath5k_hw_reg_write(ah, s_seq[i], - AR5K_QUEUE_DCU_SEQNUM(i)); - } else { - ath5k_hw_reg_write(ah, s_seq[0], - AR5K_QUEUE_DCU_SEQNUM(0)); - } - - - if (ah->ah_version == AR5K_AR5211) { - ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32); - ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); - } + if (ah->ah_version == AR5K_AR5211) { + ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32); + ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); } } @@ -1146,203 +1240,34 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR); ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); - /* Restore sta_id flags and preserve our mac address*/ - ath5k_hw_reg_write(ah, - get_unaligned_le32(common->macaddr), - AR5K_STA_ID0); - ath5k_hw_reg_write(ah, - staid1_flags | get_unaligned_le16(common->macaddr + 4), - AR5K_STA_ID1); - - /* - * Configure PCU + * Initialize PCU */ - - /* Restore bssid and bssid mask */ - ath5k_hw_set_bssid(ah); - - /* Set PCU config */ - ath5k_hw_set_opmode(ah, op_mode); - - /* Clear any pending interrupts - * PISR/SISR Not available on 5210 */ - if (ah->ah_version != AR5K_AR5210) - ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); - - /* Set RSSI/BRSSI thresholds - * - * Note: If we decide to set this value - * dynamically, keep in mind that when AR5K_RSSI_THR - * register is read, it might return 0x40 if we haven't - * written anything to it. Also, BMISS RSSI threshold is zeroed. - * So doing a save/restore procedure here isn't the right - * choice. Instead, store it in ath5k_hw */ - ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | - AR5K_TUNE_BMISS_THRES << - AR5K_RSSI_THR_BMISS_S), - AR5K_RSSI_THR); - - /* MIC QoS support */ - if (ah->ah_mac_srev >= AR5K_SREV_AR2413) { - ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL); - ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL); - } - - /* QoS NOACK Policy */ - if (ah->ah_version == AR5K_AR5212) { - ath5k_hw_reg_write(ah, - AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) | - AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) | - AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET), - AR5K_QOS_NOACK); - } - + ath5k_hw_pcu_init(ah, op_mode, mode); /* - * Configure PHY + * Initialize PHY */ - - /* Set channel on PHY */ - ret = ath5k_hw_channel(ah, channel); - if (ret) + ret = ath5k_hw_phy_init(ah, channel, mode, false); + if (ret) { + ATH5K_ERR(ah->ah_sc, + "failed to initialize PHY (%i) !\n", ret); return ret; - - /* - * Enable the PHY and wait until completion - * This includes BaseBand and Synthesizer - * activation. - */ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); - - /* - * On 5211+ read activation -> rx delay - * and use it. - * - * TODO: Half/quarter rate support - */ - if (ah->ah_version != AR5K_AR5210) { - u32 delay; - delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & - AR5K_PHY_RX_DELAY_M; - delay = (channel->hw_value & CHANNEL_CCK) ? - ((delay << 2) / 22) : (delay / 10); - - udelay(100 + (2 * delay)); - } else { - mdelay(1); } /* - * Perform ADC test to see if baseband is ready - * Set TX hold and check ADC test register - */ - phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); - ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); - for (i = 0; i <= 20; i++) { - if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) - break; - udelay(200); - } - ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); - - /* - * Start automatic gain control calibration - * - * During AGC calibration RX path is re-routed to - * a power detector so we don't receive anything. - * - * This method is used to calibrate some static offsets - * used together with on-the fly I/Q calibration (the - * one performed via ath5k_hw_phy_calibrate), which doesn't - * interrupt rx path. - * - * While rx path is re-routed to the power detector we also - * start a noise floor calibration to measure the - * card's noise floor (the noise we measure when we are not - * transmitting or receiving anything). - * - * If we are in a noisy environment, AGC calibration may time - * out and/or noise floor calibration might timeout. - */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); - - /* At the same time start I/Q calibration for QAM constellation - * -no need for CCK- */ - ah->ah_calibration = false; - if (!(mode == AR5K_MODE_11B)) { - ah->ah_calibration = true; - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_RUN); - } - - /* Wait for gain calibration to finish (we check for I/Q calibration - * during ath5k_phy_calibrate) */ - if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL, 0, false)) { - ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", - channel->center_freq); - } - - /* Restore antenna mode */ - ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); - - /* Restore slot time and ACK timeouts */ - if (ah->ah_coverage_class > 0) - ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); - - /* * Configure QCUs/DCUs */ + ret = ath5k_hw_init_queues(ah); + if (ret) + return ret; - /* TODO: HW Compression support for data queues */ - /* TODO: Burst prefetch for data queues */ - - /* - * Reset queues and start beacon timers at the end of the reset routine - * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping - * Note: If we want we can assign multiple qcus on one dcu. - */ - for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { - ret = ath5k_hw_reset_tx_queue(ah, i); - if (ret) { - ATH5K_ERR(ah->ah_sc, - "failed to reset TX queue #%d\n", i); - return ret; - } - } - - - /* - * Configure DMA/Interrupts - */ /* - * Set Rx/Tx DMA Configuration - * - * Set standard DMA size (128). Note that - * a DMA size of 512 causes rx overruns and tx errors - * on pci-e cards (tested on 5424 but since rx overruns - * also occur on 5416/5418 with madwifi we set 128 - * for all PCI-E cards to be safe). - * - * XXX: need to check 5210 for this - * TODO: Check out tx triger level, it's always 64 on dumps but I - * guess we can tweak it and see how it goes ;-) + * Initialize DMA/Interrupts */ - if (ah->ah_version != AR5K_AR5210) { - AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); - AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, - AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); - } + ath5k_hw_dma_init(ah); - /* Pre-enable interrupts on 5211/5212*/ - if (ah->ah_version != AR5K_AR5210) - ath5k_hw_set_imr(ah, ah->ah_imr); /* Enable 32KHz clock function for AR5212+ chips * Set clocks to 32KHz operation and use an diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h index 3ac4cff4239d..16b67e84906d 100644 --- a/drivers/net/wireless/ath/ath5k/rfbuffer.h +++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h @@ -51,7 +51,7 @@ struct ath5k_ini_rfbuffer { u8 rfb_bank; /* RF Bank number */ u16 rfb_ctrl_register; /* RF Buffer control register */ - u32 rfb_mode_data[5]; /* RF Buffer data for each mode */ + u32 rfb_mode_data[3]; /* RF Buffer data for each mode */ }; /* @@ -79,8 +79,10 @@ struct ath5k_rf_reg { * life easier by using an index for each register * instead of a full rfb_field */ enum ath5k_rf_regs_idx { + /* BANK 2 */ + AR5K_RF_TURBO = 0, /* BANK 6 */ - AR5K_RF_OB_2GHZ = 0, + AR5K_RF_OB_2GHZ, AR5K_RF_OB_5GHZ, AR5K_RF_DB_2GHZ, AR5K_RF_DB_5GHZ, @@ -134,6 +136,9 @@ enum ath5k_rf_regs_idx { * RF5111 (Sombrero) * \*******************/ +/* BANK 2 len pos col */ +#define AR5K_RF5111_RF_TURBO { 1, 3, 0 } + /* BANK 6 len pos col */ #define AR5K_RF5111_OB_2GHZ { 3, 119, 0 } #define AR5K_RF5111_DB_2GHZ { 3, 122, 0 } @@ -158,6 +163,7 @@ enum ath5k_rf_regs_idx { #define AR5K_RF5111_MAX_TIME { 2, 49, 0 } static const struct ath5k_rf_reg rf_regs_5111[] = { + {2, AR5K_RF_TURBO, AR5K_RF5111_RF_TURBO}, {6, AR5K_RF_OB_2GHZ, AR5K_RF5111_OB_2GHZ}, {6, AR5K_RF_DB_2GHZ, AR5K_RF5111_DB_2GHZ}, {6, AR5K_RF_OB_5GHZ, AR5K_RF5111_OB_5GHZ}, @@ -177,97 +183,52 @@ static const struct ath5k_rf_reg rf_regs_5111[] = { /* Default mode specific settings */ static const struct ath5k_ini_rfbuffer rfb_5111[] = { - { 0, 0x989c, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } }, - { 0, 0x989c, - { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } }, - { 0, 0x98d4, - { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } }, - { 1, 0x98d4, - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d4, - { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } }, - { 3, 0x98d8, - { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } }, - { 6, 0x989c, - { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } }, - { 6, 0x989c, - { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } }, - { 6, 0x989c, - { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } }, - { 6, 0x989c, - { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } }, - { 6, 0x98d4, - { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } }, - { 7, 0x989c, - { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } }, - { 7, 0x989c, - { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } }, - { 7, 0x989c, - { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, - { 7, 0x989c, - { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } }, - { 7, 0x989c, - { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } }, - { 7, 0x989c, - { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } }, - { 7, 0x989c, - { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00380000, 0x00380000, 0x00380000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x000000c0, 0x00000080 } }, + { 0, 0x989c, { 0x000400f9, 0x000400ff, 0x000400fd } }, + { 0, 0x98d4, { 0x00000000, 0x00000004, 0x00000004 } }, + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d4, { 0x00000010, 0x00000010, 0x00000010 } }, + { 3, 0x98d8, { 0x00601068, 0x00601068, 0x00601068 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } }, + { 6, 0x989c, { 0x04000000, 0x04000000, 0x04000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x0a000000, 0x00000000 } }, + { 6, 0x989c, { 0x003800c0, 0x023800c0, 0x003800c0 } }, + { 6, 0x989c, { 0x00020006, 0x00000006, 0x00020006 } }, + { 6, 0x989c, { 0x00000089, 0x00000089, 0x00000089 } }, + { 6, 0x989c, { 0x000000a0, 0x000000a0, 0x000000a0 } }, + { 6, 0x989c, { 0x00040007, 0x00040007, 0x00040007 } }, + { 6, 0x98d4, { 0x0000001a, 0x0000001a, 0x0000001a } }, + { 7, 0x989c, { 0x00000040, 0x00000040, 0x00000040 } }, + { 7, 0x989c, { 0x00000010, 0x00000010, 0x00000010 } }, + { 7, 0x989c, { 0x00000008, 0x00000008, 0x00000008 } }, + { 7, 0x989c, { 0x0000004f, 0x0000004f, 0x0000004f } }, + { 7, 0x989c, { 0x000000f1, 0x00000061, 0x000000f1 } }, + { 7, 0x989c, { 0x0000904f, 0x0000904c, 0x0000904f } }, + { 7, 0x989c, { 0x0000125a, 0x0000129a, 0x0000125a } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000f, 0x0000000e } }, }; @@ -276,6 +237,9 @@ static const struct ath5k_ini_rfbuffer rfb_5111[] = { * RF5112/RF2112 (Derby) * \***********************/ +/* BANK 2 (Common) len pos col */ +#define AR5K_RF5112X_RF_TURBO { 1, 1, 2 } + /* BANK 7 (Common) len pos col */ #define AR5K_RF5112X_GAIN_I { 6, 14, 0 } #define AR5K_RF5112X_MIXVGA_OVR { 1, 36, 0 } @@ -307,6 +271,7 @@ static const struct ath5k_ini_rfbuffer rfb_5111[] = { #define AR5K_RF5112_PWD(_n) { 1, (302 - _n), 3 } static const struct ath5k_rf_reg rf_regs_5112[] = { + {2, AR5K_RF_TURBO, AR5K_RF5112X_RF_TURBO}, {6, AR5K_RF_OB_2GHZ, AR5K_RF5112_OB_2GHZ}, {6, AR5K_RF_DB_2GHZ, AR5K_RF5112_DB_2GHZ}, {6, AR5K_RF_OB_5GHZ, AR5K_RF5112_OB_5GHZ}, @@ -335,115 +300,61 @@ static const struct ath5k_rf_reg rf_regs_5112[] = { /* Default mode specific settings */ static const struct ath5k_ini_rfbuffer rfb_5112[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, - { 3, 0x98dc, - { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } }, - { 6, 0x989c, - { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } }, - { 6, 0x989c, - { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } }, - { 6, 0x989c, - { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } }, - { 6, 0x989c, - { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } }, - { 6, 0x989c, - { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, - { 6, 0x989c, - { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } }, - { 6, 0x989c, - { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } }, - { 6, 0x989c, - { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, - { 6, 0x989c, - { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, - { 6, 0x989c, - { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } }, - { 6, 0x989c, - { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } }, - { 6, 0x989c, - { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, - { 6, 0x989c, - { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } }, - { 6, 0x989c, - { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, - { 6, 0x989c, - { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, - { 6, 0x989c, - { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } }, - { 6, 0x989c, - { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } }, - { 6, 0x989c, - { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, - { 6, 0x989c, - { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } }, - { 6, 0x989c, - { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } }, - { 6, 0x989c, - { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } }, - { 6, 0x989c, - { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } }, - { 6, 0x989c, - { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } }, - { 6, 0x989c, - { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } }, - { 6, 0x989c, - { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } }, - { 6, 0x989c, - { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } }, - { 6, 0x989c, - { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } }, - { 6, 0x989c, - { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } }, - { 6, 0x98d0, - { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } }, - { 7, 0x989c, - { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, - { 7, 0x989c, - { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, - { 7, 0x989c, - { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } }, - { 7, 0x989c, - { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, - { 7, 0x989c, - { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } }, - { 7, 0x989c, - { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, - { 7, 0x989c, - { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, - { 7, 0x989c, - { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } }, - { 7, 0x989c, - { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } }, - { 7, 0x989c, - { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, - { 7, 0x989c, - { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, - { 7, 0x989c, - { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, - { 7, 0x98c4, - { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x03060408, 0x03060408, 0x03060408 } }, + { 3, 0x98dc, { 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0 } }, + { 6, 0x989c, { 0x00a00000, 0x00a00000, 0x00a00000 } }, + { 6, 0x989c, { 0x000a0000, 0x000a0000, 0x000a0000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00660000, 0x00660000, 0x00660000 } }, + { 6, 0x989c, { 0x00db0000, 0x00db0000, 0x00db0000 } }, + { 6, 0x989c, { 0x00f10000, 0x00f10000, 0x00f10000 } }, + { 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } }, + { 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } }, + { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x008b0000, 0x008b0000, 0x008b0000 } }, + { 6, 0x989c, { 0x00600000, 0x00600000, 0x00600000 } }, + { 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } }, + { 6, 0x989c, { 0x00840000, 0x00840000, 0x00840000 } }, + { 6, 0x989c, { 0x00640000, 0x00640000, 0x00640000 } }, + { 6, 0x989c, { 0x00200000, 0x00200000, 0x00200000 } }, + { 6, 0x989c, { 0x00240000, 0x00240000, 0x00240000 } }, + { 6, 0x989c, { 0x00250000, 0x00250000, 0x00250000 } }, + { 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } }, + { 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } }, + { 6, 0x989c, { 0x00510000, 0x00510000, 0x00510000 } }, + { 6, 0x989c, { 0x1c040000, 0x1c040000, 0x1c040000 } }, + { 6, 0x989c, { 0x000a0000, 0x000a0000, 0x000a0000 } }, + { 6, 0x989c, { 0x00a10000, 0x00a10000, 0x00a10000 } }, + { 6, 0x989c, { 0x00400000, 0x00400000, 0x00400000 } }, + { 6, 0x989c, { 0x03090000, 0x03090000, 0x03090000 } }, + { 6, 0x989c, { 0x06000000, 0x06000000, 0x06000000 } }, + { 6, 0x989c, { 0x000000b0, 0x000000a8, 0x000000a8 } }, + { 6, 0x989c, { 0x0000002e, 0x0000002e, 0x0000002e } }, + { 6, 0x989c, { 0x006c4a41, 0x006c4af1, 0x006c4a61 } }, + { 6, 0x989c, { 0x0050892a, 0x0050892b, 0x0050892b } }, + { 6, 0x989c, { 0x00842400, 0x00842400, 0x00842400 } }, + { 6, 0x989c, { 0x00c69200, 0x00c69200, 0x00c69200 } }, + { 6, 0x98d0, { 0x0002000c, 0x0002000c, 0x0002000c } }, + { 7, 0x989c, { 0x00000094, 0x00000094, 0x00000094 } }, + { 7, 0x989c, { 0x00000091, 0x00000091, 0x00000091 } }, + { 7, 0x989c, { 0x0000000a, 0x00000012, 0x00000012 } }, + { 7, 0x989c, { 0x00000080, 0x00000080, 0x00000080 } }, + { 7, 0x989c, { 0x000000c1, 0x000000c1, 0x000000c1 } }, + { 7, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } }, + { 7, 0x989c, { 0x000000f0, 0x000000f0, 0x000000f0 } }, + { 7, 0x989c, { 0x00000022, 0x00000022, 0x00000022 } }, + { 7, 0x989c, { 0x00000092, 0x00000092, 0x00000092 } }, + { 7, 0x989c, { 0x000000d4, 0x000000d4, 0x000000d4 } }, + { 7, 0x989c, { 0x000014cc, 0x000014cc, 0x000014cc } }, + { 7, 0x989c, { 0x0000048c, 0x0000048c, 0x0000048c } }, + { 7, 0x98c4, { 0x00000003, 0x00000003, 0x00000003 } }, }; /* RFX112A (Derby 2) */ @@ -477,6 +388,7 @@ static const struct ath5k_ini_rfbuffer rfb_5112[] = { #define AR5K_RF5112A_XB5_LVL { 2, 3, 3 } static const struct ath5k_rf_reg rf_regs_5112a[] = { + {2, AR5K_RF_TURBO, AR5K_RF5112X_RF_TURBO}, {6, AR5K_RF_OB_2GHZ, AR5K_RF5112A_OB_2GHZ}, {6, AR5K_RF_DB_2GHZ, AR5K_RF5112A_DB_2GHZ}, {6, AR5K_RF_OB_5GHZ, AR5K_RF5112A_OB_5GHZ}, @@ -515,119 +427,63 @@ static const struct ath5k_rf_reg rf_regs_5112a[] = { /* Default mode specific settings */ static const struct ath5k_ini_rfbuffer rfb_5112a[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } }, - { 6, 0x989c, - { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } }, - { 6, 0x989c, - { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } }, - { 6, 0x989c, - { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } }, - { 6, 0x989c, - { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } }, - { 6, 0x989c, - { 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 } }, - { 6, 0x989c, - { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } }, - { 6, 0x989c, - { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, - { 6, 0x989c, - { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } }, - { 6, 0x989c, - { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, - { 6, 0x989c, - { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } }, - { 6, 0x989c, - { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } }, - { 6, 0x989c, - { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, - { 6, 0x989c, - { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } }, - { 6, 0x989c, - { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } }, - { 6, 0x989c, - { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, - { 6, 0x989c, - { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } }, - { 6, 0x989c, - { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } }, - { 6, 0x989c, - { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } }, - { 6, 0x989c, - { 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 } }, - { 6, 0x989c, - { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } }, - { 6, 0x989c, - { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } }, - { 6, 0x989c, - { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } }, - { 6, 0x989c, - { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } }, - { 6, 0x989c, - { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } }, - { 6, 0x98d8, - { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } }, - { 7, 0x989c, - { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, - { 7, 0x989c, - { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, - { 7, 0x989c, - { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } }, - { 7, 0x989c, - { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, - { 7, 0x989c, - { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } }, - { 7, 0x989c, - { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, - { 7, 0x989c, - { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, - { 7, 0x989c, - { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } }, - { 7, 0x989c, - { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } }, - { 7, 0x989c, - { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, - { 7, 0x989c, - { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, - { 7, 0x989c, - { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, - { 7, 0x98c4, - { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x03060408, 0x03060408, 0x03060408 } }, + { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, { 0x0f000000, 0x0f000000, 0x0f000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00800000, 0x00800000, 0x00800000 } }, + { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, { 0x00010000, 0x00010000, 0x00010000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00180000, 0x00180000, 0x00180000 } }, + { 6, 0x989c, { 0x00600000, 0x006e0000, 0x006e0000 } }, + { 6, 0x989c, { 0x00c70000, 0x00c70000, 0x00c70000 } }, + { 6, 0x989c, { 0x004b0000, 0x004b0000, 0x004b0000 } }, + { 6, 0x989c, { 0x04480000, 0x04480000, 0x04480000 } }, + { 6, 0x989c, { 0x004c0000, 0x004c0000, 0x004c0000 } }, + { 6, 0x989c, { 0x00e40000, 0x00e40000, 0x00e40000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00fc0000, 0x00fc0000, 0x00fc0000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x043f0000, 0x043f0000, 0x043f0000 } }, + { 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } }, + { 6, 0x989c, { 0x02190000, 0x02190000, 0x02190000 } }, + { 6, 0x989c, { 0x00240000, 0x00240000, 0x00240000 } }, + { 6, 0x989c, { 0x00b40000, 0x00b40000, 0x00b40000 } }, + { 6, 0x989c, { 0x00990000, 0x00990000, 0x00990000 } }, + { 6, 0x989c, { 0x00500000, 0x00500000, 0x00500000 } }, + { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } }, + { 6, 0x989c, { 0xc0320000, 0xc0320000, 0xc0320000 } }, + { 6, 0x989c, { 0x01740000, 0x01740000, 0x01740000 } }, + { 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } }, + { 6, 0x989c, { 0x86280000, 0x86280000, 0x86280000 } }, + { 6, 0x989c, { 0x31840000, 0x31840000, 0x31840000 } }, + { 6, 0x989c, { 0x00f20080, 0x00f20080, 0x00f20080 } }, + { 6, 0x989c, { 0x00270019, 0x00270019, 0x00270019 } }, + { 6, 0x989c, { 0x00000003, 0x00000003, 0x00000003 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x000000b2, 0x000000b2, 0x000000b2 } }, + { 6, 0x989c, { 0x00b02084, 0x00b02084, 0x00b02084 } }, + { 6, 0x989c, { 0x004125a4, 0x004125a4, 0x004125a4 } }, + { 6, 0x989c, { 0x00119220, 0x00119220, 0x00119220 } }, + { 6, 0x989c, { 0x001a4800, 0x001a4800, 0x001a4800 } }, + { 6, 0x98d8, { 0x000b0230, 0x000b0230, 0x000b0230 } }, + { 7, 0x989c, { 0x00000094, 0x00000094, 0x00000094 } }, + { 7, 0x989c, { 0x00000091, 0x00000091, 0x00000091 } }, + { 7, 0x989c, { 0x00000012, 0x00000012, 0x00000012 } }, + { 7, 0x989c, { 0x00000080, 0x00000080, 0x00000080 } }, + { 7, 0x989c, { 0x000000d9, 0x000000d9, 0x000000d9 } }, + { 7, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } }, + { 7, 0x989c, { 0x000000f0, 0x000000f0, 0x000000f0 } }, + { 7, 0x989c, { 0x000000a2, 0x000000a2, 0x000000a2 } }, + { 7, 0x989c, { 0x00000052, 0x00000052, 0x00000052 } }, + { 7, 0x989c, { 0x000000d4, 0x000000d4, 0x000000d4 } }, + { 7, 0x989c, { 0x000014cc, 0x000014cc, 0x000014cc } }, + { 7, 0x989c, { 0x0000048c, 0x0000048c, 0x0000048c } }, + { 7, 0x98c4, { 0x00000003, 0x00000003, 0x00000003 } }, }; @@ -636,11 +492,15 @@ static const struct ath5k_ini_rfbuffer rfb_5112a[] = { * RF2413 (Griffin) * \******************/ +/* BANK 2 len pos col */ +#define AR5K_RF2413_RF_TURBO { 1, 1, 2 } + /* BANK 6 len pos col */ #define AR5K_RF2413_OB_2GHZ { 3, 168, 0 } #define AR5K_RF2413_DB_2GHZ { 3, 165, 0 } static const struct ath5k_rf_reg rf_regs_2413[] = { + {2, AR5K_RF_TURBO, AR5K_RF2413_RF_TURBO}, {6, AR5K_RF_OB_2GHZ, AR5K_RF2413_OB_2GHZ}, {6, AR5K_RF_DB_2GHZ, AR5K_RF2413_DB_2GHZ}, }; @@ -649,73 +509,40 @@ static const struct ath5k_rf_reg rf_regs_2413[] = { * XXX: a/aTurbo ??? */ static const struct ath5k_ini_rfbuffer rfb_2413[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 } }, - { 6, 0x989c, - { 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 } }, - { 6, 0x989c, - { 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 } }, - { 6, 0x989c, - { 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 } }, - { 6, 0x989c, - { 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 } }, - { 6, 0x989c, - { 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 } }, - { 6, 0x989c, - { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } }, - { 6, 0x989c, - { 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 } }, - { 6, 0x989c, - { 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 } }, - { 6, 0x989c, - { 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 } }, - { 6, 0x989c, - { 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 } }, - { 6, 0x989c, - { 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f } }, - { 6, 0x989c, - { 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 } }, - { 6, 0x98d8, - { 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, + { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, { 0xf0000000, 0xf0000000, 0xf0000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x03000000, 0x03000000, 0x03000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x40400000, 0x40400000, 0x40400000 } }, + { 6, 0x989c, { 0x65050000, 0x65050000, 0x65050000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00420000, 0x00420000, 0x00420000 } }, + { 6, 0x989c, { 0x00b50000, 0x00b50000, 0x00b50000 } }, + { 6, 0x989c, { 0x00030000, 0x00030000, 0x00030000 } }, + { 6, 0x989c, { 0x00f70000, 0x00f70000, 0x00f70000 } }, + { 6, 0x989c, { 0x009d0000, 0x009d0000, 0x009d0000 } }, + { 6, 0x989c, { 0x00220000, 0x00220000, 0x00220000 } }, + { 6, 0x989c, { 0x04220000, 0x04220000, 0x04220000 } }, + { 6, 0x989c, { 0x00230018, 0x00230018, 0x00230018 } }, + { 6, 0x989c, { 0x00280000, 0x00280060, 0x00280060 } }, + { 6, 0x989c, { 0x005000c0, 0x005000c3, 0x005000c3 } }, + { 6, 0x989c, { 0x0004007f, 0x0004007f, 0x0004007f } }, + { 6, 0x989c, { 0x00000458, 0x00000458, 0x00000458 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x0000c000, 0x0000c000, 0x0000c000 } }, + { 6, 0x98d8, { 0x00400230, 0x00400230, 0x00400230 } }, + { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, }; @@ -724,88 +551,57 @@ static const struct ath5k_ini_rfbuffer rfb_2413[] = { * RF2315/RF2316 (Cobra SoC) * \***************************/ +/* BANK 2 len pos col */ +#define AR5K_RF2316_RF_TURBO { 1, 1, 2 } + /* BANK 6 len pos col */ #define AR5K_RF2316_OB_2GHZ { 3, 178, 0 } #define AR5K_RF2316_DB_2GHZ { 3, 175, 0 } static const struct ath5k_rf_reg rf_regs_2316[] = { + {2, AR5K_RF_TURBO, AR5K_RF2316_RF_TURBO}, {6, AR5K_RF_OB_2GHZ, AR5K_RF2316_OB_2GHZ}, {6, AR5K_RF_DB_2GHZ, AR5K_RF2316_DB_2GHZ}, }; /* Default mode specific settings */ static const struct ath5k_ini_rfbuffer rfb_2316[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 } }, - { 6, 0x989c, - { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, - { 6, 0x989c, - { 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 } }, - { 6, 0x989c, - { 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 } }, - { 6, 0x989c, - { 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 } }, - { 6, 0x989c, - { 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 } }, - { 6, 0x989c, - { 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 } }, - { 6, 0x989c, - { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } }, - { 6, 0x989c, - { 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 } }, - { 6, 0x989c, - { 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 } }, - { 6, 0x989c, - { 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 } }, - { 6, 0x989c, - { 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 } }, - { 6, 0x989c, - { 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d } }, - { 6, 0x989c, - { 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 } }, - { 6, 0x989c, - { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, - { 6, 0x989c, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 6, 0x989c, - { 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 } }, - { 6, 0x989c, - { 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 } }, - { 6, 0x98c0, - { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, + { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0xc0000000, 0xc0000000, 0xc0000000 } }, + { 6, 0x989c, { 0x0f000000, 0x0f000000, 0x0f000000 } }, + { 6, 0x989c, { 0x02000000, 0x02000000, 0x02000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0xf8000000, 0xf8000000, 0xf8000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x95150000, 0x95150000, 0x95150000 } }, + { 6, 0x989c, { 0xc1000000, 0xc1000000, 0xc1000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00080000, 0x00080000, 0x00080000 } }, + { 6, 0x989c, { 0x00d50000, 0x00d50000, 0x00d50000 } }, + { 6, 0x989c, { 0x000e0000, 0x000e0000, 0x000e0000 } }, + { 6, 0x989c, { 0x00dc0000, 0x00dc0000, 0x00dc0000 } }, + { 6, 0x989c, { 0x00770000, 0x00770000, 0x00770000 } }, + { 6, 0x989c, { 0x008a0000, 0x008a0000, 0x008a0000 } }, + { 6, 0x989c, { 0x10880000, 0x10880000, 0x10880000 } }, + { 6, 0x989c, { 0x008c0060, 0x008c0060, 0x008c0060 } }, + { 6, 0x989c, { 0x00a00000, 0x00a00080, 0x00a00080 } }, + { 6, 0x989c, { 0x00400000, 0x0040000d, 0x0040000d } }, + { 6, 0x989c, { 0x00110400, 0x00110400, 0x00110400 } }, + { 6, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } }, + { 6, 0x989c, { 0x00000001, 0x00000001, 0x00000001 } }, + { 6, 0x989c, { 0x00000b00, 0x00000b00, 0x00000b00 } }, + { 6, 0x989c, { 0x00000be8, 0x00000be8, 0x00000be8 } }, + { 6, 0x98c0, { 0x00010000, 0x00010000, 0x00010000 } }, + { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, }; @@ -835,93 +631,50 @@ static const struct ath5k_rf_reg rf_regs_5413[] = { /* Default mode specific settings */ static const struct ath5k_ini_rfbuffer rfb_5413[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, - { 3, 0x98dc, - { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } }, - { 6, 0x989c, - { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } }, - { 6, 0x989c, - { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } }, - { 6, 0x989c, - { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } }, - { 6, 0x989c, - { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, - { 6, 0x989c, - { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, - { 6, 0x989c, - { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } }, - { 6, 0x989c, - { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } }, - { 6, 0x989c, - { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } }, - { 6, 0x989c, - { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } }, - { 6, 0x989c, - { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } }, - { 6, 0x989c, - { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } }, - { 6, 0x989c, - { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } }, - { 6, 0x989c, - { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } }, - { 6, 0x989c, - { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, - { 6, 0x989c, - { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } }, - { 6, 0x989c, - { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } }, - { 6, 0x989c, - { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } }, - { 6, 0x989c, - { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } }, - { 6, 0x989c, - { 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 } }, - { 6, 0x989c, - { 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } }, - { 6, 0x989c, - { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 } }, - { 6, 0x98c8, - { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x00000008, 0x00000008, 0x00000008 } }, + { 3, 0x98dc, { 0x00a000c0, 0x00e000c0, 0x00e000c0 } }, + { 6, 0x989c, { 0x33000000, 0x33000000, 0x33000000 } }, + { 6, 0x989c, { 0x01000000, 0x01000000, 0x01000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x1f000000, 0x1f000000, 0x1f000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00b80000, 0x00b80000, 0x00b80000 } }, + { 6, 0x989c, { 0x00b70000, 0x00b70000, 0x00b70000 } }, + { 6, 0x989c, { 0x00840000, 0x00840000, 0x00840000 } }, + { 6, 0x989c, { 0x00980000, 0x00980000, 0x00980000 } }, + { 6, 0x989c, { 0x00c00000, 0x00c00000, 0x00c00000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x00d70000, 0x00d70000, 0x00d70000 } }, + { 6, 0x989c, { 0x00610000, 0x00610000, 0x00610000 } }, + { 6, 0x989c, { 0x00fe0000, 0x00fe0000, 0x00fe0000 } }, + { 6, 0x989c, { 0x00de0000, 0x00de0000, 0x00de0000 } }, + { 6, 0x989c, { 0x007f0000, 0x007f0000, 0x007f0000 } }, + { 6, 0x989c, { 0x043d0000, 0x043d0000, 0x043d0000 } }, + { 6, 0x989c, { 0x00770000, 0x00770000, 0x00770000 } }, + { 6, 0x989c, { 0x00440000, 0x00440000, 0x00440000 } }, + { 6, 0x989c, { 0x00980000, 0x00980000, 0x00980000 } }, + { 6, 0x989c, { 0x00100080, 0x00100080, 0x00100080 } }, + { 6, 0x989c, { 0x0005c034, 0x0005c034, 0x0005c034 } }, + { 6, 0x989c, { 0x003100f0, 0x003100f0, 0x003100f0 } }, + { 6, 0x989c, { 0x000c011f, 0x000c011f, 0x000c011f } }, + { 6, 0x989c, { 0x00510040, 0x00510040, 0x00510040 } }, + { 6, 0x989c, { 0x005000da, 0x005000da, 0x005000da } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00004044, 0x00004044, 0x00004044 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x000060c0, 0x000060c0, 0x000060c0 } }, + { 6, 0x989c, { 0x00002c00, 0x00003600, 0x00003600 } }, + { 6, 0x98c8, { 0x00000403, 0x00040403, 0x00040403 } }, + { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, }; @@ -931,92 +684,59 @@ static const struct ath5k_ini_rfbuffer rfb_5413[] = { * AR2317 (Spider SoC) * \***************************/ +/* BANK 2 len pos col */ +#define AR5K_RF2425_RF_TURBO { 1, 1, 2 } + /* BANK 6 len pos col */ #define AR5K_RF2425_OB_2GHZ { 3, 193, 0 } #define AR5K_RF2425_DB_2GHZ { 3, 190, 0 } static const struct ath5k_rf_reg rf_regs_2425[] = { + {2, AR5K_RF_TURBO, AR5K_RF2425_RF_TURBO}, {6, AR5K_RF_OB_2GHZ, AR5K_RF2425_OB_2GHZ}, {6, AR5K_RF_DB_2GHZ, AR5K_RF2425_DB_2GHZ}, }; /* Default mode specific settings - * XXX: a/aTurbo ? */ static const struct ath5k_ini_rfbuffer rfb_2425[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, - { 6, 0x989c, - { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, - { 6, 0x989c, - { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } }, - { 6, 0x989c, - { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } }, - { 6, 0x989c, - { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, - { 6, 0x989c, - { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } }, - { 6, 0x989c, - { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, - { 6, 0x989c, - { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, - { 6, 0x989c, - { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, - { 6, 0x989c, - { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } }, - { 6, 0x98c4, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, + { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } }, + { 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } }, + { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } }, + { 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } }, + { 6, 0x989c, { 0x00e70000, 0x00e70000, 0x00e70000 } }, + { 6, 0x989c, { 0x00140000, 0x00140000, 0x00140000 } }, + { 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } }, + { 6, 0x989c, { 0x0007001a, 0x0007001a, 0x0007001a } }, + { 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } }, + { 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } }, + { 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } }, + { 6, 0x989c, { 0x00001688, 0x00001688, 0x00001688 } }, + { 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } }, + { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, }; /* @@ -1024,158 +744,85 @@ static const struct ath5k_ini_rfbuffer rfb_2425[] = { * bank modification and get rid of this */ static const struct ath5k_ini_rfbuffer rfb_2317[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, - { 6, 0x989c, - { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, - { 6, 0x989c, - { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } }, - { 6, 0x989c, - { 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 } }, - { 6, 0x989c, - { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, - { 6, 0x989c, - { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } }, - { 6, 0x989c, - { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, - { 6, 0x989c, - { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, - { 6, 0x989c, - { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, - { 6, 0x989c, - { 0x00009688, 0x00009688, 0x00009688, 0x00009688, 0x00009688 } }, - { 6, 0x98c4, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, + { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } }, + { 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } }, + { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } }, + { 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } }, + { 6, 0x989c, { 0x00e70000, 0x00e70000, 0x00e70000 } }, + { 6, 0x989c, { 0x00140100, 0x00140100, 0x00140100 } }, + { 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } }, + { 6, 0x989c, { 0x0007001a, 0x0007001a, 0x0007001a } }, + { 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } }, + { 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } }, + { 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } }, + { 6, 0x989c, { 0x00009688, 0x00009688, 0x00009688 } }, + { 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } }, + { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, }; /* * TODO: Handle the few differences with swan during * bank modification and get rid of this - * XXX: a/aTurbo ? */ static const struct ath5k_ini_rfbuffer rfb_2417[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, - { 6, 0x989c, - { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, - { 6, 0x989c, - { 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 } }, - { 6, 0x989c, - { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } }, - { 6, 0x989c, - { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, - { 6, 0x989c, - { 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a } }, - { 6, 0x989c, - { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, - { 6, 0x989c, - { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, - { 6, 0x989c, - { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, - { 6, 0x989c, - { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } }, - { 6, 0x98c4, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, + { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } }, + { 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } }, + { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } }, + { 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } }, + { 6, 0x989c, { 0x00e70000, 0x80e70000, 0x80e70000 } }, + { 6, 0x989c, { 0x00140000, 0x00140000, 0x00140000 } }, + { 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } }, + { 6, 0x989c, { 0x0007001a, 0x0207001a, 0x0207001a } }, + { 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } }, + { 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } }, + { 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } }, + { 6, 0x989c, { 0x00001688, 0x00001688, 0x00001688 } }, + { 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } }, + { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, }; diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c index 90757de7bf59..929c68cdf8ab 100644 --- a/drivers/net/wireless/ath/ath5k/sysfs.c +++ b/drivers/net/wireless/ath/ath5k/sysfs.c @@ -95,7 +95,7 @@ static struct attribute_group ath5k_attribute_group_ani = { int ath5k_sysfs_register(struct ath5k_softc *sc) { - struct device *dev = &sc->pdev->dev; + struct device *dev = sc->dev; int err; err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani); @@ -110,7 +110,7 @@ ath5k_sysfs_register(struct ath5k_softc *sc) void ath5k_sysfs_unregister(struct ath5k_softc *sc) { - struct device *dev = &sc->pdev->dev; + struct device *dev = sc->dev; sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani); } diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 1a984b02e9e5..25a6e4417cdb 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -35,10 +35,9 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) pdata = (struct ath9k_platform_data *) pdev->dev.platform_data; if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { - ath_print(common, ATH_DBG_FATAL, - "%s: flash read failed, offset %08x " - "is out of range\n", - __func__, off); + ath_err(common, + "%s: flash read failed, offset %08x is out of range\n", + __func__, off); return false; } diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 63ccb39cdcd4..2e31c775351f 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -135,8 +135,8 @@ static void ath9k_ani_restart(struct ath_hw *ah) cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high; } - ath_print(common, ATH_DBG_ANI, - "Writing ofdmbase=%u cckbase=%u\n", ofdm_base, cck_base); + ath_dbg(common, ATH_DBG_ANI, + "Writing ofdmbase=%u cckbase=%u\n", ofdm_base, cck_base); ENABLE_REGWRITE_BUFFER(ah); @@ -267,11 +267,11 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) aniState->noiseFloor = BEACON_RSSI(ah); - ath_print(common, ATH_DBG_ANI, - "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", - aniState->ofdmNoiseImmunityLevel, - immunityLevel, aniState->noiseFloor, - aniState->rssiThrLow, aniState->rssiThrHigh); + ath_dbg(common, ATH_DBG_ANI, + "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", + aniState->ofdmNoiseImmunityLevel, + immunityLevel, aniState->noiseFloor, + aniState->rssiThrLow, aniState->rssiThrHigh); aniState->ofdmNoiseImmunityLevel = immunityLevel; @@ -334,11 +334,11 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) const struct ani_cck_level_entry *entry_cck; aniState->noiseFloor = BEACON_RSSI(ah); - ath_print(common, ATH_DBG_ANI, - "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", - aniState->cckNoiseImmunityLevel, immunityLevel, - aniState->noiseFloor, aniState->rssiThrLow, - aniState->rssiThrHigh); + ath_dbg(common, ATH_DBG_ANI, + "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", + aniState->cckNoiseImmunityLevel, immunityLevel, + aniState->noiseFloor, aniState->rssiThrLow, + aniState->rssiThrHigh); if ((ah->opmode == NL80211_IFTYPE_STATION || ah->opmode == NL80211_IFTYPE_ADHOC) && @@ -358,7 +358,7 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) entry_cck->fir_step_level); /* Skip MRC CCK for pre AR9003 families */ - if (!AR_SREV_9300_20_OR_LATER(ah)) + if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah)) return; if (aniState->mrcCCKOff == entry_cck->mrc_cck_on) @@ -478,8 +478,8 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) if (ah->opmode != NL80211_IFTYPE_STATION && ah->opmode != NL80211_IFTYPE_ADHOC) { - ath_print(common, ATH_DBG_ANI, - "Reset ANI state opmode %u\n", ah->opmode); + ath_dbg(common, ATH_DBG_ANI, + "Reset ANI state opmode %u\n", ah->opmode); ah->stats.ast_ani_reset++; if (ah->opmode == NL80211_IFTYPE_AP) { @@ -584,16 +584,14 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) ATH9K_ANI_OFDM_DEF_LEVEL || aniState->cckNoiseImmunityLevel != ATH9K_ANI_CCK_DEF_LEVEL) { - ath_print(common, ATH_DBG_ANI, - "Restore defaults: opmode %u " - "chan %d Mhz/0x%x is_scanning=%d " - "ofdm:%d cck:%d\n", - ah->opmode, - chan->channel, - chan->channelFlags, - is_scanning, - aniState->ofdmNoiseImmunityLevel, - aniState->cckNoiseImmunityLevel); + ath_dbg(common, ATH_DBG_ANI, + "Restore defaults: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n", + ah->opmode, + chan->channel, + chan->channelFlags, + is_scanning, + aniState->ofdmNoiseImmunityLevel, + aniState->cckNoiseImmunityLevel); ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL); ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL); @@ -602,16 +600,14 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) /* * restore historical levels for this channel */ - ath_print(common, ATH_DBG_ANI, - "Restore history: opmode %u " - "chan %d Mhz/0x%x is_scanning=%d " - "ofdm:%d cck:%d\n", - ah->opmode, - chan->channel, - chan->channelFlags, - is_scanning, - aniState->ofdmNoiseImmunityLevel, - aniState->cckNoiseImmunityLevel); + ath_dbg(common, ATH_DBG_ANI, + "Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n", + ah->opmode, + chan->channel, + chan->channelFlags, + is_scanning, + aniState->ofdmNoiseImmunityLevel, + aniState->cckNoiseImmunityLevel); ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel); @@ -666,19 +662,17 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) { if (phyCnt1 < ofdm_base) { - ath_print(common, ATH_DBG_ANI, - "phyCnt1 0x%x, resetting " - "counter value to 0x%x\n", - phyCnt1, ofdm_base); + ath_dbg(common, ATH_DBG_ANI, + "phyCnt1 0x%x, resetting counter value to 0x%x\n", + phyCnt1, ofdm_base); REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base); REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); } if (phyCnt2 < cck_base) { - ath_print(common, ATH_DBG_ANI, - "phyCnt2 0x%x, resetting " - "counter value to 0x%x\n", - phyCnt2, cck_base); + ath_dbg(common, ATH_DBG_ANI, + "phyCnt2 0x%x, resetting counter value to 0x%x\n", + phyCnt2, cck_base); REG_WRITE(ah, AR_PHY_ERR_2, cck_base); REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); @@ -719,13 +713,12 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) cckPhyErrRate = aniState->cckPhyErrCount * 1000 / aniState->listenTime; - ath_print(common, ATH_DBG_ANI, - "listenTime=%d OFDM:%d errs=%d/s CCK:%d " - "errs=%d/s ofdm_turn=%d\n", - aniState->listenTime, - aniState->ofdmNoiseImmunityLevel, - ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, - cckPhyErrRate, aniState->ofdmsTurn); + ath_dbg(common, ATH_DBG_ANI, + "listenTime=%d OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n", + aniState->listenTime, + aniState->ofdmNoiseImmunityLevel, + ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, + cckPhyErrRate, aniState->ofdmsTurn); if (aniState->listenTime > 5 * ah->aniperiod) { if (ofdmPhyErrRate <= ah->config.ofdm_trig_low && @@ -755,7 +748,7 @@ void ath9k_enable_mib_counters(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - ath_print(common, ATH_DBG_ANI, "Enable MIB counters\n"); + ath_dbg(common, ATH_DBG_ANI, "Enable MIB counters\n"); ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); @@ -777,7 +770,7 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - ath_print(common, ATH_DBG_ANI, "Disable MIB counters\n"); + ath_dbg(common, ATH_DBG_ANI, "Disable MIB counters\n"); REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); @@ -834,10 +827,10 @@ void ath9k_hw_ani_setup(struct ath_hw *ah) { int i; - const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; - const int coarseHigh[] = { -14, -14, -14, -14, -12 }; - const int coarseLow[] = { -64, -64, -64, -64, -70 }; - const int firpwr[] = { -78, -78, -78, -78, -80 }; + static const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; + static const int coarseHigh[] = { -14, -14, -14, -14, -12 }; + static const int coarseLow[] = { -64, -64, -64, -64, -70 }; + static const int firpwr[] = { -78, -78, -78, -78, -80 }; for (i = 0; i < 5; i++) { ah->totalSizeDesired[i] = totalSizeDesired[i]; @@ -852,7 +845,7 @@ void ath9k_hw_ani_init(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); int i; - ath_print(common, ATH_DBG_ANI, "Initialize ANI\n"); + ath_dbg(common, ATH_DBG_ANI, "Initialize ANI\n"); if (use_new_ani(ah)) { ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW; diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index ea9f4497f58c..ffcf44a4058b 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -130,9 +130,8 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq) /* pre-reverse this field */ tmp_reg = ath9k_hw_reverse_bits(new_bias, 3); - ath_print(common, ATH_DBG_CONFIG, - "Force rf_pwd_icsyndiv to %1d on %4d\n", - new_bias, synth_freq); + ath_dbg(common, ATH_DBG_CONFIG, "Force rf_pwd_icsyndiv to %1d on %4d\n", + new_bias, synth_freq); /* swizzle rf_pwd_icsyndiv */ ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3); @@ -173,8 +172,7 @@ static int ar5008_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) channelSel = ((freq - 704) * 2 - 3040) / 10; bModeSynth = 1; } else { - ath_print(common, ATH_DBG_FATAL, - "Invalid channel %u MHz\n", freq); + ath_err(common, "Invalid channel %u MHz\n", freq); return -EINVAL; } @@ -206,8 +204,7 @@ static int ar5008_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); aModeRefSel = ath9k_hw_reverse_bits(1, 2); } else { - ath_print(common, ATH_DBG_FATAL, - "Invalid channel %u MHz\n", freq); + ath_err(common, "Invalid channel %u MHz\n", freq); return -EINVAL; } @@ -244,13 +241,15 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah, int upper, lower, cur_vit_mask; int tmp, new; int i; - int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, - AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 + static int pilot_mask_reg[4] = { + AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 }; - 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 chan_mask_reg[4] = { + AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 }; - int inc[4] = { 0, 100, 0, 0 }; + static int inc[4] = { 0, 100, 0, 0 }; int8_t mask_m[123]; int8_t mask_p[123]; @@ -446,8 +445,7 @@ static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah) #define ATH_ALLOC_BANK(bank, size) do { \ bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \ if (!bank) { \ - ath_print(common, ATH_DBG_FATAL, \ - "Cannot allocate RF banks\n"); \ + ath_err(common, "Cannot allocate RF banks\n"); \ return -ENOMEM; \ } \ } while (0); @@ -873,12 +871,11 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit)); + (u32) regulatory->power_limit), false); /* Write analog registers */ if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "ar5416SetRfRegs failed\n"); + ath_err(ath9k_hw_common(ah), "ar5416SetRfRegs failed\n"); return -EIO; } @@ -964,18 +961,6 @@ static void ar5008_hw_rfbus_done(struct ath_hw *ah) REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); } -static void ar5008_hw_enable_rfkill(struct ath_hw *ah) -{ - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, - AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); - - REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, - AR_GPIO_INPUT_MUX2_RFSILENT); - - ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); - REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); -} - static void ar5008_restore_chainmask(struct ath_hw *ah) { int rx_chainmask = ah->rxchainmask; @@ -1056,10 +1041,9 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, u32 level = param; if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { - ath_print(common, ATH_DBG_ANI, - "level out of range (%u > %u)\n", - level, - (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); + ath_dbg(common, ATH_DBG_ANI, + "level out of range (%u > %zu)\n", + level, ARRAY_SIZE(ah->totalSizeDesired)); return false; } @@ -1084,12 +1068,12 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, break; } case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ - const int m1ThreshLow[] = { 127, 50 }; - const int m2ThreshLow[] = { 127, 40 }; - const int m1Thresh[] = { 127, 0x4d }; - const int m2Thresh[] = { 127, 0x40 }; - const int m2CountThr[] = { 31, 16 }; - const int m2CountThrLow[] = { 63, 48 }; + static const int m1ThreshLow[] = { 127, 50 }; + static const int m2ThreshLow[] = { 127, 40 }; + static const int m1Thresh[] = { 127, 0x4d }; + static const int m2Thresh[] = { 127, 0x40 }; + static const int m2CountThr[] = { 31, 16 }; + static const int m2CountThrLow[] = { 63, 48 }; u32 on = param ? 1 : 0; REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, @@ -1141,7 +1125,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, break; } case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ - const int weakSigThrCck[] = { 8, 6 }; + static const int weakSigThrCck[] = { 8, 6 }; u32 high = param ? 1 : 0; REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, @@ -1157,14 +1141,13 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, break; } case ATH9K_ANI_FIRSTEP_LEVEL:{ - const int firstep[] = { 0, 4, 8 }; + static const int firstep[] = { 0, 4, 8 }; u32 level = param; if (level >= ARRAY_SIZE(firstep)) { - ath_print(common, ATH_DBG_ANI, - "level out of range (%u > %u)\n", - level, - (unsigned) ARRAY_SIZE(firstep)); + ath_dbg(common, ATH_DBG_ANI, + "level out of range (%u > %zu)\n", + level, ARRAY_SIZE(firstep)); return false; } REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, @@ -1178,14 +1161,13 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, break; } case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ - const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; + static const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; u32 level = param; if (level >= ARRAY_SIZE(cycpwrThr1)) { - ath_print(common, ATH_DBG_ANI, - "level out of range (%u > %u)\n", - level, - (unsigned) ARRAY_SIZE(cycpwrThr1)); + ath_dbg(common, ATH_DBG_ANI, + "level out of range (%u > %zu)\n", + level, ARRAY_SIZE(cycpwrThr1)); return false; } REG_RMW_FIELD(ah, AR_PHY_TIMING5, @@ -1201,25 +1183,22 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, case ATH9K_ANI_PRESENT: break; default: - ath_print(common, ATH_DBG_ANI, - "invalid cmd %u\n", cmd); + ath_dbg(common, ATH_DBG_ANI, "invalid cmd %u\n", cmd); return false; } - ath_print(common, ATH_DBG_ANI, "ANI parameters:\n"); - ath_print(common, ATH_DBG_ANI, - "noiseImmunityLevel=%d, spurImmunityLevel=%d, " - "ofdmWeakSigDetectOff=%d\n", - aniState->noiseImmunityLevel, - aniState->spurImmunityLevel, - !aniState->ofdmWeakSigDetectOff); - ath_print(common, ATH_DBG_ANI, - "cckWeakSigThreshold=%d, " - "firstepLevel=%d, listenTime=%d\n", - aniState->cckWeakSigThreshold, - aniState->firstepLevel, - aniState->listenTime); - ath_print(common, ATH_DBG_ANI, + ath_dbg(common, ATH_DBG_ANI, "ANI parameters:\n"); + ath_dbg(common, ATH_DBG_ANI, + "noiseImmunityLevel=%d, spurImmunityLevel=%d, ofdmWeakSigDetectOff=%d\n", + aniState->noiseImmunityLevel, + aniState->spurImmunityLevel, + !aniState->ofdmWeakSigDetectOff); + ath_dbg(common, ATH_DBG_ANI, + "cckWeakSigThreshold=%d, firstepLevel=%d, listenTime=%d\n", + aniState->cckWeakSigThreshold, + aniState->firstepLevel, + aniState->listenTime); + ath_dbg(common, ATH_DBG_ANI, "ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", aniState->ofdmPhyErrCount, aniState->cckPhyErrCount); @@ -1304,12 +1283,12 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); if (!on != aniState->ofdmWeakSigDetectOff) { - ath_print(common, ATH_DBG_ANI, - "** ch %d: ofdm weak signal: %s=>%s\n", - chan->channel, - !aniState->ofdmWeakSigDetectOff ? - "on" : "off", - on ? "on" : "off"); + ath_dbg(common, ATH_DBG_ANI, + "** ch %d: ofdm weak signal: %s=>%s\n", + chan->channel, + !aniState->ofdmWeakSigDetectOff ? + "on" : "off", + on ? "on" : "off"); if (on) ah->stats.ast_ani_ofdmon++; else @@ -1322,11 +1301,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, u32 level = param; if (level >= ARRAY_SIZE(firstep_table)) { - ath_print(common, ATH_DBG_ANI, - "ATH9K_ANI_FIRSTEP_LEVEL: level " - "out of range (%u > %u)\n", - level, - (unsigned) ARRAY_SIZE(firstep_table)); + ath_dbg(common, ATH_DBG_ANI, + "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n", + level, ARRAY_SIZE(firstep_table)); return false; } @@ -1361,24 +1338,22 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, AR_PHY_FIND_SIG_FIRSTEP_LOW, value2); if (level != aniState->firstepLevel) { - ath_print(common, ATH_DBG_ANI, - "** ch %d: level %d=>%d[def:%d] " - "firstep[level]=%d ini=%d\n", - chan->channel, - aniState->firstepLevel, - level, - ATH9K_ANI_FIRSTEP_LVL_NEW, - value, - aniState->iniDef.firstep); - ath_print(common, ATH_DBG_ANI, - "** ch %d: level %d=>%d[def:%d] " - "firstep_low[level]=%d ini=%d\n", - chan->channel, - aniState->firstepLevel, - level, - ATH9K_ANI_FIRSTEP_LVL_NEW, - value2, - aniState->iniDef.firstepLow); + ath_dbg(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n", + chan->channel, + aniState->firstepLevel, + level, + ATH9K_ANI_FIRSTEP_LVL_NEW, + value, + aniState->iniDef.firstep); + ath_dbg(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n", + chan->channel, + aniState->firstepLevel, + level, + ATH9K_ANI_FIRSTEP_LVL_NEW, + value2, + aniState->iniDef.firstepLow); if (level > aniState->firstepLevel) ah->stats.ast_ani_stepup++; else if (level < aniState->firstepLevel) @@ -1391,11 +1366,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, u32 level = param; if (level >= ARRAY_SIZE(cycpwrThr1_table)) { - ath_print(common, ATH_DBG_ANI, - "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level " - "out of range (%u > %u)\n", - level, - (unsigned) ARRAY_SIZE(cycpwrThr1_table)); + ath_dbg(common, ATH_DBG_ANI, + "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n", + level, ARRAY_SIZE(cycpwrThr1_table)); return false; } /* @@ -1429,24 +1402,22 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2); if (level != aniState->spurImmunityLevel) { - ath_print(common, ATH_DBG_ANI, - "** ch %d: level %d=>%d[def:%d] " - "cycpwrThr1[level]=%d ini=%d\n", - chan->channel, - aniState->spurImmunityLevel, - level, - ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, - value, - aniState->iniDef.cycpwrThr1); - ath_print(common, ATH_DBG_ANI, - "** ch %d: level %d=>%d[def:%d] " - "cycpwrThr1Ext[level]=%d ini=%d\n", - chan->channel, - aniState->spurImmunityLevel, - level, - ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, - value2, - aniState->iniDef.cycpwrThr1Ext); + ath_dbg(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n", + chan->channel, + aniState->spurImmunityLevel, + level, + ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, + value, + aniState->iniDef.cycpwrThr1); + ath_dbg(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n", + chan->channel, + aniState->spurImmunityLevel, + level, + ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, + value2, + aniState->iniDef.cycpwrThr1Ext); if (level > aniState->spurImmunityLevel) ah->stats.ast_ani_spurup++; else if (level < aniState->spurImmunityLevel) @@ -1465,22 +1436,19 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, case ATH9K_ANI_PRESENT: break; default: - ath_print(common, ATH_DBG_ANI, - "invalid cmd %u\n", cmd); + ath_dbg(common, ATH_DBG_ANI, "invalid cmd %u\n", cmd); return false; } - ath_print(common, ATH_DBG_ANI, - "ANI parameters: SI=%d, ofdmWS=%s FS=%d " - "MRCcck=%s listenTime=%d " - "ofdmErrs=%d cckErrs=%d\n", - aniState->spurImmunityLevel, - !aniState->ofdmWeakSigDetectOff ? "on" : "off", - aniState->firstepLevel, - !aniState->mrcCCKOff ? "on" : "off", - aniState->listenTime, - aniState->ofdmPhyErrCount, - aniState->cckPhyErrCount); + ath_dbg(common, ATH_DBG_ANI, + "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n", + aniState->spurImmunityLevel, + !aniState->ofdmWeakSigDetectOff ? "on" : "off", + aniState->firstepLevel, + !aniState->mrcCCKOff ? "on" : "off", + aniState->listenTime, + aniState->ofdmPhyErrCount, + aniState->cckPhyErrCount); return true; } @@ -1490,25 +1458,25 @@ static void ar5008_hw_do_getnf(struct ath_hw *ah, int16_t nf; nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); - nfarray[0] = sign_extend(nf, 9); + nfarray[0] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR); - nfarray[1] = sign_extend(nf, 9); + nfarray[1] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); - nfarray[2] = sign_extend(nf, 9); + nfarray[2] = sign_extend32(nf, 8); if (!IS_CHAN_HT40(ah->curchan)) return; nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); - nfarray[3] = sign_extend(nf, 9); + nfarray[3] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR); - nfarray[4] = sign_extend(nf, 9); + nfarray[4] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); - nfarray[5] = sign_extend(nf, 9); + nfarray[5] = sign_extend32(nf, 8); } /* @@ -1526,13 +1494,12 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) iniDef = &aniState->iniDef; - ath_print(common, ATH_DBG_ANI, - "ver %d.%d opmode %u chan %d Mhz/0x%x\n", - ah->hw_version.macVersion, - ah->hw_version.macRev, - ah->opmode, - chan->channel, - chan->channelFlags); + ath_dbg(common, ATH_DBG_ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n", + ah->hw_version.macVersion, + ah->hw_version.macRev, + ah->opmode, + chan->channel, + chan->channelFlags); val = REG_READ(ah, AR_PHY_SFCORR); iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); @@ -1579,10 +1546,55 @@ static void ar5008_hw_set_nf_limits(struct ath_hw *ah) ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; } +static void ar5008_hw_set_radar_params(struct ath_hw *ah, + struct ath_hw_radar_conf *conf) +{ + u32 radar_0 = 0, radar_1 = 0; + + if (!conf) { + REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); + return; + } + + radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA; + radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR); + radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI); + radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT); + radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); + radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); + + radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; + radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; + radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); + radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH); + radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH); + + REG_WRITE(ah, AR_PHY_RADAR_0, radar_0); + REG_WRITE(ah, AR_PHY_RADAR_1, radar_1); + if (conf->ext_channel) + REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); + else + REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); +} + +static void ar5008_hw_set_radar_conf(struct ath_hw *ah) +{ + struct ath_hw_radar_conf *conf = &ah->radar_conf; + + conf->fir_power = -33; + conf->radar_rssi = 20; + conf->pulse_height = 10; + conf->pulse_rssi = 24; + conf->pulse_inband = 15; + conf->pulse_maxlen = 255; + conf->pulse_inband_step = 12; + conf->radar_inband = 8; +} + void ar5008_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); - const u32 ar5416_cca_regs[6] = { + static const u32 ar5416_cca_regs[6] = { AR_PHY_CCA, AR_PHY_CH1_CCA, AR_PHY_CH2_CCA, @@ -1605,10 +1617,10 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->set_delta_slope = ar5008_hw_set_delta_slope; priv_ops->rfbus_req = ar5008_hw_rfbus_req; priv_ops->rfbus_done = ar5008_hw_rfbus_done; - priv_ops->enable_rfkill = ar5008_hw_enable_rfkill; priv_ops->restore_chainmask = ar5008_restore_chainmask; priv_ops->set_diversity = ar5008_set_diversity; priv_ops->do_getnf = ar5008_hw_do_getnf; + priv_ops->set_radar_params = ar5008_hw_set_radar_params; if (modparam_force_new_ani) { priv_ops->ani_control = ar5008_hw_ani_control_new; @@ -1624,5 +1636,6 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->compute_pll_control = ar5008_hw_compute_pll_control; ar5008_hw_set_nf_limits(ah); + ar5008_hw_set_radar_conf(ah); memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs)); } diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 15f62cd0cc38..01880aa13e36 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -39,18 +39,18 @@ static void ar9002_hw_setup_calibration(struct ath_hw *ah, switch (currCal->calData->calType) { case IQ_MISMATCH_CAL: REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); - ath_print(common, ATH_DBG_CALIBRATE, - "starting IQ Mismatch Calibration\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "starting IQ Mismatch Calibration\n"); break; case ADC_GAIN_CAL: REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); - ath_print(common, ATH_DBG_CALIBRATE, - "starting ADC Gain Calibration\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "starting ADC Gain Calibration\n"); break; case ADC_DC_CAL: REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); - ath_print(common, ATH_DBG_CALIBRATE, - "starting ADC DC Calibration\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "starting ADC DC Calibration\n"); break; } @@ -107,11 +107,11 @@ static void ar9002_hw_iqcal_collect(struct ath_hw *ah) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); ah->totalIqCorrMeas[i] += (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, - "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", - ah->cal_samples, i, ah->totalPowerMeasI[i], - ah->totalPowerMeasQ[i], - ah->totalIqCorrMeas[i]); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", + ah->cal_samples, i, ah->totalPowerMeasI[i], + ah->totalPowerMeasQ[i], + ah->totalIqCorrMeas[i]); } } @@ -129,14 +129,13 @@ static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah) ah->totalAdcQEvenPhase[i] += REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, - "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " - "oddq=0x%08x; evenq=0x%08x;\n", - ah->cal_samples, i, - ah->totalAdcIOddPhase[i], - ah->totalAdcIEvenPhase[i], - ah->totalAdcQOddPhase[i], - ah->totalAdcQEvenPhase[i]); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", + ah->cal_samples, i, + ah->totalAdcIOddPhase[i], + ah->totalAdcIEvenPhase[i], + ah->totalAdcQOddPhase[i], + ah->totalAdcQEvenPhase[i]); } } @@ -154,14 +153,13 @@ static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah) ah->totalAdcDcOffsetQEvenPhase[i] += (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, - "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " - "oddq=0x%08x; evenq=0x%08x;\n", - ah->cal_samples, i, - ah->totalAdcDcOffsetIOddPhase[i], - ah->totalAdcDcOffsetIEvenPhase[i], - ah->totalAdcDcOffsetQOddPhase[i], - ah->totalAdcDcOffsetQEvenPhase[i]); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", + ah->cal_samples, i, + ah->totalAdcDcOffsetIOddPhase[i], + ah->totalAdcDcOffsetIEvenPhase[i], + ah->totalAdcDcOffsetQOddPhase[i], + ah->totalAdcDcOffsetQEvenPhase[i]); } } @@ -178,13 +176,13 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) powerMeasQ = ah->totalPowerMeasQ[i]; iqCorrMeas = ah->totalIqCorrMeas[i]; - ath_print(common, ATH_DBG_CALIBRATE, - "Starting IQ Cal and Correction for Chain %d\n", - i); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Starting IQ Cal and Correction for Chain %d\n", + i); - ath_print(common, ATH_DBG_CALIBRATE, - "Orignal: Chn %diq_corr_meas = 0x%08x\n", - i, ah->totalIqCorrMeas[i]); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Orignal: Chn %diq_corr_meas = 0x%08x\n", + i, ah->totalIqCorrMeas[i]); iqCorrNeg = 0; @@ -193,12 +191,12 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) iqCorrNeg = 1; } - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); - ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", - iqCorrNeg); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); + ath_dbg(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", + iqCorrNeg); iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; qCoffDenom = powerMeasQ / 64; @@ -207,14 +205,14 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) (qCoffDenom != 0)) { iCoff = iqCorrMeas / iCoffDenom; qCoff = powerMeasI / qCoffDenom - 64; - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d iCoff = 0x%08x\n", i, iCoff); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d qCoff = 0x%08x\n", i, qCoff); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d iCoff = 0x%08x\n", i, iCoff); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d qCoff = 0x%08x\n", i, qCoff); iCoff = iCoff & 0x3f; - ath_print(common, ATH_DBG_CALIBRATE, - "New: Chn %d iCoff = 0x%08x\n", i, iCoff); + ath_dbg(common, ATH_DBG_CALIBRATE, + "New: Chn %d iCoff = 0x%08x\n", i, iCoff); if (iqCorrNeg == 0x0) iCoff = 0x40 - iCoff; @@ -223,9 +221,9 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) else if (qCoff <= -16) qCoff = -16; - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", - i, iCoff, qCoff); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", + i, iCoff, qCoff); REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, @@ -233,9 +231,9 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff); - ath_print(common, ATH_DBG_CALIBRATE, - "IQ Cal and Correction done for Chain %d\n", - i); + ath_dbg(common, ATH_DBG_CALIBRATE, + "IQ Cal and Correction done for Chain %d\n", + i); } } @@ -255,21 +253,21 @@ static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) qOddMeasOffset = ah->totalAdcQOddPhase[i]; qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; - ath_print(common, ATH_DBG_CALIBRATE, - "Starting ADC Gain Cal for Chain %d\n", i); - - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_i = 0x%08x\n", i, - iOddMeasOffset); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_i = 0x%08x\n", i, - iEvenMeasOffset); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_q = 0x%08x\n", i, - qOddMeasOffset); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_q = 0x%08x\n", i, - qEvenMeasOffset); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Starting ADC Gain Cal for Chain %d\n", i); + + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_odd_i = 0x%08x\n", i, + iOddMeasOffset); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_even_i = 0x%08x\n", i, + iEvenMeasOffset); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_odd_q = 0x%08x\n", i, + qOddMeasOffset); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_even_q = 0x%08x\n", i, + qEvenMeasOffset); if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { iGainMismatch = @@ -279,20 +277,20 @@ static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) ((qOddMeasOffset * 32) / qEvenMeasOffset) & 0x3f; - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d gain_mismatch_i = 0x%08x\n", i, - iGainMismatch); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d gain_mismatch_q = 0x%08x\n", i, - qGainMismatch); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d gain_mismatch_i = 0x%08x\n", i, + iGainMismatch); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d gain_mismatch_q = 0x%08x\n", i, + qGainMismatch); val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); val &= 0xfffff000; val |= (qGainMismatch) | (iGainMismatch << 6); REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - ath_print(common, ATH_DBG_CALIBRATE, - "ADC Gain Cal done for Chain %d\n", i); + ath_dbg(common, ATH_DBG_CALIBRATE, + "ADC Gain Cal done for Chain %d\n", i); } } @@ -317,41 +315,41 @@ static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; - ath_print(common, ATH_DBG_CALIBRATE, - "Starting ADC DC Offset Cal for Chain %d\n", i); - - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_i = %d\n", i, - iOddMeasOffset); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_i = %d\n", i, - iEvenMeasOffset); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_q = %d\n", i, - qOddMeasOffset); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_q = %d\n", i, - qEvenMeasOffset); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Starting ADC DC Offset Cal for Chain %d\n", i); + + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_odd_i = %d\n", i, + iOddMeasOffset); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_even_i = %d\n", i, + iEvenMeasOffset); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_odd_q = %d\n", i, + qOddMeasOffset); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_even_q = %d\n", i, + qEvenMeasOffset); iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / numSamples) & 0x1ff; qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / numSamples) & 0x1ff; - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, - iDcMismatch); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, - qDcMismatch); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, + iDcMismatch); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, + qDcMismatch); val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); val &= 0xc0000fff; val |= (qDcMismatch << 12) | (iDcMismatch << 21); REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - ath_print(common, ATH_DBG_CALIBRATE, - "ADC DC Offset Cal done for Chain %d\n", i); + ath_dbg(common, ATH_DBG_CALIBRATE, + "ADC DC Offset Cal done for Chain %d\n", i); } REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), @@ -540,7 +538,7 @@ static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) { 0x7838, 0 }, }; - ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); /* PA CAL is not needed for high power solution */ if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == @@ -721,9 +719,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { - ath_print(common, ATH_DBG_CALIBRATE, "offset " - "calibration failed to complete in " - "1ms; noisy ??\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "offset calibration failed to complete in 1ms; noisy environment?\n"); return false; } REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); @@ -736,8 +733,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { - ath_print(common, ATH_DBG_CALIBRATE, "offset calibration " - "failed to complete in 1ms; noisy ??\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "offset calibration failed to complete in 1ms; noisy environment?\n"); return false; } @@ -829,9 +826,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { - ath_print(common, ATH_DBG_CALIBRATE, - "offset calibration failed to " - "complete in 1ms; noisy environment?\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "offset calibration failed to complete in 1ms; noisy environment?\n"); return false; } @@ -866,19 +862,19 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) INIT_CAL(&ah->adcgain_caldata); INSERT_CAL(ah, &ah->adcgain_caldata); - ath_print(common, ATH_DBG_CALIBRATE, - "enabling ADC Gain Calibration.\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "enabling ADC Gain Calibration.\n"); INIT_CAL(&ah->adcdc_caldata); INSERT_CAL(ah, &ah->adcdc_caldata); - ath_print(common, ATH_DBG_CALIBRATE, - "enabling ADC DC Calibration.\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "enabling ADC DC Calibration.\n"); } INIT_CAL(&ah->iq_caldata); INSERT_CAL(ah, &ah->iq_caldata); - ath_print(common, ATH_DBG_CALIBRATE, - "enabling IQ Calibration.\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "enabling IQ Calibration.\n"); ah->cal_list_curr = ah->cal_list; diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 48261b7252d0..f8a7771faee2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -22,28 +22,10 @@ int modparam_force_new_ani; module_param_named(force_new_ani, modparam_force_new_ani, int, 0444); -MODULE_PARM_DESC(nohwcrypt, "Force new ANI for AR5008, AR9001, AR9002"); +MODULE_PARM_DESC(force_new_ani, "Force new ANI for AR5008, AR9001, AR9002"); /* General hardware code for the A5008/AR9001/AR9002 hadware families */ -static bool ar9002_hw_macversion_supported(u32 macversion) -{ - switch (macversion) { - case AR_SREV_VERSION_5416_PCI: - case AR_SREV_VERSION_5416_PCIE: - case AR_SREV_VERSION_9160: - case AR_SREV_VERSION_9100: - case AR_SREV_VERSION_9280: - case AR_SREV_VERSION_9285: - case AR_SREV_VERSION_9287: - case AR_SREV_VERSION_9271: - return true; - default: - break; - } - return false; -} - static void ar9002_hw_init_mode_regs(struct ath_hw *ah) { if (AR_SREV_9271(ah)) { @@ -494,9 +476,9 @@ int ar9002_hw_rf_claim(struct ath_hw *ah) case AR_RAD2122_SREV_MAJOR: break; default: - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "Radio Chip Rev 0x%02X not supported\n", - val & AR_RADIO_SREV_MAJOR); + ath_err(ath9k_hw_common(ah), + "Radio Chip Rev 0x%02X not supported\n", + val & AR_RADIO_SREV_MAJOR); return -EOPNOTSUPP; } @@ -565,7 +547,6 @@ void ar9002_hw_attach_ops(struct ath_hw *ah) priv_ops->init_mode_regs = ar9002_hw_init_mode_regs; priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs; - priv_ops->macversion_supported = ar9002_hw_macversion_supported; ops->config_pci_powersave = ar9002_hw_configpcipowersave; diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 50dda394f8be..399ab3bb299b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -90,13 +90,10 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) *masked = isr & ATH9K_INT_COMMON; - if (ah->config.rx_intr_mitigation) { - if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) - *masked |= ATH9K_INT_RX; - } - - if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) + if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM | + AR_ISR_RXOK | AR_ISR_RXERR)) *masked |= ATH9K_INT_RX; + if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) { @@ -114,16 +111,8 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) } if (isr & AR_ISR_RXORN) { - ath_print(common, ATH_DBG_INTERRUPT, - "receive FIFO overrun interrupt\n"); - } - - if (!AR_SREV_9100(ah)) { - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - u32 isr5 = REG_READ(ah, AR_ISR_S5_S); - if (isr5 & AR_ISR_S5_TIM_TIMER) - *masked |= ATH9K_INT_TIM_TIMER; - } + ath_dbg(common, ATH_DBG_INTERRUPT, + "receive FIFO overrun interrupt\n"); } *masked |= mask2; @@ -136,17 +125,18 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) u32 s5_s; s5_s = REG_READ(ah, AR_ISR_S5_S); - if (isr & AR_ISR_GENTMR) { - ah->intr_gen_timer_trigger = + ah->intr_gen_timer_trigger = MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); - ah->intr_gen_timer_thresh = - MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); + ah->intr_gen_timer_thresh = + MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); - if (ah->intr_gen_timer_trigger) - *masked |= ATH9K_INT_GENTIMER; + if (ah->intr_gen_timer_trigger) + *masked |= ATH9K_INT_GENTIMER; - } + if ((s5_s & AR_ISR_S5_TIM_TIMER) && + !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) + *masked |= ATH9K_INT_TIM_TIMER; } if (sync_cause) { @@ -157,25 +147,25 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) if (fatal_int) { if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { - ath_print(common, ATH_DBG_ANY, - "received PCI FATAL interrupt\n"); + ath_dbg(common, ATH_DBG_ANY, + "received PCI FATAL interrupt\n"); } if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { - ath_print(common, ATH_DBG_ANY, - "received PCI PERR interrupt\n"); + ath_dbg(common, ATH_DBG_ANY, + "received PCI PERR interrupt\n"); } *masked |= ATH9K_INT_FATAL; } if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { - ath_print(common, ATH_DBG_INTERRUPT, - "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); + ath_dbg(common, ATH_DBG_INTERRUPT, + "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); REG_WRITE(ah, AR_RC, 0); *masked |= ATH9K_INT_FATAL; } if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { - ath_print(common, ATH_DBG_INTERRUPT, - "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); + ath_dbg(common, ATH_DBG_INTERRUPT, + "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); } REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); @@ -218,77 +208,70 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_status *ts) { struct ar5416_desc *ads = AR5416DESC(ds); + u32 status; - if ((ads->ds_txstatus9 & AR_TxDone) == 0) + status = ACCESS_ONCE(ads->ds_txstatus9); + if ((status & AR_TxDone) == 0) return -EINPROGRESS; - ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); ts->ts_tstamp = ads->AR_SendTimestamp; ts->ts_status = 0; ts->ts_flags = 0; - if (ads->ds_txstatus1 & AR_FrmXmitOK) + if (status & AR_TxOpExceeded) + ts->ts_status |= ATH9K_TXERR_XTXOP; + ts->tid = MS(status, AR_TxTid); + ts->ts_rateindex = MS(status, AR_FinalTxIdx); + ts->ts_seqnum = MS(status, AR_SeqNum); + + status = ACCESS_ONCE(ads->ds_txstatus0); + ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); + ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); + ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); + if (status & AR_TxBaStatus) { + ts->ts_flags |= ATH9K_TX_BA; + ts->ba_low = ads->AR_BaBitmapLow; + ts->ba_high = ads->AR_BaBitmapHigh; + } + + status = ACCESS_ONCE(ads->ds_txstatus1); + if (status & AR_FrmXmitOK) ts->ts_status |= ATH9K_TX_ACKED; - if (ads->ds_txstatus1 & AR_ExcessiveRetries) - ts->ts_status |= ATH9K_TXERR_XRETRY; - if (ads->ds_txstatus1 & AR_Filtered) - ts->ts_status |= ATH9K_TXERR_FILT; - if (ads->ds_txstatus1 & AR_FIFOUnderrun) { - ts->ts_status |= ATH9K_TXERR_FIFO; - ath9k_hw_updatetxtriglevel(ah, true); + else { + if (status & AR_ExcessiveRetries) + ts->ts_status |= ATH9K_TXERR_XRETRY; + if (status & AR_Filtered) + ts->ts_status |= ATH9K_TXERR_FILT; + if (status & AR_FIFOUnderrun) { + ts->ts_status |= ATH9K_TXERR_FIFO; + ath9k_hw_updatetxtriglevel(ah, true); + } } - if (ads->ds_txstatus9 & AR_TxOpExceeded) - ts->ts_status |= ATH9K_TXERR_XTXOP; - if (ads->ds_txstatus1 & AR_TxTimerExpired) + if (status & AR_TxTimerExpired) ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; - - if (ads->ds_txstatus1 & AR_DescCfgErr) + if (status & AR_DescCfgErr) ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; - if (ads->ds_txstatus1 & AR_TxDataUnderrun) { + if (status & AR_TxDataUnderrun) { ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; ath9k_hw_updatetxtriglevel(ah, true); } - if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { + if (status & AR_TxDelimUnderrun) { ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; ath9k_hw_updatetxtriglevel(ah, true); } - if (ads->ds_txstatus0 & AR_TxBaStatus) { - ts->ts_flags |= ATH9K_TX_BA; - ts->ba_low = ads->AR_BaBitmapLow; - ts->ba_high = ads->AR_BaBitmapHigh; - } + ts->ts_shortretry = MS(status, AR_RTSFailCnt); + ts->ts_longretry = MS(status, AR_DataFailCnt); + ts->ts_virtcol = MS(status, AR_VirtRetryCnt); - ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); - switch (ts->ts_rateindex) { - case 0: - ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); - break; - case 1: - ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); - break; - case 2: - ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); - break; - case 3: - ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); - break; - } + status = ACCESS_ONCE(ads->ds_txstatus5); + ts->ts_rssi = MS(status, AR_TxRSSICombined); + ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); + ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); + ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); - ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); - ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); - ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); - ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); - ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); - ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); - ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); ts->evm0 = ads->AR_TxEVM0; ts->evm1 = ads->AR_TxEVM1; ts->evm2 = ads->AR_TxEVM2; - ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); - ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); - ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); - ts->tid = MS(ads->ds_txstatus9, AR_TxTid); - ts->ts_antenna = 0; return 0; } @@ -300,7 +283,6 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, { struct ar5416_desc *ads = AR5416DESC(ds); - txPower += ah->txpower_indexoffset; if (txPower > 63) txPower = 63; diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index c00cdc67b55b..7d68d61e406b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -175,13 +175,15 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah, int upper, lower, cur_vit_mask; int tmp, newVal; int i; - 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 pilot_mask_reg[4] = { + AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 }; - 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 chan_mask_reg[4] = { + AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 }; - int inc[4] = { 0, 100, 0, 0 }; + static const int inc[4] = { 0, 100, 0, 0 }; struct chan_centers centers; int8_t mask_m[123]; @@ -201,13 +203,14 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah, for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); + if (AR_NO_SPUR == cur_bb_spur) + break; + 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 (IS_CHAN_HT40(chan)) { @@ -473,21 +476,21 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah, int16_t nf; nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); - nfarray[0] = sign_extend(nf, 9); + nfarray[0] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR); if (IS_CHAN_HT40(ah->curchan)) - nfarray[3] = sign_extend(nf, 9); + nfarray[3] = sign_extend32(nf, 8); if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) return; nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR); - nfarray[1] = sign_extend(nf, 9); + nfarray[1] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR); if (IS_CHAN_HT40(ah->curchan)) - nfarray[4] = sign_extend(nf, 9); + nfarray[4] = sign_extend32(nf, 8); } static void ar9002_hw_set_nf_limits(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index a14a5e43cf56..81f9cf294dec 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -34,9 +34,9 @@ static const u32 ar9300_2p2_radio_postamble[][5] = { static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, - {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, - {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, + {0x0000a2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, + {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, + {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, @@ -56,21 +56,21 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, @@ -88,44 +88,44 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, - {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, - {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, - {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, - {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, - {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, - {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, + {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, + {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, + {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, + {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, + {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, - {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, - {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, + {0x0000c2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, + {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, + {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, @@ -638,6 +638,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = { {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0}, {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, + {0x0000a22c, 0x01026a2f, 0x01026a2f, 0x01026a2f, 0x01026a2f}, {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, @@ -680,7 +681,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = { {0x0000981c, 0x00020028}, {0x00009834, 0x6400a290}, {0x00009838, 0x0108ecff}, - {0x0000983c, 0x14750600}, + {0x0000983c, 0x0d000600}, {0x00009880, 0x201fff00}, {0x00009884, 0x00001042}, {0x000098a4, 0x00200400}, @@ -722,7 +723,6 @@ static const u32 ar9300_2p2_baseband_core[][2] = { {0x0000a220, 0x00000000}, {0x0000a224, 0x00000000}, {0x0000a228, 0x10002310}, - {0x0000a22c, 0x01036a27}, {0x0000a23c, 0x00000000}, {0x0000a244, 0x0c000000}, {0x0000a2a0, 0x00000001}, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 9e6edffe0bd1..4a4cd88429c0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -18,6 +18,16 @@ #include "hw-ops.h" #include "ar9003_phy.h" +#define MPASS 3 +#define MAX_MEASUREMENT 8 +#define MAX_DIFFERENCE 10 + +struct coeff { + int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; + int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; + int iqc_coeff[2]; +}; + enum ar9003_cal_types { IQ_MISMATCH_CAL = BIT(0), TEMP_COMP_CAL = BIT(1), @@ -40,8 +50,8 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah, currCal->calData->calCountMax); REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); - ath_print(common, ATH_DBG_CALIBRATE, - "starting IQ Mismatch Calibration\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "starting IQ Mismatch Calibration\n"); /* Kick-off cal */ REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL); @@ -52,8 +62,8 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM, AR_PHY_65NM_CH0_THERM_START, 1); - ath_print(common, ATH_DBG_CALIBRATE, - "starting Temperature Compensation Calibration\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "starting Temperature Compensation Calibration\n"); break; } } @@ -181,11 +191,11 @@ static void ar9003_hw_iqcal_collect(struct ath_hw *ah) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); ah->totalIqCorrMeas[i] += (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, - "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", - ah->cal_samples, i, ah->totalPowerMeasI[i], - ah->totalPowerMeasQ[i], - ah->totalIqCorrMeas[i]); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", + ah->cal_samples, i, ah->totalPowerMeasI[i], + ah->totalPowerMeasQ[i], + ah->totalIqCorrMeas[i]); } } @@ -196,7 +206,7 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) u32 qCoffDenom, iCoffDenom; int32_t qCoff, iCoff; int iqCorrNeg, i; - const u_int32_t offset_array[3] = { + static const u_int32_t offset_array[3] = { AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_B1, AR_PHY_RX_IQCAL_CORR_B2, @@ -207,13 +217,13 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) powerMeasQ = ah->totalPowerMeasQ[i]; iqCorrMeas = ah->totalIqCorrMeas[i]; - ath_print(common, ATH_DBG_CALIBRATE, - "Starting IQ Cal and Correction for Chain %d\n", - i); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Starting IQ Cal and Correction for Chain %d\n", + i); - ath_print(common, ATH_DBG_CALIBRATE, - "Orignal: Chn %diq_corr_meas = 0x%08x\n", - i, ah->totalIqCorrMeas[i]); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Orignal: Chn %diq_corr_meas = 0x%08x\n", + i, ah->totalIqCorrMeas[i]); iqCorrNeg = 0; @@ -222,12 +232,12 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) iqCorrNeg = 1; } - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); - ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", - iqCorrNeg); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); + ath_dbg(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", + iqCorrNeg); iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256; qCoffDenom = powerMeasQ / 64; @@ -235,10 +245,10 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) if ((iCoffDenom != 0) && (qCoffDenom != 0)) { iCoff = iqCorrMeas / iCoffDenom; qCoff = powerMeasI / qCoffDenom - 64; - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d iCoff = 0x%08x\n", i, iCoff); - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d qCoff = 0x%08x\n", i, qCoff); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d iCoff = 0x%08x\n", i, iCoff); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d qCoff = 0x%08x\n", i, qCoff); /* Force bounds on iCoff */ if (iCoff >= 63) @@ -259,14 +269,13 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) iCoff = iCoff & 0x7f; qCoff = qCoff & 0x7f; - ath_print(common, ATH_DBG_CALIBRATE, - "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", - i, iCoff, qCoff); - ath_print(common, ATH_DBG_CALIBRATE, - "Register offset (0x%04x) " - "before update = 0x%x\n", - offset_array[i], - REG_READ(ah, offset_array[i])); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", + i, iCoff, qCoff); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Register offset (0x%04x) before update = 0x%x\n", + offset_array[i], + REG_READ(ah, offset_array[i])); REG_RMW_FIELD(ah, offset_array[i], AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, @@ -274,33 +283,29 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) REG_RMW_FIELD(ah, offset_array[i], AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, qCoff); - ath_print(common, ATH_DBG_CALIBRATE, - "Register offset (0x%04x) QI COFF " - "(bitfields 0x%08x) after update = 0x%x\n", - offset_array[i], - AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, - REG_READ(ah, offset_array[i])); - ath_print(common, ATH_DBG_CALIBRATE, - "Register offset (0x%04x) QQ COFF " - "(bitfields 0x%08x) after update = 0x%x\n", - offset_array[i], - AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, - REG_READ(ah, offset_array[i])); - - ath_print(common, ATH_DBG_CALIBRATE, - "IQ Cal and Correction done for Chain %d\n", - i); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n", + offset_array[i], + AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, + REG_READ(ah, offset_array[i])); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n", + offset_array[i], + AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, + REG_READ(ah, offset_array[i])); + + ath_dbg(common, ATH_DBG_CALIBRATE, + "IQ Cal and Correction done for Chain %d\n", i); } } REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE); - ath_print(common, ATH_DBG_CALIBRATE, - "IQ Cal and Correction (offset 0x%04x) enabled " - "(bit position 0x%08x). New Value 0x%08x\n", - (unsigned) (AR_PHY_RX_IQCAL_CORR_B0), - AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE, - REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0)); + ath_dbg(common, ATH_DBG_CALIBRATE, + "IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n", + (unsigned) (AR_PHY_RX_IQCAL_CORR_B0), + AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE, + REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0)); } static const struct ath9k_percal_data iq_cal_single_sample = { @@ -340,7 +345,7 @@ static bool ar9003_hw_solve_iq_cal(struct ath_hw *ah, f2 = (f1 * f1 + f3 * f3) / result_shift; if (!f2) { - ath_print(common, ATH_DBG_CALIBRATE, "Divide by 0\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, "Divide by 0\n"); return false; } @@ -461,11 +466,14 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) || (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) { - ath_print(common, ATH_DBG_CALIBRATE, - "Divide by 0:\na0_d0=%d\n" - "a0_d1=%d\na2_d0=%d\na1_d1=%d\n", - i2_p_q2_a0_d0, i2_p_q2_a0_d1, - i2_p_q2_a1_d0, i2_p_q2_a1_d1); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Divide by 0:\n" + "a0_d0=%d\n" + "a0_d1=%d\n" + "a2_d0=%d\n" + "a1_d1=%d\n", + i2_p_q2_a0_d0, i2_p_q2_a0_d1, + i2_p_q2_a1_d0, i2_p_q2_a1_d1); return false; } @@ -498,9 +506,9 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2); if ((mag1 == 0) || (mag2 == 0)) { - ath_print(common, ATH_DBG_CALIBRATE, - "Divide by 0: mag1=%d, mag2=%d\n", - mag1, mag2); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Divide by 0: mag1=%d, mag2=%d\n", + mag1, mag2); return false; } @@ -517,8 +525,8 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, mag_a0_d0, phs_a0_d0, mag_a1_d0, phs_a1_d0, solved_eq)) { - ath_print(common, ATH_DBG_CALIBRATE, - "Call to ar9003_hw_solve_iq_cal() failed.\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Call to ar9003_hw_solve_iq_cal() failed.\n"); return false; } @@ -527,14 +535,14 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, mag_rx = solved_eq[2]; phs_rx = solved_eq[3]; - ath_print(common, ATH_DBG_CALIBRATE, - "chain %d: mag mismatch=%d phase mismatch=%d\n", - chain_idx, mag_tx/res_scale, phs_tx/res_scale); + ath_dbg(common, ATH_DBG_CALIBRATE, + "chain %d: mag mismatch=%d phase mismatch=%d\n", + chain_idx, mag_tx/res_scale, phs_tx/res_scale); if (res_scale == mag_tx) { - ath_print(common, ATH_DBG_CALIBRATE, - "Divide by 0: mag_tx=%d, res_scale=%d\n", - mag_tx, res_scale); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Divide by 0: mag_tx=%d, res_scale=%d\n", + mag_tx, res_scale); return false; } @@ -545,9 +553,9 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, q_q_coff = (mag_corr_tx * 128 / res_scale); q_i_coff = (phs_corr_tx * 256 / res_scale); - ath_print(common, ATH_DBG_CALIBRATE, - "tx chain %d: mag corr=%d phase corr=%d\n", - chain_idx, q_q_coff, q_i_coff); + ath_dbg(common, ATH_DBG_CALIBRATE, + "tx chain %d: mag corr=%d phase corr=%d\n", + chain_idx, q_q_coff, q_i_coff); if (q_i_coff < -63) q_i_coff = -63; @@ -560,14 +568,14 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, iqc_coeff[0] = (q_q_coff * 128) + q_i_coff; - ath_print(common, ATH_DBG_CALIBRATE, - "tx chain %d: iq corr coeff=%x\n", - chain_idx, iqc_coeff[0]); + ath_dbg(common, ATH_DBG_CALIBRATE, + "tx chain %d: iq corr coeff=%x\n", + chain_idx, iqc_coeff[0]); if (-mag_rx == res_scale) { - ath_print(common, ATH_DBG_CALIBRATE, - "Divide by 0: mag_rx=%d, res_scale=%d\n", - mag_rx, res_scale); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Divide by 0: mag_rx=%d, res_scale=%d\n", + mag_rx, res_scale); return false; } @@ -578,9 +586,9 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, q_q_coff = (mag_corr_rx * 128 / res_scale); q_i_coff = (phs_corr_rx * 256 / res_scale); - ath_print(common, ATH_DBG_CALIBRATE, - "rx chain %d: mag corr=%d phase corr=%d\n", - chain_idx, q_q_coff, q_i_coff); + ath_dbg(common, ATH_DBG_CALIBRATE, + "rx chain %d: mag corr=%d phase corr=%d\n", + chain_idx, q_q_coff, q_i_coff); if (q_i_coff < -63) q_i_coff = -63; @@ -593,140 +601,367 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, iqc_coeff[1] = (q_q_coff * 128) + q_i_coff; - ath_print(common, ATH_DBG_CALIBRATE, - "rx chain %d: iq corr coeff=%x\n", - chain_idx, iqc_coeff[1]); + ath_dbg(common, ATH_DBG_CALIBRATE, + "rx chain %d: iq corr coeff=%x\n", + chain_idx, iqc_coeff[1]); + + return true; +} + +static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg) +{ + int diff[MPASS]; + + diff[0] = abs(mp_coeff[0] - mp_coeff[1]); + diff[1] = abs(mp_coeff[1] - mp_coeff[2]); + diff[2] = abs(mp_coeff[2] - mp_coeff[0]); + + if (diff[0] > MAX_DIFFERENCE && + diff[1] > MAX_DIFFERENCE && + diff[2] > MAX_DIFFERENCE) + return false; + + if (diff[0] <= diff[1] && diff[0] <= diff[2]) + *mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2; + else if (diff[1] <= diff[2]) + *mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2; + else + *mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2; return true; } +static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, + u8 num_chains, + struct coeff *coeff) +{ + struct ath_common *common = ath9k_hw_common(ah); + int i, im, nmeasurement; + int magnitude, phase; + u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS]; + + memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff)); + for (i = 0; i < MAX_MEASUREMENT / 2; i++) { + tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] = + AR_PHY_TX_IQCAL_CORR_COEFF_B0(i); + if (!AR_SREV_9485(ah)) { + tx_corr_coeff[i * 2][1] = + tx_corr_coeff[(i * 2) + 1][1] = + AR_PHY_TX_IQCAL_CORR_COEFF_B1(i); + + tx_corr_coeff[i * 2][2] = + tx_corr_coeff[(i * 2) + 1][2] = + AR_PHY_TX_IQCAL_CORR_COEFF_B2(i); + } + } + + /* Load the average of 2 passes */ + for (i = 0; i < num_chains; i++) { + if (AR_SREV_9485(ah)) + nmeasurement = REG_READ_FIELD(ah, + AR_PHY_TX_IQCAL_STATUS_B0_9485, + AR_PHY_CALIBRATED_GAINS_0); + else + nmeasurement = REG_READ_FIELD(ah, + AR_PHY_TX_IQCAL_STATUS_B0, + AR_PHY_CALIBRATED_GAINS_0); + + if (nmeasurement > MAX_MEASUREMENT) + nmeasurement = MAX_MEASUREMENT; + + for (im = 0; im < nmeasurement; im++) { + /* + * Determine which 2 passes are closest and compute avg + * magnitude + */ + if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im], + &magnitude)) + goto disable_txiqcal; + + /* + * Determine which 2 passes are closest and compute avg + * phase + */ + if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im], + &phase)) + goto disable_txiqcal; + + coeff->iqc_coeff[0] = (magnitude & 0x7f) | + ((phase & 0x7f) << 7); + + if ((im % 2) == 0) + REG_RMW_FIELD(ah, tx_corr_coeff[im][i], + AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE, + coeff->iqc_coeff[0]); + else + REG_RMW_FIELD(ah, tx_corr_coeff[im][i], + AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE, + coeff->iqc_coeff[0]); + } + } + + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, + AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1); + REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, + AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); + + return; + +disable_txiqcal: + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, + AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0); + REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, + AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0); + + ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n"); +} + static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - const u32 txiqcal_status[AR9300_MAX_CHAINS] = { + static const u32 txiqcal_status[AR9300_MAX_CHAINS] = { AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_TX_IQCAL_STATUS_B1, AR_PHY_TX_IQCAL_STATUS_B2, }; - const u32 tx_corr_coeff[AR9300_MAX_CHAINS] = { - AR_PHY_TX_IQCAL_CORR_COEFF_01_B0, - AR_PHY_TX_IQCAL_CORR_COEFF_01_B1, - AR_PHY_TX_IQCAL_CORR_COEFF_01_B2, - }; - const u32 rx_corr[AR9300_MAX_CHAINS] = { - AR_PHY_RX_IQCAL_CORR_B0, - AR_PHY_RX_IQCAL_CORR_B1, - AR_PHY_RX_IQCAL_CORR_B2, - }; - const u_int32_t chan_info_tab[] = { + static const u32 chan_info_tab[] = { AR_PHY_CHAN_INFO_TAB_0, AR_PHY_CHAN_INFO_TAB_1, AR_PHY_CHAN_INFO_TAB_2, }; + struct coeff coeff; s32 iq_res[6]; - s32 iqc_coeff[2]; - s32 i, j; - u32 num_chains = 0; + s32 i, j, ip, im, nmeasurement; + u8 nchains = get_streams(common->tx_chainmask); + + for (ip = 0; ip < MPASS; ip++) { + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, + AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, + DELPT); + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, + AR_PHY_TX_IQCAL_START_DO_CAL, + AR_PHY_TX_IQCAL_START_DO_CAL); + + if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, + AR_PHY_TX_IQCAL_START_DO_CAL, + 0, AH_WAIT_TIMEOUT)) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Tx IQ Cal not complete.\n"); + goto TX_IQ_CAL_FAILED; + } - for (i = 0; i < AR9300_MAX_CHAINS; i++) { - if (ah->txchainmask & (1 << i)) - num_chains++; - } + nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0, + AR_PHY_CALIBRATED_GAINS_0); + if (nmeasurement > MAX_MEASUREMENT) + nmeasurement = MAX_MEASUREMENT; + + for (i = 0; i < nchains; i++) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Doing Tx IQ Cal for chain %d.\n", i); + for (im = 0; im < nmeasurement; im++) { + if (REG_READ(ah, txiqcal_status[i]) & + AR_PHY_TX_IQCAL_STATUS_FAILED) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Tx IQ Cal failed for chain %d.\n", i); + goto TX_IQ_CAL_FAILED; + } - REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, - AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, - DELPT); - REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, - AR_PHY_TX_IQCAL_START_DO_CAL, - AR_PHY_TX_IQCAL_START_DO_CAL); + for (j = 0; j < 3; j++) { + u8 idx = 2 * j, + offset = 4 * (3 * im + j); - if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, - AR_PHY_TX_IQCAL_START_DO_CAL, - 0, AH_WAIT_TIMEOUT)) { - ath_print(common, ATH_DBG_CALIBRATE, - "Tx IQ Cal not complete.\n"); - goto TX_IQ_CAL_FAILED; - } + REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, + AR_PHY_CHAN_INFO_TAB_S2_READ, + 0); - for (i = 0; i < num_chains; i++) { - ath_print(common, ATH_DBG_CALIBRATE, - "Doing Tx IQ Cal for chain %d.\n", i); + /* 32 bits */ + iq_res[idx] = REG_READ(ah, + chan_info_tab[i] + + offset); - if (REG_READ(ah, txiqcal_status[i]) & - AR_PHY_TX_IQCAL_STATUS_FAILED) { - ath_print(common, ATH_DBG_CALIBRATE, - "Tx IQ Cal failed for chain %d.\n", i); - goto TX_IQ_CAL_FAILED; - } + REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, + AR_PHY_CHAN_INFO_TAB_S2_READ, + 1); - for (j = 0; j < 3; j++) { - u_int8_t idx = 2 * j, - offset = 4 * j; + /* 16 bits */ + iq_res[idx+1] = 0xffff & REG_READ(ah, + chan_info_tab[i] + + offset); - REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, - AR_PHY_CHAN_INFO_TAB_S2_READ, 0); - - /* 32 bits */ - iq_res[idx] = REG_READ(ah, chan_info_tab[i] + offset); + ath_dbg(common, ATH_DBG_CALIBRATE, + "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n", + idx, iq_res[idx], idx+1, iq_res[idx+1]); + } - REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, - AR_PHY_CHAN_INFO_TAB_S2_READ, 1); + if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, + coeff.iqc_coeff)) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Failed in calculation of IQ correction.\n"); + goto TX_IQ_CAL_FAILED; + } + coeff.mag_coeff[i][im][ip] = + coeff.iqc_coeff[0] & 0x7f; + coeff.phs_coeff[i][im][ip] = + (coeff.iqc_coeff[0] >> 7) & 0x7f; - /* 16 bits */ - iq_res[idx+1] = 0xffff & REG_READ(ah, - chan_info_tab[i] + - offset); + if (coeff.mag_coeff[i][im][ip] > 63) + coeff.mag_coeff[i][im][ip] -= 128; + if (coeff.phs_coeff[i][im][ip] > 63) + coeff.phs_coeff[i][im][ip] -= 128; - ath_print(common, ATH_DBG_CALIBRATE, - "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n", - idx, iq_res[idx], idx+1, iq_res[idx+1]); - } - - if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, iqc_coeff)) { - ath_print(common, ATH_DBG_CALIBRATE, - "Failed in calculation of IQ correction.\n"); - goto TX_IQ_CAL_FAILED; + } } - - ath_print(common, ATH_DBG_CALIBRATE, - "IQ_COEFF[0] = 0x%x IQ_COEFF[1] = 0x%x\n", - iqc_coeff[0], iqc_coeff[1]); - - REG_RMW_FIELD(ah, tx_corr_coeff[i], - AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE, - iqc_coeff[0]); - REG_RMW_FIELD(ah, rx_corr[i], - AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF, - iqc_coeff[1] >> 7); - REG_RMW_FIELD(ah, rx_corr[i], - AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF, - iqc_coeff[1]); } - REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, - AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1); - REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, - AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); + ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff); return; TX_IQ_CAL_FAILED: - ath_print(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); +} + +static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) +{ + u8 tx_gain_forced; + + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485, + AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); + tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN, + AR_PHY_TXGAIN_FORCE); + if (tx_gain_forced) + REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, + AR_PHY_TXGAIN_FORCE, 0); + + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485, + AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1); } +static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + const u32 txiqcal_status[AR9300_MAX_CHAINS] = { + AR_PHY_TX_IQCAL_STATUS_B0_9485, + AR_PHY_TX_IQCAL_STATUS_B1, + AR_PHY_TX_IQCAL_STATUS_B2, + }; + const u_int32_t chan_info_tab[] = { + AR_PHY_CHAN_INFO_TAB_0, + AR_PHY_CHAN_INFO_TAB_1, + AR_PHY_CHAN_INFO_TAB_2, + }; + struct coeff coeff; + s32 iq_res[6]; + u8 num_chains = 0; + int i, ip, im, j; + int nmeasurement; + + for (i = 0; i < AR9300_MAX_CHAINS; i++) { + if (ah->txchainmask & (1 << i)) + num_chains++; + } + + for (ip = 0; ip < MPASS; ip++) { + for (i = 0; i < num_chains; i++) { + nmeasurement = REG_READ_FIELD(ah, + AR_PHY_TX_IQCAL_STATUS_B0_9485, + AR_PHY_CALIBRATED_GAINS_0); + if (nmeasurement > MAX_MEASUREMENT) + nmeasurement = MAX_MEASUREMENT; + + for (im = 0; im < nmeasurement; im++) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Doing Tx IQ Cal for chain %d.\n", i); + + if (REG_READ(ah, txiqcal_status[i]) & + AR_PHY_TX_IQCAL_STATUS_FAILED) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Tx IQ Cal failed for chain %d.\n", i); + goto tx_iqcal_fail; + } + + for (j = 0; j < 3; j++) { + u32 idx = 2 * j, offset = 4 * (3 * im + j); + + REG_RMW_FIELD(ah, + AR_PHY_CHAN_INFO_MEMORY, + AR_PHY_CHAN_INFO_TAB_S2_READ, + 0); + + /* 32 bits */ + iq_res[idx] = REG_READ(ah, + chan_info_tab[i] + + offset); + + REG_RMW_FIELD(ah, + AR_PHY_CHAN_INFO_MEMORY, + AR_PHY_CHAN_INFO_TAB_S2_READ, + 1); + + /* 16 bits */ + iq_res[idx + 1] = 0xffff & REG_READ(ah, + chan_info_tab[i] + offset); + + ath_dbg(common, ATH_DBG_CALIBRATE, + "IQ RES[%d]=0x%x" + "IQ_RES[%d]=0x%x\n", + idx, iq_res[idx], idx + 1, + iq_res[idx + 1]); + } + + if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, + coeff.iqc_coeff)) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Failed in calculation of IQ correction.\n"); + goto tx_iqcal_fail; + } + + coeff.mag_coeff[i][im][ip] = + coeff.iqc_coeff[0] & 0x7f; + coeff.phs_coeff[i][im][ip] = + (coeff.iqc_coeff[0] >> 7) & 0x7f; + + if (coeff.mag_coeff[i][im][ip] > 63) + coeff.mag_coeff[i][im][ip] -= 128; + if (coeff.phs_coeff[i][im][ip] > 63) + coeff.phs_coeff[i][im][ip] -= 128; + } + } + } + ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff); + + return; + +tx_iqcal_fail: + ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); + return; +} static bool ar9003_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { struct ath_common *common = ath9k_hw_common(ah); + int val; - /* - * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain mode before - * running AGC/TxIQ cals - */ - ar9003_hw_set_chain_masks(ah, 0x7, 0x7); + val = REG_READ(ah, AR_ENT_OTP); + ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); + + if (AR_SREV_9485(ah)) + ar9003_hw_set_chain_masks(ah, 0x1, 0x1); + else if (val & AR_ENT_OTP_CHAIN2_DISABLE) + ar9003_hw_set_chain_masks(ah, 0x3, 0x3); + else + /* + * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain + * mode before running AGC/TxIQ cals + */ + ar9003_hw_set_chain_masks(ah, 0x7, 0x7); /* Do Tx IQ Calibration */ - ar9003_hw_tx_iq_cal(ah); + if (AR_SREV_9485(ah)) + ar9003_hw_tx_iq_cal_run(ah); + else + ar9003_hw_tx_iq_cal(ah); + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); udelay(5); REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); @@ -739,12 +974,14 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, /* Poll for offset calibration complete */ if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { - ath_print(common, ATH_DBG_CALIBRATE, - "offset calibration failed to " - "complete in 1ms; noisy environment?\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "offset calibration failed to complete in 1ms; noisy environment?\n"); return false; } + if (AR_SREV_9485(ah)) + ar9003_hw_tx_iq_cal_post_proc(ah); + /* Revert chainmasks to their original values before NF cal */ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); @@ -757,15 +994,15 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, if (ah->supp_cals & IQ_MISMATCH_CAL) { INIT_CAL(&ah->iq_caldata); INSERT_CAL(ah, &ah->iq_caldata); - ath_print(common, ATH_DBG_CALIBRATE, - "enabling IQ Calibration.\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "enabling IQ Calibration.\n"); } if (ah->supp_cals & TEMP_COMP_CAL) { INIT_CAL(&ah->tempCompCalData); INSERT_CAL(ah, &ah->tempCompCalData); - ath_print(common, ATH_DBG_CALIBRATE, - "enabling Temperature Compensation Calibration.\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "enabling Temperature Compensation Calibration.\n"); } /* Initialize current pointer to first element in list */ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index a7b82f0085d2..4819747fa4c3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -22,12 +22,14 @@ #define COMP_CKSUM_LEN 2 #define AR_CH0_TOP (0x00016288) -#define AR_CH0_TOP_XPABIASLVL (0x3) +#define AR_CH0_TOP_XPABIASLVL (0x300) #define AR_CH0_TOP_XPABIASLVL_S (8) #define AR_CH0_THERM (0x00016290) -#define AR_CH0_THERM_SPARE (0x3f) -#define AR_CH0_THERM_SPARE_S (0) +#define AR_CH0_THERM_XPABIASLVL_MSB 0x3 +#define AR_CH0_THERM_XPABIASLVL_MSB_S 0 +#define AR_CH0_THERM_XPASHORT2GND 0x4 +#define AR_CH0_THERM_XPASHORT2GND_S 2 #define AR_SWITCH_TABLE_COM_ALL (0xffff) #define AR_SWITCH_TABLE_COM_ALL_S (0) @@ -57,6 +59,12 @@ #define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6)) +#define EEPROM_DATA_LEN_9485 1088 + +static int ar9003_hw_power_interpolate(int32_t x, + int32_t *px, int32_t *py, u_int16_t np); + + static const struct ar9300_eeprom ar9300_default = { .eepromVersion = 2, .templateVersion = 2, @@ -67,7 +75,7 @@ static const struct ar9300_eeprom ar9300_default = { .regDmn = { LE16(0), LE16(0x1f) }, .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ .opCapFlags = { - .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A, + .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, .eepMisc = 0, }, .rfSilent = 0, @@ -146,13 +154,16 @@ static const struct ar9300_eeprom ar9300_default = { .txEndToRxOn = 0x2, .txFrameToXpaOn = 0xe, .thresh62 = 28, - .papdRateMaskHt20 = LE32(0x80c080), - .papdRateMaskHt40 = LE32(0x80c080), + .papdRateMaskHt20 = LE32(0x0cf0e0e0), + .papdRateMaskHt40 = LE32(0x6cf0e0e0), .futureModal = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, }, + .base_ext1 = { + .ant_div_control = 0, + .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }, .calFreqPier2G = { FREQ2FBIN(2412, 1), FREQ2FBIN(2437, 1), @@ -287,8 +298,7 @@ static const struct ar9300_eeprom ar9300_default = { /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), - /* Data[11].ctlEdges[3].bChannel */ - FREQ2FBIN(2462, 1), + /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), } }, .ctlPowerData_2G = { @@ -346,13 +356,20 @@ static const struct ar9300_eeprom ar9300_default = { .txEndToRxOn = 0x2, .txFrameToXpaOn = 0xe, .thresh62 = 28, - .papdRateMaskHt20 = LE32(0xf0e0e0), - .papdRateMaskHt40 = LE32(0xf0e0e0), + .papdRateMaskHt20 = LE32(0x0c80c080), + .papdRateMaskHt40 = LE32(0x0080c080), .futureModal = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, }, + .base_ext2 = { + .tempSlopeLow = 0, + .tempSlopeHigh = 0, + .xatten1DBLow = {0, 0, 0}, + .xatten1MarginLow = {0, 0, 0}, + .xatten1DBHigh = {0, 0, 0}, + .xatten1MarginHigh = {0, 0, 0} + }, .calFreqPier5G = { FREQ2FBIN(5180, 0), FREQ2FBIN(5220, 0), @@ -626,9 +643,2341 @@ static const struct ar9300_eeprom ar9300_default = { } }; +static const struct ar9300_eeprom ar9300_x113 = { + .eepromVersion = 2, + .templateVersion = 6, + .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0}, + .custData = {"x113-023-f0000"}, + .baseEepHeader = { + .regDmn = { LE16(0), LE16(0x1f) }, + .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, + .eepMisc = 0, + }, + .rfSilent = 0, + .blueToothOptions = 0, + .deviceCap = 0, + .deviceType = 5, /* takes lower byte in eeprom location */ + .pwrTableOffset = AR9300_PWR_TABLE_OFFSET, + .params_for_tuning_caps = {0, 0}, + .featureEnable = 0x0d, + /* + * bit0 - enable tx temp comp - disabled + * bit1 - enable tx volt comp - disabled + * bit2 - enable fastClock - enabled + * bit3 - enable doubling - enabled + * bit4 - enable internal regulator - disabled + * bit5 - enable pa predistortion - disabled + */ + .miscConfiguration = 0, /* bit0 - turn down drivestrength */ + .eepromWriteEnableGpio = 6, + .wlanDisableGpio = 0, + .wlanLedGpio = 8, + .rxBandSelectGpio = 0xff, + .txrxgain = 0x21, + .swreg = 0, + }, + .modalHeader2G = { + /* ar9300_modal_eep_header 2g */ + /* 4 idle,t1,t2,b(4 bits per setting) */ + .antCtrlCommon = LE32(0x110), + /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ + .antCtrlCommon2 = LE32(0x44444), + + /* + * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, + * rx1, rx12, b (2 bits each) + */ + .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) }, + + /* + * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db + * for ar9280 (0xa20c/b20c 5:0) + */ + .xatten1DB = {0, 0, 0}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for ar9280 (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0, 0, 0}, + .tempSlope = 25, + .voltSlope = 0, + + /* + * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur + * channels in usual fbin coding format + */ + .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0}, + + /* + * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check + * if the register is per chain + */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {1, 1, 1},/* 3 chain */ + .db_stage2 = {1, 1, 1}, /* 3 chain */ + .db_stage3 = {0, 0, 0}, + .db_stage4 = {0, 0, 0}, + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2c, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0c80c080), + .papdRateMaskHt40 = LE32(0x0080c080), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext1 = { + .ant_div_control = 0, + .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }, + .calFreqPier2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1), + }, + /* ar9300_cal_data_per_freq_op_loop 2g */ + .calPierData2G = { + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + }, + .calTarget_freqbin_Cck = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2472, 1), + }, + .calTarget_freqbin_2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT20 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT40 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTargetPowerCck = { + /* 1L-5L,5S,11L,11S */ + { {34, 34, 34, 34} }, + { {34, 34, 34, 34} }, + }, + .calTargetPower2G = { + /* 6-24,36,48,54 */ + { {34, 34, 32, 32} }, + { {34, 34, 32, 32} }, + { {34, 34, 32, 32} }, + }, + .calTargetPower2GHT20 = { + { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} }, + { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} }, + { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} }, + }, + .calTargetPower2GHT40 = { + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, + }, + .ctlIndex_2G = { + 0x11, 0x12, 0x15, 0x17, 0x41, 0x42, + 0x45, 0x47, 0x31, 0x32, 0x35, 0x37, + }, + .ctl_freqbin_2G = { + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2457, 1), + FREQ2FBIN(2462, 1) + }, + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + { + FREQ2FBIN(2422, 1), + FREQ2FBIN(2427, 1), + FREQ2FBIN(2447, 1), + FREQ2FBIN(2452, 1) + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1), + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + }, + + { + /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), + } + }, + .ctlPowerData_2G = { + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, + + { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + }, + .modalHeader5G = { + /* 4 idle,t1,t2,b (4 bits per setting) */ + .antCtrlCommon = LE32(0x220), + /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ + .antCtrlCommon2 = LE32(0x11111), + /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ + .antCtrlChain = { + LE16(0x150), LE16(0x150), LE16(0x150), + }, + /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ + .xatten1DB = {0, 0, 0}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for merlin (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0, 0, 0}, + .tempSlope = 68, + .voltSlope = 0, + /* spurChans spur channels in usual fbin coding format */ + .spurChans = {FREQ2FBIN(5500, 0), 0, 0, 0, 0}, + /* noiseFloorThreshCh Check if the register is per chain */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {3, 3, 3}, /* 3 chain */ + .db_stage2 = {3, 3, 3}, /* 3 chain */ + .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ + .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2d, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0cf0e0e0), + .papdRateMaskHt40 = LE32(0x6cf0e0e0), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext2 = { + .tempSlopeLow = 72, + .tempSlopeHigh = 105, + .xatten1DBLow = {0, 0, 0}, + .xatten1MarginLow = {0, 0, 0}, + .xatten1DBHigh = {0, 0, 0}, + .xatten1MarginHigh = {0, 0, 0} + }, + .calFreqPier5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5785, 0) + }, + .calPierData5G = { + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + + }, + .calTarget_freqbin_5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5785, 0) + }, + .calTarget_freqbin_5GHT20 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT40 = { + FREQ2FBIN(5190, 0), + FREQ2FBIN(5230, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5410, 0), + FREQ2FBIN(5510, 0), + FREQ2FBIN(5670, 0), + FREQ2FBIN(5755, 0), + FREQ2FBIN(5825, 0) + }, + .calTargetPower5G = { + /* 6-24,36,48,54 */ + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + }, + .calTargetPower5GHT20 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, + { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, + { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, + { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, + { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, + { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, + { {38, 38, 38, 38, 32, 28, 38, 38, 32, 28, 38, 38, 32, 26} }, + { {36, 36, 36, 36, 32, 28, 36, 36, 32, 28, 36, 36, 32, 26} }, + }, + .calTargetPower5GHT40 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, + { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, + { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, + { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, + { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, + { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, + { {36, 36, 36, 36, 30, 26, 36, 36, 30, 26, 36, 36, 30, 24} }, + { {34, 34, 34, 34, 30, 26, 34, 34, 30, 26, 34, 34, 30, 24} }, + }, + .ctlIndex_5G = { + 0x10, 0x16, 0x18, 0x40, 0x46, + 0x48, 0x30, 0x36, 0x38 + }, + .ctl_freqbin_5G = { + { + /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0), + /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + { + /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0), + /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0), + /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0), + /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0), + /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0), + /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0) + }, + + { + /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0), + /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0), + /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[3].ctlEdges[6].bChannel */ 0xFF, + /* Data[3].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0), + /* Data[4].ctlEdges[4].bChannel */ 0xFF, + /* Data[4].ctlEdges[5].bChannel */ 0xFF, + /* Data[4].ctlEdges[6].bChannel */ 0xFF, + /* Data[4].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0), + /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0), + /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[5].ctlEdges[6].bChannel */ 0xFF, + /* Data[5].ctlEdges[7].bChannel */ 0xFF + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0), + /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0), + /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0), + /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0), + /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0) + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0), + /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0), + /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0), + /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0) + } + }, + .ctlPowerData_5G = { + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + } + }, + } +}; + + +static const struct ar9300_eeprom ar9300_h112 = { + .eepromVersion = 2, + .templateVersion = 3, + .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0}, + .custData = {"h112-241-f0000"}, + .baseEepHeader = { + .regDmn = { LE16(0), LE16(0x1f) }, + .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, + .eepMisc = 0, + }, + .rfSilent = 0, + .blueToothOptions = 0, + .deviceCap = 0, + .deviceType = 5, /* takes lower byte in eeprom location */ + .pwrTableOffset = AR9300_PWR_TABLE_OFFSET, + .params_for_tuning_caps = {0, 0}, + .featureEnable = 0x0d, + /* + * bit0 - enable tx temp comp - disabled + * bit1 - enable tx volt comp - disabled + * bit2 - enable fastClock - enabled + * bit3 - enable doubling - enabled + * bit4 - enable internal regulator - disabled + * bit5 - enable pa predistortion - disabled + */ + .miscConfiguration = 0, /* bit0 - turn down drivestrength */ + .eepromWriteEnableGpio = 6, + .wlanDisableGpio = 0, + .wlanLedGpio = 8, + .rxBandSelectGpio = 0xff, + .txrxgain = 0x10, + .swreg = 0, + }, + .modalHeader2G = { + /* ar9300_modal_eep_header 2g */ + /* 4 idle,t1,t2,b(4 bits per setting) */ + .antCtrlCommon = LE32(0x110), + /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ + .antCtrlCommon2 = LE32(0x44444), + + /* + * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, + * rx1, rx12, b (2 bits each) + */ + .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) }, + + /* + * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db + * for ar9280 (0xa20c/b20c 5:0) + */ + .xatten1DB = {0, 0, 0}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for ar9280 (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0, 0, 0}, + .tempSlope = 25, + .voltSlope = 0, + + /* + * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur + * channels in usual fbin coding format + */ + .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0}, + + /* + * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check + * if the register is per chain + */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {1, 1, 1},/* 3 chain */ + .db_stage2 = {1, 1, 1}, /* 3 chain */ + .db_stage3 = {0, 0, 0}, + .db_stage4 = {0, 0, 0}, + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2c, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x80c080), + .papdRateMaskHt40 = LE32(0x80c080), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext1 = { + .ant_div_control = 0, + .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }, + .calFreqPier2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1), + }, + /* ar9300_cal_data_per_freq_op_loop 2g */ + .calPierData2G = { + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + }, + .calTarget_freqbin_Cck = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2484, 1), + }, + .calTarget_freqbin_2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT20 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT40 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTargetPowerCck = { + /* 1L-5L,5S,11L,11S */ + { {34, 34, 34, 34} }, + { {34, 34, 34, 34} }, + }, + .calTargetPower2G = { + /* 6-24,36,48,54 */ + { {34, 34, 32, 32} }, + { {34, 34, 32, 32} }, + { {34, 34, 32, 32} }, + }, + .calTargetPower2GHT20 = { + { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} }, + { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} }, + { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} }, + }, + .calTargetPower2GHT40 = { + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} }, + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} }, + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} }, + }, + .ctlIndex_2G = { + 0x11, 0x12, 0x15, 0x17, 0x41, 0x42, + 0x45, 0x47, 0x31, 0x32, 0x35, 0x37, + }, + .ctl_freqbin_2G = { + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2457, 1), + FREQ2FBIN(2462, 1) + }, + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + { + FREQ2FBIN(2422, 1), + FREQ2FBIN(2427, 1), + FREQ2FBIN(2447, 1), + FREQ2FBIN(2452, 1) + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1), + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + }, + + { + /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), + } + }, + .ctlPowerData_2G = { + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, + + { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + }, + .modalHeader5G = { + /* 4 idle,t1,t2,b (4 bits per setting) */ + .antCtrlCommon = LE32(0x220), + /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ + .antCtrlCommon2 = LE32(0x44444), + /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ + .antCtrlChain = { + LE16(0x150), LE16(0x150), LE16(0x150), + }, + /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ + .xatten1DB = {0, 0, 0}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for merlin (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0, 0, 0}, + .tempSlope = 45, + .voltSlope = 0, + /* spurChans spur channels in usual fbin coding format */ + .spurChans = {0, 0, 0, 0, 0}, + /* noiseFloorThreshCh Check if the register is per chain */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {3, 3, 3}, /* 3 chain */ + .db_stage2 = {3, 3, 3}, /* 3 chain */ + .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ + .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2d, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0cf0e0e0), + .papdRateMaskHt40 = LE32(0x6cf0e0e0), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext2 = { + .tempSlopeLow = 40, + .tempSlopeHigh = 50, + .xatten1DBLow = {0, 0, 0}, + .xatten1MarginLow = {0, 0, 0}, + .xatten1DBHigh = {0, 0, 0}, + .xatten1MarginHigh = {0, 0, 0} + }, + .calFreqPier5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5825, 0) + }, + .calPierData5G = { + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + + }, + .calTarget_freqbin_5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT20 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT40 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5825, 0) + }, + .calTargetPower5G = { + /* 6-24,36,48,54 */ + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + }, + .calTargetPower5GHT20 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} }, + { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} }, + { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} }, + { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} }, + { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} }, + { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} }, + { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} }, + { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} }, + }, + .calTargetPower5GHT40 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} }, + { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} }, + { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} }, + { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} }, + { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} }, + { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} }, + { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} }, + { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} }, + }, + .ctlIndex_5G = { + 0x10, 0x16, 0x18, 0x40, 0x46, + 0x48, 0x30, 0x36, 0x38 + }, + .ctl_freqbin_5G = { + { + /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0), + /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + { + /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0), + /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0), + /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0), + /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0), + /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0), + /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0) + }, + + { + /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0), + /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0), + /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[3].ctlEdges[6].bChannel */ 0xFF, + /* Data[3].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0), + /* Data[4].ctlEdges[4].bChannel */ 0xFF, + /* Data[4].ctlEdges[5].bChannel */ 0xFF, + /* Data[4].ctlEdges[6].bChannel */ 0xFF, + /* Data[4].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0), + /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0), + /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[5].ctlEdges[6].bChannel */ 0xFF, + /* Data[5].ctlEdges[7].bChannel */ 0xFF + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0), + /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0), + /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0), + /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0), + /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0) + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0), + /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0), + /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0), + /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0) + } + }, + .ctlPowerData_5G = { + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + } + }, + } +}; + + +static const struct ar9300_eeprom ar9300_x112 = { + .eepromVersion = 2, + .templateVersion = 5, + .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0}, + .custData = {"x112-041-f0000"}, + .baseEepHeader = { + .regDmn = { LE16(0), LE16(0x1f) }, + .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, + .eepMisc = 0, + }, + .rfSilent = 0, + .blueToothOptions = 0, + .deviceCap = 0, + .deviceType = 5, /* takes lower byte in eeprom location */ + .pwrTableOffset = AR9300_PWR_TABLE_OFFSET, + .params_for_tuning_caps = {0, 0}, + .featureEnable = 0x0d, + /* + * bit0 - enable tx temp comp - disabled + * bit1 - enable tx volt comp - disabled + * bit2 - enable fastclock - enabled + * bit3 - enable doubling - enabled + * bit4 - enable internal regulator - disabled + * bit5 - enable pa predistortion - disabled + */ + .miscConfiguration = 0, /* bit0 - turn down drivestrength */ + .eepromWriteEnableGpio = 6, + .wlanDisableGpio = 0, + .wlanLedGpio = 8, + .rxBandSelectGpio = 0xff, + .txrxgain = 0x0, + .swreg = 0, + }, + .modalHeader2G = { + /* ar9300_modal_eep_header 2g */ + /* 4 idle,t1,t2,b(4 bits per setting) */ + .antCtrlCommon = LE32(0x110), + /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ + .antCtrlCommon2 = LE32(0x22222), + + /* + * antCtrlChain[ar9300_max_chains]; 6 idle, t, r, + * rx1, rx12, b (2 bits each) + */ + .antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) }, + + /* + * xatten1DB[AR9300_max_chains]; 3 xatten1_db + * for ar9280 (0xa20c/b20c 5:0) + */ + .xatten1DB = {0x1b, 0x1b, 0x1b}, + + /* + * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin + * for ar9280 (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0x15, 0x15, 0x15}, + .tempSlope = 50, + .voltSlope = 0, + + /* + * spurChans[OSPrey_eeprom_modal_sPURS]; spur + * channels in usual fbin coding format + */ + .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0}, + + /* + * noiseFloorThreshch[ar9300_max_cHAINS]; 3 Check + * if the register is per chain + */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {1, 1, 1},/* 3 chain */ + .db_stage2 = {1, 1, 1}, /* 3 chain */ + .db_stage3 = {0, 0, 0}, + .db_stage4 = {0, 0, 0}, + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2c, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0c80c080), + .papdRateMaskHt40 = LE32(0x0080c080), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext1 = { + .ant_div_control = 0, + .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }, + .calFreqPier2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1), + }, + /* ar9300_cal_data_per_freq_op_loop 2g */ + .calPierData2G = { + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + }, + .calTarget_freqbin_Cck = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2472, 1), + }, + .calTarget_freqbin_2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT20 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT40 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTargetPowerCck = { + /* 1L-5L,5S,11L,11s */ + { {38, 38, 38, 38} }, + { {38, 38, 38, 38} }, + }, + .calTargetPower2G = { + /* 6-24,36,48,54 */ + { {38, 38, 36, 34} }, + { {38, 38, 36, 34} }, + { {38, 38, 34, 32} }, + }, + .calTargetPower2GHT20 = { + { {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} }, + { {36, 36, 36, 36, 36, 34, 36, 34, 32, 30, 30, 30, 28, 26} }, + { {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} }, + }, + .calTargetPower2GHT40 = { + { {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} }, + { {36, 36, 36, 36, 34, 32, 34, 32, 30, 28, 28, 28, 28, 24} }, + { {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} }, + }, + .ctlIndex_2G = { + 0x11, 0x12, 0x15, 0x17, 0x41, 0x42, + 0x45, 0x47, 0x31, 0x32, 0x35, 0x37, + }, + .ctl_freqbin_2G = { + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2457, 1), + FREQ2FBIN(2462, 1) + }, + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + { + FREQ2FBIN(2422, 1), + FREQ2FBIN(2427, 1), + FREQ2FBIN(2447, 1), + FREQ2FBIN(2452, 1) + }, + + { + /* Data[4].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), + /* Data[4].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), + /* Data[4].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), + /* Data[4].ctledges[3].bchannel */ FREQ2FBIN(2484, 1), + }, + + { + /* Data[5].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), + /* Data[5].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), + /* Data[5].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[6].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), + /* Data[6].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), + FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[7].ctledges[0].bchannel */ FREQ2FBIN(2422, 1), + /* Data[7].ctledges[1].bchannel */ FREQ2FBIN(2427, 1), + /* Data[7].ctledges[2].bchannel */ FREQ2FBIN(2447, 1), + /* Data[7].ctledges[3].bchannel */ FREQ2FBIN(2462, 1), + }, + + { + /* Data[8].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), + /* Data[8].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), + /* Data[8].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), + }, + + { + /* Data[9].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), + /* Data[9].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), + /* Data[9].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[10].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), + /* Data[10].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), + /* Data[10].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[11].ctledges[0].bchannel */ FREQ2FBIN(2422, 1), + /* Data[11].ctledges[1].bchannel */ FREQ2FBIN(2427, 1), + /* Data[11].ctledges[2].bchannel */ FREQ2FBIN(2447, 1), + /* Data[11].ctledges[3].bchannel */ FREQ2FBIN(2462, 1), + } + }, + .ctlPowerData_2G = { + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, + + { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + }, + .modalHeader5G = { + /* 4 idle,t1,t2,b (4 bits per setting) */ + .antCtrlCommon = LE32(0x110), + /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ + .antCtrlCommon2 = LE32(0x22222), + /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ + .antCtrlChain = { + LE16(0x0), LE16(0x0), LE16(0x0), + }, + /* xatten1DB 3 xatten1_db for ar9280 (0xa20c/b20c 5:0) */ + .xatten1DB = {0x13, 0x19, 0x17}, + + /* + * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin + * for merlin (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0x19, 0x19, 0x19}, + .tempSlope = 70, + .voltSlope = 15, + /* spurChans spur channels in usual fbin coding format */ + .spurChans = {0, 0, 0, 0, 0}, + /* noiseFloorThreshch check if the register is per chain */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {3, 3, 3}, /* 3 chain */ + .db_stage2 = {3, 3, 3}, /* 3 chain */ + .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ + .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2d, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0cf0e0e0), + .papdRateMaskHt40 = LE32(0x6cf0e0e0), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext2 = { + .tempSlopeLow = 72, + .tempSlopeHigh = 105, + .xatten1DBLow = {0x10, 0x14, 0x10}, + .xatten1MarginLow = {0x19, 0x19 , 0x19}, + .xatten1DBHigh = {0x1d, 0x20, 0x24}, + .xatten1MarginHigh = {0x10, 0x10, 0x10} + }, + .calFreqPier5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5785, 0) + }, + .calPierData5G = { + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + + }, + .calTarget_freqbin_5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5725, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT20 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5725, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT40 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5725, 0), + FREQ2FBIN(5825, 0) + }, + .calTargetPower5G = { + /* 6-24,36,48,54 */ + { {32, 32, 28, 26} }, + { {32, 32, 28, 26} }, + { {32, 32, 28, 26} }, + { {32, 32, 26, 24} }, + { {32, 32, 26, 24} }, + { {32, 32, 24, 22} }, + { {30, 30, 24, 22} }, + { {30, 30, 24, 22} }, + }, + .calTargetPower5GHT20 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} }, + { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} }, + { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} }, + { {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 22, 22, 20, 20} }, + { {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 20, 18, 16, 16} }, + { {32, 32, 32, 32, 28, 26, 32, 24, 20, 16, 18, 16, 14, 14} }, + { {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} }, + { {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} }, + }, + .calTargetPower5GHT40 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} }, + { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} }, + { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} }, + { {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 22, 22, 20, 20} }, + { {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 20, 18, 16, 16} }, + { {32, 32, 32, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} }, + { {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} }, + { {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} }, + }, + .ctlIndex_5G = { + 0x10, 0x16, 0x18, 0x40, 0x46, + 0x48, 0x30, 0x36, 0x38 + }, + .ctl_freqbin_5G = { + { + /* Data[0].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), + /* Data[0].ctledges[1].bchannel */ FREQ2FBIN(5260, 0), + /* Data[0].ctledges[2].bchannel */ FREQ2FBIN(5280, 0), + /* Data[0].ctledges[3].bchannel */ FREQ2FBIN(5500, 0), + /* Data[0].ctledges[4].bchannel */ FREQ2FBIN(5600, 0), + /* Data[0].ctledges[5].bchannel */ FREQ2FBIN(5700, 0), + /* Data[0].ctledges[6].bchannel */ FREQ2FBIN(5745, 0), + /* Data[0].ctledges[7].bchannel */ FREQ2FBIN(5825, 0) + }, + { + /* Data[1].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), + /* Data[1].ctledges[1].bchannel */ FREQ2FBIN(5260, 0), + /* Data[1].ctledges[2].bchannel */ FREQ2FBIN(5280, 0), + /* Data[1].ctledges[3].bchannel */ FREQ2FBIN(5500, 0), + /* Data[1].ctledges[4].bchannel */ FREQ2FBIN(5520, 0), + /* Data[1].ctledges[5].bchannel */ FREQ2FBIN(5700, 0), + /* Data[1].ctledges[6].bchannel */ FREQ2FBIN(5745, 0), + /* Data[1].ctledges[7].bchannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[2].ctledges[0].bchannel */ FREQ2FBIN(5190, 0), + /* Data[2].ctledges[1].bchannel */ FREQ2FBIN(5230, 0), + /* Data[2].ctledges[2].bchannel */ FREQ2FBIN(5270, 0), + /* Data[2].ctledges[3].bchannel */ FREQ2FBIN(5310, 0), + /* Data[2].ctledges[4].bchannel */ FREQ2FBIN(5510, 0), + /* Data[2].ctledges[5].bchannel */ FREQ2FBIN(5550, 0), + /* Data[2].ctledges[6].bchannel */ FREQ2FBIN(5670, 0), + /* Data[2].ctledges[7].bchannel */ FREQ2FBIN(5755, 0) + }, + + { + /* Data[3].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), + /* Data[3].ctledges[1].bchannel */ FREQ2FBIN(5200, 0), + /* Data[3].ctledges[2].bchannel */ FREQ2FBIN(5260, 0), + /* Data[3].ctledges[3].bchannel */ FREQ2FBIN(5320, 0), + /* Data[3].ctledges[4].bchannel */ FREQ2FBIN(5500, 0), + /* Data[3].ctledges[5].bchannel */ FREQ2FBIN(5700, 0), + /* Data[3].ctledges[6].bchannel */ 0xFF, + /* Data[3].ctledges[7].bchannel */ 0xFF, + }, + + { + /* Data[4].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), + /* Data[4].ctledges[1].bchannel */ FREQ2FBIN(5260, 0), + /* Data[4].ctledges[2].bchannel */ FREQ2FBIN(5500, 0), + /* Data[4].ctledges[3].bchannel */ FREQ2FBIN(5700, 0), + /* Data[4].ctledges[4].bchannel */ 0xFF, + /* Data[4].ctledges[5].bchannel */ 0xFF, + /* Data[4].ctledges[6].bchannel */ 0xFF, + /* Data[4].ctledges[7].bchannel */ 0xFF, + }, + + { + /* Data[5].ctledges[0].bchannel */ FREQ2FBIN(5190, 0), + /* Data[5].ctledges[1].bchannel */ FREQ2FBIN(5270, 0), + /* Data[5].ctledges[2].bchannel */ FREQ2FBIN(5310, 0), + /* Data[5].ctledges[3].bchannel */ FREQ2FBIN(5510, 0), + /* Data[5].ctledges[4].bchannel */ FREQ2FBIN(5590, 0), + /* Data[5].ctledges[5].bchannel */ FREQ2FBIN(5670, 0), + /* Data[5].ctledges[6].bchannel */ 0xFF, + /* Data[5].ctledges[7].bchannel */ 0xFF + }, + + { + /* Data[6].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), + /* Data[6].ctledges[1].bchannel */ FREQ2FBIN(5200, 0), + /* Data[6].ctledges[2].bchannel */ FREQ2FBIN(5220, 0), + /* Data[6].ctledges[3].bchannel */ FREQ2FBIN(5260, 0), + /* Data[6].ctledges[4].bchannel */ FREQ2FBIN(5500, 0), + /* Data[6].ctledges[5].bchannel */ FREQ2FBIN(5600, 0), + /* Data[6].ctledges[6].bchannel */ FREQ2FBIN(5700, 0), + /* Data[6].ctledges[7].bchannel */ FREQ2FBIN(5745, 0) + }, + + { + /* Data[7].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), + /* Data[7].ctledges[1].bchannel */ FREQ2FBIN(5260, 0), + /* Data[7].ctledges[2].bchannel */ FREQ2FBIN(5320, 0), + /* Data[7].ctledges[3].bchannel */ FREQ2FBIN(5500, 0), + /* Data[7].ctledges[4].bchannel */ FREQ2FBIN(5560, 0), + /* Data[7].ctledges[5].bchannel */ FREQ2FBIN(5700, 0), + /* Data[7].ctledges[6].bchannel */ FREQ2FBIN(5745, 0), + /* Data[7].ctledges[7].bchannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[8].ctledges[0].bchannel */ FREQ2FBIN(5190, 0), + /* Data[8].ctledges[1].bchannel */ FREQ2FBIN(5230, 0), + /* Data[8].ctledges[2].bchannel */ FREQ2FBIN(5270, 0), + /* Data[8].ctledges[3].bchannel */ FREQ2FBIN(5510, 0), + /* Data[8].ctledges[4].bchannel */ FREQ2FBIN(5550, 0), + /* Data[8].ctledges[5].bchannel */ FREQ2FBIN(5670, 0), + /* Data[8].ctledges[6].bchannel */ FREQ2FBIN(5755, 0), + /* Data[8].ctledges[7].bchannel */ FREQ2FBIN(5795, 0) + } + }, + .ctlPowerData_5G = { + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + } + }, + } +}; + +static const struct ar9300_eeprom ar9300_h116 = { + .eepromVersion = 2, + .templateVersion = 4, + .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0}, + .custData = {"h116-041-f0000"}, + .baseEepHeader = { + .regDmn = { LE16(0), LE16(0x1f) }, + .txrxMask = 0x33, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, + .eepMisc = 0, + }, + .rfSilent = 0, + .blueToothOptions = 0, + .deviceCap = 0, + .deviceType = 5, /* takes lower byte in eeprom location */ + .pwrTableOffset = AR9300_PWR_TABLE_OFFSET, + .params_for_tuning_caps = {0, 0}, + .featureEnable = 0x0d, + /* + * bit0 - enable tx temp comp - disabled + * bit1 - enable tx volt comp - disabled + * bit2 - enable fastClock - enabled + * bit3 - enable doubling - enabled + * bit4 - enable internal regulator - disabled + * bit5 - enable pa predistortion - disabled + */ + .miscConfiguration = 0, /* bit0 - turn down drivestrength */ + .eepromWriteEnableGpio = 6, + .wlanDisableGpio = 0, + .wlanLedGpio = 8, + .rxBandSelectGpio = 0xff, + .txrxgain = 0x10, + .swreg = 0, + }, + .modalHeader2G = { + /* ar9300_modal_eep_header 2g */ + /* 4 idle,t1,t2,b(4 bits per setting) */ + .antCtrlCommon = LE32(0x110), + /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ + .antCtrlCommon2 = LE32(0x44444), + + /* + * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, + * rx1, rx12, b (2 bits each) + */ + .antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) }, + + /* + * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db + * for ar9280 (0xa20c/b20c 5:0) + */ + .xatten1DB = {0x1f, 0x1f, 0x1f}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for ar9280 (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0x12, 0x12, 0x12}, + .tempSlope = 25, + .voltSlope = 0, + + /* + * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur + * channels in usual fbin coding format + */ + .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0}, + + /* + * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check + * if the register is per chain + */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {1, 1, 1},/* 3 chain */ + .db_stage2 = {1, 1, 1}, /* 3 chain */ + .db_stage3 = {0, 0, 0}, + .db_stage4 = {0, 0, 0}, + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2c, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0c80C080), + .papdRateMaskHt40 = LE32(0x0080C080), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext1 = { + .ant_div_control = 0, + .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }, + .calFreqPier2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1), + }, + /* ar9300_cal_data_per_freq_op_loop 2g */ + .calPierData2G = { + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + }, + .calTarget_freqbin_Cck = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2472, 1), + }, + .calTarget_freqbin_2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT20 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT40 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTargetPowerCck = { + /* 1L-5L,5S,11L,11S */ + { {34, 34, 34, 34} }, + { {34, 34, 34, 34} }, + }, + .calTargetPower2G = { + /* 6-24,36,48,54 */ + { {34, 34, 32, 32} }, + { {34, 34, 32, 32} }, + { {34, 34, 32, 32} }, + }, + .calTargetPower2GHT20 = { + { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} }, + { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} }, + { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} }, + }, + .calTargetPower2GHT40 = { + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, + }, + .ctlIndex_2G = { + 0x11, 0x12, 0x15, 0x17, 0x41, 0x42, + 0x45, 0x47, 0x31, 0x32, 0x35, 0x37, + }, + .ctl_freqbin_2G = { + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2457, 1), + FREQ2FBIN(2462, 1) + }, + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + { + FREQ2FBIN(2422, 1), + FREQ2FBIN(2427, 1), + FREQ2FBIN(2447, 1), + FREQ2FBIN(2452, 1) + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1), + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + }, + + { + /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), + } + }, + .ctlPowerData_2G = { + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, + + { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + }, + .modalHeader5G = { + /* 4 idle,t1,t2,b (4 bits per setting) */ + .antCtrlCommon = LE32(0x220), + /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ + .antCtrlCommon2 = LE32(0x44444), + /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ + .antCtrlChain = { + LE16(0x150), LE16(0x150), LE16(0x150), + }, + /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ + .xatten1DB = {0x19, 0x19, 0x19}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for merlin (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0x14, 0x14, 0x14}, + .tempSlope = 70, + .voltSlope = 0, + /* spurChans spur channels in usual fbin coding format */ + .spurChans = {0, 0, 0, 0, 0}, + /* noiseFloorThreshCh Check if the register is per chain */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {3, 3, 3}, /* 3 chain */ + .db_stage2 = {3, 3, 3}, /* 3 chain */ + .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ + .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2d, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0cf0e0e0), + .papdRateMaskHt40 = LE32(0x6cf0e0e0), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext2 = { + .tempSlopeLow = 35, + .tempSlopeHigh = 50, + .xatten1DBLow = {0, 0, 0}, + .xatten1MarginLow = {0, 0, 0}, + .xatten1DBHigh = {0, 0, 0}, + .xatten1MarginHigh = {0, 0, 0} + }, + .calFreqPier5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5785, 0) + }, + .calPierData5G = { + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + + }, + .calTarget_freqbin_5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT20 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT40 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5825, 0) + }, + .calTargetPower5G = { + /* 6-24,36,48,54 */ + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + }, + .calTargetPower5GHT20 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} }, + { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} }, + { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} }, + { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} }, + { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} }, + { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} }, + { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} }, + { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} }, + }, + .calTargetPower5GHT40 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} }, + { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} }, + { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} }, + { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} }, + { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} }, + { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} }, + { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} }, + { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} }, + }, + .ctlIndex_5G = { + 0x10, 0x16, 0x18, 0x40, 0x46, + 0x48, 0x30, 0x36, 0x38 + }, + .ctl_freqbin_5G = { + { + /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0), + /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + { + /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0), + /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0), + /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0), + /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0), + /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0), + /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0) + }, + + { + /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0), + /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0), + /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[3].ctlEdges[6].bChannel */ 0xFF, + /* Data[3].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0), + /* Data[4].ctlEdges[4].bChannel */ 0xFF, + /* Data[4].ctlEdges[5].bChannel */ 0xFF, + /* Data[4].ctlEdges[6].bChannel */ 0xFF, + /* Data[4].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0), + /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0), + /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[5].ctlEdges[6].bChannel */ 0xFF, + /* Data[5].ctlEdges[7].bChannel */ 0xFF + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0), + /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0), + /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0), + /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0), + /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0) + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0), + /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0), + /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0), + /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0) + } + }, + .ctlPowerData_5G = { + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + } + }, + } +}; + + +static const struct ar9300_eeprom *ar9300_eep_templates[] = { + &ar9300_default, + &ar9300_x112, + &ar9300_h116, + &ar9300_h112, + &ar9300_x113, +}; + +static const struct ar9300_eeprom *ar9003_eeprom_struct_find_by_id(int id) +{ +#define N_LOOP (sizeof(ar9300_eep_templates) / sizeof(ar9300_eep_templates[0])) + int it; + + for (it = 0; it < N_LOOP; it++) + if (ar9300_eep_templates[it]->templateVersion == id) + return ar9300_eep_templates[it]; + return NULL; +#undef N_LOOP +} + + static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) { - if (fbin == AR9300_BCHAN_UNUSED) + if (fbin == AR5416_BCHAN_UNUSED) return fbin; return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); @@ -639,6 +2988,16 @@ static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah) return 0; } +static int interpolate(int x, int xa, int xb, int ya, int yb) +{ + int bf, factor, plus; + + bf = 2 * (yb - ya) * (x - xa) / (xb - xa); + factor = bf / 2; + plus = bf % 2; + return ya + factor + plus; +} + static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, enum eeprom_param param) { @@ -676,6 +3035,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, return le32_to_cpu(pBase->swreg); case EEP_PAPRD: return !!(pBase->featureEnable & BIT(5)); + case EEP_CHAIN_MASK_REDUCE: + return (pBase->miscConfiguration >> 0x3) & 0x1; + case EEP_ANT_DIV_CTL1: + return le32_to_cpu(eep->base_ext1.ant_div_control); default: return 0; } @@ -714,8 +3077,8 @@ static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer, int i; if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) { - ath_print(common, ATH_DBG_EEPROM, - "eeprom address not in range\n"); + ath_dbg(common, ATH_DBG_EEPROM, + "eeprom address not in range\n"); return false; } @@ -746,11 +3109,41 @@ static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer, return true; error: - ath_print(common, ATH_DBG_EEPROM, - "unable to read eeprom region at offset %d\n", address); + ath_dbg(common, ATH_DBG_EEPROM, + "unable to read eeprom region at offset %d\n", address); return false; } +static bool ar9300_otp_read_word(struct ath_hw *ah, int addr, u32 *data) +{ + REG_READ(ah, AR9300_OTP_BASE + (4 * addr)); + + if (!ath9k_hw_wait(ah, AR9300_OTP_STATUS, AR9300_OTP_STATUS_TYPE, + AR9300_OTP_STATUS_VALID, 1000)) + return false; + + *data = REG_READ(ah, AR9300_OTP_READ_DATA); + return true; +} + +static bool ar9300_read_otp(struct ath_hw *ah, int address, u8 *buffer, + int count) +{ + u32 data; + int i; + + for (i = 0; i < count; i++) { + int offset = 8 * ((address - i) % 4); + if (!ar9300_otp_read_word(ah, (address - i) / 4, &data)) + return false; + + buffer[i] = (data >> offset) & 0xff; + } + + return true; +} + + static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference, int *length, int *major, int *minor) { @@ -801,17 +3194,15 @@ static bool ar9300_uncompress_block(struct ath_hw *ah, length &= 0xff; if (length > 0 && spot >= 0 && spot+length <= mdataSize) { - ath_print(common, ATH_DBG_EEPROM, - "Restore at %d: spot=%d " - "offset=%d length=%d\n", - it, spot, offset, length); + ath_dbg(common, ATH_DBG_EEPROM, + "Restore at %d: spot=%d offset=%d length=%d\n", + it, spot, offset, length); memcpy(&mptr[spot], &block[it+2], length); spot += length; } else if (length > 0) { - ath_print(common, ATH_DBG_EEPROM, - "Bad restore at %d: spot=%d " - "offset=%d length=%d\n", - it, spot, offset, length); + ath_dbg(common, ATH_DBG_EEPROM, + "Bad restore at %d: spot=%d offset=%d length=%d\n", + it, spot, offset, length); return false; } } @@ -827,45 +3218,80 @@ static int ar9300_compress_decision(struct ath_hw *ah, { struct ath_common *common = ath9k_hw_common(ah); u8 *dptr; + const struct ar9300_eeprom *eep = NULL; switch (code) { case _CompressNone: if (length != mdata_size) { - ath_print(common, ATH_DBG_EEPROM, - "EEPROM structure size mismatch" - "memory=%d eeprom=%d\n", mdata_size, length); + ath_dbg(common, ATH_DBG_EEPROM, + "EEPROM structure size mismatch memory=%d eeprom=%d\n", + mdata_size, length); return -1; } memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length); - ath_print(common, ATH_DBG_EEPROM, "restored eeprom %d:" - " uncompressed, length %d\n", it, length); + ath_dbg(common, ATH_DBG_EEPROM, + "restored eeprom %d: uncompressed, length %d\n", + it, length); break; case _CompressBlock: if (reference == 0) { dptr = mptr; } else { - if (reference != 2) { - ath_print(common, ATH_DBG_EEPROM, - "cant find reference eeprom" - "struct %d\n", reference); + eep = ar9003_eeprom_struct_find_by_id(reference); + if (eep == NULL) { + ath_dbg(common, ATH_DBG_EEPROM, + "cant find reference eeprom struct %d\n", + reference); return -1; } - memcpy(mptr, &ar9300_default, mdata_size); + memcpy(mptr, eep, mdata_size); } - ath_print(common, ATH_DBG_EEPROM, - "restore eeprom %d: block, reference %d," - " length %d\n", it, reference, length); + ath_dbg(common, ATH_DBG_EEPROM, + "restore eeprom %d: block, reference %d, length %d\n", + it, reference, length); ar9300_uncompress_block(ah, mptr, mdata_size, (u8 *) (word + COMP_HDR_LEN), length); break; default: - ath_print(common, ATH_DBG_EEPROM, "unknown compression" - " code %d\n", code); + ath_dbg(common, ATH_DBG_EEPROM, + "unknown compression code %d\n", code); return -1; } return 0; } +typedef bool (*eeprom_read_op)(struct ath_hw *ah, int address, u8 *buffer, + int count); + +static bool ar9300_check_header(void *data) +{ + u32 *word = data; + return !(*word == 0 || *word == ~0); +} + +static bool ar9300_check_eeprom_header(struct ath_hw *ah, eeprom_read_op read, + int base_addr) +{ + u8 header[4]; + + if (!read(ah, base_addr, header, 4)) + return false; + + return ar9300_check_header(header); +} + +static int ar9300_eeprom_restore_flash(struct ath_hw *ah, u8 *mptr, + int mdata_size) +{ + struct ath_common *common = ath9k_hw_common(ah); + u16 *data = (u16 *) mptr; + int i; + + for (i = 0; i < mdata_size / 2; i++, data++) + ath9k_hw_nvram_read(common, i, data); + + return 0; +} /* * Read the configuration data from the eeprom. * The data can be put in any specified memory buffer. @@ -886,6 +3312,10 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah, int it; u16 checksum, mchecksum; struct ath_common *common = ath9k_hw_common(ah); + eeprom_read_op read; + + if (ath9k_hw_use_flash(ah)) + return ar9300_eeprom_restore_flash(ah, mptr, mdata_size); word = kzalloc(2048, GFP_KERNEL); if (!word) @@ -893,43 +3323,73 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah, memcpy(mptr, &ar9300_default, mdata_size); + read = ar9300_read_eeprom; + if (AR_SREV_9485(ah)) + cptr = AR9300_BASE_ADDR_4K; + else + cptr = AR9300_BASE_ADDR; + ath_dbg(common, ATH_DBG_EEPROM, + "Trying EEPROM accesss at Address 0x%04x\n", cptr); + if (ar9300_check_eeprom_header(ah, read, cptr)) + goto found; + + cptr = AR9300_BASE_ADDR_512; + ath_dbg(common, ATH_DBG_EEPROM, + "Trying EEPROM accesss at Address 0x%04x\n", cptr); + if (ar9300_check_eeprom_header(ah, read, cptr)) + goto found; + + read = ar9300_read_otp; cptr = AR9300_BASE_ADDR; + ath_dbg(common, ATH_DBG_EEPROM, + "Trying OTP accesss at Address 0x%04x\n", cptr); + if (ar9300_check_eeprom_header(ah, read, cptr)) + goto found; + + cptr = AR9300_BASE_ADDR_512; + ath_dbg(common, ATH_DBG_EEPROM, + "Trying OTP accesss at Address 0x%04x\n", cptr); + if (ar9300_check_eeprom_header(ah, read, cptr)) + goto found; + + goto fail; + +found: + ath_dbg(common, ATH_DBG_EEPROM, "Found valid EEPROM data\n"); + for (it = 0; it < MSTATE; it++) { - if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN)) + if (!read(ah, cptr, word, COMP_HDR_LEN)) goto fail; - if ((word[0] == 0 && word[1] == 0 && word[2] == 0 && - word[3] == 0) || (word[0] == 0xff && word[1] == 0xff - && word[2] == 0xff && word[3] == 0xff)) + if (!ar9300_check_header(word)) break; ar9300_comp_hdr_unpack(word, &code, &reference, &length, &major, &minor); - ath_print(common, ATH_DBG_EEPROM, - "Found block at %x: code=%d ref=%d" - "length=%d major=%d minor=%d\n", cptr, code, - reference, length, major, minor); - if (length >= 1024) { - ath_print(common, ATH_DBG_EEPROM, - "Skipping bad header\n"); + ath_dbg(common, ATH_DBG_EEPROM, + "Found block at %x: code=%d ref=%d length=%d major=%d minor=%d\n", + cptr, code, reference, length, major, minor); + if ((!AR_SREV_9485(ah) && length >= 1024) || + (AR_SREV_9485(ah) && length > EEPROM_DATA_LEN_9485)) { + ath_dbg(common, ATH_DBG_EEPROM, + "Skipping bad header\n"); cptr -= COMP_HDR_LEN; continue; } osize = length; - ar9300_read_eeprom(ah, cptr, word, - COMP_HDR_LEN + osize + COMP_CKSUM_LEN); + read(ah, cptr, word, COMP_HDR_LEN + osize + COMP_CKSUM_LEN); checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length); mchecksum = word[COMP_HDR_LEN + osize] | (word[COMP_HDR_LEN + osize + 1] << 8); - ath_print(common, ATH_DBG_EEPROM, - "checksum %x %x\n", checksum, mchecksum); + ath_dbg(common, ATH_DBG_EEPROM, + "checksum %x %x\n", checksum, mchecksum); if (checksum == mchecksum) { ar9300_compress_decision(ah, it, code, reference, mptr, word, length, mdata_size); } else { - ath_print(common, ATH_DBG_EEPROM, - "skipping block with bad checksum\n"); + ath_dbg(common, ATH_DBG_EEPROM, + "skipping block with bad checksum\n"); } cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN); } @@ -970,18 +3430,6 @@ static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah) return 0; } -static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah, - enum ath9k_hal_freq_band freq_band) -{ - return 1; -} - -static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - return -EINVAL; -} - static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz) { struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; @@ -995,9 +3443,15 @@ static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz) static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) { int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz); - REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, (bias & 0x3)); - REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_SPARE, - ((bias >> 2) & 0x3)); + + if (AR_SREV_9485(ah)) + REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); + else { + REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); + REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB, + bias >> 2); + REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1); + } } static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz) @@ -1052,11 +3506,25 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value); - value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); - REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value); + if (!AR_SREV_9485(ah)) { + value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); + REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, + value); - value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz); - REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value); + value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz); + REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, + value); + } + + if (AR_SREV_9485(ah)) { + value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1); + REG_RMW_FIELD(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_CTRL_ALL, + value); + REG_RMW_FIELD(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE, + value >> 6); + REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE, + value >> 7); + } } static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) @@ -1100,28 +3568,177 @@ static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg); } +static u16 ar9003_hw_atten_chain_get(struct ath_hw *ah, int chain, + struct ath9k_channel *chan) +{ + int f[3], t[3]; + u16 value; + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + if (chain >= 0 && chain < 3) { + if (IS_CHAN_2GHZ(chan)) + return eep->modalHeader2G.xatten1DB[chain]; + else if (eep->base_ext2.xatten1DBLow[chain] != 0) { + t[0] = eep->base_ext2.xatten1DBLow[chain]; + f[0] = 5180; + t[1] = eep->modalHeader5G.xatten1DB[chain]; + f[1] = 5500; + t[2] = eep->base_ext2.xatten1DBHigh[chain]; + f[2] = 5785; + value = ar9003_hw_power_interpolate((s32) chan->channel, + f, t, 3); + return value; + } else + return eep->modalHeader5G.xatten1DB[chain]; + } + + return 0; +} + + +static u16 ar9003_hw_atten_chain_get_margin(struct ath_hw *ah, int chain, + struct ath9k_channel *chan) +{ + int f[3], t[3]; + u16 value; + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + if (chain >= 0 && chain < 3) { + if (IS_CHAN_2GHZ(chan)) + return eep->modalHeader2G.xatten1Margin[chain]; + else if (eep->base_ext2.xatten1MarginLow[chain] != 0) { + t[0] = eep->base_ext2.xatten1MarginLow[chain]; + f[0] = 5180; + t[1] = eep->modalHeader5G.xatten1Margin[chain]; + f[1] = 5500; + t[2] = eep->base_ext2.xatten1MarginHigh[chain]; + f[2] = 5785; + value = ar9003_hw_power_interpolate((s32) chan->channel, + f, t, 3); + return value; + } else + return eep->modalHeader5G.xatten1Margin[chain]; + } + + return 0; +} + +static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan) +{ + int i; + u16 value; + unsigned long ext_atten_reg[3] = {AR_PHY_EXT_ATTEN_CTL_0, + AR_PHY_EXT_ATTEN_CTL_1, + AR_PHY_EXT_ATTEN_CTL_2, + }; + + /* Test value. if 0 then attenuation is unused. Don't load anything. */ + for (i = 0; i < 3; i++) { + value = ar9003_hw_atten_chain_get(ah, i, chan); + REG_RMW_FIELD(ah, ext_atten_reg[i], + AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); + + value = ar9003_hw_atten_chain_get_margin(ah, i, chan); + REG_RMW_FIELD(ah, ext_atten_reg[i], + AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); + } +} + +static bool is_pmu_set(struct ath_hw *ah, u32 pmu_reg, int pmu_set) +{ + int timeout = 100; + + while (pmu_set != REG_READ(ah, pmu_reg)) { + if (timeout-- == 0) + return false; + REG_WRITE(ah, pmu_reg, pmu_set); + udelay(10); + } + + return true; +} + static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah) { int internal_regulator = ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR); if (internal_regulator) { - /* Internal regulator is ON. Write swreg register. */ - int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG); - REG_WRITE(ah, AR_RTC_REG_CONTROL1, - REG_READ(ah, AR_RTC_REG_CONTROL1) & - (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM)); - REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg); - /* Set REG_CONTROL1.SWREG_PROGRAM */ - REG_WRITE(ah, AR_RTC_REG_CONTROL1, - REG_READ(ah, - AR_RTC_REG_CONTROL1) | - AR_RTC_REG_CONTROL1_SWREG_PROGRAM); + if (AR_SREV_9485(ah)) { + int reg_pmu_set; + + reg_pmu_set = REG_READ(ah, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM; + REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set); + if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set)) + return; + + reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) | + (7 << 14) | (6 << 17) | (1 << 20) | + (3 << 24) | (1 << 28); + + REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set); + if (!is_pmu_set(ah, AR_PHY_PMU1, reg_pmu_set)) + return; + + reg_pmu_set = (REG_READ(ah, AR_PHY_PMU2) & ~0xFFC00000) + | (4 << 26); + REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set); + if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set)) + return; + + reg_pmu_set = (REG_READ(ah, AR_PHY_PMU2) & ~0x00200000) + | (1 << 21); + REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set); + if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set)) + return; + } else { + /* Internal regulator is ON. Write swreg register. */ + int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG); + REG_WRITE(ah, AR_RTC_REG_CONTROL1, + REG_READ(ah, AR_RTC_REG_CONTROL1) & + (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM)); + REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg); + /* Set REG_CONTROL1.SWREG_PROGRAM */ + REG_WRITE(ah, AR_RTC_REG_CONTROL1, + REG_READ(ah, + AR_RTC_REG_CONTROL1) | + AR_RTC_REG_CONTROL1_SWREG_PROGRAM); + } } else { - REG_WRITE(ah, AR_RTC_SLEEP_CLK, - (REG_READ(ah, - AR_RTC_SLEEP_CLK) | - AR_RTC_FORCE_SWREG_PRD)); + if (AR_SREV_9485(ah)) { + REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0); + while (REG_READ_FIELD(ah, AR_PHY_PMU2, + AR_PHY_PMU2_PGM)) + udelay(10); + + REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1); + while (!REG_READ_FIELD(ah, AR_PHY_PMU1, + AR_PHY_PMU1_PWD)) + udelay(10); + REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0x1); + while (!REG_READ_FIELD(ah, AR_PHY_PMU2, + AR_PHY_PMU2_PGM)) + udelay(10); + } else + REG_WRITE(ah, AR_RTC_SLEEP_CLK, + (REG_READ(ah, + AR_RTC_SLEEP_CLK) | + AR_RTC_FORCE_SWREG_PRD)); + } + +} + +static void ar9003_hw_apply_tuning_caps(struct ath_hw *ah) +{ + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0]; + + if (eep->baseEepHeader.featureEnable & 0x40) { + tuning_caps_param &= 0x7f; + REG_RMW_FIELD(ah, AR_CH0_XTAL, AR_CH0_XTAL_CAPINDAC, + tuning_caps_param); + REG_RMW_FIELD(ah, AR_CH0_XTAL, AR_CH0_XTAL_CAPOUTDAC, + tuning_caps_param); } } @@ -1131,7 +3748,10 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan)); ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan)); ar9003_hw_drive_strength_apply(ah); + ar9003_hw_atten_apply(ah, chan); ar9003_hw_internal_regulator_apply(ah); + if (AR_SREV_9485(ah)) + ar9003_hw_apply_tuning_caps(ah); } static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah, @@ -1192,7 +3812,7 @@ static int ar9003_hw_power_interpolate(int32_t x, if (hx == lx) y = ly; else /* interpolate */ - y = ly + (((x - lx) * (hy - ly)) / (hx - lx)); + y = interpolate(x, lx, hx, ly, hy); } else /* only low is good, use it */ y = ly; } else if (hhave) /* only high is good, use it */ @@ -1561,22 +4181,9 @@ static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq, ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq, is2GHz) + ht40PowerIncForPdadc; - while (i < ar9300RateSize) { - ath_print(common, ATH_DBG_EEPROM, - "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); - i++; - - ath_print(common, ATH_DBG_EEPROM, - "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); - i++; - - ath_print(common, ATH_DBG_EEPROM, - "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); - i++; - - ath_print(common, ATH_DBG_EEPROM, - "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); - i++; + for (i = 0; i < ar9300RateSize; i++) { + ath_dbg(common, ATH_DBG_EEPROM, + "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); } } @@ -1595,18 +4202,17 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah, struct ath_common *common = ath9k_hw_common(ah); if (ichain >= AR9300_MAX_CHAINS) { - ath_print(common, ATH_DBG_EEPROM, - "Invalid chain index, must be less than %d\n", - AR9300_MAX_CHAINS); + ath_dbg(common, ATH_DBG_EEPROM, + "Invalid chain index, must be less than %d\n", + AR9300_MAX_CHAINS); return -1; } if (mode) { /* 5GHz */ if (ipier >= AR9300_NUM_5G_CAL_PIERS) { - ath_print(common, ATH_DBG_EEPROM, - "Invalid 5GHz cal pier index, must " - "be less than %d\n", - AR9300_NUM_5G_CAL_PIERS); + ath_dbg(common, ATH_DBG_EEPROM, + "Invalid 5GHz cal pier index, must be less than %d\n", + AR9300_NUM_5G_CAL_PIERS); return -1; } pCalPier = &(eep->calFreqPier5G[ipier]); @@ -1614,9 +4220,9 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah, is2GHz = 0; } else { if (ipier >= AR9300_NUM_2G_CAL_PIERS) { - ath_print(common, ATH_DBG_EEPROM, - "Invalid 2GHz cal pier index, must " - "be less than %d\n", AR9300_NUM_2G_CAL_PIERS); + ath_dbg(common, ATH_DBG_EEPROM, + "Invalid 2GHz cal pier index, must be less than %d\n", + AR9300_NUM_2G_CAL_PIERS); return -1; } @@ -1640,27 +4246,32 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah, { int tempSlope = 0; struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + int f[3], t[3]; REG_RMW(ah, AR_PHY_TPC_11_B0, (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), AR_PHY_TPC_OLPC_GAIN_DELTA); - REG_RMW(ah, AR_PHY_TPC_11_B1, - (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), - AR_PHY_TPC_OLPC_GAIN_DELTA); - REG_RMW(ah, AR_PHY_TPC_11_B2, - (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), - AR_PHY_TPC_OLPC_GAIN_DELTA); + if (ah->caps.tx_chainmask & BIT(1)) + REG_RMW(ah, AR_PHY_TPC_11_B1, + (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), + AR_PHY_TPC_OLPC_GAIN_DELTA); + if (ah->caps.tx_chainmask & BIT(2)) + REG_RMW(ah, AR_PHY_TPC_11_B2, + (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), + AR_PHY_TPC_OLPC_GAIN_DELTA); /* enable open loop power control on chip */ REG_RMW(ah, AR_PHY_TPC_6_B0, (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), AR_PHY_TPC_6_ERROR_EST_MODE); - REG_RMW(ah, AR_PHY_TPC_6_B1, - (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), - AR_PHY_TPC_6_ERROR_EST_MODE); - REG_RMW(ah, AR_PHY_TPC_6_B2, - (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), - AR_PHY_TPC_6_ERROR_EST_MODE); + if (ah->caps.tx_chainmask & BIT(1)) + REG_RMW(ah, AR_PHY_TPC_6_B1, + (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), + AR_PHY_TPC_6_ERROR_EST_MODE); + if (ah->caps.tx_chainmask & BIT(2)) + REG_RMW(ah, AR_PHY_TPC_6_B2, + (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), + AR_PHY_TPC_6_ERROR_EST_MODE); /* * enable temperature compensation @@ -1668,7 +4279,16 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah, */ if (frequency < 4000) tempSlope = eep->modalHeader2G.tempSlope; - else + else if (eep->base_ext2.tempSlopeLow != 0) { + t[0] = eep->base_ext2.tempSlopeLow; + f[0] = 5180; + t[1] = eep->modalHeader5G.tempSlope; + f[1] = 5500; + t[2] = eep->base_ext2.tempSlopeHigh; + f[2] = 5785; + tempSlope = ar9003_hw_power_interpolate((s32) frequency, + f, t, 3); + } else tempSlope = eep->modalHeader5G.tempSlope; REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope); @@ -1756,11 +4376,11 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) /* interpolate */ for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { - ath_print(common, ATH_DBG_EEPROM, - "ch=%d f=%d low=%d %d h=%d %d\n", - ichain, frequency, lfrequency[ichain], - lcorrection[ichain], hfrequency[ichain], - hcorrection[ichain]); + ath_dbg(common, ATH_DBG_EEPROM, + "ch=%d f=%d low=%d %d h=%d %d\n", + ichain, frequency, lfrequency[ichain], + lcorrection[ichain], hfrequency[ichain], + hcorrection[ichain]); /* they're the same, so just pick one */ if (hfrequency[ichain] == lfrequency[ichain]) { correction[ichain] = lcorrection[ichain]; @@ -1772,25 +4392,23 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) /* so is the high frequency, interpolate */ if (hfrequency[ichain] - frequency < 1000) { - correction[ichain] = lcorrection[ichain] + - (((frequency - lfrequency[ichain]) * - (hcorrection[ichain] - - lcorrection[ichain])) / - (hfrequency[ichain] - lfrequency[ichain])); - - temperature[ichain] = ltemperature[ichain] + - (((frequency - lfrequency[ichain]) * - (htemperature[ichain] - - ltemperature[ichain])) / - (hfrequency[ichain] - lfrequency[ichain])); - - voltage[ichain] = - lvoltage[ichain] + - (((frequency - - lfrequency[ichain]) * (hvoltage[ichain] - - lvoltage[ichain])) - / (hfrequency[ichain] - - lfrequency[ichain])); + correction[ichain] = interpolate(frequency, + lfrequency[ichain], + hfrequency[ichain], + lcorrection[ichain], + hcorrection[ichain]); + + temperature[ichain] = interpolate(frequency, + lfrequency[ichain], + hfrequency[ichain], + ltemperature[ichain], + htemperature[ichain]); + + voltage[ichain] = interpolate(frequency, + lfrequency[ichain], + hfrequency[ichain], + lvoltage[ichain], + hvoltage[ichain]); } /* only low is good, use it */ else { @@ -1814,9 +4432,9 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) ar9003_hw_power_control_override(ah, frequency, correction, voltage, temperature); - ath_print(common, ATH_DBG_EEPROM, - "for frequency=%d, calibration correction = %d %d %d\n", - frequency, correction[0], correction[1], correction[2]); + ath_dbg(common, ATH_DBG_EEPROM, + "for frequency=%d, calibration correction = %d %d %d\n", + frequency, correction[0], correction[1], correction[2]); return 0; } @@ -1858,7 +4476,7 @@ static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep, return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge - 1]); } - return AR9300_MAX_RATE_POWER; + return MAX_RATE_POWER; } /* @@ -1867,7 +4485,7 @@ static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep, static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep, u16 freq, int idx, bool is2GHz) { - u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER; + u16 twiceMaxEdgePower = MAX_RATE_POWER; u8 *ctl_freqbin = is2GHz ? &eep->ctl_freqbin_2G[idx][0] : &eep->ctl_freqbin_5G[idx][0]; @@ -1877,7 +4495,7 @@ static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep, /* Get the edge power */ for (edge = 0; - (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED); + (edge < num_edges) && (ctl_freqbin[edge] != AR5416_BCHAN_UNUSED); edge++) { /* * If there's an exact channel match or an inband flag set @@ -1915,21 +4533,23 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_common *common = ath9k_hw_common(ah); struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep; - u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER; + u16 twiceMaxEdgePower = MAX_RATE_POWER; static const u16 tpScaleReductionTable[5] = { - 0, 3, 6, 9, AR9300_MAX_RATE_POWER + 0, 3, 6, 9, MAX_RATE_POWER }; int i; int16_t twiceLargestAntenna; u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 ctlModesFor11a[] = { + static const u16 ctlModesFor11a[] = { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 }; - u16 ctlModesFor11g[] = { + static const u16 ctlModesFor11g[] = { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 }; - u16 numCtlModes, *pCtlMode, ctlMode, freq; + u16 numCtlModes; + const u16 *pCtlMode; + u16 ctlMode, freq; struct chan_centers centers; u8 *ctlIndex; u8 ctlNum; @@ -2019,11 +4639,10 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, else freq = centers.ctl_center; - ath_print(common, ATH_DBG_REGULATORY, - "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " - "EXT_ADDITIVE %d\n", - ctlMode, numCtlModes, isHt40CtlMode, - (pCtlMode[ctlMode] & EXT_ADDITIVE)); + ath_dbg(common, ATH_DBG_REGULATORY, + "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, EXT_ADDITIVE %d\n", + ctlMode, numCtlModes, isHt40CtlMode, + (pCtlMode[ctlMode] & EXT_ADDITIVE)); /* walk through each CTL index stored in EEPROM */ if (is2ghz) { @@ -2035,12 +4654,10 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, } for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) { - ath_print(common, ATH_DBG_REGULATORY, - "LOOP-Ctlidx %d: cfgCtl 0x%2.2x " - "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " - "chan %dn", - i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i], - chan->channel); + ath_dbg(common, ATH_DBG_REGULATORY, + "LOOP-Ctlidx %d: cfgCtl 0x%2.2x pCtlMode 0x%2.2x ctlIndex 0x%2.2x chan %d\n", + i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i], + chan->channel); /* * compare test group from regulatory @@ -2079,11 +4696,10 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); - ath_print(common, ATH_DBG_REGULATORY, - "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d " - "sP %d minCtlPwr %d\n", - ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, - scaledPower, minCtlPower); + ath_dbg(common, ATH_DBG_REGULATORY, + "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d sP %d minCtlPwr %d\n", + ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, + scaledPower, minCtlPower); /* Apply ctl mode to correct target power set */ switch (pCtlMode[ctlMode]) { @@ -2130,40 +4746,101 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, } /* end ctl mode checking */ } +static inline u8 mcsidx_to_tgtpwridx(unsigned int mcs_idx, u8 base_pwridx) +{ + u8 mod_idx = mcs_idx % 8; + + if (mod_idx <= 3) + return mod_idx ? (base_pwridx + 1) : base_pwridx; + else + return base_pwridx + 4 * (mcs_idx / 8) + mod_idx - 2; +} + static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, struct ath9k_channel *chan, u16 cfgCtl, u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower, - u8 powerLimit) + u8 powerLimit, bool test) { + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_common *common = ath9k_hw_common(ah); + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + struct ar9300_modal_eep_header *modal_hdr; u8 targetPowerValT2[ar9300RateSize]; - unsigned int i = 0; + u8 target_power_val_t2_eep[ar9300RateSize]; + unsigned int i = 0, paprd_scale_factor = 0; + u8 pwr_idx, min_pwridx = 0; ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2); + + if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) { + if (IS_CHAN_2GHZ(chan)) + modal_hdr = &eep->modalHeader2G; + else + modal_hdr = &eep->modalHeader5G; + + ah->paprd_ratemask = + le32_to_cpu(modal_hdr->papdRateMaskHt20) & + AR9300_PAPRD_RATE_MASK; + + ah->paprd_ratemask_ht40 = + le32_to_cpu(modal_hdr->papdRateMaskHt40) & + AR9300_PAPRD_RATE_MASK; + + paprd_scale_factor = ar9003_get_paprd_scale_factor(ah, chan); + min_pwridx = IS_CHAN_HT40(chan) ? ALL_TARGET_HT40_0_8_16 : + ALL_TARGET_HT20_0_8_16; + + if (!ah->paprd_table_write_done) { + memcpy(target_power_val_t2_eep, targetPowerValT2, + sizeof(targetPowerValT2)); + for (i = 0; i < 24; i++) { + pwr_idx = mcsidx_to_tgtpwridx(i, min_pwridx); + if (ah->paprd_ratemask & (1 << i)) { + if (targetPowerValT2[pwr_idx] && + targetPowerValT2[pwr_idx] == + target_power_val_t2_eep[pwr_idx]) + targetPowerValT2[pwr_idx] -= + paprd_scale_factor; + } + } + } + memcpy(target_power_val_t2_eep, targetPowerValT2, + sizeof(targetPowerValT2)); + } + ar9003_hw_set_power_per_rate_table(ah, chan, targetPowerValT2, cfgCtl, twiceAntennaReduction, twiceMaxRegulatoryPower, powerLimit); - while (i < ar9300RateSize) { - ath_print(common, ATH_DBG_EEPROM, - "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); - i++; - ath_print(common, ATH_DBG_EEPROM, - "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); - i++; - ath_print(common, ATH_DBG_EEPROM, - "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); - i++; - ath_print(common, ATH_DBG_EEPROM, - "TPC[%02d] 0x%08x\n\n", i, targetPowerValT2[i]); - i++; + if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) { + for (i = 0; i < ar9300RateSize; i++) { + if ((ah->paprd_ratemask & (1 << i)) && + (abs(targetPowerValT2[i] - + target_power_val_t2_eep[i]) > + paprd_scale_factor)) { + ah->paprd_ratemask &= ~(1 << i); + ath_dbg(common, ATH_DBG_EEPROM, + "paprd disabled for mcs %d\n", i); + } + } } - /* Write target power array to registers */ - ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); + regulatory->max_power_level = 0; + for (i = 0; i < ar9300RateSize; i++) { + if (targetPowerValT2[i] > regulatory->max_power_level) + regulatory->max_power_level = targetPowerValT2[i]; + } + + if (test) + return; + + for (i = 0; i < ar9300RateSize; i++) { + ath_dbg(common, ATH_DBG_EEPROM, + "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); + } /* * This is the TX power we send back to driver core, @@ -2183,8 +4860,24 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, i = ALL_TARGET_HT20_0_8_16; /* ht20 */ ah->txpower_limit = targetPowerValT2[i]; + regulatory->max_power_level = targetPowerValT2[i]; + /* Write target power array to registers */ + ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); ar9003_hw_calibration_apply(ah, chan->channel); + + if (IS_CHAN_2GHZ(chan)) { + if (IS_CHAN_HT40(chan)) + i = ALL_TARGET_HT40_0_8_16; + else + i = ALL_TARGET_HT20_0_8_16; + } else { + if (IS_CHAN_HT40(chan)) + i = ALL_TARGET_HT40_7; + else + i = ALL_TARGET_HT20_7; + } + ah->paprd_target_power = targetPowerValT2[i]; } static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah, @@ -2207,14 +4900,43 @@ s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah) return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */ } +u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz) +{ + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + if (is_2ghz) + return eep->modalHeader2G.spurChans; + else + return eep->modalHeader5G.spurChans; +} + +unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + if (IS_CHAN_2GHZ(chan)) + return MS(le32_to_cpu(eep->modalHeader2G.papdRateMaskHt20), + AR9300_PAPRD_SCALE_1); + else { + if (chan->channel >= 5700) + return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20), + AR9300_PAPRD_SCALE_1); + else if (chan->channel >= 5400) + return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), + AR9300_PAPRD_SCALE_2); + else + return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), + AR9300_PAPRD_SCALE_1); + } +} + const struct eeprom_ops eep_ar9300_ops = { .check_eeprom = ath9k_hw_ar9300_check_eeprom, .get_eeprom = ath9k_hw_ar9300_get_eeprom, .fill_eeprom = ath9k_hw_ar9300_fill_eeprom, .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver, .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev, - .get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config, - .get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg, .set_board_values = ath9k_hw_ar9300_set_board_values, .set_addac = ath9k_hw_ar9300_set_addac, .set_txpower = ath9k_hw_ar9300_set_txpower, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 655b3033396c..afb0b5ee1865 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -20,47 +20,22 @@ /* #define AR9300_NUM_CTLS 21 */ #define AR9300_NUM_CTLS_5G 9 #define AR9300_NUM_CTLS_2G 12 -#define AR9300_CTL_MODE_M 0xF #define AR9300_NUM_BAND_EDGES_5G 8 #define AR9300_NUM_BAND_EDGES_2G 4 -#define AR9300_NUM_PD_GAINS 4 -#define AR9300_PD_GAINS_IN_MASK 4 -#define AR9300_PD_GAIN_ICEPTS 5 -#define AR9300_EEPROM_MODAL_SPURS 5 -#define AR9300_MAX_RATE_POWER 63 -#define AR9300_NUM_PDADC_VALUES 128 -#define AR9300_NUM_RATES 16 -#define AR9300_BCHAN_UNUSED 0xFF -#define AR9300_MAX_PWR_RANGE_IN_HALF_DB 64 -#define AR9300_OPFLAGS_11A 0x01 -#define AR9300_OPFLAGS_11G 0x02 -#define AR9300_OPFLAGS_5G_HT40 0x04 -#define AR9300_OPFLAGS_2G_HT40 0x08 -#define AR9300_OPFLAGS_5G_HT20 0x10 -#define AR9300_OPFLAGS_2G_HT20 0x20 #define AR9300_EEPMISC_BIG_ENDIAN 0x01 #define AR9300_EEPMISC_WOW 0x02 #define AR9300_CUSTOMER_DATA_SIZE 20 -#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) #define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x)) #define AR9300_MAX_CHAINS 3 #define AR9300_ANT_16S 25 #define AR9300_FUTURE_MODAL_SZ 6 -#define AR9300_NUM_ANT_CHAIN_FIELDS 7 -#define AR9300_NUM_ANT_COMMON_FIELDS 4 -#define AR9300_SIZE_ANT_CHAIN_FIELD 3 -#define AR9300_SIZE_ANT_COMMON_FIELD 4 -#define AR9300_ANT_CHAIN_MASK 0x7 -#define AR9300_ANT_COMMON_MASK 0xf -#define AR9300_CHAIN_0_IDX 0 -#define AR9300_CHAIN_1_IDX 1 -#define AR9300_CHAIN_2_IDX 2 - -#define AR928X_NUM_ANT_CHAIN_FIELDS 6 -#define AR928X_SIZE_ANT_CHAIN_FIELD 2 -#define AR928X_ANT_CHAIN_MASK 0x3 +#define AR9300_PAPRD_RATE_MASK 0x01ffffff +#define AR9300_PAPRD_SCALE_1 0x0e000000 +#define AR9300_PAPRD_SCALE_1_S 25 +#define AR9300_PAPRD_SCALE_2 0x70000000 +#define AR9300_PAPRD_SCALE_2_S 28 /* Delta from which to start power to pdadc table */ /* This offset is used in both open loop and closed loop power control @@ -71,14 +46,20 @@ */ #define AR9300_PWR_TABLE_OFFSET 0 -/* enable flags for voltage and temp compensation */ -#define ENABLE_TEMP_COMPENSATION 0x01 -#define ENABLE_VOLT_COMPENSATION 0x02 /* byte addressable */ #define AR9300_EEPROM_SIZE (16*1024) -#define FIXED_CCA_THRESHOLD 15 +#define AR9300_BASE_ADDR_4K 0xfff #define AR9300_BASE_ADDR 0x3ff +#define AR9300_BASE_ADDR_512 0x1ff + +#define AR9300_OTP_BASE 0x14000 +#define AR9300_OTP_STATUS 0x15f18 +#define AR9300_OTP_STATUS_TYPE 0x7 +#define AR9300_OTP_STATUS_VALID 0x4 +#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 +#define AR9300_OTP_STATUS_SM_BUSY 0x1 +#define AR9300_OTP_READ_DATA 0x15f1c enum targetPowerHTRates { HT_TARGET_RATE_0_8_16, @@ -216,7 +197,7 @@ struct ar9300_modal_eep_header { int8_t tempSlope; int8_t voltSlope; /* spur channels in usual fbin coding format */ - u8 spurChans[AR9300_EEPROM_MODAL_SPURS]; + u8 spurChans[AR_EEPROM_MODAL_SPURS]; /* 3 Check if the register is per chain */ int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS]; u8 ob[AR9300_MAX_CHAINS]; @@ -236,7 +217,7 @@ struct ar9300_modal_eep_header { u8 thresh62; __le32 papdRateMaskHt20; __le32 papdRateMaskHt40; - u8 futureModal[24]; + u8 futureModal[10]; } __packed; struct ar9300_cal_data_per_freq_op_loop { @@ -269,6 +250,20 @@ struct cal_ctl_data_5g { u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G]; } __packed; +struct ar9300_BaseExtension_1 { + u8 ant_div_control; + u8 future[13]; +} __packed; + +struct ar9300_BaseExtension_2 { + int8_t tempSlopeLow; + int8_t tempSlopeHigh; + u8 xatten1DBLow[AR9300_MAX_CHAINS]; + u8 xatten1MarginLow[AR9300_MAX_CHAINS]; + u8 xatten1DBHigh[AR9300_MAX_CHAINS]; + u8 xatten1MarginHigh[AR9300_MAX_CHAINS]; +} __packed; + struct ar9300_eeprom { u8 eepromVersion; u8 templateVersion; @@ -278,6 +273,7 @@ struct ar9300_eeprom { struct ar9300_base_eep_hdr baseEepHeader; struct ar9300_modal_eep_header modalHeader2G; + struct ar9300_BaseExtension_1 base_ext1; u8 calFreqPier2G[AR9300_NUM_2G_CAL_PIERS]; struct ar9300_cal_data_per_freq_op_loop calPierData2G[AR9300_MAX_CHAINS][AR9300_NUM_2G_CAL_PIERS]; @@ -297,6 +293,7 @@ struct ar9300_eeprom { u8 ctl_freqbin_2G[AR9300_NUM_CTLS_2G][AR9300_NUM_BAND_EDGES_2G]; struct cal_ctl_data_2g ctlPowerData_2G[AR9300_NUM_CTLS_2G]; struct ar9300_modal_eep_header modalHeader5G; + struct ar9300_BaseExtension_2 base_ext2; u8 calFreqPier5G[AR9300_NUM_5G_CAL_PIERS]; struct ar9300_cal_data_per_freq_op_loop calPierData5G[AR9300_MAX_CHAINS][AR9300_NUM_5G_CAL_PIERS]; @@ -317,4 +314,8 @@ struct ar9300_eeprom { s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah); s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah); +u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz); + +unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah, + struct ath9k_channel *chan); #endif diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index c2a057156bfa..6137634e46ca 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -17,20 +17,10 @@ #include "hw.h" #include "ar9003_mac.h" #include "ar9003_2p2_initvals.h" +#include "ar9485_initvals.h" /* General hardware code for the AR9003 hadware family */ -static bool ar9003_hw_macversion_supported(u32 macversion) -{ - switch (macversion) { - case AR_SREV_VERSION_9300: - return true; - default: - break; - } - return false; -} - /* * The AR9003 family uses a new INI format (pre, core, post * arrays per subsystem). This provides support for the @@ -38,72 +28,134 @@ static bool ar9003_hw_macversion_supported(u32 macversion) */ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) { - /* mac */ - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], - ar9300_2p2_mac_core, - ARRAY_SIZE(ar9300_2p2_mac_core), 2); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], - ar9300_2p2_mac_postamble, - ARRAY_SIZE(ar9300_2p2_mac_postamble), 5); - - /* bb */ - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], - ar9300_2p2_baseband_core, - ARRAY_SIZE(ar9300_2p2_baseband_core), 2); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], - ar9300_2p2_baseband_postamble, - ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5); - - /* radio */ - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], - ar9300_2p2_radio_core, - ARRAY_SIZE(ar9300_2p2_radio_core), 2); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], - ar9300_2p2_radio_postamble, - ARRAY_SIZE(ar9300_2p2_radio_postamble), 5); - - /* soc */ - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], - ar9300_2p2_soc_preamble, - ARRAY_SIZE(ar9300_2p2_soc_preamble), 2); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], - ar9300_2p2_soc_postamble, - ARRAY_SIZE(ar9300_2p2_soc_postamble), 5); - - /* rx/tx gain */ - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9300Common_rx_gain_table_2p2, - ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2); - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_lowest_ob_db_tx_gain_table_2p2, - ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), - 5); - - /* Load PCIE SERDES settings from INI */ - - /* Awake Setting */ - - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9300PciePhy_pll_on_clkreq_disable_L1_2p2, - ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2), - 2); - - /* Sleep Setting */ - - INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, - ar9300PciePhy_clkreq_enable_L1_2p2, - ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p2), - 2); - - /* Fast clock modal settings */ - INIT_INI_ARRAY(&ah->iniModesAdditional, - ar9300Modes_fast_clock_2p2, - ARRAY_SIZE(ar9300Modes_fast_clock_2p2), - 3); + if (AR_SREV_9485(ah)) { + /* mac */ + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], + ar9485_1_0_mac_core, + ARRAY_SIZE(ar9485_1_0_mac_core), 2); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], + ar9485_1_0_mac_postamble, + ARRAY_SIZE(ar9485_1_0_mac_postamble), 5); + + /* bb */ + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_0, + ARRAY_SIZE(ar9485_1_0), 2); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], + ar9485_1_0_baseband_core, + ARRAY_SIZE(ar9485_1_0_baseband_core), 2); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], + ar9485_1_0_baseband_postamble, + ARRAY_SIZE(ar9485_1_0_baseband_postamble), 5); + + /* radio */ + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], + ar9485_1_0_radio_core, + ARRAY_SIZE(ar9485_1_0_radio_core), 2); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], + ar9485_1_0_radio_postamble, + ARRAY_SIZE(ar9485_1_0_radio_postamble), 2); + + /* soc */ + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], + ar9485_1_0_soc_preamble, + ARRAY_SIZE(ar9485_1_0_soc_preamble), 2); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0); + + /* rx/tx gain */ + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9485Common_rx_gain_1_0, + ARRAY_SIZE(ar9485Common_rx_gain_1_0), 2); + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9485Modes_lowest_ob_db_tx_gain_1_0, + ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0), + 5); + + /* Load PCIE SERDES settings from INI */ + + /* Awake Setting */ + + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1, + ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1), + 2); + + /* Sleep Setting */ + + INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, + ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1, + ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1), + 2); + } else { + /* mac */ + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], + ar9300_2p2_mac_core, + ARRAY_SIZE(ar9300_2p2_mac_core), 2); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], + ar9300_2p2_mac_postamble, + ARRAY_SIZE(ar9300_2p2_mac_postamble), 5); + + /* bb */ + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], + ar9300_2p2_baseband_core, + ARRAY_SIZE(ar9300_2p2_baseband_core), 2); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], + ar9300_2p2_baseband_postamble, + ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5); + + /* radio */ + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], + ar9300_2p2_radio_core, + ARRAY_SIZE(ar9300_2p2_radio_core), 2); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], + ar9300_2p2_radio_postamble, + ARRAY_SIZE(ar9300_2p2_radio_postamble), 5); + + /* soc */ + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], + ar9300_2p2_soc_preamble, + ARRAY_SIZE(ar9300_2p2_soc_preamble), 2); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], + ar9300_2p2_soc_postamble, + ARRAY_SIZE(ar9300_2p2_soc_postamble), 5); + + /* rx/tx gain */ + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9300Common_rx_gain_table_2p2, + ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2); + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_lowest_ob_db_tx_gain_table_2p2, + ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), + 5); + + /* Load PCIE SERDES settings from INI */ + + /* Awake Setting */ + + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9300PciePhy_pll_on_clkreq_disable_L1_2p2, + ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2), + 2); + + /* Sleep Setting */ + + INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, + ar9300PciePhy_clkreq_enable_L1_2p2, + ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p2), + 2); + + /* Fast clock modal settings */ + INIT_INI_ARRAY(&ah->iniModesAdditional, + ar9300Modes_fast_clock_2p2, + ARRAY_SIZE(ar9300Modes_fast_clock_2p2), + 3); + } } static void ar9003_tx_gain_table_apply(struct ath_hw *ah) @@ -111,22 +163,52 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) switch (ar9003_hw_get_tx_gain_idx(ah)) { case 0: default: - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_lowest_ob_db_tx_gain_table_2p2, - ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), - 5); + if (AR_SREV_9485(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9485Modes_lowest_ob_db_tx_gain_1_0, + ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0), + 5); + else + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_lowest_ob_db_tx_gain_table_2p2, + ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), + 5); break; case 1: - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_high_ob_db_tx_gain_table_2p2, - ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2), - 5); + if (AR_SREV_9485(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9485Modes_high_ob_db_tx_gain_1_0, + ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0), + 5); + else + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_high_ob_db_tx_gain_table_2p2, + ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2), + 5); break; case 2: - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_low_ob_db_tx_gain_table_2p2, - ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2), - 5); + if (AR_SREV_9485(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9485Modes_low_ob_db_tx_gain_1_0, + ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0), + 5); + else + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_low_ob_db_tx_gain_table_2p2, + ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2), + 5); + break; + case 3: + if (AR_SREV_9485(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9485Modes_high_power_tx_gain_1_0, + ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_0), + 5); + else + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_high_power_tx_gain_table_2p2, + ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2), + 5); break; } } @@ -136,16 +218,28 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) switch (ar9003_hw_get_rx_gain_idx(ah)) { case 0: default: - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9300Common_rx_gain_table_2p2, - ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), - 2); + if (AR_SREV_9485(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9485Common_rx_gain_1_0, + ARRAY_SIZE(ar9485Common_rx_gain_1_0), + 2); + else + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9300Common_rx_gain_table_2p2, + ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), + 2); break; case 1: - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9300Common_wo_xlna_rx_gain_table_2p2, - ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2), - 2); + if (AR_SREV_9485(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9485Common_wo_xlna_rx_gain_1_0, + ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_0), + 2); + else + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9300Common_wo_xlna_rx_gain_table_2p2, + ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2), + 2); break; } } @@ -216,7 +310,6 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) priv_ops->init_mode_regs = ar9003_hw_init_mode_regs; priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; - priv_ops->macversion_supported = ar9003_hw_macversion_supported; ops->config_pci_powersave = ar9003_hw_configpcipowersave; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 3b424ca1ba84..4ceddbbdfcee 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -182,8 +182,8 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) } if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) - ath_print(common, ATH_DBG_INTERRUPT, - "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); + ath_dbg(common, ATH_DBG_INTERRUPT, + "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); @@ -237,73 +237,76 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_status *ts) { struct ar9003_txs *ads; + u32 status; ads = &ah->ts_ring[ah->ts_tail]; - if ((ads->status8 & AR_TxDone) == 0) + status = ACCESS_ONCE(ads->status8); + if ((status & AR_TxDone) == 0) return -EINPROGRESS; ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) || (MS(ads->ds_info, AR_TxRxDesc) != 1)) { - ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT, - "Tx Descriptor error %x\n", ads->ds_info); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT, + "Tx Descriptor error %x\n", ads->ds_info); memset(ads, 0, sizeof(*ads)); return -EIO; } + if (status & AR_TxOpExceeded) + ts->ts_status |= ATH9K_TXERR_XTXOP; + ts->ts_rateindex = MS(status, AR_FinalTxIdx); + ts->ts_seqnum = MS(status, AR_SeqNum); + ts->tid = MS(status, AR_TxTid); + ts->qid = MS(ads->ds_info, AR_TxQcuNum); ts->desc_id = MS(ads->status1, AR_TxDescId); - ts->ts_seqnum = MS(ads->status8, AR_SeqNum); ts->ts_tstamp = ads->status4; ts->ts_status = 0; ts->ts_flags = 0; - if (ads->status3 & AR_ExcessiveRetries) + status = ACCESS_ONCE(ads->status2); + ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); + ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); + ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); + if (status & AR_TxBaStatus) { + ts->ts_flags |= ATH9K_TX_BA; + ts->ba_low = ads->status5; + ts->ba_high = ads->status6; + } + + status = ACCESS_ONCE(ads->status3); + if (status & AR_ExcessiveRetries) ts->ts_status |= ATH9K_TXERR_XRETRY; - if (ads->status3 & AR_Filtered) + if (status & AR_Filtered) ts->ts_status |= ATH9K_TXERR_FILT; - if (ads->status3 & AR_FIFOUnderrun) { + if (status & AR_FIFOUnderrun) { ts->ts_status |= ATH9K_TXERR_FIFO; ath9k_hw_updatetxtriglevel(ah, true); } - if (ads->status8 & AR_TxOpExceeded) - ts->ts_status |= ATH9K_TXERR_XTXOP; - if (ads->status3 & AR_TxTimerExpired) + if (status & AR_TxTimerExpired) ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; - - if (ads->status3 & AR_DescCfgErr) + if (status & AR_DescCfgErr) ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; - if (ads->status3 & AR_TxDataUnderrun) { + if (status & AR_TxDataUnderrun) { ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; ath9k_hw_updatetxtriglevel(ah, true); } - if (ads->status3 & AR_TxDelimUnderrun) { + if (status & AR_TxDelimUnderrun) { ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; ath9k_hw_updatetxtriglevel(ah, true); } - if (ads->status2 & AR_TxBaStatus) { - ts->ts_flags |= ATH9K_TX_BA; - ts->ba_low = ads->status5; - ts->ba_high = ads->status6; - } + ts->ts_shortretry = MS(status, AR_RTSFailCnt); + ts->ts_longretry = MS(status, AR_DataFailCnt); + ts->ts_virtcol = MS(status, AR_VirtRetryCnt); - ts->ts_rateindex = MS(ads->status8, AR_FinalTxIdx); - - ts->ts_rssi = MS(ads->status7, AR_TxRSSICombined); - ts->ts_rssi_ctl0 = MS(ads->status2, AR_TxRSSIAnt00); - ts->ts_rssi_ctl1 = MS(ads->status2, AR_TxRSSIAnt01); - ts->ts_rssi_ctl2 = MS(ads->status2, AR_TxRSSIAnt02); - ts->ts_rssi_ext0 = MS(ads->status7, AR_TxRSSIAnt10); - ts->ts_rssi_ext1 = MS(ads->status7, AR_TxRSSIAnt11); - ts->ts_rssi_ext2 = MS(ads->status7, AR_TxRSSIAnt12); - ts->ts_shortretry = MS(ads->status3, AR_RTSFailCnt); - ts->ts_longretry = MS(ads->status3, AR_DataFailCnt); - ts->ts_virtcol = MS(ads->status3, AR_VirtRetryCnt); - ts->ts_antenna = 0; - - ts->tid = MS(ads->status8, AR_TxTid); + status = ACCESS_ONCE(ads->status7); + ts->ts_rssi = MS(status, AR_TxRSSICombined); + ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); + ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); + ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); memset(ads, 0, sizeof(*ads)); @@ -319,7 +322,6 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, if (txpower > ah->txpower_limit) txpower = ah->txpower_limit; - txpower += ah->txpower_indexoffset; if (txpower > 63) txpower = 63; @@ -407,12 +409,36 @@ static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, u32 aggrLen) { +#define FIRST_DESC_NDELIMS 60 struct ar9003_txc *ads = (struct ar9003_txc *) ds; ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); - ads->ctl17 &= ~AR_AggrLen; - ads->ctl17 |= SM(aggrLen, AR_AggrLen); + if (ah->ent_mode & AR_ENT_OTP_MPSD) { + u32 ctl17, ndelim; + /* + * Add delimiter when using RTS/CTS with aggregation + * and non enterprise AR9003 card + */ + ctl17 = ads->ctl17; + ndelim = MS(ctl17, AR_PadDelim); + + if (ndelim < FIRST_DESC_NDELIMS) { + aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4; + ndelim = FIRST_DESC_NDELIMS; + } + + ctl17 &= ~AR_AggrLen; + ctl17 |= SM(aggrLen, AR_AggrLen); + + ctl17 &= ~AR_PadDelim; + ctl17 |= SM(ndelim, AR_PadDelim); + + ads->ctl17 = ctl17; + } else { + ads->ctl17 &= ~AR_AggrLen; + ads->ctl17 |= SM(aggrLen, AR_AggrLen); + } } static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, @@ -587,9 +613,9 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, * possibly be reviewing the last subframe. AR_CRCErr * is the CRC of the actual data. */ - if (rxsp->status11 & AR_CRCErr) { + if (rxsp->status11 & AR_CRCErr) rxs->rs_status |= ATH9K_RXERR_CRC; - } else if (rxsp->status11 & AR_PHYErr) { + if (rxsp->status11 & AR_PHYErr) { phyerr = MS(rxsp->status11, AR_PHYErrCode); /* * If we reach a point here where AR_PostDelimCRCErr is @@ -612,11 +638,12 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, rxs->rs_phyerr = phyerr; } - } else if (rxsp->status11 & AR_DecryptCRCErr) { + } + if (rxsp->status11 & AR_DecryptCRCErr) rxs->rs_status |= ATH9K_RXERR_DECRYPT; - } else if (rxsp->status11 & AR_MichaelErr) { + if (rxsp->status11 & AR_MichaelErr) rxs->rs_status |= ATH9K_RXERR_MIC; - } else if (rxsp->status11 & AR_KeyMiss) + if (rxsp->status11 & AR_KeyMiss) rxs->rs_status |= ATH9K_RXERR_DECRYPT; } @@ -631,10 +658,10 @@ void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah) memset((void *) ah->ts_ring, 0, ah->ts_size * sizeof(struct ar9003_txs)); - ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT, - "TS Start 0x%x End 0x%x Virt %p, Size %d\n", - ah->ts_paddr_start, ah->ts_paddr_end, - ah->ts_ring, ah->ts_size); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT, + "TS Start 0x%x End 0x%x Virt %p, Size %d\n", + ah->ts_paddr_start, ah->ts_paddr_end, + ah->ts_ring, ah->ts_size); REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start); REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index 9f2cea70a840..45cc7e80436c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h @@ -65,7 +65,7 @@ struct ar9003_rxs { u32 status9; u32 status10; u32 status11; -} __packed; +} __packed __aligned(4); /* Transmit Control Descriptor */ struct ar9003_txc { @@ -93,7 +93,7 @@ struct ar9003_txc { u32 ctl21; /* DMA control 21 */ u32 ctl22; /* DMA control 22 */ u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */ -} __packed; +} __packed __aligned(4); struct ar9003_txs { u32 ds_info; @@ -105,7 +105,7 @@ struct ar9003_txs { u32 status6; u32 status7; u32 status8; -} __packed; +} __packed __aligned(4); void ar9003_hw_attach_mac_ops(struct ath_hw *hw); void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 716db414c258..356d2fd78822 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -19,45 +19,124 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val) { + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + struct ath9k_channel *chan = ah->curchan; + + if (val) { + ah->paprd_table_write_done = true; + + ah->eep_ops->set_txpower(ah, chan, + ath9k_regd_get_ctl(regulatory, chan), + chan->chan->max_antenna_gain * 2, + chan->chan->max_power * 2, + min((u32) MAX_RATE_POWER, + (u32) regulatory->power_limit), false); + } + REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0, AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); - REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1, - AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); - REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2, - AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); + if (ah->caps.tx_chainmask & BIT(1)) + REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1, + AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); + if (ah->caps.tx_chainmask & BIT(2)) + REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2, + AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); } EXPORT_SYMBOL(ar9003_paprd_enable); -static void ar9003_paprd_setup_single_table(struct ath_hw *ah) +static int ar9003_get_training_power_2g(struct ath_hw *ah) +{ + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G; + unsigned int power, scale, delta; + + scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1); + power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, + AR_PHY_POWERTX_RATE5_POWERTXHT20_0); + + delta = abs((int) ah->paprd_target_power - (int) power); + if (delta > scale) + return -1; + + if (delta < 4) + power -= 4 - delta; + + return power; +} + +static int ar9003_get_training_power_5g(struct ath_hw *ah) { + struct ath_common *common = ath9k_hw_common(ah); struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; - struct ar9300_modal_eep_header *hdr; - const u32 ctrl0[3] = { + struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G; + struct ath9k_channel *chan = ah->curchan; + unsigned int power, scale, delta; + + if (chan->channel >= 5700) + scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), + AR9300_PAPRD_SCALE_1); + else if (chan->channel >= 5400) + scale = MS(le32_to_cpu(hdr->papdRateMaskHt40), + AR9300_PAPRD_SCALE_2); + else + scale = MS(le32_to_cpu(hdr->papdRateMaskHt40), + AR9300_PAPRD_SCALE_1); + + if (IS_CHAN_HT40(chan)) + power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8, + AR_PHY_POWERTX_RATE8_POWERTXHT40_5); + else + power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE6, + AR_PHY_POWERTX_RATE6_POWERTXHT20_5); + + power += scale; + delta = abs((int) ah->paprd_target_power - (int) power); + if (delta > scale) + return -1; + + power += 2 * get_streams(common->tx_chainmask); + return power; +} + +static int ar9003_paprd_setup_single_table(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + static const u32 ctrl0[3] = { AR_PHY_PAPRD_CTRL0_B0, AR_PHY_PAPRD_CTRL0_B1, AR_PHY_PAPRD_CTRL0_B2 }; - const u32 ctrl1[3] = { + static const u32 ctrl1[3] = { AR_PHY_PAPRD_CTRL1_B0, AR_PHY_PAPRD_CTRL1_B1, AR_PHY_PAPRD_CTRL1_B2 }; - u32 am_mask, ht40_mask; + int training_power; int i; - if (ah->curchan && IS_CHAN_5GHZ(ah->curchan)) - hdr = &eep->modalHeader5G; + if (IS_CHAN_2GHZ(ah->curchan)) + training_power = ar9003_get_training_power_2g(ah); else - hdr = &eep->modalHeader2G; - - am_mask = le32_to_cpu(hdr->papdRateMaskHt20); - ht40_mask = le32_to_cpu(hdr->papdRateMaskHt40); + training_power = ar9003_get_training_power_5g(ah); - REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, am_mask); - REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, am_mask); - REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ht40_mask); - - for (i = 0; i < 3; i++) { + if (training_power < 0) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "PAPRD target power delta out of range"); + return -ERANGE; + } + ah->paprd_training_power = training_power; + ath_dbg(common, ATH_DBG_CALIBRATE, + "Training power: %d, Target power: %d\n", + ah->paprd_training_power, ah->paprd_target_power); + + REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, + ah->paprd_ratemask); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, + ah->paprd_ratemask); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, + ah->paprd_ratemask_ht40); + + for (i = 0; i < ah->caps.max_txchains; i++) { REG_RMW_FIELD(ah, ctrl0[i], AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1); REG_RMW_FIELD(ah, ctrl1[i], @@ -102,8 +181,14 @@ static void ar9003_paprd_setup_single_table(struct ath_hw *ah) AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7); REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1); - REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, - AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, -6); + if (AR_SREV_9485(ah)) + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, + -3); + else + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, + -6); REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE, -15); @@ -132,6 +217,7 @@ static void ar9003_paprd_setup_single_table(struct ath_hw *ah) AR_PHY_PAPRD_PRE_POST_SCALING, 185706); REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0, AR_PHY_PAPRD_PRE_POST_SCALING, 175487); + return 0; } static void ar9003_paprd_get_gain_table(struct ath_hw *ah) @@ -586,15 +672,10 @@ void ar9003_paprd_populate_single_table(struct ath_hw *ah, { u32 *paprd_table_val = caldata->pa_table[chain]; u32 small_signal_gain = caldata->small_signal_gain[chain]; - u32 training_power; + u32 training_power = ah->paprd_training_power; u32 reg = 0; int i; - training_power = - REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, - AR_PHY_POWERTX_RATE5_POWERTXHT20_0); - training_power -= 4; - if (chain == 0) reg = AR_PHY_PAPRD_MEM_TAB_B0; else if (chain == 1) @@ -620,26 +701,22 @@ void ar9003_paprd_populate_single_table(struct ath_hw *ah, AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, training_power); - REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B1, - AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, - training_power); + if (ah->caps.tx_chainmask & BIT(1)) + REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B1, + AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, + training_power); - REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2, - AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, - training_power); + if (ah->caps.tx_chainmask & BIT(2)) + REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2, + AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, + training_power); } EXPORT_SYMBOL(ar9003_paprd_populate_single_table); int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) { - unsigned int i, desired_gain, gain_index; - unsigned int train_power; - - train_power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, - AR_PHY_POWERTX_RATE5_POWERTXHT20_0); - - train_power = train_power - 4; + unsigned int train_power = ah->paprd_training_power; desired_gain = ar9003_get_desired_gain(ah, chain, train_power); @@ -705,7 +782,12 @@ EXPORT_SYMBOL(ar9003_paprd_create_curve); int ar9003_paprd_init_table(struct ath_hw *ah) { - ar9003_paprd_setup_single_table(ah); + int ret; + + ret = ar9003_paprd_setup_single_table(ah); + if (ret < 0) + return ret; + ar9003_paprd_get_gain_table(ah); return 0; } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 669b777729b3..8d60f4f09acc 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -75,7 +75,10 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) freq = centers.synth_center; if (freq < 4800) { /* 2 GHz, fractional mode */ - channelSel = CHANSEL_2G(freq); + if (AR_SREV_9485(ah)) + channelSel = CHANSEL_2G_9485(freq); + else + channelSel = CHANSEL_2G(freq); /* Set to 2G mode */ bMode = 1; } else { @@ -128,24 +131,53 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, struct ath9k_channel *chan) { - u32 spur_freq[4] = { 2420, 2440, 2464, 2480 }; + static const u32 spur_freq[4] = { 2420, 2440, 2464, 2480 }; int cur_bb_spur, negative = 0, cck_spur_freq; int i; + int range, max_spur_cnts, synth_freq; + u8 *spur_fbin_ptr = NULL; /* * Need to verify range +/- 10 MHz in control channel, otherwise spur * is out-of-band and can be ignored. */ - for (i = 0; i < 4; i++) { + if (AR_SREV_9485(ah)) { + spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah, + IS_CHAN_2GHZ(chan)); + if (spur_fbin_ptr[0] == 0) /* No spur */ + return; + max_spur_cnts = 5; + if (IS_CHAN_HT40(chan)) { + range = 19; + if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, + AR_PHY_GC_DYN2040_PRI_CH) == 0) + synth_freq = chan->channel + 10; + else + synth_freq = chan->channel - 10; + } else { + range = 10; + synth_freq = chan->channel; + } + } else { + range = 10; + max_spur_cnts = 4; + synth_freq = chan->channel; + } + + for (i = 0; i < max_spur_cnts; i++) { negative = 0; - cur_bb_spur = spur_freq[i] - chan->channel; + if (AR_SREV_9485(ah)) + cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i], + IS_CHAN_2GHZ(chan)) - synth_freq; + else + cur_bb_spur = spur_freq[i] - synth_freq; if (cur_bb_spur < 0) { negative = 1; cur_bb_spur = -cur_bb_spur; } - if (cur_bb_spur < 10) { + if (cur_bb_spur < range) { cck_spur_freq = (int)((cur_bb_spur << 19) / 11); if (negative == 1) @@ -487,7 +519,11 @@ void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) break; } - REG_WRITE(ah, AR_SELFGEN_MASK, tx); + if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) + REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); + else + REG_WRITE(ah, AR_SELFGEN_MASK, tx); + if (tx == 0x5) { REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); @@ -542,10 +578,7 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah, u32 reg = INI_RA(iniArr, i, 0); u32 val = INI_RA(iniArr, i, column); - if (reg >= 0x16000 && reg < 0x17000) - ath9k_hw_analog_shift_regwrite(ah, reg, val); - else - REG_WRITE(ah, reg, val); + REG_WRITE(ah, reg, val); DO_DELAY(regWrites); } @@ -614,7 +647,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit)); + (u32) regulatory->power_limit), false); return 0; } @@ -712,28 +745,6 @@ static void ar9003_hw_rfbus_done(struct ath_hw *ah) REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); } -/* - * 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. - */ -static void ar9003_hw_enable_rfkill(struct ath_hw *ah) -{ - /* Connect rfsilent_bb_l to baseband */ - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, - AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); - /* Set input mux for rfsilent_bb_l to GPIO #0 */ - REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, - AR_GPIO_INPUT_MUX2_RFSILENT); - - /* - * Configure the desired GPIO port for input and - * enable baseband rf silence. - */ - ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); - REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); -} - static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value) { u32 v = REG_READ(ah, AR_PHY_CCK_DETECT); @@ -820,12 +831,12 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); if (!on != aniState->ofdmWeakSigDetectOff) { - ath_print(common, ATH_DBG_ANI, - "** ch %d: ofdm weak signal: %s=>%s\n", - chan->channel, - !aniState->ofdmWeakSigDetectOff ? - "on" : "off", - on ? "on" : "off"); + ath_dbg(common, ATH_DBG_ANI, + "** ch %d: ofdm weak signal: %s=>%s\n", + chan->channel, + !aniState->ofdmWeakSigDetectOff ? + "on" : "off", + on ? "on" : "off"); if (on) ah->stats.ast_ani_ofdmon++; else @@ -838,11 +849,9 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, u32 level = param; if (level >= ARRAY_SIZE(firstep_table)) { - ath_print(common, ATH_DBG_ANI, - "ATH9K_ANI_FIRSTEP_LEVEL: level " - "out of range (%u > %u)\n", - level, - (unsigned) ARRAY_SIZE(firstep_table)); + ath_dbg(common, ATH_DBG_ANI, + "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n", + level, ARRAY_SIZE(firstep_table)); return false; } @@ -877,24 +886,22 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2); if (level != aniState->firstepLevel) { - ath_print(common, ATH_DBG_ANI, - "** ch %d: level %d=>%d[def:%d] " - "firstep[level]=%d ini=%d\n", - chan->channel, - aniState->firstepLevel, - level, - ATH9K_ANI_FIRSTEP_LVL_NEW, - value, - aniState->iniDef.firstep); - ath_print(common, ATH_DBG_ANI, - "** ch %d: level %d=>%d[def:%d] " - "firstep_low[level]=%d ini=%d\n", - chan->channel, - aniState->firstepLevel, - level, - ATH9K_ANI_FIRSTEP_LVL_NEW, - value2, - aniState->iniDef.firstepLow); + ath_dbg(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n", + chan->channel, + aniState->firstepLevel, + level, + ATH9K_ANI_FIRSTEP_LVL_NEW, + value, + aniState->iniDef.firstep); + ath_dbg(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n", + chan->channel, + aniState->firstepLevel, + level, + ATH9K_ANI_FIRSTEP_LVL_NEW, + value2, + aniState->iniDef.firstepLow); if (level > aniState->firstepLevel) ah->stats.ast_ani_stepup++; else if (level < aniState->firstepLevel) @@ -907,11 +914,9 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, u32 level = param; if (level >= ARRAY_SIZE(cycpwrThr1_table)) { - ath_print(common, ATH_DBG_ANI, - "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level " - "out of range (%u > %u)\n", - level, - (unsigned) ARRAY_SIZE(cycpwrThr1_table)); + ath_dbg(common, ATH_DBG_ANI, + "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n", + level, ARRAY_SIZE(cycpwrThr1_table)); return false; } /* @@ -945,24 +950,22 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, AR_PHY_EXT_CYCPWR_THR1, value2); if (level != aniState->spurImmunityLevel) { - ath_print(common, ATH_DBG_ANI, - "** ch %d: level %d=>%d[def:%d] " - "cycpwrThr1[level]=%d ini=%d\n", - chan->channel, - aniState->spurImmunityLevel, - level, - ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, - value, - aniState->iniDef.cycpwrThr1); - ath_print(common, ATH_DBG_ANI, - "** ch %d: level %d=>%d[def:%d] " - "cycpwrThr1Ext[level]=%d ini=%d\n", - chan->channel, - aniState->spurImmunityLevel, - level, - ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, - value2, - aniState->iniDef.cycpwrThr1Ext); + ath_dbg(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n", + chan->channel, + aniState->spurImmunityLevel, + level, + ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, + value, + aniState->iniDef.cycpwrThr1); + ath_dbg(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n", + chan->channel, + aniState->spurImmunityLevel, + level, + ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, + value2, + aniState->iniDef.cycpwrThr1Ext); if (level > aniState->spurImmunityLevel) ah->stats.ast_ani_spurup++; else if (level < aniState->spurImmunityLevel) @@ -982,11 +985,11 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, AR_PHY_MRC_CCK_MUX_REG, is_on); if (!is_on != aniState->mrcCCKOff) { - ath_print(common, ATH_DBG_ANI, - "** ch %d: MRC CCK: %s=>%s\n", - chan->channel, - !aniState->mrcCCKOff ? "on" : "off", - is_on ? "on" : "off"); + ath_dbg(common, ATH_DBG_ANI, + "** ch %d: MRC CCK: %s=>%s\n", + chan->channel, + !aniState->mrcCCKOff ? "on" : "off", + is_on ? "on" : "off"); if (is_on) ah->stats.ast_ani_ccklow++; else @@ -998,22 +1001,19 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, case ATH9K_ANI_PRESENT: break; default: - ath_print(common, ATH_DBG_ANI, - "invalid cmd %u\n", cmd); + ath_dbg(common, ATH_DBG_ANI, "invalid cmd %u\n", cmd); return false; } - ath_print(common, ATH_DBG_ANI, - "ANI parameters: SI=%d, ofdmWS=%s FS=%d " - "MRCcck=%s listenTime=%d " - "ofdmErrs=%d cckErrs=%d\n", - aniState->spurImmunityLevel, - !aniState->ofdmWeakSigDetectOff ? "on" : "off", - aniState->firstepLevel, - !aniState->mrcCCKOff ? "on" : "off", - aniState->listenTime, - aniState->ofdmPhyErrCount, - aniState->cckPhyErrCount); + ath_dbg(common, ATH_DBG_ANI, + "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n", + aniState->spurImmunityLevel, + !aniState->ofdmWeakSigDetectOff ? "on" : "off", + aniState->firstepLevel, + !aniState->mrcCCKOff ? "on" : "off", + aniState->listenTime, + aniState->ofdmPhyErrCount, + aniState->cckPhyErrCount); return true; } @@ -1023,25 +1023,25 @@ static void ar9003_hw_do_getnf(struct ath_hw *ah, int16_t nf; nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR); - nfarray[0] = sign_extend(nf, 9); + nfarray[0] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR); - nfarray[1] = sign_extend(nf, 9); + nfarray[1] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR); - nfarray[2] = sign_extend(nf, 9); + nfarray[2] = sign_extend32(nf, 8); if (!IS_CHAN_HT40(ah->curchan)) return; nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); - nfarray[3] = sign_extend(nf, 9); + nfarray[3] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR); - nfarray[4] = sign_extend(nf, 9); + nfarray[4] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR); - nfarray[5] = sign_extend(nf, 9); + nfarray[5] = sign_extend32(nf, 8); } static void ar9003_hw_set_nf_limits(struct ath_hw *ah) @@ -1070,13 +1070,13 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) aniState = &ah->curchan->ani; iniDef = &aniState->iniDef; - ath_print(common, ATH_DBG_ANI, - "ver %d.%d opmode %u chan %d Mhz/0x%x\n", - ah->hw_version.macVersion, - ah->hw_version.macRev, - ah->opmode, - chan->channel, - chan->channelFlags); + ath_dbg(common, ATH_DBG_ANI, + "ver %d.%d opmode %u chan %d Mhz/0x%x\n", + ah->hw_version.macVersion, + ah->hw_version.macRev, + ah->opmode, + chan->channel, + chan->channelFlags); val = REG_READ(ah, AR_PHY_SFCORR); iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); @@ -1113,10 +1113,55 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK; } +static void ar9003_hw_set_radar_params(struct ath_hw *ah, + struct ath_hw_radar_conf *conf) +{ + u32 radar_0 = 0, radar_1 = 0; + + if (!conf) { + REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); + return; + } + + radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA; + radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR); + radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI); + radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT); + radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); + radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); + + radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; + radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; + radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); + radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH); + radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH); + + REG_WRITE(ah, AR_PHY_RADAR_0, radar_0); + REG_WRITE(ah, AR_PHY_RADAR_1, radar_1); + if (conf->ext_channel) + REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); + else + REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); +} + +static void ar9003_hw_set_radar_conf(struct ath_hw *ah) +{ + struct ath_hw_radar_conf *conf = &ah->radar_conf; + + conf->fir_power = -28; + conf->radar_rssi = 0; + conf->pulse_height = 10; + conf->pulse_rssi = 24; + conf->pulse_inband = 8; + conf->pulse_maxlen = 255; + conf->pulse_inband_step = 12; + conf->radar_inband = 8; +} + void ar9003_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); - const u32 ar9300_cca_regs[6] = { + static const u32 ar9300_cca_regs[6] = { AR_PHY_CCA_0, AR_PHY_CCA_1, AR_PHY_CCA_2, @@ -1136,13 +1181,14 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->set_delta_slope = ar9003_hw_set_delta_slope; priv_ops->rfbus_req = ar9003_hw_rfbus_req; priv_ops->rfbus_done = ar9003_hw_rfbus_done; - priv_ops->enable_rfkill = ar9003_hw_enable_rfkill; priv_ops->set_diversity = ar9003_hw_set_diversity; priv_ops->ani_control = ar9003_hw_ani_control; priv_ops->do_getnf = ar9003_hw_do_getnf; priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; + priv_ops->set_radar_params = ar9003_hw_set_radar_params; ar9003_hw_set_nf_limits(ah); + ar9003_hw_set_radar_conf(ah); memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs)); } @@ -1165,7 +1211,7 @@ void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) ~(AR_PHY_WATCHDOG_NON_IDLE_ENABLE | AR_PHY_WATCHDOG_IDLE_ENABLE)); - ath_print(common, ATH_DBG_RESET, "Disabled BB Watchdog\n"); + ath_dbg(common, ATH_DBG_RESET, "Disabled BB Watchdog\n"); return; } @@ -1201,9 +1247,9 @@ void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) AR_PHY_WATCHDOG_IDLE_MASK | (AR_PHY_WATCHDOG_NON_IDLE_MASK & (idle_count << 2))); - ath_print(common, ATH_DBG_RESET, - "Enabled BB Watchdog timeout (%u ms)\n", - idle_tmo_ms); + ath_dbg(common, ATH_DBG_RESET, + "Enabled BB Watchdog timeout (%u ms)\n", + idle_tmo_ms); } void ar9003_hw_bb_watchdog_read(struct ath_hw *ah) @@ -1231,37 +1277,35 @@ void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah) return; status = ah->bb_watchdog_last_status; - ath_print(common, ATH_DBG_RESET, - "\n==== BB update: BB status=0x%08x ====\n", status); - ath_print(common, ATH_DBG_RESET, - "** BB state: wd=%u det=%u rdar=%u rOFDM=%d " - "rCCK=%u tOFDM=%u tCCK=%u agc=%u src=%u **\n", - MS(status, AR_PHY_WATCHDOG_INFO), - MS(status, AR_PHY_WATCHDOG_DET_HANG), - MS(status, AR_PHY_WATCHDOG_RADAR_SM), - MS(status, AR_PHY_WATCHDOG_RX_OFDM_SM), - MS(status, AR_PHY_WATCHDOG_RX_CCK_SM), - MS(status, AR_PHY_WATCHDOG_TX_OFDM_SM), - MS(status, AR_PHY_WATCHDOG_TX_CCK_SM), - MS(status, AR_PHY_WATCHDOG_AGC_SM), - MS(status,AR_PHY_WATCHDOG_SRCH_SM)); - - ath_print(common, ATH_DBG_RESET, - "** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n", - REG_READ(ah, AR_PHY_WATCHDOG_CTL_1), - REG_READ(ah, AR_PHY_WATCHDOG_CTL_2)); - ath_print(common, ATH_DBG_RESET, - "** BB mode: BB_gen_controls=0x%08x **\n", - REG_READ(ah, AR_PHY_GEN_CTRL)); + ath_dbg(common, ATH_DBG_RESET, + "\n==== BB update: BB status=0x%08x ====\n", status); + ath_dbg(common, ATH_DBG_RESET, + "** BB state: wd=%u det=%u rdar=%u rOFDM=%d rCCK=%u tOFDM=%u tCCK=%u agc=%u src=%u **\n", + MS(status, AR_PHY_WATCHDOG_INFO), + MS(status, AR_PHY_WATCHDOG_DET_HANG), + MS(status, AR_PHY_WATCHDOG_RADAR_SM), + MS(status, AR_PHY_WATCHDOG_RX_OFDM_SM), + MS(status, AR_PHY_WATCHDOG_RX_CCK_SM), + MS(status, AR_PHY_WATCHDOG_TX_OFDM_SM), + MS(status, AR_PHY_WATCHDOG_TX_CCK_SM), + MS(status, AR_PHY_WATCHDOG_AGC_SM), + MS(status, AR_PHY_WATCHDOG_SRCH_SM)); + + ath_dbg(common, ATH_DBG_RESET, + "** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n", + REG_READ(ah, AR_PHY_WATCHDOG_CTL_1), + REG_READ(ah, AR_PHY_WATCHDOG_CTL_2)); + ath_dbg(common, ATH_DBG_RESET, + "** BB mode: BB_gen_controls=0x%08x **\n", + REG_READ(ah, AR_PHY_GEN_CTRL)); #define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles) if (common->cc_survey.cycles) - ath_print(common, ATH_DBG_RESET, - "** BB busy times: rx_clear=%d%%, " - "rx_frame=%d%%, tx_frame=%d%% **\n", - PCT(rx_busy), PCT(rx_frame), PCT(tx_frame)); + ath_dbg(common, ATH_DBG_RESET, + "** BB busy times: rx_clear=%d%%, rx_frame=%d%%, tx_frame=%d%% **\n", + PCT(rx_busy), PCT(rx_frame), PCT(tx_frame)); - ath_print(common, ATH_DBG_RESET, - "==== BB update: done ====\n\n"); + ath_dbg(common, ATH_DBG_RESET, + "==== BB update: done ====\n\n"); } EXPORT_SYMBOL(ar9003_hw_bb_watchdog_dbg_info); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 3394dfe52b42..59bab6bd8a74 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -260,7 +260,13 @@ #define AR_PHY_CCA_0 (AR_AGC_BASE + 0x1c) #define AR_PHY_EXT_CCA0 (AR_AGC_BASE + 0x20) #define AR_PHY_RESTART (AR_AGC_BASE + 0x24) + #define AR_PHY_MC_GAIN_CTRL (AR_AGC_BASE + 0x28) +#define AR_ANT_DIV_CTRL_ALL 0x7e000000 +#define AR_ANT_DIV_CTRL_ALL_S 25 +#define AR_ANT_DIV_ENABLE 0x1000000 +#define AR_ANT_DIV_ENABLE_S 24 + #define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c) #define AR_PHY_EXT_CHN_WIN (AR_AGC_BASE + 0x30) #define AR_PHY_20_40_DET_THR (AR_AGC_BASE + 0x34) @@ -271,7 +277,11 @@ #define AR_PHY_RX_GAIN_BOUNDS_2 (AR_AGC_BASE + 0x48) #define AR_PHY_RSSI_0 (AR_AGC_BASE + 0x180) #define AR_PHY_SPUR_CCK_REP0 (AR_AGC_BASE + 0x184) + #define AR_PHY_CCK_DETECT (AR_AGC_BASE + 0x1c0) +#define AR_FAST_DIV_ENABLE 0x2000 +#define AR_FAST_DIV_ENABLE_S 13 + #define AR_PHY_DAG_CTRLCCK (AR_AGC_BASE + 0x1c4) #define AR_PHY_IQCORR_CTRL_CCK (AR_AGC_BASE + 0x1c8) @@ -536,10 +546,18 @@ #define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300) +#define AR_PHY_TX_IQCAL_START_9485 (AR_SM_BASE + 0x3c4) +#define AR_PHY_TX_IQCAL_START_DO_CAL_9485 0x80000000 +#define AR_PHY_TX_IQCAL_START_DO_CAL_9485_S 31 +#define AR_PHY_TX_IQCAL_CONTROL_1_9485 (AR_SM_BASE + 0x3c8) +#define AR_PHY_TX_IQCAL_STATUS_B0_9485 (AR_SM_BASE + 0x3f0) + #define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448) #define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440) #define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) -#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B0 (AR_SM_BASE + 0x450) +#define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \ + (AR_SREV_9485(ah) ? \ + 0x3d0 : 0x450) + ((_i) << 2)) #define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0) #define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4) @@ -568,7 +586,7 @@ #define AR_PHY_65NM_CH0_BIAS2 0x160c4 #define AR_PHY_65NM_CH0_BIAS4 0x160cc #define AR_PHY_65NM_CH0_RXTX4 0x1610c -#define AR_PHY_65NM_CH0_THERM 0x16290 +#define AR_PHY_65NM_CH0_THERM (AR_SREV_9485(ah) ? 0x1628c : 0x16290) #define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000 #define AR_PHY_65NM_CH0_THERM_LOCAL_S 31 @@ -584,6 +602,24 @@ #define AR_PHY_65NM_CH2_RXTX1 0x16900 #define AR_PHY_65NM_CH2_RXTX2 0x16904 +#define AR_CH0_TOP2 (AR_SREV_9485(ah) ? 0x00016284 : 0x0001628c) +#define AR_CH0_TOP2_XPABIASLVL 0xf000 +#define AR_CH0_TOP2_XPABIASLVL_S 12 + +#define AR_CH0_XTAL (AR_SREV_9485(ah) ? 0x16290 : 0x16294) +#define AR_CH0_XTAL_CAPINDAC 0x7f000000 +#define AR_CH0_XTAL_CAPINDAC_S 24 +#define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000 +#define AR_CH0_XTAL_CAPOUTDAC_S 17 + +#define AR_PHY_PMU1 0x16c40 +#define AR_PHY_PMU1_PWD 0x1 +#define AR_PHY_PMU1_PWD_S 0 + +#define AR_PHY_PMU2 0x16c44 +#define AR_PHY_PMU2_PGM 0x00200000 +#define AR_PHY_PMU2_PGM_S 21 + #define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT 0x00380000 #define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT_S 19 #define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT 0x00c00000 @@ -683,6 +719,7 @@ #define AR_PHY_TPCGR1_FORCED_DAC_GAIN_S 1 #define AR_PHY_TPCGR1_FORCE_DAC_GAIN 0x00000001 #define AR_PHY_TXGAIN_FORCE 0x00000001 +#define AR_PHY_TXGAIN_FORCE_S 0 #define AR_PHY_TXGAIN_FORCED_PADVGNRA 0x00003c00 #define AR_PHY_TXGAIN_FORCED_PADVGNRA_S 10 #define AR_PHY_TXGAIN_FORCED_PADVGNRB 0x0003c000 @@ -725,8 +762,13 @@ #define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 #define AR_PHY_TX_IQCAL_STATUS_FAILED 0x00000001 -#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE 0x00003fff -#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S 0 +#define AR_PHY_CALIBRATED_GAINS_0 0x3e +#define AR_PHY_CALIBRATED_GAINS_0_S 1 + +#define AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE 0x00003fff +#define AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE_S 0 +#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE 0x0fffc000 +#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S 14 #define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000 #define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28 @@ -785,7 +827,7 @@ #define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220) #define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + 0x240) #define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c) -#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B1 (AR_SM1_BASE + 0x450) +#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i) (AR_SM_BASE + 0x450 + ((_i) << 2)) /* * Channel 2 Register Map @@ -838,7 +880,7 @@ #define AR_PHY_TPC_11_B2 (AR_SM2_BASE + 0x220) #define AR_PHY_PDADC_TAB_2 (AR_SM2_BASE + 0x240) #define AR_PHY_TX_IQCAL_STATUS_B2 (AR_SM2_BASE + 0x48c) -#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B2 (AR_SM2_BASE + 0x450) +#define AR_PHY_TX_IQCAL_CORR_COEFF_B2(_i) (AR_SM2_BASE + 0x450 + ((_i) << 2)) #define AR_PHY_TX_IQCAL_STATUS_B2_FAILED 0x00000001 @@ -945,7 +987,9 @@ #define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT 0x0ffe0000 #define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT_S 17 -#define AR_PHY_PAPRD_TRAINER_CNTL1 (AR_SM_BASE + 0x490) +#define AR_PHY_PAPRD_TRAINER_CNTL1 (AR_SM_BASE + \ + (AR_SREV_9485(ah) ? \ + 0x580 : 0x490)) #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE 0x00000001 #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE_S 0 #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING 0x0000007e @@ -961,11 +1005,15 @@ #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP 0x0003f000 #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP_S 12 -#define AR_PHY_PAPRD_TRAINER_CNTL2 (AR_SM_BASE + 0x494) +#define AR_PHY_PAPRD_TRAINER_CNTL2 (AR_SM_BASE + \ + (AR_SREV_9485(ah) ? \ + 0x584 : 0x494)) #define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN 0xFFFFFFFF #define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN_S 0 -#define AR_PHY_PAPRD_TRAINER_CNTL3 (AR_SM_BASE + 0x498) +#define AR_PHY_PAPRD_TRAINER_CNTL3 (AR_SM_BASE + \ + (AR_SREV_9485(ah) ? \ + 0x588 : 0x498)) #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE 0x0000003f #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE_S 0 #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP 0x00000fc0 @@ -981,7 +1029,9 @@ #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE 0x20000000 #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE_S 29 -#define AR_PHY_PAPRD_TRAINER_CNTL4 (AR_SM_BASE + 0x49c) +#define AR_PHY_PAPRD_TRAINER_CNTL4 (AR_SM_BASE + \ + (AR_SREV_9485(ah) ? \ + 0x58c : 0x49c)) #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES 0x03ff0000 #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES_S 16 #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA 0x0000f000 @@ -1040,6 +1090,14 @@ #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0 0x3F #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0_S 0 +#define AR_PHY_POWERTX_RATE6 (AR_SM_BASE + 0x1d4) +#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5 0x3F00 +#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5_S 8 + +#define AR_PHY_POWERTX_RATE8 (AR_SM_BASE + 0x1dc) +#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5 0x3F00 +#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S 8 + void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); #endif /* AR9003_PHY_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h new file mode 100644 index 000000000000..70de3d89a7b5 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h @@ -0,0 +1,943 @@ +/* + * 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. + */ + +#ifndef INITVALS_9485_H +#define INITVALS_9485_H + +static const u32 ar9485Common_1_0[][2] = { + /* Addr allmodes */ + {0x00007010, 0x00000022}, + {0x00007020, 0x00000000}, + {0x00007034, 0x00000002}, + {0x00007038, 0x000004c2}, +}; + +static const u32 ar9485_1_0_mac_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, + {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, + {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, +}; + +static const u32 ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1[][2] = { + /* Addr allmodes */ + {0x00018c00, 0x10212e5e}, + {0x00018c04, 0x000801d8}, + {0x00018c08, 0x0000580c}, +}; + +static const u32 ar9485Common_wo_xlna_rx_gain_1_0[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x01800082}, + {0x0000a014, 0x01820181}, + {0x0000a018, 0x01840183}, + {0x0000a01c, 0x01880185}, + {0x0000a020, 0x018a0189}, + {0x0000a024, 0x02850284}, + {0x0000a028, 0x02890288}, + {0x0000a02c, 0x03850384}, + {0x0000a030, 0x03890388}, + {0x0000a034, 0x038b038a}, + {0x0000a038, 0x038d038c}, + {0x0000a03c, 0x03910390}, + {0x0000a040, 0x03930392}, + {0x0000a044, 0x03950394}, + {0x0000a048, 0x00000396}, + {0x0000a04c, 0x00000000}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x28282828}, + {0x0000a084, 0x28282828}, + {0x0000a088, 0x28282828}, + {0x0000a08c, 0x28282828}, + {0x0000a090, 0x28282828}, + {0x0000a094, 0x21212128}, + {0x0000a098, 0x171c1c1c}, + {0x0000a09c, 0x02020212}, + {0x0000a0a0, 0x00000202}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x111f1100}, + {0x0000a0c8, 0x111d111e}, + {0x0000a0cc, 0x111b111c}, + {0x0000a0d0, 0x22032204}, + {0x0000a0d4, 0x22012202}, + {0x0000a0d8, 0x221f2200}, + {0x0000a0dc, 0x221d221e}, + {0x0000a0e0, 0x33013302}, + {0x0000a0e4, 0x331f3300}, + {0x0000a0e8, 0x4402331e}, + {0x0000a0ec, 0x44004401}, + {0x0000a0f0, 0x441e441f}, + {0x0000a0f4, 0x55015502}, + {0x0000a0f8, 0x551f5500}, + {0x0000a0fc, 0x6602551e}, + {0x0000a100, 0x66006601}, + {0x0000a104, 0x661e661f}, + {0x0000a108, 0x7703661d}, + {0x0000a10c, 0x77017702}, + {0x0000a110, 0x00007700}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x111f1100}, + {0x0000a148, 0x111d111e}, + {0x0000a14c, 0x111b111c}, + {0x0000a150, 0x22032204}, + {0x0000a154, 0x22012202}, + {0x0000a158, 0x221f2200}, + {0x0000a15c, 0x221d221e}, + {0x0000a160, 0x33013302}, + {0x0000a164, 0x331f3300}, + {0x0000a168, 0x4402331e}, + {0x0000a16c, 0x44004401}, + {0x0000a170, 0x441e441f}, + {0x0000a174, 0x55015502}, + {0x0000a178, 0x551f5500}, + {0x0000a17c, 0x6602551e}, + {0x0000a180, 0x66006601}, + {0x0000a184, 0x661e661f}, + {0x0000a188, 0x7703661d}, + {0x0000a18c, 0x77017702}, + {0x0000a190, 0x00007700}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000296}, +}; + +static const u32 ar9485Modes_high_power_tx_gain_1_0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, + {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, + {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, + {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, + {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, + {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, + {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, + {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, + {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, + {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, + {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, + {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, + {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, + {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, + {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, + {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, + {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, + {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, + {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, + {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, + {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, + {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, + {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, + {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, + {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, + {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, + {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, +}; + +static const u32 ar9485_1_0[][2] = { + /* Addr allmodes */ + {0x0000a580, 0x00000000}, + {0x0000a584, 0x00000000}, + {0x0000a588, 0x00000000}, + {0x0000a58c, 0x00000000}, + {0x0000a590, 0x00000000}, + {0x0000a594, 0x00000000}, + {0x0000a598, 0x00000000}, + {0x0000a59c, 0x00000000}, + {0x0000a5a0, 0x00000000}, + {0x0000a5a4, 0x00000000}, + {0x0000a5a8, 0x00000000}, + {0x0000a5ac, 0x00000000}, + {0x0000a5b0, 0x00000000}, + {0x0000a5b4, 0x00000000}, + {0x0000a5b8, 0x00000000}, + {0x0000a5bc, 0x00000000}, +}; + +static const u32 ar9485_1_0_radio_core[][2] = { + /* Addr allmodes */ + {0x00016000, 0x36db6db6}, + {0x00016004, 0x6db6db40}, + {0x00016008, 0x73800000}, + {0x0001600c, 0x00000000}, + {0x00016040, 0x7f80fff8}, + {0x00016048, 0x6c92426e}, + {0x0001604c, 0x000f0278}, + {0x00016050, 0x6db6db6c}, + {0x00016054, 0x6db60000}, + {0x00016080, 0x00080000}, + {0x00016084, 0x0e48048c}, + {0x00016088, 0x14214514}, + {0x0001608c, 0x119f081e}, + {0x00016090, 0x24926490}, + {0x00016098, 0xd28b3330}, + {0x000160a0, 0xc2108ffe}, + {0x000160a4, 0x812fc370}, + {0x000160a8, 0x423c8000}, + {0x000160b4, 0x92480040}, + {0x000160c0, 0x006db6db}, + {0x000160c4, 0x0186db60}, + {0x000160c8, 0x6db6db6c}, + {0x000160cc, 0x6de6fbe0}, + {0x000160d0, 0xf7dfcf3c}, + {0x00016100, 0x04cb0001}, + {0x00016104, 0xfff80015}, + {0x00016108, 0x00080010}, + {0x00016144, 0x01884080}, + {0x00016148, 0x00008040}, + {0x00016180, 0x08453333}, + {0x00016184, 0x18e82f01}, + {0x00016188, 0x00000000}, + {0x0001618c, 0x00000000}, + {0x00016240, 0x08400000}, + {0x00016244, 0x1bf90f00}, + {0x00016248, 0x00000000}, + {0x0001624c, 0x00000000}, + {0x00016280, 0x01000015}, + {0x00016284, 0x00d30000}, + {0x00016288, 0x00318000}, + {0x0001628c, 0x50000000}, + {0x00016290, 0x4b96210f}, + {0x00016380, 0x00000000}, + {0x00016384, 0x00000000}, + {0x00016388, 0x00800700}, + {0x0001638c, 0x00800700}, + {0x00016390, 0x00800700}, + {0x00016394, 0x00000000}, + {0x00016398, 0x00000000}, + {0x0001639c, 0x00000000}, + {0x000163a0, 0x00000001}, + {0x000163a4, 0x00000001}, + {0x000163a8, 0x00000000}, + {0x000163ac, 0x00000000}, + {0x000163b0, 0x00000000}, + {0x000163b4, 0x00000000}, + {0x000163b8, 0x00000000}, + {0x000163bc, 0x00000000}, + {0x000163c0, 0x000000a0}, + {0x000163c4, 0x000c0000}, + {0x000163c8, 0x14021402}, + {0x000163cc, 0x00001402}, + {0x000163d0, 0x00000000}, + {0x000163d4, 0x00000000}, + {0x00016c40, 0x1319c178}, + {0x00016c44, 0x10000000}, +}; + +static const u32 ar9485Modes_lowest_ob_db_tx_gain_1_0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, + {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, + {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, + {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, + {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, + {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, + {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, + {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, + {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, + {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, + {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, + {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, + {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, + {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, + {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, + {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, + {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, + {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, + {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, + {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, + {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, + {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, + {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, + {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, + {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, + {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, + {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, +}; + +static const u32 ar9485_1_0_baseband_core[][2] = { + /* Addr allmodes */ + {0x00009800, 0xafe68e30}, + {0x00009804, 0xfd14e000}, + {0x00009808, 0x9c0a8f6b}, + {0x0000980c, 0x04800000}, + {0x00009814, 0x9280c00a}, + {0x00009818, 0x00000000}, + {0x0000981c, 0x00020028}, + {0x00009834, 0x5f3ca3de}, + {0x00009838, 0x0108ecff}, + {0x0000983c, 0x14750600}, + {0x00009880, 0x201fff00}, + {0x00009884, 0x00001042}, + {0x000098a4, 0x00200400}, + {0x000098b0, 0x52440bbe}, + {0x000098bc, 0x00000002}, + {0x000098d0, 0x004b6a8e}, + {0x000098d4, 0x00000820}, + {0x000098dc, 0x00000000}, + {0x000098f0, 0x00000000}, + {0x000098f4, 0x00000000}, + {0x00009c04, 0x00000000}, + {0x00009c08, 0x03200000}, + {0x00009c0c, 0x00000000}, + {0x00009c10, 0x00000000}, + {0x00009c14, 0x00046384}, + {0x00009c18, 0x05b6b440}, + {0x00009c1c, 0x00b6b440}, + {0x00009d00, 0xc080a333}, + {0x00009d04, 0x40206c10}, + {0x00009d08, 0x009c4060}, + {0x00009d0c, 0x1883800a}, + {0x00009d10, 0x01834061}, + {0x00009d14, 0x00c00400}, + {0x00009d18, 0x00000000}, + {0x00009d1c, 0x00000000}, + {0x00009e08, 0x0038233c}, + {0x00009e24, 0x990bb515}, + {0x00009e28, 0x0a6f0000}, + {0x00009e30, 0x06336f77}, + {0x00009e34, 0x6af6532f}, + {0x00009e38, 0x0cc80c00}, + {0x00009e40, 0x0d261820}, + {0x00009e4c, 0x00001004}, + {0x00009e50, 0x00ff03f1}, + {0x00009fc0, 0x80be4788}, + {0x00009fc4, 0x0001efb5}, + {0x00009fcc, 0x40000014}, + {0x0000a20c, 0x00000000}, + {0x0000a210, 0x00000000}, + {0x0000a220, 0x00000000}, + {0x0000a224, 0x00000000}, + {0x0000a228, 0x10002310}, + {0x0000a23c, 0x00000000}, + {0x0000a244, 0x0c000000}, + {0x0000a2a0, 0x00000001}, + {0x0000a2c0, 0x00000001}, + {0x0000a2c8, 0x00000000}, + {0x0000a2cc, 0x18c43433}, + {0x0000a2d4, 0x00000000}, + {0x0000a2dc, 0x00000000}, + {0x0000a2e0, 0x00000000}, + {0x0000a2e4, 0x00000000}, + {0x0000a2e8, 0x00000000}, + {0x0000a2ec, 0x00000000}, + {0x0000a2f0, 0x00000000}, + {0x0000a2f4, 0x00000000}, + {0x0000a2f8, 0x00000000}, + {0x0000a344, 0x00000000}, + {0x0000a34c, 0x00000000}, + {0x0000a350, 0x0000a000}, + {0x0000a364, 0x00000000}, + {0x0000a370, 0x00000000}, + {0x0000a390, 0x00000001}, + {0x0000a394, 0x00000444}, + {0x0000a398, 0x001f0e0f}, + {0x0000a39c, 0x0075393f}, + {0x0000a3a0, 0xb79f6427}, + {0x0000a3a4, 0x00000000}, + {0x0000a3a8, 0xaaaaaaaa}, + {0x0000a3ac, 0x3c466478}, + {0x0000a3c0, 0x20202020}, + {0x0000a3c4, 0x22222220}, + {0x0000a3c8, 0x20200020}, + {0x0000a3cc, 0x20202020}, + {0x0000a3d0, 0x20202020}, + {0x0000a3d4, 0x20202020}, + {0x0000a3d8, 0x20202020}, + {0x0000a3dc, 0x20202020}, + {0x0000a3e0, 0x20202020}, + {0x0000a3e4, 0x20202020}, + {0x0000a3e8, 0x20202020}, + {0x0000a3ec, 0x20202020}, + {0x0000a3f0, 0x00000000}, + {0x0000a3f4, 0x00000006}, + {0x0000a3f8, 0x0cdbd380}, + {0x0000a3fc, 0x000f0f01}, + {0x0000a400, 0x8fa91f01}, + {0x0000a404, 0x00000000}, + {0x0000a408, 0x0e79e5c6}, + {0x0000a40c, 0x00820820}, + {0x0000a414, 0x1ce739ce}, + {0x0000a418, 0x2d0011ce}, + {0x0000a41c, 0x1ce739ce}, + {0x0000a420, 0x000001ce}, + {0x0000a424, 0x1ce739ce}, + {0x0000a428, 0x000001ce}, + {0x0000a42c, 0x1ce739ce}, + {0x0000a430, 0x1ce739ce}, + {0x0000a434, 0x00000000}, + {0x0000a438, 0x00001801}, + {0x0000a43c, 0x00000000}, + {0x0000a440, 0x00000000}, + {0x0000a444, 0x00000000}, + {0x0000a448, 0x04000000}, + {0x0000a44c, 0x00000001}, + {0x0000a450, 0x00010000}, + {0x0000a458, 0x00000000}, + {0x0000a5c4, 0x3fad9d74}, + {0x0000a5c8, 0x0048060a}, + {0x0000a5cc, 0x00000637}, + {0x0000a760, 0x03020100}, + {0x0000a764, 0x09080504}, + {0x0000a768, 0x0d0c0b0a}, + {0x0000a76c, 0x13121110}, + {0x0000a770, 0x31301514}, + {0x0000a774, 0x35343332}, + {0x0000a778, 0x00000036}, + {0x0000a780, 0x00000838}, + {0x0000a7c0, 0x00000000}, + {0x0000a7c4, 0xfffffffc}, + {0x0000a7c8, 0x00000000}, + {0x0000a7cc, 0x00000000}, + {0x0000a7d0, 0x00000000}, + {0x0000a7d4, 0x00000004}, + {0x0000a7dc, 0x00000001}, +}; + +static const u32 ar9485Modes_high_ob_db_tx_gain_1_0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, + {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, + {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, + {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, + {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, + {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, + {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, + {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, + {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, + {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, + {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, + {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, + {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, + {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, + {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, + {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, + {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, + {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, + {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, + {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, + {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, + {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, + {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, + {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, + {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, + {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, + {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, +}; + +static const u32 ar9485Common_rx_gain_1_0[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x01800082}, + {0x0000a014, 0x01820181}, + {0x0000a018, 0x01840183}, + {0x0000a01c, 0x01880185}, + {0x0000a020, 0x018a0189}, + {0x0000a024, 0x02850284}, + {0x0000a028, 0x02890288}, + {0x0000a02c, 0x03850384}, + {0x0000a030, 0x03890388}, + {0x0000a034, 0x038b038a}, + {0x0000a038, 0x038d038c}, + {0x0000a03c, 0x03910390}, + {0x0000a040, 0x03930392}, + {0x0000a044, 0x03950394}, + {0x0000a048, 0x00000396}, + {0x0000a04c, 0x00000000}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x28282828}, + {0x0000a084, 0x28282828}, + {0x0000a088, 0x28282828}, + {0x0000a08c, 0x28282828}, + {0x0000a090, 0x28282828}, + {0x0000a094, 0x21212128}, + {0x0000a098, 0x171c1c1c}, + {0x0000a09c, 0x02020212}, + {0x0000a0a0, 0x00000202}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x111f1100}, + {0x0000a0c8, 0x111d111e}, + {0x0000a0cc, 0x111b111c}, + {0x0000a0d0, 0x22032204}, + {0x0000a0d4, 0x22012202}, + {0x0000a0d8, 0x221f2200}, + {0x0000a0dc, 0x221d221e}, + {0x0000a0e0, 0x33013302}, + {0x0000a0e4, 0x331f3300}, + {0x0000a0e8, 0x4402331e}, + {0x0000a0ec, 0x44004401}, + {0x0000a0f0, 0x441e441f}, + {0x0000a0f4, 0x55015502}, + {0x0000a0f8, 0x551f5500}, + {0x0000a0fc, 0x6602551e}, + {0x0000a100, 0x66006601}, + {0x0000a104, 0x661e661f}, + {0x0000a108, 0x7703661d}, + {0x0000a10c, 0x77017702}, + {0x0000a110, 0x00007700}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x111f1100}, + {0x0000a148, 0x111d111e}, + {0x0000a14c, 0x111b111c}, + {0x0000a150, 0x22032204}, + {0x0000a154, 0x22012202}, + {0x0000a158, 0x221f2200}, + {0x0000a15c, 0x221d221e}, + {0x0000a160, 0x33013302}, + {0x0000a164, 0x331f3300}, + {0x0000a168, 0x4402331e}, + {0x0000a16c, 0x44004401}, + {0x0000a170, 0x441e441f}, + {0x0000a174, 0x55015502}, + {0x0000a178, 0x551f5500}, + {0x0000a17c, 0x6602551e}, + {0x0000a180, 0x66006601}, + {0x0000a184, 0x661e661f}, + {0x0000a188, 0x7703661d}, + {0x0000a18c, 0x77017702}, + {0x0000a190, 0x00007700}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000296}, +}; + +static const u32 ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1[][2] = { + /* Addr allmodes */ + {0x00018c00, 0x10252e5e}, + {0x00018c04, 0x000801d8}, + {0x00018c08, 0x0000580c}, +}; + +static const u32 ar9485_1_0_pcie_phy_clkreq_enable_L1[][2] = { + /* Addr allmodes */ + {0x00018c00, 0x10253e5e}, + {0x00018c04, 0x000801d8}, + {0x00018c08, 0x0000580c}, +}; + +static const u32 ar9485_1_0_soc_preamble[][2] = { + /* Addr allmodes */ + {0x000040a4, 0x00a0c9c9}, + {0x00007048, 0x00000004}, +}; + +static const u32 ar9485_fast_clock_1_0_baseband_postamble[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + {0x00009e00, 0x03721821, 0x03721821}, + {0x0000a230, 0x0000400b, 0x00004016}, + {0x0000a254, 0x00000898, 0x00001130}, +}; + +static const u32 ar9485_1_0_baseband_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, + {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e}, + {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, + {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, + {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044}, + {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, + {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020}, + {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, + {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e}, + {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, + {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, + {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, + {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, + {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, + {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, + {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, + {0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0}, + {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, + {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, + {0x0000a234, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff}, + {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, + {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, + {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, + {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, + {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501}, + {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, + {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0}, + {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, + {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, + {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000be04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, + {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +}; + +static const u32 ar9485Modes_low_ob_db_tx_gain_1_0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, + {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, + {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, + {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, + {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, + {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, + {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, + {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, + {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, + {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, + {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, + {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, + {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, + {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, + {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, + {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, + {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, + {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, + {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, + {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, + {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, + {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, + {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, + {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, + {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, + {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, + {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, +}; + +static const u32 ar9485_1_0_pcie_phy_clkreq_disable_L1[][2] = { + /* Addr allmodes */ + {0x00018c00, 0x10213e5e}, + {0x00018c04, 0x000801d8}, + {0x00018c08, 0x0000580c}, +}; + +static const u32 ar9485_1_0_radio_postamble[][2] = { + /* Addr allmodes */ + {0x0001609c, 0x0b283f31}, + {0x000160ac, 0x24611800}, + {0x000160b0, 0x03284f3e}, + {0x0001610c, 0x00170000}, + {0x00016140, 0x10804008}, +}; + +static const u32 ar9485_1_0_mac_core[][2] = { + /* Addr allmodes */ + {0x00000008, 0x00000000}, + {0x00000030, 0x00020085}, + {0x00000034, 0x00000005}, + {0x00000040, 0x00000000}, + {0x00000044, 0x00000000}, + {0x00000048, 0x00000008}, + {0x0000004c, 0x00000010}, + {0x00000050, 0x00000000}, + {0x00001040, 0x002ffc0f}, + {0x00001044, 0x002ffc0f}, + {0x00001048, 0x002ffc0f}, + {0x0000104c, 0x002ffc0f}, + {0x00001050, 0x002ffc0f}, + {0x00001054, 0x002ffc0f}, + {0x00001058, 0x002ffc0f}, + {0x0000105c, 0x002ffc0f}, + {0x00001060, 0x002ffc0f}, + {0x00001064, 0x002ffc0f}, + {0x000010f0, 0x00000100}, + {0x00001270, 0x00000000}, + {0x000012b0, 0x00000000}, + {0x000012f0, 0x00000000}, + {0x0000143c, 0x00000000}, + {0x0000147c, 0x00000000}, + {0x00008000, 0x00000000}, + {0x00008004, 0x00000000}, + {0x00008008, 0x00000000}, + {0x0000800c, 0x00000000}, + {0x00008018, 0x00000000}, + {0x00008020, 0x00000000}, + {0x00008038, 0x00000000}, + {0x0000803c, 0x00000000}, + {0x00008040, 0x00000000}, + {0x00008044, 0x00000000}, + {0x00008048, 0x00000000}, + {0x0000804c, 0xffffffff}, + {0x00008054, 0x00000000}, + {0x00008058, 0x00000000}, + {0x0000805c, 0x000fc78f}, + {0x00008060, 0x0000000f}, + {0x00008064, 0x00000000}, + {0x00008070, 0x00000310}, + {0x00008074, 0x00000020}, + {0x00008078, 0x00000000}, + {0x0000809c, 0x0000000f}, + {0x000080a0, 0x00000000}, + {0x000080a4, 0x02ff0000}, + {0x000080a8, 0x0e070605}, + {0x000080ac, 0x0000000d}, + {0x000080b0, 0x00000000}, + {0x000080b4, 0x00000000}, + {0x000080b8, 0x00000000}, + {0x000080bc, 0x00000000}, + {0x000080c0, 0x2a800000}, + {0x000080c4, 0x06900168}, + {0x000080c8, 0x13881c20}, + {0x000080cc, 0x01f40000}, + {0x000080d0, 0x00252500}, + {0x000080d4, 0x00a00000}, + {0x000080d8, 0x00400000}, + {0x000080dc, 0x00000000}, + {0x000080e0, 0xffffffff}, + {0x000080e4, 0x0000ffff}, + {0x000080e8, 0x3f3f3f3f}, + {0x000080ec, 0x00000000}, + {0x000080f0, 0x00000000}, + {0x000080f4, 0x00000000}, + {0x000080fc, 0x00020000}, + {0x00008100, 0x00000000}, + {0x00008108, 0x00000052}, + {0x0000810c, 0x00000000}, + {0x00008110, 0x00000000}, + {0x00008114, 0x000007ff}, + {0x00008118, 0x000000aa}, + {0x0000811c, 0x00003210}, + {0x00008124, 0x00000000}, + {0x00008128, 0x00000000}, + {0x0000812c, 0x00000000}, + {0x00008130, 0x00000000}, + {0x00008134, 0x00000000}, + {0x00008138, 0x00000000}, + {0x0000813c, 0x0000ffff}, + {0x00008144, 0xffffffff}, + {0x00008168, 0x00000000}, + {0x0000816c, 0x00000000}, + {0x00008170, 0x18486200}, + {0x00008174, 0x33332210}, + {0x00008178, 0x00000000}, + {0x0000817c, 0x00020000}, + {0x000081c0, 0x00000000}, + {0x000081c4, 0x33332210}, + {0x000081c8, 0x00000000}, + {0x000081cc, 0x00000000}, + {0x000081d4, 0x00000000}, + {0x000081ec, 0x00000000}, + {0x000081f0, 0x00000000}, + {0x000081f4, 0x00000000}, + {0x000081f8, 0x00000000}, + {0x000081fc, 0x00000000}, + {0x00008240, 0x00100000}, + {0x00008244, 0x0010f400}, + {0x00008248, 0x00000800}, + {0x0000824c, 0x0001e800}, + {0x00008250, 0x00000000}, + {0x00008254, 0x00000000}, + {0x00008258, 0x00000000}, + {0x0000825c, 0x40000000}, + {0x00008260, 0x00080922}, + {0x00008264, 0x9ca00010}, + {0x00008268, 0xffffffff}, + {0x0000826c, 0x0000ffff}, + {0x00008270, 0x00000000}, + {0x00008274, 0x40000000}, + {0x00008278, 0x003e4180}, + {0x0000827c, 0x00000004}, + {0x00008284, 0x0000002c}, + {0x00008288, 0x0000002c}, + {0x0000828c, 0x000000ff}, + {0x00008294, 0x00000000}, + {0x00008298, 0x00000000}, + {0x0000829c, 0x00000000}, + {0x00008300, 0x00000140}, + {0x00008314, 0x00000000}, + {0x0000831c, 0x0000010d}, + {0x00008328, 0x00000000}, + {0x0000832c, 0x00000007}, + {0x00008330, 0x00000302}, + {0x00008334, 0x00000700}, + {0x00008338, 0x00ff0000}, + {0x0000833c, 0x02400000}, + {0x00008340, 0x000107ff}, + {0x00008344, 0xa248105b}, + {0x00008348, 0x008f0000}, + {0x0000835c, 0x00000000}, + {0x00008360, 0xffffffff}, + {0x00008364, 0xffffffff}, + {0x00008368, 0x00000000}, + {0x00008370, 0x00000000}, + {0x00008374, 0x000000ff}, + {0x00008378, 0x00000000}, + {0x0000837c, 0x00000000}, + {0x00008380, 0xffffffff}, + {0x00008384, 0xffffffff}, + {0x00008390, 0xffffffff}, + {0x00008394, 0xffffffff}, + {0x00008398, 0x00000000}, + {0x0000839c, 0x00000000}, + {0x000083a0, 0x00000000}, + {0x000083a4, 0x0000fa14}, + {0x000083a8, 0x000f0c00}, + {0x000083ac, 0x33332210}, + {0x000083b0, 0x33332210}, + {0x000083b4, 0x33332210}, + {0x000083b8, 0x33332210}, + {0x000083bc, 0x00000000}, + {0x000083c0, 0x00000000}, + {0x000083c4, 0x00000000}, + {0x000083c8, 0x00000000}, + {0x000083cc, 0x00000200}, + {0x000083d0, 0x000301ff}, +}; +#endif diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 0963071e8f90..3681caf54282 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -57,6 +57,8 @@ struct ath_node; #define A_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define ATH9K_PM_QOS_DEFAULT_VALUE 55 + #define TSF_TO_TU(_h,_l) \ ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) @@ -87,33 +89,19 @@ struct ath_config { /** * enum buffer_type - Buffer type flags * - * @BUF_HT: Send this buffer using HT capabilities * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX) * @BUF_AGGR: Indicates whether the buffer can be aggregated * (used in aggregation scheduling) - * @BUF_RETRY: Indicates whether the buffer is retried * @BUF_XRETRY: To denote excessive retries of the buffer */ enum buffer_type { - BUF_HT = BIT(1), BUF_AMPDU = BIT(2), BUF_AGGR = BIT(3), - BUF_RETRY = BIT(4), BUF_XRETRY = BIT(5), }; -#define bf_nframes bf_state.bfs_nframes -#define bf_al bf_state.bfs_al -#define bf_frmlen bf_state.bfs_frmlen -#define bf_retries bf_state.bfs_retries -#define bf_seqno bf_state.bfs_seqno -#define bf_tidno bf_state.bfs_tidno -#define bf_keyix bf_state.bfs_keyix -#define bf_keytype bf_state.bfs_keytype -#define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT) #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) #define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) -#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY) #define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) #define ATH_TXSTATUS_RING_SIZE 64 @@ -178,8 +166,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, /* returns delimiter padding required given the packet length */ #define ATH_AGGR_GET_NDELIM(_len) \ - (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \ - (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2) + (((_len) >= ATH_AGGR_MINPLEN) ? 0 : \ + DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ)) #define BAW_WITHIN(_start, _bawsz, _seqno) \ ((((_seqno) - (_start)) & 4095) < (_bawsz)) @@ -196,12 +184,12 @@ enum ATH_AGGR_STATUS { #define ATH_TXFIFO_DEPTH 8 struct ath_txq { - int axq_class; u32 axq_qnum; u32 *axq_link; struct list_head axq_q; spinlock_t axq_lock; u32 axq_depth; + u32 axq_ampdu_depth; bool stopped; bool axq_tx_inprogress; struct list_head axq_acq; @@ -209,27 +197,28 @@ struct ath_txq { struct list_head txq_fifo_pending; u8 txq_headidx; u8 txq_tailidx; + int pending_frames; }; struct ath_atx_ac { + struct ath_txq *txq; int sched; - int qnum; struct list_head list; struct list_head tid_q; }; +struct ath_frame_info { + int framelen; + u32 keyix; + enum ath9k_key_type keytype; + u8 retries; + u16 seqno; +}; + struct ath_buf_state { - int bfs_nframes; - u16 bfs_al; - u16 bfs_frmlen; - int bfs_seqno; - int bfs_tidno; - int bfs_retries; u8 bf_type; u8 bfs_paprd; - unsigned long bfs_paprd_timestamp; - u32 bfs_keyix; - enum ath9k_key_type bfs_keytype; + enum ath9k_internal_frame_type bfs_ftype; }; struct ath_buf { @@ -242,7 +231,6 @@ struct ath_buf { dma_addr_t bf_daddr; /* physical addr of desc */ dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */ bool bf_stale; - bool bf_tx_aborted; u16 bf_flags; struct ath_buf_state bf_state; struct ath_wiphy *aphy; @@ -271,7 +259,6 @@ struct ath_node { struct ath_atx_ac ac[WME_NUM_AC]; u16 maxampdu; u8 mpdudensity; - int last_rssi; }; #define AGGR_CLEANUP BIT(1) @@ -280,6 +267,7 @@ struct ath_node { struct ath_tx_control { struct ath_txq *txq; + struct ath_node *an; int if_id; enum ath9k_internal_frame_type frame_type; u8 paprd; @@ -292,12 +280,11 @@ struct ath_tx_control { struct ath_tx { u16 seq_no; u32 txqsetup; - int hwq_map[WME_NUM_AC]; spinlock_t txbuflock; struct list_head txbuf; struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; struct ath_descdma txdma; - int pending_frames[WME_NUM_AC]; + struct ath_txq *txq_map[WME_NUM_AC]; }; struct ath_rx_edma { @@ -311,7 +298,6 @@ struct ath_rx { u8 rxotherant; u32 *rxlink; unsigned int rxfilter; - spinlock_t pcu_lock; spinlock_t rxbuflock; struct list_head rxbuf; struct ath_descdma rxdma; @@ -328,7 +314,6 @@ void ath_rx_cleanup(struct ath_softc *sc); int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp); struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); -int ath_tx_setup(struct ath_softc *sc, int haltype); bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx); @@ -343,7 +328,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath_tx_control *txctl); void ath_tx_tasklet(struct ath_softc *sc); void ath_tx_edma_tasklet(struct ath_softc *sc); -void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb); int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid, u16 *ssn); void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); @@ -564,6 +548,7 @@ struct ath_ant_comb { #define SC_OP_BT_PRIORITY_DETECTED BIT(12) #define SC_OP_BT_SCAN BIT(13) #define SC_OP_ANI_RUN BIT(14) +#define SC_OP_ENABLE_APM BIT(15) /* Powersave flags */ #define PS_WAIT_FOR_BEACON BIT(0) @@ -601,13 +586,14 @@ struct ath_softc { struct ath_hw *sc_ah; void __iomem *mem; int irq; - spinlock_t sc_resetlock; spinlock_t sc_serial_rw; spinlock_t sc_pm_lock; + spinlock_t sc_pcu_lock; struct mutex mutex; struct work_struct paprd_work; struct work_struct hw_check_work; struct completion paprd_complete; + bool paprd_pending; u32 intrstatus; u32 sc_flags; /* SC_OP_* */ @@ -665,11 +651,11 @@ struct ath_wiphy { bool idle; int chan_idx; int chan_is_ht; + int last_rssi; }; void ath9k_tasklet(unsigned long data); int ath_reset(struct ath_softc *sc, bool retry_tx); -int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); int ath_cabq_update(struct ath_softc *); static inline void ath_read_cachesize(struct ath_common *common, int *csz) @@ -678,17 +664,19 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) } extern struct ieee80211_ops ath9k_ops; -extern int modparam_nohwcrypt; +extern int ath9k_modparam_nohwcrypt; extern int led_blink; +extern int ath9k_pm_qos_value; +extern bool is_ath9k_unloaded; irqreturn_t ath_isr(int irq, void *dev); +void ath9k_init_crypto(struct ath_softc *sc); int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, const struct ath_bus_ops *bus_ops); void ath9k_deinit_device(struct ath_softc *sc); void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, struct ath9k_channel *ichan); -void ath_update_chainmask(struct ath_softc *sc, int is_ht); int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, struct ath9k_channel *hchan); @@ -715,10 +703,12 @@ static inline void ath_ahb_exit(void) {}; void ath9k_ps_wakeup(struct ath_softc *sc); void ath9k_ps_restore(struct ath_softc *sc); +u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); + void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int ath9k_wiphy_add(struct ath_softc *sc); int ath9k_wiphy_del(struct ath_wiphy *aphy); -void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb); +void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype); int ath9k_wiphy_pause(struct ath_wiphy *aphy); int ath9k_wiphy_unpause(struct ath_wiphy *aphy); int ath9k_wiphy_select(struct ath_wiphy *aphy); diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 19891e7d49ae..385ba03134ba 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -28,7 +28,7 @@ int ath_beaconq_config(struct ath_softc *sc) struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_tx_queue_info qi, qi_be; - int qnum; + struct ath_txq *txq; ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { @@ -38,16 +38,16 @@ int ath_beaconq_config(struct ath_softc *sc) qi.tqi_cwmax = 0; } else { /* Adhoc mode; important thing is to use 2x cwmin. */ - qnum = sc->tx.hwq_map[WME_AC_BE]; - ath9k_hw_get_txq_props(ah, qnum, &qi_be); + txq = sc->tx.txq_map[WME_AC_BE]; + ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be); qi.tqi_aifs = qi_be.tqi_aifs; qi.tqi_cwmin = 4*qi_be.tqi_cwmin; qi.tqi_cwmax = qi_be.tqi_cwmax; } if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to update h/w beacon queue parameters\n"); + ath_err(common, + "Unable to update h/w beacon queue parameters\n"); return 0; } else { ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); @@ -103,12 +103,32 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); series[0].Tries = 1; series[0].Rate = rate; - series[0].ChSel = common->tx_chainmask; + series[0].ChSel = ath_txchainmask_reduction(sc, + common->tx_chainmask, series[0].Rate); series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, series, 4, 0); } +static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_tx_control txctl; + + memset(&txctl, 0, sizeof(struct ath_tx_control)); + txctl.txq = sc->beacon.cabq; + + ath_dbg(common, ATH_DBG_XMIT, + "transmitting CABQ packet, skb: %p\n", skb); + + if (ath_tx_start(hw, skb, &txctl) != 0) { + ath_dbg(common, ATH_DBG_XMIT, "CABQ TX failed\n"); + dev_kfree_skb_any(skb); + } +} + static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -169,8 +189,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; bf->bf_buf_addr = 0; - ath_print(common, ATH_DBG_FATAL, - "dma_mapping_error on beaconing\n"); + ath_err(common, "dma_mapping_error on beaconing\n"); return NULL; } @@ -190,8 +209,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, if (skb && cabq_depth) { if (sc->nvifs > 1) { - ath_print(common, ATH_DBG_BEACON, - "Flushing previous cabq traffic\n"); + ath_dbg(common, ATH_DBG_BEACON, + "Flushing previous cabq traffic\n"); ath_draintxq(sc, cabq, false); } } @@ -263,7 +282,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) /* NB: the beacon data buffer must be 32-bit aligned. */ skb = ieee80211_beacon_get(sc->hw, vif); if (skb == NULL) { - ath_print(common, ATH_DBG_BEACON, "cannot get skb\n"); + ath_dbg(common, ATH_DBG_BEACON, "cannot get skb\n"); return -ENOMEM; } @@ -287,10 +306,9 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) tsfadjust = intval * avp->av_bslot / ATH_BCBUF; avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); - ath_print(common, ATH_DBG_BEACON, - "stagger beacons, bslot %d intval " - "%u tsfadjust %llu\n", - avp->av_bslot, intval, (unsigned long long)tsfadjust); + ath_dbg(common, ATH_DBG_BEACON, + "stagger beacons, bslot %d intval %u tsfadjust %llu\n", + avp->av_bslot, intval, (unsigned long long)tsfadjust); ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = avp->tsf_adjust; @@ -304,8 +322,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; bf->bf_buf_addr = 0; - ath_print(common, ATH_DBG_FATAL, - "dma_mapping_error on beacon alloc\n"); + ath_err(common, "dma_mapping_error on beacon alloc\n"); return -ENOMEM; } @@ -362,13 +379,13 @@ void ath_beacon_tasklet(unsigned long data) sc->beacon.bmisscnt++; if (sc->beacon.bmisscnt < BSTUCK_THRESH) { - ath_print(common, ATH_DBG_BSTUCK, - "missed %u consecutive beacons\n", - sc->beacon.bmisscnt); + ath_dbg(common, ATH_DBG_BSTUCK, + "missed %u consecutive beacons\n", + sc->beacon.bmisscnt); ath9k_hw_bstuck_nfcal(ah); } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { - ath_print(common, ATH_DBG_BSTUCK, - "beacon is officially stuck\n"); + ath_dbg(common, ATH_DBG_BSTUCK, + "beacon is officially stuck\n"); sc->sc_flags |= SC_OP_TSF_RESET; ath_reset(sc, true); } @@ -377,9 +394,9 @@ void ath_beacon_tasklet(unsigned long data) } if (sc->beacon.bmisscnt != 0) { - ath_print(common, ATH_DBG_BSTUCK, - "resume beacon xmit after %u misses\n", - sc->beacon.bmisscnt); + ath_dbg(common, ATH_DBG_BSTUCK, + "resume beacon xmit after %u misses\n", + sc->beacon.bmisscnt); sc->beacon.bmisscnt = 0; } @@ -405,9 +422,9 @@ void ath_beacon_tasklet(unsigned long data) vif = sc->beacon.bslot[slot]; aphy = sc->beacon.bslot_aphy[slot]; - ath_print(common, ATH_DBG_BEACON, - "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", - slot, tsf, tsftu, intval, vif); + ath_dbg(common, ATH_DBG_BEACON, + "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", + slot, tsf, tsftu, intval, vif); bfaddr = 0; if (vif) { @@ -449,8 +466,8 @@ void ath_beacon_tasklet(unsigned long data) * are still pending on the queue. */ if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) { - ath_print(common, ATH_DBG_FATAL, - "beacon queue %u did not stop?\n", sc->beacon.beaconq); + ath_err(common, "beacon queue %u did not stop?\n", + sc->beacon.beaconq); } /* NB: cabq traffic should already be queued and primed */ @@ -503,7 +520,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc, /* Set the computed AP beacon timers */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; ath9k_hw_set_interrupts(ah, ah->imask); @@ -536,8 +553,8 @@ static void ath_beacon_config_sta(struct ath_softc *sc, /* No need to configure beacon if we are not associated */ if (!common->curaid) { - ath_print(common, ATH_DBG_BEACON, - "STA is not yet associated..skipping beacon config\n"); + ath_dbg(common, ATH_DBG_BEACON, + "STA is not yet associated..skipping beacon config\n"); return; } @@ -549,8 +566,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc, * last beacon we received (which may be none). */ dtimperiod = conf->dtim_period; - if (dtimperiod <= 0) /* NB: 0 if not known */ - dtimperiod = 1; dtimcount = conf->dtim_count; if (dtimcount >= dtimperiod) /* NB: sanity check */ dtimcount = 0; @@ -558,8 +573,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc, cfpcount = 0; sleepduration = conf->listen_interval * intval; - if (sleepduration <= 0) - sleepduration = intval; /* * Pull nexttbtt forward to reflect the current @@ -630,23 +643,22 @@ static void ath_beacon_config_sta(struct ath_softc *sc, /* TSF out of range threshold fixed at 1 second */ bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; - ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); - ath_print(common, ATH_DBG_BEACON, - "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", - bs.bs_bmissthreshold, bs.bs_sleepduration, - bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); + ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); + ath_dbg(common, ATH_DBG_BEACON, + "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", + bs.bs_bmissthreshold, bs.bs_sleepduration, + bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); /* Set the computed STA beacon timers */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath9k_hw_set_sta_beacon_timers(ah, &bs); ah->imask |= ATH9K_INT_BMISS; ath9k_hw_set_interrupts(ah, ah->imask); } static void ath_beacon_config_adhoc(struct ath_softc *sc, - struct ath_beacon_config *conf, - struct ieee80211_vif *vif) + struct ath_beacon_config *conf) { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); @@ -670,9 +682,9 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, nexttbtt += intval; } while (nexttbtt < tsftu); - ath_print(common, ATH_DBG_BEACON, - "IBSS nexttbtt %u intval %u (%u)\n", - nexttbtt, intval, conf->beacon_interval); + ath_dbg(common, ATH_DBG_BEACON, + "IBSS nexttbtt %u intval %u (%u)\n", + nexttbtt, intval, conf->beacon_interval); /* * In IBSS mode enable the beacon timers but only enable SWBA interrupts @@ -686,7 +698,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, /* Set the computed ADHOC beacon timers */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; ath9k_hw_set_interrupts(ah, ah->imask); @@ -701,18 +713,17 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) /* Setup the beacon configuration parameters */ if (vif) { struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - iftype = vif->type; - cur_conf->beacon_interval = bss_conf->beacon_int; cur_conf->dtim_period = bss_conf->dtim_period; + } else { + iftype = sc->sc_ah->opmode; + } + cur_conf->listen_interval = 1; cur_conf->dtim_count = 1; cur_conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; - } else { - iftype = sc->sc_ah->opmode; - } /* * It looks like mac80211 may end up using beacon interval of zero in @@ -723,20 +734,27 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) if (cur_conf->beacon_interval == 0) cur_conf->beacon_interval = 100; + /* + * Some times we dont parse dtim period from mac80211, in that case + * use a default value + */ + if (cur_conf->dtim_period == 0) + cur_conf->dtim_period = 1; + switch (iftype) { case NL80211_IFTYPE_AP: ath_beacon_config_ap(sc, cur_conf); break; case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: - ath_beacon_config_adhoc(sc, cur_conf, vif); + ath_beacon_config_adhoc(sc, cur_conf); break; case NL80211_IFTYPE_STATION: ath_beacon_config_sta(sc, cur_conf); break; default: - ath_print(common, ATH_DBG_CONFIG, - "Unsupported beaconing mode\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "Unsupported beaconing mode\n"); return; } diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 6a92e57fddf0..d33bf204c995 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -35,29 +35,6 @@ struct ath_btcoex_config { bool bt_hold_rx_clear; }; -static const u16 ath_subsysid_tbl[] = { - AR9280_COEX2WIRE_SUBSYSID, - AT9285_COEX3WIRE_SA_SUBSYSID, - AT9285_COEX3WIRE_DA_SUBSYSID -}; - -/* - * Checks the subsystem id of the device to see if it - * supports btcoex - */ -bool ath9k_hw_btcoex_supported(struct ath_hw *ah) -{ - int i; - - if (!ah->hw_version.subsysid) - return false; - - for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++) - if (ah->hw_version.subsysid == ath_subsysid_tbl[i]) - return true; - - return false; -} void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) { diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 1ee5a15ccbb1..588dfd464dd1 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h @@ -49,7 +49,6 @@ struct ath_btcoex_hw { u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ }; -bool ath9k_hw_btcoex_supported(struct ath_hw *ah); void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah); void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah); void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum); diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 6d509484b5f6..b68a1acbddd0 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -97,12 +97,12 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, if (h[i].privNF > limit->max) { high_nf_mid = true; - ath_print(common, ATH_DBG_CALIBRATE, - "NFmid[%d] (%d) > MAX (%d), %s\n", - i, h[i].privNF, limit->max, - (cal->nfcal_interference ? - "not corrected (due to interference)" : - "correcting to MAX")); + ath_dbg(common, ATH_DBG_CALIBRATE, + "NFmid[%d] (%d) > MAX (%d), %s\n", + i, h[i].privNF, limit->max, + (cal->nfcal_interference ? + "not corrected (due to interference)" : + "correcting to MAX")); /* * Normally we limit the average noise floor by the @@ -180,18 +180,18 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah) return true; if (currCal->calState != CAL_DONE) { - ath_print(common, ATH_DBG_CALIBRATE, - "Calibration state incorrect, %d\n", - currCal->calState); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Calibration state incorrect, %d\n", + currCal->calState); return true; } if (!(ah->supp_cals & currCal->calData->calType)) return true; - ath_print(common, ATH_DBG_CALIBRATE, - "Resetting Cal %d state for channel %u\n", - currCal->calData->calType, conf->channel->center_freq); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Resetting Cal %d state for channel %u\n", + currCal->calData->calType, conf->channel->center_freq); ah->caldata->CalValid &= ~currCal->calData->calType; currCal->calState = CAL_WAITING; @@ -279,9 +279,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) * noisefloor until the next calibration timer. */ if (j == 1000) { - ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf " - "to load: AR_PHY_AGC_CONTROL=0x%x\n", - REG_READ(ah, AR_PHY_AGC_CONTROL)); + ath_dbg(common, ATH_DBG_ANY, + "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n", + REG_READ(ah, AR_PHY_AGC_CONTROL)); return; } @@ -318,19 +318,19 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) if (!nf[i]) continue; - ath_print(common, ATH_DBG_CALIBRATE, - "NF calibrated [%s] [chain %d] is %d\n", - (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]); + ath_dbg(common, ATH_DBG_CALIBRATE, + "NF calibrated [%s] [chain %d] is %d\n", + (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]); if (nf[i] > ATH9K_NF_TOO_HIGH) { - ath_print(common, ATH_DBG_CALIBRATE, - "NF[%d] (%d) > MAX (%d), correcting to MAX", - i, nf[i], ATH9K_NF_TOO_HIGH); + ath_dbg(common, ATH_DBG_CALIBRATE, + "NF[%d] (%d) > MAX (%d), correcting to MAX\n", + i, nf[i], ATH9K_NF_TOO_HIGH); nf[i] = limit->max; } else if (nf[i] < limit->min) { - ath_print(common, ATH_DBG_CALIBRATE, - "NF[%d] (%d) < MIN (%d), correcting to NOM", - i, nf[i], limit->min); + ath_dbg(common, ATH_DBG_CALIBRATE, + "NF[%d] (%d) < MIN (%d), correcting to NOM\n", + i, nf[i], limit->min); nf[i] = limit->nominal; } } @@ -347,8 +347,8 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) chan->channelFlags &= (~CHANNEL_CW_INT); if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { - ath_print(common, ATH_DBG_CALIBRATE, - "NF did not complete in calibration window\n"); + ath_dbg(common, ATH_DBG_CALIBRATE, + "NF did not complete in calibration window\n"); return false; } @@ -357,10 +357,9 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) nf = nfarray[0]; if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh) && nf > nfThresh) { - ath_print(common, ATH_DBG_CALIBRATE, - "noise floor failed detected; " - "detected %d, threshold %d\n", - nf, nfThresh); + ath_dbg(common, ATH_DBG_CALIBRATE, + "noise floor failed detected; detected %d, threshold %d\n", + nf, nfThresh); chan->channelFlags |= CHANNEL_CW_INT; } diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index f43a2d98421c..df1998d48253 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -107,12 +107,10 @@ static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, /* * Update internal channel flags. */ -void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, - struct ath9k_channel *ichan) +void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) { - struct ieee80211_channel *chan = hw->conf.channel; - struct ieee80211_conf *conf = &hw->conf; - ichan->channel = chan->center_freq; ichan->chan = chan; @@ -124,9 +122,8 @@ void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; } - if (conf_is_ht(conf)) - ichan->chanmode = ath9k_get_extchanmode(chan, - conf->channel_type); + if (channel_type != NL80211_CHAN_NO_HT) + ichan->chanmode = ath9k_get_extchanmode(chan, channel_type); } EXPORT_SYMBOL(ath9k_cmn_update_ichannel); @@ -142,7 +139,7 @@ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, chan_idx = curchan->hw_value; channel = &ah->channels[chan_idx]; - ath9k_cmn_update_ichannel(hw, channel); + ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type); return channel; } @@ -183,8 +180,8 @@ void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, AR_STOMP_NONE_WLAN_WGHT); break; default: - ath_print(common, ATH_DBG_BTCOEX, - "Invalid Stomptype\n"); + ath_dbg(common, ATH_DBG_BTCOEX, + "Invalid Stomptype\n"); break; } diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index fea3b3315391..a126bddebb0a 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -17,7 +17,6 @@ #include <net/mac80211.h> #include "../ath.h" -#include "../debug.h" #include "hw.h" #include "hw-ops.h" @@ -31,10 +30,11 @@ #define WME_MAX_BA WME_BA_BMP_SIZE #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) -#define WME_AC_BE 0 -#define WME_AC_BK 1 -#define WME_AC_VI 2 -#define WME_AC_VO 3 +/* These must match mac80211 skb queue mapping numbers */ +#define WME_AC_VO 0 +#define WME_AC_VI 1 +#define WME_AC_BE 2 +#define WME_AC_BK 3 #define WME_NUM_AC 4 #define ATH_RSSI_DUMMY_MARKER 0x127 @@ -62,8 +62,9 @@ enum ath_stomp_type { int ath9k_cmn_padpos(__le16 frame_control); int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); -void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, - struct ath9k_channel *ichan); +void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type); struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, struct ath_hw *ah); int ath9k_cmn_count_streams(unsigned int chainmask, int max); diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 43e71a944cb1..3586c43077a7 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -24,8 +24,6 @@ #define REG_READ_D(_ah, _reg) \ ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) -static struct dentry *ath9k_debugfs_root; - static int ath9k_debugfs_open(struct inode *inode, struct file *file) { file->private_data = inode->i_private; @@ -461,16 +459,16 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, /* Put variable-length stuff down here, and check for overflows. */ for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - if (aphy == NULL) + struct ath_wiphy *aphy_tmp = sc->sec_wiphy[i]; + if (aphy_tmp == NULL) continue; - chan = aphy->hw->conf.channel; + chan = aphy_tmp->hw->conf.channel; len += snprintf(buf + len, sizeof(buf) - len, "secondary: %s (%s chan=%d ht=%d)\n", - wiphy_name(aphy->hw->wiphy), - ath_wiphy_state_str(aphy->state), + wiphy_name(aphy_tmp->hw->wiphy), + ath_wiphy_state_str(aphy_tmp->state), ieee80211_frequency_to_channel(chan->center_freq), - aphy->chan_is_ht); + aphy_tmp->chan_is_ht); } if (len > sizeof(buf)) len = sizeof(buf); @@ -585,10 +583,10 @@ static const struct file_operations fops_wiphy = { do { \ len += snprintf(buf + len, size - len, \ "%s%13u%11u%10u%10u\n", str, \ - sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BE]].elem, \ - sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BK]].elem, \ - sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VI]].elem, \ - sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VO]].elem); \ + sc->debug.stats.txstats[WME_AC_BE].elem, \ + sc->debug.stats.txstats[WME_AC_BK].elem, \ + sc->debug.stats.txstats[WME_AC_VI].elem, \ + sc->debug.stats.txstats[WME_AC_VO].elem); \ } while(0) static ssize_t read_file_xmit(struct file *file, char __user *user_buf, @@ -630,33 +628,35 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, return retval; } -void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf, struct ath_tx_status *ts) +void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, + struct ath_tx_status *ts) { - TX_STAT_INC(txq->axq_qnum, tx_pkts_all); - sc->debug.stats.txstats[txq->axq_qnum].tx_bytes_all += bf->bf_mpdu->len; + int qnum = skb_get_queue_mapping(bf->bf_mpdu); + + TX_STAT_INC(qnum, tx_pkts_all); + sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len; if (bf_isampdu(bf)) { if (bf_isxretried(bf)) - TX_STAT_INC(txq->axq_qnum, a_xretries); + TX_STAT_INC(qnum, a_xretries); else - TX_STAT_INC(txq->axq_qnum, a_completed); + TX_STAT_INC(qnum, a_completed); } else { - TX_STAT_INC(txq->axq_qnum, completed); + TX_STAT_INC(qnum, completed); } if (ts->ts_status & ATH9K_TXERR_FIFO) - TX_STAT_INC(txq->axq_qnum, fifo_underrun); + TX_STAT_INC(qnum, fifo_underrun); if (ts->ts_status & ATH9K_TXERR_XTXOP) - TX_STAT_INC(txq->axq_qnum, xtxop); + TX_STAT_INC(qnum, xtxop); if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED) - TX_STAT_INC(txq->axq_qnum, timer_exp); + TX_STAT_INC(qnum, timer_exp); if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR) - TX_STAT_INC(txq->axq_qnum, desc_cfg_err); + TX_STAT_INC(qnum, desc_cfg_err); if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN) - TX_STAT_INC(txq->axq_qnum, data_underrun); + TX_STAT_INC(qnum, data_underrun); if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) - TX_STAT_INC(txq->axq_qnum, delim_underrun); + TX_STAT_INC(qnum, delim_underrun); } static const struct file_operations fops_xmit = { @@ -876,11 +876,8 @@ int ath9k_init_debug(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); struct ath_softc *sc = (struct ath_softc *) common->priv; - if (!ath9k_debugfs_root) - return -ENOENT; - - sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), - ath9k_debugfs_root); + sc->debug.debugfs_phy = debugfs_create_dir("ath9k", + sc->hw->wiphy->debugfsdir); if (!sc->debug.debugfs_phy) return -ENOMEM; @@ -933,29 +930,7 @@ int ath9k_init_debug(struct ath_hw *ah) sc->debug.regidx = 0; return 0; err: - ath9k_exit_debug(ah); - return -ENOMEM; -} - -void ath9k_exit_debug(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath_softc *sc = (struct ath_softc *) common->priv; - debugfs_remove_recursive(sc->debug.debugfs_phy); -} - -int ath9k_debug_create_root(void) -{ - ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (!ath9k_debugfs_root) - return -ENOENT; - - return 0; -} - -void ath9k_debug_remove_root(void) -{ - debugfs_remove(ath9k_debugfs_root); - ath9k_debugfs_root = NULL; + sc->debug.debugfs_phy = NULL; + return -ENOMEM; } diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index bb0823242ba0..1e5078bd0344 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -164,13 +164,10 @@ struct ath9k_debug { }; int ath9k_init_debug(struct ath_hw *ah); -void ath9k_exit_debug(struct ath_hw *ah); -int ath9k_debug_create_root(void); -void ath9k_debug_remove_root(void); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); -void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf, struct ath_tx_status *ts); +void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, + struct ath_tx_status *ts); void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); #else @@ -180,26 +177,12 @@ static inline int ath9k_init_debug(struct ath_hw *ah) return 0; } -static inline void ath9k_exit_debug(struct ath_hw *ah) -{ -} - -static inline int ath9k_debug_create_root(void) -{ - return 0; -} - -static inline void ath9k_debug_remove_root(void) -{ -} - static inline void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) { } static inline void ath_debug_stat_tx(struct ath_softc *sc, - struct ath_txq *txq, struct ath_buf *bf, struct ath_tx_status *ts) { diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index 2bbf94d0191e..d05163159572 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -234,7 +234,7 @@ void ath9k_hw_get_target_powers(struct ath_hw *ah, u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, bool is2GHz, int num_band_edges) { - u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + u16 twiceMaxEdgePower = MAX_RATE_POWER; int i; for (i = 0; (i < num_band_edges) && @@ -273,12 +273,225 @@ void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah) regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; break; default: - ath_print(common, ATH_DBG_EEPROM, - "Invalid chainmask configuration\n"); + ath_dbg(common, ATH_DBG_EEPROM, + "Invalid chainmask configuration\n"); break; } } +void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah, + struct ath9k_channel *chan, + void *pRawDataSet, + u8 *bChans, u16 availPiers, + u16 tPdGainOverlap, + u16 *pPdGainBoundaries, u8 *pPDADCValues, + u16 numXpdGains) +{ + int i, j, k; + int16_t ss; + u16 idxL = 0, idxR = 0, numPiers; + static u8 vpdTableL[AR5416_NUM_PD_GAINS] + [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + static u8 vpdTableR[AR5416_NUM_PD_GAINS] + [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + static u8 vpdTableI[AR5416_NUM_PD_GAINS] + [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + + u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; + u8 minPwrT4[AR5416_NUM_PD_GAINS]; + u8 maxPwrT4[AR5416_NUM_PD_GAINS]; + int16_t vpdStep; + int16_t tmpVal; + u16 sizeCurrVpdTable, maxIndex, tgtIndex; + bool match; + int16_t minDelta = 0; + struct chan_centers centers; + int pdgain_boundary_default; + struct cal_data_per_freq *data_def = pRawDataSet; + struct cal_data_per_freq_4k *data_4k = pRawDataSet; + struct cal_data_per_freq_ar9287 *data_9287 = pRawDataSet; + bool eeprom_4k = AR_SREV_9285(ah) || AR_SREV_9271(ah); + int intercepts; + + if (AR_SREV_9287(ah)) + intercepts = AR9287_PD_GAIN_ICEPTS; + else + intercepts = AR5416_PD_GAIN_ICEPTS; + + memset(&minPwrT4, 0, AR5416_NUM_PD_GAINS); + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + + for (numPiers = 0; numPiers < availPiers; numPiers++) { + if (bChans[numPiers] == AR5416_BCHAN_UNUSED) + break; + } + + match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center, + IS_CHAN_2GHZ(chan)), + bChans, numPiers, &idxL, &idxR); + + if (match) { + if (AR_SREV_9287(ah)) { + /* FIXME: array overrun? */ + for (i = 0; i < numXpdGains; i++) { + minPwrT4[i] = data_9287[idxL].pwrPdg[i][0]; + maxPwrT4[i] = data_9287[idxL].pwrPdg[i][4]; + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + data_9287[idxL].pwrPdg[i], + data_9287[idxL].vpdPdg[i], + intercepts, + vpdTableI[i]); + } + } else if (eeprom_4k) { + for (i = 0; i < numXpdGains; i++) { + minPwrT4[i] = data_4k[idxL].pwrPdg[i][0]; + maxPwrT4[i] = data_4k[idxL].pwrPdg[i][4]; + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + data_4k[idxL].pwrPdg[i], + data_4k[idxL].vpdPdg[i], + intercepts, + vpdTableI[i]); + } + } else { + for (i = 0; i < numXpdGains; i++) { + minPwrT4[i] = data_def[idxL].pwrPdg[i][0]; + maxPwrT4[i] = data_def[idxL].pwrPdg[i][4]; + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + data_def[idxL].pwrPdg[i], + data_def[idxL].vpdPdg[i], + intercepts, + vpdTableI[i]); + } + } + } else { + for (i = 0; i < numXpdGains; i++) { + if (AR_SREV_9287(ah)) { + pVpdL = data_9287[idxL].vpdPdg[i]; + pPwrL = data_9287[idxL].pwrPdg[i]; + pVpdR = data_9287[idxR].vpdPdg[i]; + pPwrR = data_9287[idxR].pwrPdg[i]; + } else if (eeprom_4k) { + pVpdL = data_4k[idxL].vpdPdg[i]; + pPwrL = data_4k[idxL].pwrPdg[i]; + pVpdR = data_4k[idxR].vpdPdg[i]; + pPwrR = data_4k[idxR].pwrPdg[i]; + } else { + pVpdL = data_def[idxL].vpdPdg[i]; + pPwrL = data_def[idxL].pwrPdg[i]; + pVpdR = data_def[idxR].vpdPdg[i]; + pPwrR = data_def[idxR].pwrPdg[i]; + } + + minPwrT4[i] = max(pPwrL[0], pPwrR[0]); + + maxPwrT4[i] = + min(pPwrL[intercepts - 1], + pPwrR[intercepts - 1]); + + + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + pPwrL, pVpdL, + intercepts, + vpdTableL[i]); + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + pPwrR, pVpdR, + intercepts, + vpdTableR[i]); + + for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { + vpdTableI[i][j] = + (u8)(ath9k_hw_interpolate((u16) + FREQ2FBIN(centers. + synth_center, + IS_CHAN_2GHZ + (chan)), + bChans[idxL], bChans[idxR], + vpdTableL[i][j], vpdTableR[i][j])); + } + } + } + + k = 0; + + for (i = 0; i < numXpdGains; i++) { + if (i == (numXpdGains - 1)) + pPdGainBoundaries[i] = + (u16)(maxPwrT4[i] / 2); + else + pPdGainBoundaries[i] = + (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); + + pPdGainBoundaries[i] = + min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]); + + if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { + minDelta = pPdGainBoundaries[0] - 23; + pPdGainBoundaries[0] = 23; + } else { + minDelta = 0; + } + + if (i == 0) { + if (AR_SREV_9280_20_OR_LATER(ah)) + ss = (int16_t)(0 - (minPwrT4[i] / 2)); + else + ss = 0; + } else { + 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); + + while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { + tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); + pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); + tgtIndex = (u8)(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); + + if (tgtIndex >= maxIndex) { + while ((ss <= tgtIndex) && + (k < (AR5416_NUM_PDADC_VALUES - 1))) { + tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + + (ss - maxIndex + 1) * vpdStep)); + pPDADCValues[k++] = (u8)((tmpVal > 255) ? + 255 : tmpVal); + ss++; + } + } + } + + if (eeprom_4k) + pdgain_boundary_default = 58; + else + pdgain_boundary_default = pPdGainBoundaries[i - 1]; + + while (i < AR5416_PD_GAINS_IN_MASK) { + pPdGainBoundaries[i] = pdgain_boundary_default; + i++; + } + + while (k < AR5416_NUM_PDADC_VALUES) { + pPDADCValues[k] = pPDADCValues[k - 1]; + k++; + } +} + int ath9k_hw_eeprom_init(struct ath_hw *ah) { int status; diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index dd59f09441a3..58e2ddc927a9 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -17,12 +17,12 @@ #ifndef EEPROM_H #define EEPROM_H +#define AR_EEPROM_MODAL_SPURS 5 + #include "../ath.h" #include <net/cfg80211.h> #include "ar9003_eeprom.h" -#define AH_USE_EEPROM 0x1 - #ifdef __BIG_ENDIAN #define AR5416_EEPROM_MAGIC 0x5aa5 #else @@ -149,8 +149,6 @@ #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_BCHAN_UNUSED 0xFF #define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 @@ -175,8 +173,6 @@ #define AR5416_EEP4K_NUM_CTLS 12 #define AR5416_EEP4K_NUM_BAND_EDGES 4 #define AR5416_EEP4K_NUM_PD_GAINS 2 -#define AR5416_EEP4K_PD_GAINS_IN_MASK 4 -#define AR5416_EEP4K_PD_GAIN_ICEPTS 5 #define AR5416_EEP4K_MAX_CHAINS 1 #define AR9280_TX_GAIN_TABLE_SIZE 22 @@ -198,35 +194,12 @@ #define AR9287_NUM_2G_40_TARGET_POWERS 3 #define AR9287_NUM_CTLS 12 #define AR9287_NUM_BAND_EDGES 4 -#define AR9287_NUM_PD_GAINS 4 -#define AR9287_PD_GAINS_IN_MASK 4 #define AR9287_PD_GAIN_ICEPTS 1 -#define AR9287_EEPROM_MODAL_SPURS 5 -#define AR9287_MAX_RATE_POWER 63 -#define AR9287_NUM_PDADC_VALUES 128 -#define AR9287_NUM_RATES 16 -#define AR9287_BCHAN_UNUSED 0xFF -#define AR9287_MAX_PWR_RANGE_IN_HALF_DB 64 -#define AR9287_OPFLAGS_11A 0x01 -#define AR9287_OPFLAGS_11G 0x02 -#define AR9287_OPFLAGS_2G_HT40 0x08 -#define AR9287_OPFLAGS_2G_HT20 0x20 -#define AR9287_OPFLAGS_5G_HT40 0x04 -#define AR9287_OPFLAGS_5G_HT20 0x10 #define AR9287_EEPMISC_BIG_ENDIAN 0x01 #define AR9287_EEPMISC_WOW 0x02 #define AR9287_MAX_CHAINS 2 #define AR9287_ANT_16S 32 -#define AR9287_custdatasize 20 - -#define AR9287_NUM_ANT_CHAIN_FIELDS 6 -#define AR9287_NUM_ANT_COMMON_FIELDS 4 -#define AR9287_SIZE_ANT_CHAIN_FIELD 2 -#define AR9287_SIZE_ANT_COMMON_FIELD 4 -#define AR9287_ANT_CHAIN_MASK 0x3 -#define AR9287_ANT_COMMON_MASK 0xf -#define AR9287_CHAIN_0_IDX 0 -#define AR9287_CHAIN_1_IDX 1 + #define AR9287_DATA_SZ 32 #define AR9287_PWR_TABLE_OFFSET_DB -5 @@ -280,6 +253,7 @@ enum eeprom_param { EEP_PAPRD, EEP_MODAL_VER, EEP_ANT_DIV_CTL1, + EEP_CHAIN_MASK_REDUCE }; enum ar5416_rates { @@ -395,7 +369,7 @@ struct modal_eep_header { u16 xpaBiasLvlFreq[3]; u8 futureModal[6]; - struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; + struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS]; } __packed; struct calDataPerFreqOpLoop { @@ -463,7 +437,7 @@ struct modal_eep_4k_header { u8 db2_4:4, reserved:4; #endif u8 futureModal[4]; - struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; + struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS]; } __packed; struct base_eep_ar9287_header { @@ -521,7 +495,7 @@ struct modal_eep_ar9287_header { u8 ob_qam; u8 ob_pal_off; u8 futureModal[30]; - struct spur_chan spurChans[AR9287_EEPROM_MODAL_SPURS]; + struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS]; } __packed; struct cal_data_per_freq { @@ -530,8 +504,8 @@ struct cal_data_per_freq { } __packed; struct cal_data_per_freq_4k { - u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS]; - u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS]; + u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; + u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; } __packed; struct cal_target_power_leg { @@ -557,8 +531,8 @@ struct cal_data_op_loop_ar9287 { } __packed; struct cal_data_per_freq_ar9287 { - u8 pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; - u8 vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; + u8 pwrPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; + u8 vpdPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; } __packed; union cal_data_per_freq_ar9287_u { @@ -673,15 +647,12 @@ struct eeprom_ops { bool (*fill_eeprom)(struct ath_hw *hw); int (*get_eeprom_ver)(struct ath_hw *hw); int (*get_eeprom_rev)(struct ath_hw *hw); - u8 (*get_num_ant_config)(struct ath_hw *hw, - enum ath9k_hal_freq_band band); - u32 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, - struct ath9k_channel *chan); void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, u16 cfgCtl, u8 twiceAntennaReduction, - u8 twiceMaxRegulatoryPower, u8 powerLimit); + u8 twiceMaxRegulatoryPower, u8 powerLimit, + bool test); u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); }; @@ -714,6 +685,14 @@ u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah); int ath9k_hw_eeprom_init(struct ath_hw *ah); +void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah, + struct ath9k_channel *chan, + void *pRawDataSet, + u8 *bChans, u16 availPiers, + u16 tPdGainOverlap, + u16 *pPdGainBoundaries, u8 *pPDADCValues, + u16 numXpdGains); + #define ar5416_get_ntxchains(_txchainmask) \ (((_txchainmask >> 2) & 1) + \ ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 4fa4d8e28c64..fbdff7e47952 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -37,14 +37,14 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) eep_start_loc = 64; if (!ath9k_hw_use_flash(ah)) { - ath_print(common, ATH_DBG_EEPROM, - "Reading from EEPROM, not flash\n"); + ath_dbg(common, ATH_DBG_EEPROM, + "Reading from EEPROM, not flash\n"); } for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) { - ath_print(common, ATH_DBG_EEPROM, - "Unable to read eeprom region\n"); + ath_dbg(common, ATH_DBG_EEPROM, + "Unable to read eeprom region\n"); return false; } eep_data++; @@ -69,13 +69,12 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) if (!ath9k_hw_use_flash(ah)) { if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { - ath_print(common, ATH_DBG_FATAL, - "Reading Magic # failed\n"); + ath_err(common, "Reading Magic # failed\n"); return false; } - ath_print(common, ATH_DBG_EEPROM, - "Read Magic = 0x%04X\n", magic); + ath_dbg(common, ATH_DBG_EEPROM, + "Read Magic = 0x%04X\n", magic); if (magic != AR5416_EEPROM_MAGIC) { magic2 = swab16(magic); @@ -90,16 +89,15 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) eepdata++; } } else { - ath_print(common, ATH_DBG_FATAL, - "Invalid EEPROM Magic. " - "endianness mismatch.\n"); + ath_err(common, + "Invalid EEPROM Magic. Endianness mismatch.\n"); return -EINVAL; } } } - ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", - need_swap ? "True" : "False"); + ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n", + need_swap ? "True" : "False"); if (need_swap) el = swab16(ah->eeprom.map4k.baseEepHeader.length); @@ -120,8 +118,8 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) u32 integer; u16 word; - ath_print(common, ATH_DBG_EEPROM, - "EEPROM Endianness is not native.. Changing\n"); + ath_dbg(common, ATH_DBG_EEPROM, + "EEPROM Endianness is not native.. Changing\n"); word = swab16(eep->baseEepHeader.length); eep->baseEepHeader.length = word; @@ -155,7 +153,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) eep->modalHeader.antCtrlChain[i] = integer; } - for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { word = swab16(eep->modalHeader.spurChans[i].spurChan); eep->modalHeader.spurChans[i].spurChan = word; } @@ -163,9 +161,8 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { - ath_print(common, ATH_DBG_FATAL, - "Bad EEPROM checksum 0x%x or revision 0x%04x\n", - sum, ah->eep_ops->get_eeprom_ver(ah)); + ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", + sum, ah->eep_ops->get_eeprom_ver(ah)); return -EINVAL; } @@ -230,173 +227,6 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, } } -static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_data_per_freq_4k *pRawDataSet, - u8 *bChans, u16 availPiers, - u16 tPdGainOverlap, - u16 *pPdGainBoundaries, u8 *pPDADCValues, - u16 numXpdGains) -{ -#define TMP_VAL_VPD_TABLE \ - ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); - int i, j, k; - int16_t ss; - u16 idxL = 0, idxR = 0, numPiers; - static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - - u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; - u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; - u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; - int16_t vpdStep; - int16_t tmpVal; - u16 sizeCurrVpdTable, maxIndex, tgtIndex; - bool match; - int16_t minDelta = 0; - struct chan_centers centers; -#define PD_GAIN_BOUNDARY_DEFAULT 58; - - memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS); - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - for (numPiers = 0; numPiers < availPiers; numPiers++) { - if (bChans[numPiers] == AR5416_BCHAN_UNUSED) - break; - } - - match = ath9k_hw_get_lower_upper_index( - (u8)FREQ2FBIN(centers.synth_center, - IS_CHAN_2GHZ(chan)), bChans, numPiers, - &idxL, &idxR); - - if (match) { - for (i = 0; i < numXpdGains; i++) { - minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; - maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pRawDataSet[idxL].pwrPdg[i], - pRawDataSet[idxL].vpdPdg[i], - AR5416_EEP4K_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]; - - minPwrT4[i] = max(pPwrL[0], pPwrR[0]); - - maxPwrT4[i] = - min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1], - pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]); - - - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrL, pVpdL, - AR5416_EEP4K_PD_GAIN_ICEPTS, - vpdTableL[i]); - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrR, pVpdR, - AR5416_EEP4K_PD_GAIN_ICEPTS, - vpdTableR[i]); - - for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { - vpdTableI[i][j] = - (u8)(ath9k_hw_interpolate((u16) - FREQ2FBIN(centers. - synth_center, - IS_CHAN_2GHZ - (chan)), - bChans[idxL], bChans[idxR], - vpdTableL[i][j], vpdTableR[i][j])); - } - } - } - - k = 0; - - for (i = 0; i < numXpdGains; i++) { - if (i == (numXpdGains - 1)) - pPdGainBoundaries[i] = - (u16)(maxPwrT4[i] / 2); - else - pPdGainBoundaries[i] = - (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); - - pPdGainBoundaries[i] = - min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); - - if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { - minDelta = pPdGainBoundaries[0] - 23; - pPdGainBoundaries[0] = 23; - } else { - minDelta = 0; - } - - if (i == 0) { - if (AR_SREV_9280_20_OR_LATER(ah)) - ss = (int16_t)(0 - (minPwrT4[i] / 2)); - else - ss = 0; - } else { - 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); - - while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); - pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); - ss++; - } - - sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); - tgtIndex = (u8)(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); - - if (tgtIndex >= maxIndex) { - while ((ss <= tgtIndex) && - (k < (AR5416_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t) TMP_VAL_VPD_TABLE; - pPDADCValues[k++] = (u8)((tmpVal > 255) ? - 255 : tmpVal); - ss++; - } - } - } - - while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) { - pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT; - i++; - } - - while (k < AR5416_NUM_PDADC_VALUES) { - pPDADCValues[k] = pPDADCValues[k - 1]; - k++; - } - - return; -#undef TMP_VAL_VPD_TABLE -} - static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset) @@ -407,7 +237,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, u8 *pCalBChans = NULL; u16 pdGainOverlap_t2; static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; - u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK]; + u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; u16 numPiers, i, j; u16 numXpdGain, xpdMask; u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 }; @@ -429,12 +259,12 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, numXpdGain = 0; - for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) { - if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) { + for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { + if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS) break; xpdGainValues[numXpdGain] = - (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i); + (u16)(AR5416_PD_GAINS_IN_MASK - i); numXpdGain++; } } @@ -458,7 +288,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, if (pEepData->baseEepHeader.txMask & (1 << i)) { pRawDataset = pEepData->calPierData2G[i]; - ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan, + ath9k_hw_get_gain_boundaries_pdadcs(ah, chan, pRawDataset, pCalBChans, numPiers, pdGainOverlap_t2, gainBoundaries, @@ -488,21 +318,20 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, ((pdadcValues[4 * j + 3] & 0xFF) << 24); REG_WRITE(ah, regOffset, reg32); - ath_print(common, ATH_DBG_EEPROM, - "PDADC (%d,%4x): %4.4x %8.8x\n", - i, regChainOffset, regOffset, - reg32); - ath_print(common, ATH_DBG_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]); + ath_dbg(common, ATH_DBG_EEPROM, + "PDADC (%d,%4x): %4.4x %8.8x\n", + i, regChainOffset, regOffset, + reg32); + ath_dbg(common, ATH_DBG_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; } @@ -532,14 +361,16 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, int i; int16_t twiceLargestAntenna; u16 twiceMinEdgePower; - u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + u16 twiceMaxEdgePower = MAX_RATE_POWER; u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 numCtlModes, *pCtlMode, ctlMode, freq; + u16 numCtlModes; + const u16 *pCtlMode; + u16 ctlMode, freq; struct chan_centers centers; struct cal_ctl_data_4k *rep; struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; static const u16 tpScaleReductionTable[5] = - { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; + { 0, 3, 6, 9, MAX_RATE_POWER }; struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { 0, { 0, 0, 0, 0} }; @@ -550,10 +381,10 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { 0, {0, 0, 0, 0} }; - u16 ctlModesFor11g[] = - { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, - CTL_2GHT40 - }; + static const u16 ctlModesFor11g[] = { + CTL_11B, CTL_11G, CTL_2GHT20, + CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 + }; ath9k_hw_get_channel_centers(ah, chan, ¢ers); @@ -615,7 +446,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, if (ah->eep_ops->get_eeprom_ver(ah) == 14 && ah->eep_ops->get_eeprom_rev(ah) <= 2) - twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + twiceMaxEdgePower = MAX_RATE_POWER; for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { @@ -726,7 +557,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, u16 cfgCtl, u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower, - u8 powerLimit) + u8 powerLimit, bool test) { struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; @@ -751,15 +582,20 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset); + regulatory->max_power_level = 0; for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); - if (ratesArray[i] > AR5416_MAX_RATE_POWER) - ratesArray[i] = AR5416_MAX_RATE_POWER; + if (ratesArray[i] > MAX_RATE_POWER) + ratesArray[i] = MAX_RATE_POWER; + + if (ratesArray[i] > regulatory->max_power_level) + regulatory->max_power_level = ratesArray[i]; } + if (test) + return; /* Update regulatory */ - i = rate6mb; if (IS_CHAN_HT40(chan)) i = rateHt40_0; @@ -934,8 +770,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, pModal = &eep->modalHeader; txRxAttenLocal = 23; - REG_WRITE(ah, AR_PHY_SWITCH_COM, - ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); + REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); /* Single chain for 4K EEPROM*/ ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal); @@ -1151,21 +986,6 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, } } -static u32 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; - struct modal_eep_4k_header *pModal = &eep->modalHeader; - - return pModal->antCtrlCommon; -} - -static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah, - enum ath9k_hal_freq_band freq_band) -{ - return 1; -} - static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) { #define EEP_MAP4K_SPURCHAN \ @@ -1174,17 +994,17 @@ static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) u16 spur_val = AR_NO_SPUR; - ath_print(common, ATH_DBG_ANI, - "Getting spur idx %d is2Ghz. %d val %x\n", - i, is2GHz, ah->config.spurchans[i][is2GHz]); + ath_dbg(common, ATH_DBG_ANI, + "Getting spur idx:%d is2Ghz:%d val:%x\n", + i, is2GHz, ah->config.spurchans[i][is2GHz]); switch (ah->config.spurmode) { case SPUR_DISABLE: break; case SPUR_ENABLE_IOCTL: spur_val = ah->config.spurchans[i][is2GHz]; - ath_print(common, ATH_DBG_ANI, - "Getting spur val from new loc. %d\n", spur_val); + ath_dbg(common, ATH_DBG_ANI, + "Getting spur val from new loc. %d\n", spur_val); break; case SPUR_ENABLE_EEPROM: spur_val = EEP_MAP4K_SPURCHAN; @@ -1202,8 +1022,6 @@ const struct eeprom_ops eep_4k_ops = { .fill_eeprom = ath9k_hw_4k_fill_eeprom, .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver, .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, - .get_num_ant_config = ath9k_hw_4k_get_num_ant_config, - .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg, .set_board_values = ath9k_hw_4k_set_board_values, .set_addac = ath9k_hw_4k_set_addac, .set_txpower = ath9k_hw_4k_set_txpower, diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 195406db3bd8..9b6bc8a953bc 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -37,21 +37,21 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) int addr, eep_start_loc; eep_data = (u16 *)eep; - if (AR9287_HTC_DEVID(ah)) + if (common->bus_ops->ath_bus_type == ATH_USB) eep_start_loc = AR9287_HTC_EEP_START_LOC; else eep_start_loc = AR9287_EEP_START_LOC; if (!ath9k_hw_use_flash(ah)) { - ath_print(common, ATH_DBG_EEPROM, - "Reading from EEPROM, not flash\n"); + ath_dbg(common, ATH_DBG_EEPROM, + "Reading from EEPROM, not flash\n"); } for (addr = 0; addr < NUM_EEP_WORDS; addr++) { if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) { - ath_print(common, ATH_DBG_EEPROM, - "Unable to read eeprom region\n"); + ath_dbg(common, ATH_DBG_EEPROM, + "Unable to read eeprom region\n"); return false; } eep_data++; @@ -72,13 +72,12 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) if (!ath9k_hw_use_flash(ah)) { if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { - ath_print(common, ATH_DBG_FATAL, - "Reading Magic # failed\n"); + ath_err(common, "Reading Magic # failed\n"); return false; } - ath_print(common, ATH_DBG_EEPROM, - "Read Magic = 0x%04X\n", magic); + ath_dbg(common, ATH_DBG_EEPROM, + "Read Magic = 0x%04X\n", magic); if (magic != AR5416_EEPROM_MAGIC) { magic2 = swab16(magic); @@ -93,16 +92,15 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) eepdata++; } } else { - ath_print(common, ATH_DBG_FATAL, - "Invalid EEPROM Magic. " - "Endianness mismatch.\n"); + ath_err(common, + "Invalid EEPROM Magic. Endianness mismatch.\n"); return -EINVAL; } } } - ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", - need_swap ? "True" : "False"); + ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n", + need_swap ? "True" : "False"); if (need_swap) el = swab16(ah->eeprom.map9287.baseEepHeader.length); @@ -152,7 +150,7 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) eep->modalHeader.antCtrlChain[i] = integer; } - for (i = 0; i < AR9287_EEPROM_MODAL_SPURS; i++) { + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { word = swab16(eep->modalHeader.spurChans[i].spurChan); eep->modalHeader.spurChans[i].spurChan = word; } @@ -160,9 +158,8 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { - ath_print(common, ATH_DBG_FATAL, - "Bad EEPROM checksum 0x%x or revision 0x%04x\n", - sum, ah->eep_ops->get_eeprom_ver(ah)); + ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", + sum, ah->eep_ops->get_eeprom_ver(ah)); return -EINVAL; } @@ -223,163 +220,6 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah, } } -static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_data_per_freq_ar9287 *pRawDataSet, - u8 *bChans, u16 availPiers, - u16 tPdGainOverlap, - u16 *pPdGainBoundaries, - u8 *pPDADCValues, - u16 numXpdGains) -{ -#define TMP_VAL_VPD_TABLE \ - ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); - - int i, j, k; - int16_t ss; - u16 idxL = 0, idxR = 0, numPiers; - u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; - u8 minPwrT4[AR9287_NUM_PD_GAINS]; - u8 maxPwrT4[AR9287_NUM_PD_GAINS]; - int16_t vpdStep; - int16_t tmpVal; - u16 sizeCurrVpdTable, maxIndex, tgtIndex; - bool match; - int16_t minDelta = 0; - struct chan_centers centers; - static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - - memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS); - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - for (numPiers = 0; numPiers < availPiers; numPiers++) { - if (bChans[numPiers] == AR9287_BCHAN_UNUSED) - break; - } - - match = ath9k_hw_get_lower_upper_index( - (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), - bChans, numPiers, &idxL, &idxR); - - if (match) { - for (i = 0; i < numXpdGains; i++) { - minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; - maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pRawDataSet[idxL].pwrPdg[i], - pRawDataSet[idxL].vpdPdg[i], - AR9287_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]; - - minPwrT4[i] = max(pPwrL[0], pPwrR[0]); - - maxPwrT4[i] = min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1], - pPwrR[AR9287_PD_GAIN_ICEPTS - 1]); - - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrL, pVpdL, - AR9287_PD_GAIN_ICEPTS, - vpdTableL[i]); - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrR, pVpdR, - AR9287_PD_GAIN_ICEPTS, - vpdTableR[i]); - - for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { - vpdTableI[i][j] = (u8)(ath9k_hw_interpolate( - (u16)FREQ2FBIN(centers. synth_center, - IS_CHAN_2GHZ(chan)), - bChans[idxL], bChans[idxR], - vpdTableL[i][j], vpdTableR[i][j])); - } - } - } - - k = 0; - - for (i = 0; i < numXpdGains; i++) { - if (i == (numXpdGains - 1)) - pPdGainBoundaries[i] = - (u16)(maxPwrT4[i] / 2); - else - pPdGainBoundaries[i] = - (u16)((maxPwrT4[i] + minPwrT4[i+1]) / 4); - - pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER, - pPdGainBoundaries[i]); - - - minDelta = 0; - - if (i == 0) { - if (AR_SREV_9280_20_OR_LATER(ah)) - ss = (int16_t)(0 - (minPwrT4[i] / 2)); - else - ss = 0; - } else { - 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); - - while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); - pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); - ss++; - } - - sizeCurrVpdTable = (u8)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); - tgtIndex = (u8)(pPdGainBoundaries[i] + - tPdGainOverlap - (minPwrT4[i] / 2)); - maxIndex = (tgtIndex < sizeCurrVpdTable) ? - tgtIndex : sizeCurrVpdTable; - - while ((ss < maxIndex) && (k < (AR9287_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); - - if (tgtIndex > maxIndex) { - while ((ss <= tgtIndex) && - (k < (AR9287_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t) TMP_VAL_VPD_TABLE; - pPDADCValues[k++] = - (u8)((tmpVal > 255) ? 255 : tmpVal); - ss++; - } - } - } - - while (i < AR9287_PD_GAINS_IN_MASK) { - pPdGainBoundaries[i] = pPdGainBoundaries[i-1]; - i++; - } - - while (k < AR9287_NUM_PDADC_VALUES) { - pPDADCValues[k] = pPDADCValues[k-1]; - k++; - } - -#undef TMP_VAL_VPD_TABLE -} - static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, struct ath9k_channel *chan, struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, @@ -392,7 +232,7 @@ static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, ath9k_hw_get_channel_centers(ah, chan, ¢ers); for (numPiers = 0; numPiers < availPiers; numPiers++) { - if (pCalChans[numPiers] == AR9287_BCHAN_UNUSED) + if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED) break; } @@ -458,11 +298,11 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; u8 *pCalBChans = NULL; u16 pdGainOverlap_t2; - u8 pdadcValues[AR9287_NUM_PDADC_VALUES]; - u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK]; + u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; + u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; u16 numPiers = 0, i, j; u16 numXpdGain, xpdMask; - u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; + u16 xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0}; u32 reg32, regOffset, regChainOffset, regval; int16_t modalIdx, diff = 0; struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; @@ -490,12 +330,12 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, numXpdGain = 0; /* Calculate the value of xpdgains from the xpdGain Mask */ - for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) { - if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) { - if (numXpdGain >= AR9287_NUM_PD_GAINS) + 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] = - (u16)(AR9287_PD_GAINS_IN_MASK-i); + (u16)(AR5416_PD_GAINS_IN_MASK-i); numXpdGain++; } } @@ -528,7 +368,7 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, (struct cal_data_per_freq_ar9287 *) pEepData->calPierData2G[i]; - ath9k_hw_get_ar9287_gain_boundaries_pdadcs(ah, chan, + ath9k_hw_get_gain_boundaries_pdadcs(ah, chan, pRawDataset, pCalBChans, numPiers, pdGainOverlap_t2, @@ -564,13 +404,13 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, (int32_t)AR9287_PWR_TABLE_OFFSET_DB); diff *= 2; - for (j = 0; j < ((u16)AR9287_NUM_PDADC_VALUES-diff); j++) + for (j = 0; j < ((u16)AR5416_NUM_PDADC_VALUES-diff); j++) pdadcValues[j] = pdadcValues[j+diff]; - for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff); - j < AR9287_NUM_PDADC_VALUES; j++) + for (j = (u16)(AR5416_NUM_PDADC_VALUES-diff); + j < AR5416_NUM_PDADC_VALUES; j++) pdadcValues[j] = - pdadcValues[AR9287_NUM_PDADC_VALUES-diff]; + pdadcValues[AR5416_NUM_PDADC_VALUES-diff]; } if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { @@ -613,9 +453,9 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + u16 twiceMaxEdgePower = MAX_RATE_POWER; static const u16 tpScaleReductionTable[5] = - { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; + { 0, 3, 6, 9, MAX_RATE_POWER }; int i; int16_t twiceLargestAntenna; struct cal_ctl_data_ar9287 *rep; @@ -626,13 +466,13 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {0, {0, 0, 0, 0} }; u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 ctlModesFor11g[] = {CTL_11B, - CTL_11G, - CTL_2GHT20, - CTL_11B_EXT, - CTL_11G_EXT, - CTL_2GHT40}; - u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq; + static const u16 ctlModesFor11g[] = { + CTL_11B, CTL_11G, CTL_2GHT20, + CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 + }; + u16 numCtlModes = 0; + const u16 *pCtlMode = NULL; + u16 ctlMode, freq; struct chan_centers centers; int tx_chainmask; u16 twiceMinEdgePower; @@ -853,7 +693,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, struct ath9k_channel *chan, u16 cfgCtl, u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower, - u8 powerLimit) + u8 powerLimit, bool test) { struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; @@ -877,12 +717,26 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset); + regulatory->max_power_level = 0; for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); - if (ratesArray[i] > AR9287_MAX_RATE_POWER) - ratesArray[i] = AR9287_MAX_RATE_POWER; + if (ratesArray[i] > MAX_RATE_POWER) + ratesArray[i] = MAX_RATE_POWER; + + if (ratesArray[i] > regulatory->max_power_level) + regulatory->max_power_level = ratesArray[i]; } + if (test) + return; + + if (IS_CHAN_2GHZ(chan)) + i = rate1l; + else + i = rate6mb; + + regulatory->max_power_level = ratesArray[i]; + if (AR_SREV_9280_20_OR_LATER(ah)) { for (i = 0; i < Ar5416RateSize; i++) ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; @@ -971,17 +825,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); } - - if (IS_CHAN_2GHZ(chan)) - i = rate1l; - else - i = rate6mb; - - if (AR_SREV_9280_20_OR_LATER(ah)) - regulatory->max_power_level = - ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; - else - regulatory->max_power_level = ratesArray[i]; } static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, @@ -1023,8 +866,7 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3); } - REG_WRITE(ah, AR_PHY_SWITCH_COM, - ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); + REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); for (i = 0; i < AR9287_MAX_CHAINS; i++) { regChainOffset = i * 0x1000; @@ -1125,21 +967,6 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, pModal->xpaBiasLvl); } -static u8 ath9k_hw_ar9287_get_num_ant_config(struct ath_hw *ah, - enum ath9k_hal_freq_band freq_band) -{ - return 1; -} - -static u32 ath9k_hw_ar9287_get_eeprom_antenna_cfg(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct ar9287_eeprom *eep = &ah->eeprom.map9287; - struct modal_eep_ar9287_header *pModal = &eep->modalHeader; - - return pModal->antCtrlCommon; -} - static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) { @@ -1149,17 +976,17 @@ static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah, struct ath_common *common = ath9k_hw_common(ah); u16 spur_val = AR_NO_SPUR; - ath_print(common, ATH_DBG_ANI, - "Getting spur idx %d is2Ghz. %d val %x\n", - i, is2GHz, ah->config.spurchans[i][is2GHz]); + ath_dbg(common, ATH_DBG_ANI, + "Getting spur idx:%d is2Ghz:%d val:%x\n", + i, is2GHz, ah->config.spurchans[i][is2GHz]); switch (ah->config.spurmode) { case SPUR_DISABLE: break; case SPUR_ENABLE_IOCTL: spur_val = ah->config.spurchans[i][is2GHz]; - ath_print(common, ATH_DBG_ANI, - "Getting spur val from new loc. %d\n", spur_val); + ath_dbg(common, ATH_DBG_ANI, + "Getting spur val from new loc. %d\n", spur_val); break; case SPUR_ENABLE_EEPROM: spur_val = EEP_MAP9287_SPURCHAN; @@ -1177,8 +1004,6 @@ const struct eeprom_ops eep_ar9287_ops = { .fill_eeprom = ath9k_hw_ar9287_fill_eeprom, .get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver, .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev, - .get_num_ant_config = ath9k_hw_ar9287_get_num_ant_config, - .get_eeprom_antenna_cfg = ath9k_hw_ar9287_get_eeprom_antenna_cfg, .set_board_values = ath9k_hw_ar9287_set_board_values, .set_addac = ath9k_hw_ar9287_set_addac, .set_txpower = ath9k_hw_ar9287_set_txpower, diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index a3ccb1b9638d..088f141f2006 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -96,8 +96,8 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { if (!ath9k_hw_nvram_read(common, addr + ar5416_eep_start_loc, eep_data)) { - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "Unable to read eeprom region\n"); + ath_err(ath9k_hw_common(ah), + "Unable to read eeprom region\n"); return false; } eep_data++; @@ -117,13 +117,13 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) int i, addr, size; if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { - ath_print(common, ATH_DBG_FATAL, "Reading Magic # failed\n"); + ath_err(common, "Reading Magic # failed\n"); return false; } if (!ath9k_hw_use_flash(ah)) { - ath_print(common, ATH_DBG_EEPROM, - "Read Magic = 0x%04X\n", magic); + ath_dbg(common, ATH_DBG_EEPROM, + "Read Magic = 0x%04X\n", magic); if (magic != AR5416_EEPROM_MAGIC) { magic2 = swab16(magic); @@ -139,16 +139,15 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) eepdata++; } } else { - ath_print(common, ATH_DBG_FATAL, - "Invalid EEPROM Magic. " - "Endianness mismatch.\n"); + ath_err(common, + "Invalid EEPROM Magic. Endianness mismatch.\n"); return -EINVAL; } } } - ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", - need_swap ? "True" : "False"); + ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n", + need_swap ? "True" : "False"); if (need_swap) el = swab16(ah->eeprom.def.baseEepHeader.length); @@ -169,8 +168,8 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) u32 integer, j; u16 word; - ath_print(common, ATH_DBG_EEPROM, - "EEPROM Endianness is not native.. Changing.\n"); + ath_dbg(common, ATH_DBG_EEPROM, + "EEPROM Endianness is not native.. Changing.\n"); word = swab16(eep->baseEepHeader.length); eep->baseEepHeader.length = word; @@ -207,7 +206,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) pModal->antCtrlChain[i] = integer; } - for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { word = swab16(pModal->spurChans[i].spurChan); pModal->spurChans[i].spurChan = word; } @@ -216,8 +215,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { - ath_print(common, ATH_DBG_FATAL, - "Bad EEPROM checksum 0x%x or revision 0x%04x\n", + ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", sum, ah->eep_ops->get_eeprom_ver(ah)); return -EINVAL; } @@ -376,8 +374,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; - REG_WRITE(ah, AR_PHY_SWITCH_COM, - ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); + REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon & 0xffff); for (i = 0; i < AR5416_MAX_CHAINS; i++) { if (AR_SREV_9280(ah)) { @@ -590,168 +587,6 @@ static void ath9k_hw_def_set_addac(struct ath_hw *ah, #undef XPA_LVL_FREQ } -static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_data_per_freq *pRawDataSet, - u8 *bChans, u16 availPiers, - u16 tPdGainOverlap, - u16 *pPdGainBoundaries, u8 *pPDADCValues, - u16 numXpdGains) -{ - int i, j, k; - int16_t ss; - u16 idxL = 0, idxR = 0, numPiers; - static u8 vpdTableL[AR5416_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableR[AR5416_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableI[AR5416_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - - u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; - u8 minPwrT4[AR5416_NUM_PD_GAINS]; - u8 maxPwrT4[AR5416_NUM_PD_GAINS]; - int16_t vpdStep; - int16_t tmpVal; - u16 sizeCurrVpdTable, maxIndex, tgtIndex; - bool match; - int16_t minDelta = 0; - struct chan_centers centers; - - memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS); - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - for (numPiers = 0; numPiers < availPiers; numPiers++) { - if (bChans[numPiers] == AR5416_BCHAN_UNUSED) - break; - } - - match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center, - IS_CHAN_2GHZ(chan)), - bChans, numPiers, &idxL, &idxR); - - if (match) { - for (i = 0; i < numXpdGains; i++) { - minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; - maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; - ath9k_hw_fill_vpd_table(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]; - - minPwrT4[i] = max(pPwrL[0], pPwrR[0]); - - maxPwrT4[i] = - min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], - pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); - - - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrL, pVpdL, - AR5416_PD_GAIN_ICEPTS, - vpdTableL[i]); - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrR, pVpdR, - AR5416_PD_GAIN_ICEPTS, - vpdTableR[i]); - - for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { - vpdTableI[i][j] = - (u8)(ath9k_hw_interpolate((u16) - FREQ2FBIN(centers. - synth_center, - IS_CHAN_2GHZ - (chan)), - bChans[idxL], bChans[idxR], - vpdTableL[i][j], vpdTableR[i][j])); - } - } - } - - k = 0; - - for (i = 0; i < numXpdGains; i++) { - if (i == (numXpdGains - 1)) - pPdGainBoundaries[i] = - (u16)(maxPwrT4[i] / 2); - else - pPdGainBoundaries[i] = - (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); - - pPdGainBoundaries[i] = - min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); - - if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { - minDelta = pPdGainBoundaries[0] - 23; - pPdGainBoundaries[0] = 23; - } else { - minDelta = 0; - } - - if (i == 0) { - if (AR_SREV_9280_20_OR_LATER(ah)) - ss = (int16_t)(0 - (minPwrT4[i] / 2)); - else - ss = 0; - } else { - 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); - - while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); - pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); - ss++; - } - - sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); - tgtIndex = (u8)(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); - - if (tgtIndex >= maxIndex) { - while ((ss <= tgtIndex) && - (k < (AR5416_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + - (ss - maxIndex + 1) * vpdStep)); - pPDADCValues[k++] = (u8)((tmpVal > 255) ? - 255 : tmpVal); - ss++; - } - } - } - - 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++; - } -} - static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah, u16 *gb, u16 numXpdGain, @@ -784,7 +619,7 @@ static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah, /* Because of a hardware limitation, ensure the gain boundary * is not larger than (63 - overlap) */ - gb_limit = (u16)(AR5416_MAX_RATE_POWER - pdGainOverlap_t2); + gb_limit = (u16)(MAX_RATE_POWER - pdGainOverlap_t2); for (k = 0; k < numXpdGain; k++) gb[k] = (u16)min(gb_limit, gb[k]); @@ -918,7 +753,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, ath9k_olc_get_pdadcs(ah, pcdacIdx, txPower/2, pdadcValues); } else { - ath9k_hw_get_def_gain_boundaries_pdadcs(ah, + ath9k_hw_get_gain_boundaries_pdadcs(ah, chan, pRawDataset, pCalBChans, numPiers, pdGainOverlap_t2, @@ -966,20 +801,19 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, ((pdadcValues[4 * j + 3] & 0xFF) << 24); REG_WRITE(ah, regOffset, reg32); - ath_print(common, ATH_DBG_EEPROM, - "PDADC (%d,%4x): %4.4x %8.8x\n", - i, regChainOffset, regOffset, - reg32); - ath_print(common, ATH_DBG_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]); + ath_dbg(common, ATH_DBG_EEPROM, + "PDADC (%d,%4x): %4.4x %8.8x\n", + i, regChainOffset, regOffset, + reg32); + ath_dbg(common, ATH_DBG_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; } @@ -1004,9 +838,9 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; - u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + u16 twiceMaxEdgePower = MAX_RATE_POWER; static const u16 tpScaleReductionTable[5] = - { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; + { 0, 3, 6, 9, MAX_RATE_POWER }; int i; int16_t twiceLargestAntenna; @@ -1022,13 +856,16 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, 0, {0, 0, 0, 0} }; u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 ctlModesFor11a[] = - { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 }; - u16 ctlModesFor11g[] = - { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, - CTL_2GHT40 - }; - u16 numCtlModes, *pCtlMode, ctlMode, freq; + static const u16 ctlModesFor11a[] = { + CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 + }; + static const u16 ctlModesFor11g[] = { + CTL_11B, CTL_11G, CTL_2GHT20, + CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 + }; + u16 numCtlModes; + const u16 *pCtlMode; + u16 ctlMode, freq; struct chan_centers centers; int tx_chainmask; u16 twiceMinEdgePower; @@ -1148,7 +985,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, if (ah->eep_ops->get_eeprom_ver(ah) == 14 && ah->eep_ops->get_eeprom_rev(ah) <= 2) - twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + twiceMaxEdgePower = MAX_RATE_POWER; for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { if ((((cfgCtl & ~CTL_MODE_M) | @@ -1263,7 +1100,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, u16 cfgCtl, u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower, - u8 powerLimit) + u8 powerLimit, bool test) { #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); @@ -1290,12 +1127,44 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset); + regulatory->max_power_level = 0; for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); - if (ratesArray[i] > AR5416_MAX_RATE_POWER) - ratesArray[i] = AR5416_MAX_RATE_POWER; + if (ratesArray[i] > MAX_RATE_POWER) + ratesArray[i] = MAX_RATE_POWER; + if (ratesArray[i] > regulatory->max_power_level) + regulatory->max_power_level = ratesArray[i]; + } + + if (!test) { + i = rate6mb; + + if (IS_CHAN_HT40(chan)) + i = rateHt40_0; + else if (IS_CHAN_HT20(chan)) + i = rateHt20_0; + + regulatory->max_power_level = ratesArray[i]; } + switch(ar5416_get_ntxchains(ah->txchainmask)) { + case 1: + break; + case 2: + regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; + break; + case 3: + regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; + break; + default: + ath_dbg(ath9k_hw_common(ah), ATH_DBG_EEPROM, + "Invalid chainmask configuration\n"); + break; + } + + if (test) + return; + if (AR_SREV_9280_20_OR_LATER(ah)) { for (i = 0; i < Ar5416RateSize; i++) { int8_t pwr_table_offset; @@ -1392,62 +1261,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, REG_WRITE(ah, AR_PHY_POWER_TX_SUB, ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); - - i = rate6mb; - - if (IS_CHAN_HT40(chan)) - i = rateHt40_0; - else if (IS_CHAN_HT20(chan)) - i = rateHt20_0; - - if (AR_SREV_9280_20_OR_LATER(ah)) - regulatory->max_power_level = - ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2; - else - regulatory->max_power_level = ratesArray[i]; - - switch(ar5416_get_ntxchains(ah->txchainmask)) { - case 1: - break; - case 2: - regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; - break; - case 3: - regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; - break; - default: - ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM, - "Invalid chainmask configuration\n"); - break; - } -} - -static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, - enum ath9k_hal_freq_band freq_band) -{ - struct ar5416_eeprom_def *eep = &ah->eeprom.def; - struct modal_eep_header *pModal = - &(eep->modalHeader[freq_band]); - struct base_eep_header *pBase = &eep->baseEepHeader; - u8 num_ant_config; - - num_ant_config = 1; - - if (pBase->version >= 0x0E0D && - (pModal->lna_ctl & LNA_CTL_USE_ANT1)) - num_ant_config += 1; - - return num_ant_config; -} - -static u32 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct ar5416_eeprom_def *eep = &ah->eeprom.def; - struct modal_eep_header *pModal = - &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); - - return pModal->antCtrlCommon; } static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) @@ -1458,17 +1271,17 @@ static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) u16 spur_val = AR_NO_SPUR; - ath_print(common, ATH_DBG_ANI, - "Getting spur idx %d is2Ghz. %d val %x\n", - i, is2GHz, ah->config.spurchans[i][is2GHz]); + ath_dbg(common, ATH_DBG_ANI, + "Getting spur idx:%d is2Ghz:%d val:%x\n", + i, is2GHz, ah->config.spurchans[i][is2GHz]); switch (ah->config.spurmode) { case SPUR_DISABLE: break; case SPUR_ENABLE_IOCTL: spur_val = ah->config.spurchans[i][is2GHz]; - ath_print(common, ATH_DBG_ANI, - "Getting spur val from new loc. %d\n", spur_val); + ath_dbg(common, ATH_DBG_ANI, + "Getting spur val from new loc. %d\n", spur_val); break; case SPUR_ENABLE_EEPROM: spur_val = EEP_DEF_SPURCHAN; @@ -1486,8 +1299,6 @@ const struct eeprom_ops eep_def_ops = { .fill_eeprom = ath9k_hw_def_fill_eeprom, .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver, .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev, - .get_num_ant_config = ath9k_hw_def_get_num_ant_config, - .get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg, .set_board_values = ath9k_hw_def_set_board_values, .set_addac = ath9k_hw_def_set_addac, .set_txpower = ath9k_hw_def_set_txpower, diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 4a9a68bba324..133764069246 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -103,8 +103,8 @@ static int ath_register_led(struct ath_softc *sc, struct ath_led *led, ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); if (ret) - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "Failed to register led:%s", led->name); + ath_err(ath9k_hw_common(sc->sc_ah), + "Failed to register led:%s", led->name); else led->registered = 1; return ret; @@ -236,13 +236,13 @@ static void ath_detect_bt_priority(struct ath_softc *sc) sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN); /* Detect if colocated bt started scanning */ if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, - "BT scan detected"); + ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, + "BT scan detected\n"); sc->sc_flags |= (SC_OP_BT_SCAN | SC_OP_BT_PRIORITY_DETECTED); } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, - "BT priority traffic detected"); + ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, + "BT priority traffic detected\n"); sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; } @@ -259,7 +259,7 @@ static void ath9k_gen_timer_start(struct ath_hw *ah, ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ah->imask |= ATH9K_INT_GENTIMER; ath9k_hw_set_interrupts(ah, ah->imask); } @@ -273,7 +273,7 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) /* if no timer is enabled, turn off interrupt mask */ if (timer_table->timer_mask.val == 0) { - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ah->imask &= ~ATH9K_INT_GENTIMER; ath9k_hw_set_interrupts(ah, ah->imask); } @@ -310,10 +310,8 @@ static void ath_btcoex_period_timer(unsigned long data) timer_period = is_btscan ? btcoex->btscan_no_stomp : btcoex->btcoex_no_stomp; - ath9k_gen_timer_start(ah, - btcoex->no_stomp_timer, - (ath9k_hw_gettsf32(ah) + - timer_period), timer_period * 10); + ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, 0, + timer_period * 10); btcoex->hw_timer_enabled = true; } @@ -333,8 +331,8 @@ static void ath_btcoex_no_stomp_timer(void *arg) struct ath_common *common = ath9k_hw_common(ah); bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; - ath_print(common, ATH_DBG_BTCOEX, - "no stomp timer running\n"); + ath_dbg(common, ATH_DBG_BTCOEX, + "no stomp timer running\n"); spin_lock_bh(&btcoex->btcoex_lock); @@ -380,8 +378,8 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc) struct ath_btcoex *btcoex = &sc->btcoex; struct ath_hw *ah = sc->sc_ah; - ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, - "Starting btcoex timers"); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "Starting btcoex timers\n"); /* make sure duty cycle timer is also stopped when resuming */ if (btcoex->hw_timer_enabled) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 0de3c3d3c245..5ab3084eb9cb 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -28,10 +28,7 @@ MODULE_FIRMWARE(FIRMWARE_AR9271); static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */ { USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */ - { USB_DEVICE(0x0cf3, 0x7010) }, /* Atheros */ - { USB_DEVICE(0x0cf3, 0x7015) }, /* Atheros */ { USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */ - { USB_DEVICE(0x0846, 0x9018) }, /* Netgear WNDA3200 */ { USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */ { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */ { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */ @@ -40,9 +37,21 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x13D3, 0x3349) }, /* Azurewave */ { USB_DEVICE(0x13D3, 0x3350) }, /* Azurewave */ { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ - { USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */ { USB_DEVICE(0x040D, 0x3801) }, /* VIA */ - { USB_DEVICE(0x1668, 0x1200) }, /* Verizon */ + { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ + + { USB_DEVICE(0x0cf3, 0x7015), + .driver_info = AR9287_USB }, /* Atheros */ + { USB_DEVICE(0x1668, 0x1200), + .driver_info = AR9287_USB }, /* Verizon */ + + { USB_DEVICE(0x0cf3, 0x7010), + .driver_info = AR9280_USB }, /* Atheros */ + { USB_DEVICE(0x0846, 0x9018), + .driver_info = AR9280_USB }, /* Netgear WNDA3200 */ + { USB_DEVICE(0x083A, 0xA704), + .driver_info = AR9280_USB }, /* SMC Networks */ + { }, }; @@ -144,16 +153,36 @@ static void hif_usb_tx_cb(struct urb *urb) case -ENODEV: case -ESHUTDOWN: /* - * The URB has been killed, free the SKBs - * and return. + * The URB has been killed, free the SKBs. */ ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); - return; + + /* + * If the URBs are being flushed, no need to add this + * URB to the free list. + */ + spin_lock(&hif_dev->tx.tx_lock); + if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { + spin_unlock(&hif_dev->tx.tx_lock); + return; + } + spin_unlock(&hif_dev->tx.tx_lock); + + /* + * In the stop() case, this URB has to be added to + * the free list. + */ + goto add_free; default: break; } - /* Check if TX has been stopped */ + /* + * Check if TX has been stopped, this is needed because + * this CB could have been invoked just after the TX lock + * was released in hif_stop() and kill_urb() hasn't been + * called yet. + */ spin_lock(&hif_dev->tx.tx_lock); if (hif_dev->tx.flags & HIF_USB_TX_STOP) { spin_unlock(&hif_dev->tx.tx_lock); @@ -305,6 +334,7 @@ static void hif_usb_start(void *hif_handle, u8 pipe_id) static void hif_usb_stop(void *hif_handle, u8 pipe_id) { struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; + struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; unsigned long flags; spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); @@ -312,6 +342,12 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id) hif_dev->tx.tx_skb_cnt = 0; hif_dev->tx.flags |= HIF_USB_TX_STOP; spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); + + /* The pending URBs have to be canceled. */ + list_for_each_entry_safe(tx_buf, tx_buf_tmp, + &hif_dev->tx.tx_pending, list) { + usb_kill_urb(tx_buf->urb); + } } static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb, @@ -353,9 +389,9 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, struct sk_buff *skb) { struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER]; - int index = 0, i = 0, chk_idx, len = skb->len; - int rx_remain_len = 0, rx_pkt_len = 0; - u16 pkt_len, pkt_tag, pool_index = 0; + int index = 0, i = 0, len = skb->len; + int rx_remain_len, rx_pkt_len; + u16 pool_index = 0; u8 *ptr; spin_lock(&hif_dev->rx_lock); @@ -389,64 +425,64 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, spin_unlock(&hif_dev->rx_lock); while (index < len) { + u16 pkt_len; + u16 pkt_tag; + u16 pad_len; + int chk_idx; + ptr = (u8 *) skb->data; pkt_len = ptr[index] + (ptr[index+1] << 8); pkt_tag = ptr[index+2] + (ptr[index+3] << 8); - if (pkt_tag == ATH_USB_RX_STREAM_MODE_TAG) { - u16 pad_len; - - pad_len = 4 - (pkt_len & 0x3); - if (pad_len == 4) - pad_len = 0; - - chk_idx = index; - index = index + 4 + pkt_len + pad_len; - - if (index > MAX_RX_BUF_SIZE) { - spin_lock(&hif_dev->rx_lock); - hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; - hif_dev->rx_transfer_len = - MAX_RX_BUF_SIZE - chk_idx - 4; - hif_dev->rx_pad_len = pad_len; - - nskb = __dev_alloc_skb(pkt_len + 32, - GFP_ATOMIC); - if (!nskb) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: RX memory allocation" - " error\n"); - spin_unlock(&hif_dev->rx_lock); - goto err; - } - skb_reserve(nskb, 32); - RX_STAT_INC(skb_allocated); - - memcpy(nskb->data, &(skb->data[chk_idx+4]), - hif_dev->rx_transfer_len); - - /* Record the buffer pointer */ - hif_dev->remain_skb = nskb; + if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) { + RX_STAT_INC(skb_dropped); + return; + } + + pad_len = 4 - (pkt_len & 0x3); + if (pad_len == 4) + pad_len = 0; + + chk_idx = index; + index = index + 4 + pkt_len + pad_len; + + if (index > MAX_RX_BUF_SIZE) { + spin_lock(&hif_dev->rx_lock); + hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; + hif_dev->rx_transfer_len = + MAX_RX_BUF_SIZE - chk_idx - 4; + hif_dev->rx_pad_len = pad_len; + + nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); + if (!nskb) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: RX memory allocation error\n"); spin_unlock(&hif_dev->rx_lock); - } else { - nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); - if (!nskb) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: RX memory allocation" - " error\n"); - goto err; - } - skb_reserve(nskb, 32); - RX_STAT_INC(skb_allocated); - - memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); - skb_put(nskb, pkt_len); - skb_pool[pool_index++] = nskb; + goto err; } + skb_reserve(nskb, 32); + RX_STAT_INC(skb_allocated); + + memcpy(nskb->data, &(skb->data[chk_idx+4]), + hif_dev->rx_transfer_len); + + /* Record the buffer pointer */ + hif_dev->remain_skb = nskb; + spin_unlock(&hif_dev->rx_lock); } else { - RX_STAT_INC(skb_dropped); - return; + nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); + if (!nskb) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: RX memory allocation error\n"); + goto err; + } + skb_reserve(nskb, 32); + RX_STAT_INC(skb_allocated); + + memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); + skb_put(nskb, pkt_len); + skb_pool[pool_index++] = nskb; } } @@ -461,7 +497,7 @@ err: static void ath9k_hif_usb_rx_cb(struct urb *urb) { struct sk_buff *skb = (struct sk_buff *) urb->context; - struct hif_device_usb *hif_dev = (struct hif_device_usb *) + struct hif_device_usb *hif_dev = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); int ret; @@ -508,7 +544,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) { struct sk_buff *skb = (struct sk_buff *) urb->context; struct sk_buff *nskb; - struct hif_device_usb *hif_dev = (struct hif_device_usb *) + struct hif_device_usb *hif_dev = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); int ret; @@ -578,6 +614,7 @@ free: static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) { struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; + unsigned long flags; list_for_each_entry_safe(tx_buf, tx_buf_tmp, &hif_dev->tx.tx_buf, list) { @@ -588,6 +625,10 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) kfree(tx_buf); } + spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + hif_dev->tx.flags |= HIF_USB_TX_FLUSH; + spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); + list_for_each_entry_safe(tx_buf, tx_buf_tmp, &hif_dev->tx.tx_pending, list) { usb_kill_urb(tx_buf->urb); @@ -776,7 +817,8 @@ static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) ath9k_hif_usb_dealloc_rx_urbs(hif_dev); } -static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) +static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev, + u32 drv_info) { int transfer, err; const void *data = hif_dev->firmware->data; @@ -807,18 +849,10 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) } kfree(buf); - switch (hif_dev->device_id) { - case 0x7010: - case 0x7015: - case 0x9018: - case 0xA704: - case 0x1200: + if (IS_AR7010_DEVICE(drv_info)) firm_offset = AR7010_FIRMWARE_TEXT; - break; - default: + else firm_offset = AR9271_FIRMWARE_TEXT; - break; - } /* * Issue FW download complete command to firmware. @@ -836,7 +870,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) return 0; } -static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) +static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info) { int ret, idx; struct usb_host_interface *alt = &hif_dev->interface->altsetting[0]; @@ -852,7 +886,7 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) } /* Download firmware */ - ret = ath9k_hif_usb_download_fw(hif_dev); + ret = ath9k_hif_usb_download_fw(hif_dev, drv_info); if (ret) { dev_err(&hif_dev->udev->dev, "ath9k_htc: Firmware - %s download failed\n", @@ -884,9 +918,9 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) return 0; -err_fw_download: - ath9k_hif_usb_dealloc_urbs(hif_dev); err_urb: + ath9k_hif_usb_dealloc_urbs(hif_dev); +err_fw_download: release_firmware(hif_dev->firmware); err_fw_req: hif_dev->firmware = NULL; @@ -931,23 +965,15 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, /* Find out which firmware to load */ - switch(hif_dev->device_id) { - case 0x7010: - case 0x7015: - case 0x9018: - case 0xA704: - case 0x1200: + if (IS_AR7010_DEVICE(id->driver_info)) if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202) hif_dev->fw_name = FIRMWARE_AR7010_1_1; else hif_dev->fw_name = FIRMWARE_AR7010; - break; - default: + else hif_dev->fw_name = FIRMWARE_AR9271; - break; - } - ret = ath9k_hif_usb_dev_init(hif_dev); + ret = ath9k_hif_usb_dev_init(hif_dev, id->driver_info); if (ret) { ret = -EINVAL; goto err_hif_init_usb; @@ -955,7 +981,7 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, ret = ath9k_htc_hw_init(hif_dev->htc_handle, &hif_dev->udev->dev, hif_dev->device_id, - hif_dev->udev->product); + hif_dev->udev->product, id->driver_info); if (ret) { ret = -EINVAL; goto err_htc_hw_init; @@ -998,18 +1024,17 @@ static void ath9k_hif_usb_reboot(struct usb_device *udev) static void ath9k_hif_usb_disconnect(struct usb_interface *interface) { struct usb_device *udev = interface_to_usbdev(interface); - struct hif_device_usb *hif_dev = - (struct hif_device_usb *) usb_get_intfdata(interface); + struct hif_device_usb *hif_dev = usb_get_intfdata(interface); + bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false; if (hif_dev) { - ath9k_htc_hw_deinit(hif_dev->htc_handle, - (udev->state == USB_STATE_NOTATTACHED) ? true : false); + ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged); ath9k_htc_hw_free(hif_dev->htc_handle); ath9k_hif_usb_dev_deinit(hif_dev); usb_set_intfdata(interface, NULL); } - if (hif_dev->flags & HIF_USB_START) + if (!unplugged && (hif_dev->flags & HIF_USB_START)) ath9k_hif_usb_reboot(udev); kfree(hif_dev); @@ -1021,8 +1046,7 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface) static int ath9k_hif_usb_suspend(struct usb_interface *interface, pm_message_t message) { - struct hif_device_usb *hif_dev = - (struct hif_device_usb *) usb_get_intfdata(interface); + struct hif_device_usb *hif_dev = usb_get_intfdata(interface); /* * The device has to be set to FULLSLEEP mode in case no @@ -1038,8 +1062,8 @@ static int ath9k_hif_usb_suspend(struct usb_interface *interface, static int ath9k_hif_usb_resume(struct usb_interface *interface) { - struct hif_device_usb *hif_dev = - (struct hif_device_usb *) usb_get_intfdata(interface); + struct hif_device_usb *hif_dev = usb_get_intfdata(interface); + struct htc_target *htc_handle = hif_dev->htc_handle; int ret; ret = ath9k_hif_usb_alloc_urbs(hif_dev); @@ -1047,7 +1071,8 @@ static int ath9k_hif_usb_resume(struct usb_interface *interface) return ret; if (hif_dev->firmware) { - ret = ath9k_hif_usb_download_fw(hif_dev); + ret = ath9k_hif_usb_download_fw(hif_dev, + htc_handle->drv_priv->ah->hw_version.usbdev); if (ret) goto fail_resume; } else { @@ -1057,7 +1082,7 @@ static int ath9k_hif_usb_resume(struct usb_interface *interface) mdelay(100); - ret = ath9k_htc_resume(hif_dev->htc_handle); + ret = ath9k_htc_resume(htc_handle); if (ret) goto fail_resume; diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 2daf97b11c08..7b9d863d4035 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -17,6 +17,8 @@ #ifndef HTC_USB_H #define HTC_USB_H +#define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB)) + #define AR9271_FIRMWARE 0x501000 #define AR9271_FIRMWARE_TEXT 0x903000 #define AR7010_FIRMWARE_TEXT 0x906000 @@ -62,6 +64,7 @@ struct tx_buf { }; #define HIF_USB_TX_STOP BIT(0) +#define HIF_USB_TX_FLUSH BIT(1) struct hif_usb_tx { u8 flags; diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index c3b561daa6c1..a099b3e87ed3 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -331,17 +331,15 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv); #define OP_INVALID BIT(0) #define OP_SCANNING BIT(1) -#define OP_FULL_RESET BIT(2) -#define OP_LED_ASSOCIATED BIT(3) -#define OP_LED_ON BIT(4) -#define OP_PREAMBLE_SHORT BIT(5) -#define OP_PROTECT_ENABLE BIT(6) -#define OP_ASSOCIATED BIT(7) -#define OP_ENABLE_BEACON BIT(8) -#define OP_LED_DEINIT BIT(9) -#define OP_UNPLUGGED BIT(10) -#define OP_BT_PRIORITY_DETECTED BIT(11) -#define OP_BT_SCAN BIT(12) +#define OP_LED_ASSOCIATED BIT(2) +#define OP_LED_ON BIT(3) +#define OP_PREAMBLE_SHORT BIT(4) +#define OP_PROTECT_ENABLE BIT(5) +#define OP_ASSOCIATED BIT(6) +#define OP_ENABLE_BEACON BIT(7) +#define OP_LED_DEINIT BIT(8) +#define OP_BT_PRIORITY_DETECTED BIT(9) +#define OP_BT_SCAN BIT(10) struct ath9k_htc_priv { struct device *dev; @@ -368,7 +366,7 @@ struct ath9k_htc_priv { u16 seq_no; u32 bmiss_cnt; - struct ath9k_hw_cal_data caldata[38]; + struct ath9k_hw_cal_data caldata[ATH9K_NUM_CHANNELS]; spinlock_t beacon_lock; @@ -378,7 +376,7 @@ struct ath9k_htc_priv { struct ieee80211_vif *vif; struct htc_beacon_config cur_beacon_conf; unsigned int rxfilter; - struct tasklet_struct wmi_tasklet; + struct tasklet_struct swba_tasklet; struct tasklet_struct rx_tasklet; struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; struct ath9k_htc_rx rx; @@ -386,6 +384,7 @@ struct ath9k_htc_priv { struct sk_buff_head tx_queue; struct delayed_work ath9k_ani_work; struct work_struct ps_work; + struct work_struct fatal_work; struct mutex htc_pm_lock; unsigned long ps_usecount; @@ -420,6 +419,8 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) common->bus_ops->read_cachesize(common, csz); } +void ath9k_htc_reset(struct ath9k_htc_priv *priv); + void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif); @@ -435,6 +436,7 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, void ath9k_htc_station_work(struct work_struct *work); void ath9k_htc_aggr_work(struct work_struct *work); void ath9k_ani_work(struct work_struct *work);; +void ath_start_ani(struct ath9k_htc_priv *priv); int ath9k_tx_init(struct ath9k_htc_priv *priv); void ath9k_tx_tasklet(unsigned long data); @@ -457,13 +459,18 @@ void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv); void ath9k_ps_work(struct work_struct *work); bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, enum ath9k_power_mode mode); +void ath_update_txpow(struct ath9k_htc_priv *priv); void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); +void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); +void ath9k_htc_radio_enable(struct ieee80211_hw *hw); +void ath9k_htc_radio_disable(struct ieee80211_hw *hw); +void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv); void ath9k_init_leds(struct ath9k_htc_priv *priv); void ath9k_deinit_leds(struct ath9k_htc_priv *priv); int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, - u16 devid, char *product); + u16 devid, char *product, u32 drv_info); void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); #ifdef CONFIG_PM void ath9k_htc_suspend(struct htc_target *htc_handle); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 1b72aa482ac7..87cc65a78a3f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -123,11 +123,11 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, /* TSF out of range threshold fixed at 1 second */ bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; - ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); - ath_print(common, ATH_DBG_BEACON, - "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", - bs.bs_bmissthreshold, bs.bs_sleepduration, - bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); + ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); + ath_dbg(common, ATH_DBG_BEACON, + "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", + bs.bs_bmissthreshold, bs.bs_sleepduration, + bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); /* Set the computed STA beacon timers */ @@ -154,9 +154,9 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, if (priv->op_flags & OP_ENABLE_BEACON) imask |= ATH9K_INT_SWBA; - ath_print(common, ATH_DBG_BEACON, - "IBSS Beacon config, intval: %d, imask: 0x%x\n", - bss_conf->beacon_interval, imask); + ath_dbg(common, ATH_DBG_BEACON, + "IBSS Beacon config, intval: %d, imask: 0x%x\n", + bss_conf->beacon_interval, imask); WMI_CMD(WMI_DISABLE_INTR_CMDID); ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); @@ -246,8 +246,8 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) qi.tqi_cwmax = qi_be.tqi_cwmax; if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "Unable to update beacon queue %u!\n", qnum); + ath_err(ath9k_hw_common(ah), + "Unable to update beacon queue %u!\n", qnum); } else { ath9k_hw_resettxqueue(ah, priv->beaconq); } @@ -278,8 +278,8 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, ath9k_htc_beacon_config_adhoc(priv, cur_conf); break; default: - ath_print(common, ATH_DBG_CONFIG, - "Unsupported beaconing mode\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "Unsupported beaconing mode\n"); return; } } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 50eec9a3b88c..fe70f67aa088 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -1,3 +1,19 @@ +/* + * 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. + */ + #include "htc.h" /******************/ @@ -20,13 +36,13 @@ static void ath_detect_bt_priority(struct ath9k_htc_priv *priv) priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); /* Detect if colocated bt started scanning */ if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { - ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, - "BT scan detected"); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "BT scan detected\n"); priv->op_flags |= (OP_BT_SCAN | OP_BT_PRIORITY_DETECTED); } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { - ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, - "BT priority traffic detected"); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "BT priority traffic detected\n"); priv->op_flags |= OP_BT_PRIORITY_DETECTED; } @@ -83,8 +99,8 @@ static void ath_btcoex_duty_cycle_work(struct work_struct *work) struct ath_common *common = ath9k_hw_common(ah); bool is_btscan = priv->op_flags & OP_BT_SCAN; - ath_print(common, ATH_DBG_BTCOEX, - "time slice work for bt and wlan\n"); + ath_dbg(common, ATH_DBG_BTCOEX, + "time slice work for bt and wlan\n"); if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); @@ -114,8 +130,7 @@ void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv) struct ath_btcoex *btcoex = &priv->btcoex; struct ath_hw *ah = priv->ah; - ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, - "Starting btcoex work"); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, "Starting btcoex work\n"); btcoex->bt_priority_cnt = 0; btcoex->bt_priority_time = jiffies; @@ -132,3 +147,314 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv) cancel_delayed_work_sync(&priv->coex_period_work); cancel_delayed_work_sync(&priv->duty_cycle_work); } + +/*******/ +/* LED */ +/*******/ + +static void ath9k_led_blink_work(struct work_struct *work) +{ + struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, + ath9k_led_blink_work.work); + + if (!(priv->op_flags & OP_LED_ASSOCIATED)) + return; + + if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) || + (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) + ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); + else + ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, + (priv->op_flags & OP_LED_ON) ? 1 : 0); + + ieee80211_queue_delayed_work(priv->hw, + &priv->ath9k_led_blink_work, + (priv->op_flags & OP_LED_ON) ? + msecs_to_jiffies(priv->led_off_duration) : + msecs_to_jiffies(priv->led_on_duration)); + + priv->led_on_duration = priv->led_on_cnt ? + max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) : + ATH_LED_ON_DURATION_IDLE; + priv->led_off_duration = priv->led_off_cnt ? + max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) : + ATH_LED_OFF_DURATION_IDLE; + priv->led_on_cnt = priv->led_off_cnt = 0; + + if (priv->op_flags & OP_LED_ON) + priv->op_flags &= ~OP_LED_ON; + else + priv->op_flags |= OP_LED_ON; +} + +static void ath9k_led_brightness_work(struct work_struct *work) +{ + struct ath_led *led = container_of(work, struct ath_led, + brightness_work.work); + struct ath9k_htc_priv *priv = led->priv; + + switch (led->brightness) { + case LED_OFF: + if (led->led_type == ATH_LED_ASSOC || + led->led_type == ATH_LED_RADIO) { + ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, + (led->led_type == ATH_LED_RADIO)); + priv->op_flags &= ~OP_LED_ASSOCIATED; + if (led->led_type == ATH_LED_RADIO) + priv->op_flags &= ~OP_LED_ON; + } else { + priv->led_off_cnt++; + } + break; + case LED_FULL: + if (led->led_type == ATH_LED_ASSOC) { + priv->op_flags |= OP_LED_ASSOCIATED; + ieee80211_queue_delayed_work(priv->hw, + &priv->ath9k_led_blink_work, 0); + } else if (led->led_type == ATH_LED_RADIO) { + ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); + priv->op_flags |= OP_LED_ON; + } else { + priv->led_on_cnt++; + } + break; + default: + break; + } +} + +static void ath9k_led_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); + struct ath9k_htc_priv *priv = led->priv; + + led->brightness = brightness; + if (!(priv->op_flags & OP_LED_DEINIT)) + ieee80211_queue_delayed_work(priv->hw, + &led->brightness_work, 0); +} + +void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv) +{ + cancel_delayed_work_sync(&priv->radio_led.brightness_work); + cancel_delayed_work_sync(&priv->assoc_led.brightness_work); + cancel_delayed_work_sync(&priv->tx_led.brightness_work); + cancel_delayed_work_sync(&priv->rx_led.brightness_work); +} + +static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led, + char *trigger) +{ + int ret; + + led->priv = priv; + led->led_cdev.name = led->name; + led->led_cdev.default_trigger = trigger; + led->led_cdev.brightness_set = ath9k_led_brightness; + + ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev); + if (ret) + ath_err(ath9k_hw_common(priv->ah), + "Failed to register led:%s", led->name); + else + led->registered = 1; + + INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work); + + return ret; +} + +static void ath9k_unregister_led(struct ath_led *led) +{ + if (led->registered) { + led_classdev_unregister(&led->led_cdev); + led->registered = 0; + } +} + +void ath9k_deinit_leds(struct ath9k_htc_priv *priv) +{ + priv->op_flags |= OP_LED_DEINIT; + ath9k_unregister_led(&priv->assoc_led); + priv->op_flags &= ~OP_LED_ASSOCIATED; + ath9k_unregister_led(&priv->tx_led); + ath9k_unregister_led(&priv->rx_led); + ath9k_unregister_led(&priv->radio_led); +} + +void ath9k_init_leds(struct ath9k_htc_priv *priv) +{ + char *trigger; + int ret; + + if (AR_SREV_9287(priv->ah)) + priv->ah->led_pin = ATH_LED_PIN_9287; + else if (AR_SREV_9271(priv->ah)) + priv->ah->led_pin = ATH_LED_PIN_9271; + else if (AR_DEVID_7010(priv->ah)) + priv->ah->led_pin = ATH_LED_PIN_7010; + else + priv->ah->led_pin = ATH_LED_PIN_DEF; + + /* Configure gpio 1 for output */ + ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + /* LED off, active low */ + ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); + + INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work); + + trigger = ieee80211_get_radio_led_name(priv->hw); + snprintf(priv->radio_led.name, sizeof(priv->radio_led.name), + "ath9k-%s::radio", wiphy_name(priv->hw->wiphy)); + ret = ath9k_register_led(priv, &priv->radio_led, trigger); + priv->radio_led.led_type = ATH_LED_RADIO; + if (ret) + goto fail; + + trigger = ieee80211_get_assoc_led_name(priv->hw); + snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name), + "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy)); + ret = ath9k_register_led(priv, &priv->assoc_led, trigger); + priv->assoc_led.led_type = ATH_LED_ASSOC; + if (ret) + goto fail; + + trigger = ieee80211_get_tx_led_name(priv->hw); + snprintf(priv->tx_led.name, sizeof(priv->tx_led.name), + "ath9k-%s::tx", wiphy_name(priv->hw->wiphy)); + ret = ath9k_register_led(priv, &priv->tx_led, trigger); + priv->tx_led.led_type = ATH_LED_TX; + if (ret) + goto fail; + + trigger = ieee80211_get_rx_led_name(priv->hw); + snprintf(priv->rx_led.name, sizeof(priv->rx_led.name), + "ath9k-%s::rx", wiphy_name(priv->hw->wiphy)); + ret = ath9k_register_led(priv, &priv->rx_led, trigger); + priv->rx_led.led_type = ATH_LED_RX; + if (ret) + goto fail; + + priv->op_flags &= ~OP_LED_DEINIT; + + return; + +fail: + cancel_delayed_work_sync(&priv->ath9k_led_blink_work); + ath9k_deinit_leds(priv); +} + +/*******************/ +/* Rfkill */ +/*******************/ + +static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv) +{ + return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) == + priv->ah->rfkill_polarity; +} + +void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + bool blocked = !!ath_is_rfkill_set(priv); + + wiphy_rfkill_set_hw_state(hw->wiphy, blocked); +} + +void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv) +{ + if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + wiphy_rfkill_start_polling(priv->hw->wiphy); +} + +void ath9k_htc_radio_enable(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + int ret; + u8 cmd_rsp; + + if (!ah->curchan) + ah->curchan = ath9k_cmn_get_curchannel(hw, ah); + + /* Reset the HW */ + ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); + if (ret) { + ath_err(common, + "Unable to reset hardware; reset status %d (freq %u MHz)\n", + ret, ah->curchan->channel); + } + + ath_update_txpow(priv); + + /* Start RX */ + WMI_CMD(WMI_START_RECV_CMDID); + ath9k_host_rx_init(priv); + + /* Start TX */ + htc_start(priv->htc); + spin_lock_bh(&priv->tx_lock); + priv->tx_queues_stop = false; + spin_unlock_bh(&priv->tx_lock); + ieee80211_wake_queues(hw); + + WMI_CMD(WMI_ENABLE_INTR_CMDID); + + /* Enable LED */ + ath9k_hw_cfg_output(ah, ah->led_pin, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_set_gpio(ah, ah->led_pin, 0); +} + +void ath9k_htc_radio_disable(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + int ret; + u8 cmd_rsp; + + ath9k_htc_ps_wakeup(priv); + + /* Disable LED */ + ath9k_hw_set_gpio(ah, ah->led_pin, 1); + ath9k_hw_cfg_gpio_input(ah, ah->led_pin); + + WMI_CMD(WMI_DISABLE_INTR_CMDID); + + /* Stop TX */ + ieee80211_stop_queues(hw); + htc_stop(priv->htc); + WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); + skb_queue_purge(&priv->tx_queue); + + /* Stop RX */ + WMI_CMD(WMI_STOP_RECV_CMDID); + + /* + * The MIB counters have to be disabled here, + * since the target doesn't do it. + */ + ath9k_hw_disable_mib_counters(ah); + + if (!ah->curchan) + ah->curchan = ath9k_cmn_get_curchannel(hw, ah); + + /* Reset the HW */ + ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); + if (ret) { + ath_err(common, + "Unable to reset hardware; reset status %d (freq %u MHz)\n", + ret, ah->curchan->channel); + } + + /* Disable the PHY */ + ath9k_hw_phy_disable(ah); + + ath9k_htc_ps_restore(priv); + ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); +} diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 8776f49ffd41..38433f9bfe59 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -142,7 +142,7 @@ static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) { ath9k_htc_exit_debug(priv->ah); ath9k_hw_deinit(priv->ah); - tasklet_kill(&priv->wmi_tasklet); + tasklet_kill(&priv->swba_tasklet); tasklet_kill(&priv->rx_tasklet); tasklet_kill(&priv->tx_tasklet); kfree(priv->ah); @@ -181,7 +181,8 @@ static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv, return htc_connect_service(priv->htc, &req, ep_id); } -static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid) +static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid, + u32 drv_info) { int ret; @@ -245,17 +246,10 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid) * the HIF layer, shouldn't matter much. */ - switch(devid) { - case 0x7010: - case 0x7015: - case 0x9018: - case 0xA704: - case 0x1200: + if (IS_AR7010_DEVICE(drv_info)) priv->htc->credits = 45; - break; - default: + else priv->htc->credits = 33; - } ret = htc_init(priv->htc); if (ret) @@ -294,9 +288,9 @@ static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset) (u8 *) &val, sizeof(val), 100); if (unlikely(r)) { - ath_print(common, ATH_DBG_WMI, - "REGISTER READ FAILED: (0x%04x, %d)\n", - reg_offset, r); + ath_dbg(common, ATH_DBG_WMI, + "REGISTER READ FAILED: (0x%04x, %d)\n", + reg_offset, r); return -EIO; } @@ -308,7 +302,7 @@ static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset) struct ath_hw *ah = (struct ath_hw *) hw_priv; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - __be32 buf[2] = { + const __be32 buf[2] = { cpu_to_be32(reg_offset), cpu_to_be32(val), }; @@ -319,9 +313,9 @@ static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset) (u8 *) &val, sizeof(val), 100); if (unlikely(r)) { - ath_print(common, ATH_DBG_WMI, - "REGISTER WRITE FAILED:(0x%04x, %d)\n", - reg_offset, r); + ath_dbg(common, ATH_DBG_WMI, + "REGISTER WRITE FAILED:(0x%04x, %d)\n", + reg_offset, r); } } @@ -351,9 +345,9 @@ static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset) (u8 *) &rsp_status, sizeof(rsp_status), 100); if (unlikely(r)) { - ath_print(common, ATH_DBG_WMI, - "REGISTER WRITE FAILED, multi len: %d\n", - priv->wmi->multi_write_idx); + ath_dbg(common, ATH_DBG_WMI, + "REGISTER WRITE FAILED, multi len: %d\n", + priv->wmi->multi_write_idx); } priv->wmi->multi_write_idx = 0; } @@ -401,9 +395,9 @@ static void ath9k_regwrite_flush(void *hw_priv) (u8 *) &rsp_status, sizeof(rsp_status), 100); if (unlikely(r)) { - ath_print(common, ATH_DBG_WMI, - "REGISTER WRITE FAILED, multi len: %d\n", - priv->wmi->multi_write_idx); + ath_dbg(common, ATH_DBG_WMI, + "REGISTER WRITE FAILED, multi len: %d\n", + priv->wmi->multi_write_idx); } priv->wmi->multi_write_idx = 0; } @@ -475,9 +469,9 @@ static void setup_ht_cap(struct ath9k_htc_priv *priv, tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2); rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2); - ath_print(common, ATH_DBG_CONFIG, - "TX streams %d, RX streams: %d\n", - tx_streams, rx_streams); + ath_dbg(common, ATH_DBG_CONFIG, + "TX streams %d, RX streams: %d\n", + tx_streams, rx_streams); if (tx_streams != rx_streams) { ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; @@ -501,37 +495,31 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv) priv->beaconq = ath9k_hw_beaconq_setup(priv->ah); if (priv->beaconq == -1) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup BEACON xmit queue\n"); + ath_err(common, "Unable to setup BEACON xmit queue\n"); goto err; } priv->cabq = ath9k_htc_cabq_setup(priv); if (priv->cabq == -1) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup CAB xmit queue\n"); + ath_err(common, "Unable to setup CAB xmit queue\n"); goto err; } if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for BE traffic\n"); + ath_err(common, "Unable to setup xmit queue for BE traffic\n"); goto err; } if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for BK traffic\n"); + ath_err(common, "Unable to setup xmit queue for BK traffic\n"); goto err; } if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for VI traffic\n"); + ath_err(common, "Unable to setup xmit queue for VI traffic\n"); goto err; } if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for VO traffic\n"); + ath_err(common, "Unable to setup xmit queue for VO traffic\n"); goto err; } @@ -549,9 +537,9 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv) /* Get the hardware key cache size. */ common->keymax = priv->ah->caps.keycache_size; if (common->keymax > ATH_KEYMAX) { - ath_print(common, ATH_DBG_ANY, - "Warning, using only %u entries in %u key cache\n", - ATH_KEYMAX, common->keymax); + ath_dbg(common, ATH_DBG_ANY, + "Warning, using only %u entries in %u key cache\n", + ATH_KEYMAX, common->keymax); common->keymax = ATH_KEYMAX; } @@ -627,7 +615,8 @@ static void ath9k_init_btcoex(struct ath9k_htc_priv *priv) } static int ath9k_init_priv(struct ath9k_htc_priv *priv, - u16 devid, char *product) + u16 devid, char *product, + u32 drv_info) { struct ath_hw *ah = NULL; struct ath_common *common; @@ -641,6 +630,8 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, ah->hw_version.devid = devid; ah->hw_version.subsysid = 0; /* FIXME */ + ah->hw_version.usbdev = drv_info; + ah->ah_flags |= AH_USE_EEPROM; priv->ah = ah; common = ath9k_hw_common(ah); @@ -656,13 +647,15 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, spin_lock_init(&priv->tx_lock); mutex_init(&priv->mutex); mutex_init(&priv->htc_pm_lock); - tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, + tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet, (unsigned long)priv); tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, (unsigned long)priv); - tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); + tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, + (unsigned long)priv); INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); INIT_WORK(&priv->ps_work, ath9k_ps_work); + INIT_WORK(&priv->fatal_work, ath9k_fatal_work); /* * Cache line size is used to size and align various @@ -673,16 +666,15 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, ret = ath9k_hw_init(ah); if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to initialize hardware; " - "initialization status: %d\n", ret); + ath_err(common, + "Unable to initialize hardware; initialization status: %d\n", + ret); goto err_hw; } ret = ath9k_htc_init_debug(ah); if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to create debugfs files\n"); + ath_err(common, "Unable to create debugfs files\n"); goto err_debug; } @@ -762,7 +754,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, } static int ath9k_init_device(struct ath9k_htc_priv *priv, - u16 devid, char *product) + u16 devid, char *product, u32 drv_info) { struct ieee80211_hw *hw = priv->hw; struct ath_common *common; @@ -771,7 +763,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, struct ath_regulatory *reg; /* Bring up device */ - error = ath9k_init_priv(priv, devid, product); + error = ath9k_init_priv(priv, devid, product, drv_info); if (error != 0) goto err_init; @@ -829,7 +821,7 @@ err_init: } int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, - u16 devid, char *product) + u16 devid, char *product, u32 drv_info) { struct ieee80211_hw *hw; struct ath9k_htc_priv *priv; @@ -856,14 +848,11 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, goto err_free; } - ret = ath9k_init_htc_services(priv, devid); + ret = ath9k_init_htc_services(priv, devid, drv_info); if (ret) goto err_init; - /* The device may have been unplugged earlier. */ - priv->op_flags &= ~OP_UNPLUGGED; - - ret = ath9k_init_device(priv, devid, product); + ret = ath9k_init_device(priv, devid, product, drv_info); if (ret) goto err_init; @@ -882,7 +871,7 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug) /* Check if the device has been yanked out. */ if (hotunplug) - htc_handle->drv_priv->op_flags |= OP_UNPLUGGED; + htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED; ath9k_deinit_device(htc_handle->drv_priv); ath9k_deinit_wmi(htc_handle->drv_priv); @@ -899,14 +888,15 @@ void ath9k_htc_suspend(struct htc_target *htc_handle) int ath9k_htc_resume(struct htc_target *htc_handle) { + struct ath9k_htc_priv *priv = htc_handle->drv_priv; int ret; - ret = ath9k_htc_wait_for_target(htc_handle->drv_priv); + ret = ath9k_htc_wait_for_target(priv); if (ret) return ret; - ret = ath9k_init_htc_services(htc_handle->drv_priv, - htc_handle->drv_priv->ah->hw_version.devid); + ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid, + priv->ah->hw_version.usbdev); return ret; } #endif diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 51977caca47f..845b4c938d16 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -24,12 +24,12 @@ static struct dentry *ath9k_debugfs_root; /* Utilities */ /*************/ -static void ath_update_txpow(struct ath9k_htc_priv *priv) +void ath_update_txpow(struct ath9k_htc_priv *priv) { struct ath_hw *ah = priv->ah; if (priv->curtxpow != priv->txpowlimit) { - ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); + ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false); /* read back in case value is clamped */ priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit; } @@ -116,6 +116,60 @@ void ath9k_ps_work(struct work_struct *work) ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); } +void ath9k_htc_reset(struct ath9k_htc_priv *priv) +{ + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_channel *channel = priv->hw->conf.channel; + struct ath9k_hw_cal_data *caldata; + enum htc_phymode mode; + __be16 htc_mode; + u8 cmd_rsp; + int ret; + + mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); + + if (priv->op_flags & OP_ASSOCIATED) + cancel_delayed_work_sync(&priv->ath9k_ani_work); + + ieee80211_stop_queues(priv->hw); + htc_stop(priv->htc); + WMI_CMD(WMI_DISABLE_INTR_CMDID); + WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); + WMI_CMD(WMI_STOP_RECV_CMDID); + + caldata = &priv->caldata[channel->hw_value]; + ret = ath9k_hw_reset(ah, ah->curchan, caldata, false); + if (ret) { + ath_err(common, + "Unable to reset device (%u Mhz) reset status %d\n", + channel->center_freq, ret); + } + + ath_update_txpow(priv); + + WMI_CMD(WMI_START_RECV_CMDID); + ath9k_host_rx_init(priv); + + mode = ath9k_htc_get_curmode(priv, ah->curchan); + htc_mode = cpu_to_be16(mode); + WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); + + WMI_CMD(WMI_ENABLE_INTR_CMDID); + htc_start(priv->htc); + + if (priv->op_flags & OP_ASSOCIATED) { + ath9k_htc_beacon_config(priv, priv->vif); + ath_start_ani(priv); + } + + ieee80211_wake_queues(priv->hw); + + ath9k_htc_ps_restore(priv); + mutex_unlock(&priv->mutex); +} + static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, struct ieee80211_hw *hw, struct ath9k_channel *hchan) @@ -123,7 +177,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, struct ath_hw *ah = priv->ah; struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_conf *conf = &common->hw->conf; - bool fastcc = true; + bool fastcc; struct ieee80211_channel *channel = hw->conf.channel; struct ath9k_hw_cal_data *caldata; enum htc_phymode mode; @@ -134,8 +188,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, if (priv->op_flags & OP_INVALID) return -EIO; - if (priv->op_flags & OP_FULL_RESET) - fastcc = false; + fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); ath9k_htc_ps_wakeup(priv); htc_stop(priv->htc); @@ -143,18 +196,18 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); - ath_print(common, ATH_DBG_CONFIG, - "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", - priv->ah->curchan->channel, - channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf), - fastcc); + ath_dbg(common, ATH_DBG_CONFIG, + "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", + priv->ah->curchan->channel, + channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf), + fastcc); caldata = &priv->caldata[channel->hw_value]; ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset channel (%u Mhz) " - "reset status %d\n", channel->center_freq, ret); + ath_err(common, + "Unable to reset channel (%u Mhz) reset status %d\n", + channel->center_freq, ret); goto err; } @@ -177,23 +230,43 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, goto err; htc_start(priv->htc); - - priv->op_flags &= ~OP_FULL_RESET; err: ath9k_htc_ps_restore(priv); return ret; } +static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_target_vif hvif; + int ret = 0; + u8 cmd_rsp; + + memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); + memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); + hvif.index = 0; /* Should do for now */ + WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); + priv->nvifs--; +} + static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) { struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_htc_target_vif hvif; + struct ath9k_htc_target_sta tsta; int ret = 0; u8 cmd_rsp; if (priv->nvifs > 0) return -ENOBUFS; + if (priv->nstations >= ATH9K_HTC_MAX_STA) + return -ENOBUFS; + + /* + * Add an interface. + */ + memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); @@ -206,23 +279,57 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) return ret; priv->nvifs++; + + /* + * Associate a station with the interface for packet injection. + */ + + memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); + + memcpy(&tsta.macaddr, common->macaddr, ETH_ALEN); + + tsta.is_vif_sta = 1; + tsta.sta_index = priv->nstations; + tsta.vif_index = hvif.index; + tsta.maxampdu = 0xffff; + + WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); + if (ret) { + ath_err(common, "Unable to add station entry for monitor mode\n"); + goto err_vif; + } + + priv->nstations++; + return 0; + +err_vif: + /* + * Remove the interface from the target. + */ + __ath9k_htc_remove_monitor_interface(priv); + return ret; } static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) { struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_target_vif hvif; int ret = 0; - u8 cmd_rsp; + u8 cmd_rsp, sta_idx; - memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); - memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); - hvif.index = 0; /* Should do for now */ - WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); - priv->nvifs--; + __ath9k_htc_remove_monitor_interface(priv); - return ret; + sta_idx = 0; /* Only single interface, for now */ + + WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); + if (ret) { + ath_err(common, "Unable to remove station entry for monitor mode\n"); + return ret; + } + + priv->nstations--; + + return 0; } static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, @@ -263,15 +370,16 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); if (ret) { if (sta) - ath_print(common, ATH_DBG_FATAL, - "Unable to add station entry for: %pM\n", sta->addr); + ath_err(common, + "Unable to add station entry for: %pM\n", + sta->addr); return ret; } if (sta) - ath_print(common, ATH_DBG_CONFIG, - "Added a station entry for: %pM (idx: %d)\n", - sta->addr, tsta.sta_index); + ath_dbg(common, ATH_DBG_CONFIG, + "Added a station entry for: %pM (idx: %d)\n", + sta->addr, tsta.sta_index); priv->nstations++; return 0; @@ -296,16 +404,16 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); if (ret) { if (sta) - ath_print(common, ATH_DBG_FATAL, - "Unable to remove station entry for: %pM\n", - sta->addr); + ath_err(common, + "Unable to remove station entry for: %pM\n", + sta->addr); return ret; } if (sta) - ath_print(common, ATH_DBG_CONFIG, - "Removed a station entry for: %pM (idx: %d)\n", - sta->addr, sta_idx); + ath_dbg(common, ATH_DBG_CONFIG, + "Removed a station entry for: %pM (idx: %d)\n", + sta->addr, sta_idx); priv->nstations--; return 0; @@ -390,8 +498,8 @@ static int ath9k_htc_send_rate_cmd(struct ath9k_htc_priv *priv, WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, trate); if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to initialize Rate information on target\n"); + ath_err(common, + "Unable to initialize Rate information on target\n"); } return ret; @@ -408,9 +516,9 @@ static void ath9k_htc_init_rate(struct ath9k_htc_priv *priv, ath9k_htc_setup_rate(priv, sta, &trate); ret = ath9k_htc_send_rate_cmd(priv, &trate); if (!ret) - ath_print(common, ATH_DBG_CONFIG, - "Updated target sta: %pM, rate caps: 0x%X\n", - sta->addr, be32_to_cpu(trate.capflags)); + ath_dbg(common, ATH_DBG_CONFIG, + "Updated target sta: %pM, rate caps: 0x%X\n", + sta->addr, be32_to_cpu(trate.capflags)); } static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv, @@ -435,9 +543,9 @@ static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv, ret = ath9k_htc_send_rate_cmd(priv, &trate); if (!ret) - ath_print(common, ATH_DBG_CONFIG, - "Updated target sta: %pM, rate caps: 0x%X\n", - bss_conf->bssid, be32_to_cpu(trate.capflags)); + ath_dbg(common, ATH_DBG_CONFIG, + "Updated target sta: %pM, rate caps: 0x%X\n", + bss_conf->bssid, be32_to_cpu(trate.capflags)); } static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, @@ -464,14 +572,14 @@ static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); if (ret) - ath_print(common, ATH_DBG_CONFIG, - "Unable to %s TX aggregation for (%pM, %d)\n", - (aggr.aggr_enable) ? "start" : "stop", sta->addr, tid); + ath_dbg(common, ATH_DBG_CONFIG, + "Unable to %s TX aggregation for (%pM, %d)\n", + (aggr.aggr_enable) ? "start" : "stop", sta->addr, tid); else - ath_print(common, ATH_DBG_CONFIG, - "%s TX aggregation for (%pM, %d)\n", - (aggr.aggr_enable) ? "Starting" : "Stopping", - sta->addr, tid); + ath_dbg(common, ATH_DBG_CONFIG, + "%s TX aggregation for (%pM, %d)\n", + (aggr.aggr_enable) ? "Starting" : "Stopping", + sta->addr, tid); spin_lock_bh(&priv->tx_lock); ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; @@ -689,7 +797,7 @@ void ath9k_htc_debug_remove_root(void) /* ANI */ /*******/ -static void ath_start_ani(struct ath9k_htc_priv *priv) +void ath_start_ani(struct ath9k_htc_priv *priv) { struct ath_common *common = ath9k_hw_common(priv->ah); unsigned long timestamp = jiffies_to_msecs(jiffies); @@ -724,7 +832,7 @@ void ath9k_ani_work(struct work_struct *work) /* Long calibration runs independently of short calibration. */ if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { longcal = true; - ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); + ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); common->ani.longcal_timer = timestamp; } @@ -733,8 +841,8 @@ void ath9k_ani_work(struct work_struct *work) if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { shortcal = true; - ath_print(common, ATH_DBG_ANI, - "shortcal @%lu\n", jiffies); + ath_dbg(common, ATH_DBG_ANI, + "shortcal @%lu\n", jiffies); common->ani.shortcal_timer = timestamp; common->ani.resetcal_timer = timestamp; } @@ -788,317 +896,6 @@ set_timer: msecs_to_jiffies(cal_interval)); } -/*******/ -/* LED */ -/*******/ - -static void ath9k_led_blink_work(struct work_struct *work) -{ - struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, - ath9k_led_blink_work.work); - - if (!(priv->op_flags & OP_LED_ASSOCIATED)) - return; - - if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) || - (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); - else - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, - (priv->op_flags & OP_LED_ON) ? 1 : 0); - - ieee80211_queue_delayed_work(priv->hw, - &priv->ath9k_led_blink_work, - (priv->op_flags & OP_LED_ON) ? - msecs_to_jiffies(priv->led_off_duration) : - msecs_to_jiffies(priv->led_on_duration)); - - priv->led_on_duration = priv->led_on_cnt ? - max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) : - ATH_LED_ON_DURATION_IDLE; - priv->led_off_duration = priv->led_off_cnt ? - max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) : - ATH_LED_OFF_DURATION_IDLE; - priv->led_on_cnt = priv->led_off_cnt = 0; - - if (priv->op_flags & OP_LED_ON) - priv->op_flags &= ~OP_LED_ON; - else - priv->op_flags |= OP_LED_ON; -} - -static void ath9k_led_brightness_work(struct work_struct *work) -{ - struct ath_led *led = container_of(work, struct ath_led, - brightness_work.work); - struct ath9k_htc_priv *priv = led->priv; - - switch (led->brightness) { - case LED_OFF: - if (led->led_type == ATH_LED_ASSOC || - led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, - (led->led_type == ATH_LED_RADIO)); - priv->op_flags &= ~OP_LED_ASSOCIATED; - if (led->led_type == ATH_LED_RADIO) - priv->op_flags &= ~OP_LED_ON; - } else { - priv->led_off_cnt++; - } - break; - case LED_FULL: - if (led->led_type == ATH_LED_ASSOC) { - priv->op_flags |= OP_LED_ASSOCIATED; - ieee80211_queue_delayed_work(priv->hw, - &priv->ath9k_led_blink_work, 0); - } else if (led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); - priv->op_flags |= OP_LED_ON; - } else { - priv->led_on_cnt++; - } - break; - default: - break; - } -} - -static void ath9k_led_brightness(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); - struct ath9k_htc_priv *priv = led->priv; - - led->brightness = brightness; - if (!(priv->op_flags & OP_LED_DEINIT)) - ieee80211_queue_delayed_work(priv->hw, - &led->brightness_work, 0); -} - -static void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv) -{ - cancel_delayed_work_sync(&priv->radio_led.brightness_work); - cancel_delayed_work_sync(&priv->assoc_led.brightness_work); - cancel_delayed_work_sync(&priv->tx_led.brightness_work); - cancel_delayed_work_sync(&priv->rx_led.brightness_work); -} - -static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led, - char *trigger) -{ - int ret; - - led->priv = priv; - led->led_cdev.name = led->name; - led->led_cdev.default_trigger = trigger; - led->led_cdev.brightness_set = ath9k_led_brightness; - - ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev); - if (ret) - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, - "Failed to register led:%s", led->name); - else - led->registered = 1; - - INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work); - - return ret; -} - -static void ath9k_unregister_led(struct ath_led *led) -{ - if (led->registered) { - led_classdev_unregister(&led->led_cdev); - led->registered = 0; - } -} - -void ath9k_deinit_leds(struct ath9k_htc_priv *priv) -{ - priv->op_flags |= OP_LED_DEINIT; - ath9k_unregister_led(&priv->assoc_led); - priv->op_flags &= ~OP_LED_ASSOCIATED; - ath9k_unregister_led(&priv->tx_led); - ath9k_unregister_led(&priv->rx_led); - ath9k_unregister_led(&priv->radio_led); -} - -void ath9k_init_leds(struct ath9k_htc_priv *priv) -{ - char *trigger; - int ret; - - if (AR_SREV_9287(priv->ah)) - priv->ah->led_pin = ATH_LED_PIN_9287; - else if (AR_SREV_9271(priv->ah)) - priv->ah->led_pin = ATH_LED_PIN_9271; - else if (AR_DEVID_7010(priv->ah)) - priv->ah->led_pin = ATH_LED_PIN_7010; - else - priv->ah->led_pin = ATH_LED_PIN_DEF; - - /* Configure gpio 1 for output */ - ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - /* LED off, active low */ - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); - - INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work); - - trigger = ieee80211_get_radio_led_name(priv->hw); - snprintf(priv->radio_led.name, sizeof(priv->radio_led.name), - "ath9k-%s::radio", wiphy_name(priv->hw->wiphy)); - ret = ath9k_register_led(priv, &priv->radio_led, trigger); - priv->radio_led.led_type = ATH_LED_RADIO; - if (ret) - goto fail; - - trigger = ieee80211_get_assoc_led_name(priv->hw); - snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name), - "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy)); - ret = ath9k_register_led(priv, &priv->assoc_led, trigger); - priv->assoc_led.led_type = ATH_LED_ASSOC; - if (ret) - goto fail; - - trigger = ieee80211_get_tx_led_name(priv->hw); - snprintf(priv->tx_led.name, sizeof(priv->tx_led.name), - "ath9k-%s::tx", wiphy_name(priv->hw->wiphy)); - ret = ath9k_register_led(priv, &priv->tx_led, trigger); - priv->tx_led.led_type = ATH_LED_TX; - if (ret) - goto fail; - - trigger = ieee80211_get_rx_led_name(priv->hw); - snprintf(priv->rx_led.name, sizeof(priv->rx_led.name), - "ath9k-%s::rx", wiphy_name(priv->hw->wiphy)); - ret = ath9k_register_led(priv, &priv->rx_led, trigger); - priv->rx_led.led_type = ATH_LED_RX; - if (ret) - goto fail; - - priv->op_flags &= ~OP_LED_DEINIT; - - return; - -fail: - cancel_delayed_work_sync(&priv->ath9k_led_blink_work); - ath9k_deinit_leds(priv); -} - -/*******************/ -/* Rfkill */ -/*******************/ - -static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv) -{ - return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) == - priv->ah->rfkill_polarity; -} - -static void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw) -{ - struct ath9k_htc_priv *priv = hw->priv; - bool blocked = !!ath_is_rfkill_set(priv); - - wiphy_rfkill_set_hw_state(hw->wiphy, blocked); -} - -void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv) -{ - if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - wiphy_rfkill_start_polling(priv->hw->wiphy); -} - -static void ath9k_htc_radio_enable(struct ieee80211_hw *hw) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ath_hw *ah = priv->ah; - struct ath_common *common = ath9k_hw_common(ah); - int ret; - u8 cmd_rsp; - - if (!ah->curchan) - ah->curchan = ath9k_cmn_get_curchannel(hw, ah); - - /* Reset the HW */ - ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); - if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d " - "(freq %u MHz)\n", ret, ah->curchan->channel); - } - - ath_update_txpow(priv); - - /* Start RX */ - WMI_CMD(WMI_START_RECV_CMDID); - ath9k_host_rx_init(priv); - - /* Start TX */ - htc_start(priv->htc); - spin_lock_bh(&priv->tx_lock); - priv->tx_queues_stop = false; - spin_unlock_bh(&priv->tx_lock); - ieee80211_wake_queues(hw); - - WMI_CMD(WMI_ENABLE_INTR_CMDID); - - /* Enable LED */ - ath9k_hw_cfg_output(ah, ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(ah, ah->led_pin, 0); -} - -static void ath9k_htc_radio_disable(struct ieee80211_hw *hw) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ath_hw *ah = priv->ah; - struct ath_common *common = ath9k_hw_common(ah); - int ret; - u8 cmd_rsp; - - ath9k_htc_ps_wakeup(priv); - - /* Disable LED */ - ath9k_hw_set_gpio(ah, ah->led_pin, 1); - ath9k_hw_cfg_gpio_input(ah, ah->led_pin); - - WMI_CMD(WMI_DISABLE_INTR_CMDID); - - /* Stop TX */ - ieee80211_stop_queues(hw); - htc_stop(priv->htc); - WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); - skb_queue_purge(&priv->tx_queue); - - /* Stop RX */ - WMI_CMD(WMI_STOP_RECV_CMDID); - - /* - * The MIB counters have to be disabled here, - * since the target doesn't do it. - */ - ath9k_hw_disable_mib_counters(ah); - - if (!ah->curchan) - ah->curchan = ath9k_cmn_get_curchannel(hw, ah); - - /* Reset the HW */ - ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); - if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d " - "(freq %u MHz)\n", ret, ah->curchan->channel); - } - - /* Disable the PHY */ - ath9k_hw_phy_disable(ah); - - ath9k_htc_ps_restore(priv); - ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); -} - /**********************/ /* mac80211 Callbacks */ /**********************/ @@ -1124,15 +921,15 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) ret = ath9k_htc_tx_start(priv, skb); if (ret != 0) { if (ret == -ENOMEM) { - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, - "Stopping TX queues\n"); + ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, + "Stopping TX queues\n"); ieee80211_stop_queues(hw); spin_lock_bh(&priv->tx_lock); priv->tx_queues_stop = true; spin_unlock_bh(&priv->tx_lock); } else { - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, - "Tx failed"); + ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, + "Tx failed\n"); } goto fail_tx; } @@ -1158,9 +955,9 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) mutex_lock(&priv->mutex); - ath_print(common, ATH_DBG_CONFIG, - "Starting driver with initial channel: %d MHz\n", - curchan->center_freq); + ath_dbg(common, ATH_DBG_CONFIG, + "Starting driver with initial channel: %d MHz\n", + curchan->center_freq); /* Ensure that HW is awake before flushing RX */ ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); @@ -1169,15 +966,12 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) /* setup initial channel */ init_channel = ath9k_cmn_get_curchannel(hw, ah); - /* Reset SERDES registers */ - ath9k_hw_configpcipowersave(ah, 0, 0); - ath9k_hw_htc_resetinit(ah); ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false); if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d " - "(freq %u MHz)\n", ret, curchan->center_freq); + ath_err(common, + "Unable to reset hardware; reset status %d (freq %u MHz)\n", + ret, curchan->center_freq); mutex_unlock(&priv->mutex); return ret; } @@ -1220,19 +1014,20 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) int ret = 0; u8 cmd_rsp; + /* Cancel all the running timers/work .. */ + cancel_work_sync(&priv->fatal_work); + cancel_work_sync(&priv->ps_work); + cancel_delayed_work_sync(&priv->ath9k_led_blink_work); + ath9k_led_stop_brightness(priv); + mutex_lock(&priv->mutex); if (priv->op_flags & OP_INVALID) { - ath_print(common, ATH_DBG_ANY, "Device not present\n"); + ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); mutex_unlock(&priv->mutex); return; } - /* Cancel all the running timers/work .. */ - cancel_work_sync(&priv->ps_work); - cancel_delayed_work_sync(&priv->ath9k_led_blink_work); - ath9k_led_stop_brightness(priv); - ath9k_htc_ps_wakeup(priv); htc_stop(priv->htc); WMI_CMD(WMI_DISABLE_INTR_CMDID); @@ -1243,11 +1038,10 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) /* Remove monitor interface here */ if (ah->opmode == NL80211_IFTYPE_MONITOR) { if (ath9k_htc_remove_monitor_interface(priv)) - ath_print(common, ATH_DBG_FATAL, - "Unable to remove monitor interface\n"); + ath_err(common, "Unable to remove monitor interface\n"); else - ath_print(common, ATH_DBG_CONFIG, - "Monitor interface removed\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "Monitor interface removed\n"); } if (ah->btcoex_hw.enabled) { @@ -1258,13 +1052,12 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) ath9k_hw_phy_disable(ah); ath9k_hw_disable(ah); - ath9k_hw_configpcipowersave(ah, 1, 1); ath9k_htc_ps_restore(priv); ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); priv->op_flags |= OP_INVALID; - ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n"); mutex_unlock(&priv->mutex); } @@ -1298,14 +1091,14 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, hvif.opmode = cpu_to_be32(HTC_M_IBSS); break; default: - ath_print(common, ATH_DBG_FATAL, + ath_err(common, "Interface type %d not yet supported\n", vif->type); ret = -EOPNOTSUPP; goto out; } - ath_print(common, ATH_DBG_CONFIG, - "Attach a VIF of type: %d\n", vif->type); + ath_dbg(common, ATH_DBG_CONFIG, + "Attach a VIF of type: %d\n", vif->type); priv->ah->opmode = vif->type; @@ -1328,8 +1121,8 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, ret = ath9k_htc_update_cap_target(priv); if (ret) - ath_print(common, ATH_DBG_CONFIG, "Failed to update" - " capability in target \n"); + ath_dbg(common, ATH_DBG_CONFIG, + "Failed to update capability in target\n"); priv->vif = vif; out: @@ -1349,7 +1142,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, int ret = 0; u8 cmd_rsp; - ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n"); mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); @@ -1386,8 +1179,8 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) mutex_unlock(&priv->htc_pm_lock); if (enable_radio) { - ath_print(common, ATH_DBG_CONFIG, - "not-idle: enabling radio\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "not-idle: enabling radio\n"); ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); ath9k_htc_radio_enable(hw); } @@ -1397,19 +1190,21 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) struct ieee80211_channel *curchan = hw->conf.channel; int pos = curchan->hw_value; - ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", - curchan->center_freq); + ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", + curchan->center_freq); - ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]); + ath9k_cmn_update_ichannel(&priv->ah->channels[pos], + hw->conf.channel, + hw->conf.channel_type); if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { - ath_print(common, ATH_DBG_FATAL, - "Unable to set channel\n"); + ath_err(common, "Unable to set channel\n"); mutex_unlock(&priv->mutex); return -EINVAL; } } + if (changed & IEEE80211_CONF_CHANGE_PS) { if (conf->flags & IEEE80211_CONF_PS) { ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); @@ -1421,14 +1216,18 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) } } + if (changed & IEEE80211_CONF_CHANGE_POWER) { + priv->txpowlimit = 2 * conf->power_level; + ath_update_txpow(priv); + } + if (changed & IEEE80211_CONF_CHANGE_MONITOR) { if (conf->flags & IEEE80211_CONF_MONITOR) { if (ath9k_htc_add_monitor_interface(priv)) - ath_print(common, ATH_DBG_FATAL, - "Failed to set monitor mode\n"); + ath_err(common, "Failed to set monitor mode\n"); else - ath_print(common, ATH_DBG_CONFIG, - "HW opmode set to Monitor mode\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "HW opmode set to Monitor mode\n"); } } @@ -1440,8 +1239,8 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) } mutex_unlock(&priv->htc_pm_lock); - ath_print(common, ATH_DBG_CONFIG, - "idle: disabling radio\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "idle: disabling radio\n"); ath9k_htc_radio_disable(hw); } @@ -1478,8 +1277,8 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, rfilt = ath9k_htc_calcrxfilter(priv); ath9k_hw_setrxfilter(priv->ah, rfilt); - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, - "Set HW RX filter: 0x%x\n", rfilt); + ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, + "Set HW RX filter: 0x%x\n", rfilt); ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); @@ -1542,15 +1341,14 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, qnum = get_hw_qnum(queue, priv->hwq_map); - ath_print(common, ATH_DBG_CONFIG, - "Configure tx [queue/hwq] [%d/%d], " - "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", - queue, qnum, params->aifs, params->cw_min, - params->cw_max, params->txop); + ath_dbg(common, ATH_DBG_CONFIG, + "Configure tx [queue/hwq] [%d/%d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", + queue, qnum, params->aifs, params->cw_min, + params->cw_max, params->txop); ret = ath_htc_txq_update(priv, qnum, &qi); if (ret) { - ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); + ath_err(common, "TXQ Update failed\n"); goto out; } @@ -1578,7 +1376,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, return -ENOSPC; mutex_lock(&priv->mutex); - ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Set HW Key\n"); ath9k_htc_ps_wakeup(priv); switch (cmd) { @@ -1624,7 +1422,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) { common->curaid = bss_conf->assoc ? bss_conf->aid : 0; - ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", bss_conf->assoc); if (bss_conf->assoc) { @@ -1641,9 +1439,9 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); ath9k_hw_write_associd(ah); - ath_print(common, ATH_DBG_CONFIG, - "BSSID: %pM aid: 0x%x\n", - common->curbssid, common->curaid); + ath_dbg(common, ATH_DBG_CONFIG, + "BSSID: %pM aid: 0x%x\n", + common->curbssid, common->curaid); } if ((changed & BSS_CHANGED_BEACON_INT) || @@ -1661,8 +1459,8 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ERP_PREAMBLE) { - ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", - bss_conf->use_short_preamble); + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", + bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) priv->op_flags |= OP_PREAMBLE_SHORT; else @@ -1670,8 +1468,8 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ERP_CTS_PROT) { - ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", - bss_conf->use_cts_prot); + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", + bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && hw->conf.channel->band != IEEE80211_BAND_5GHZ) priv->op_flags |= OP_PROTECT_ENABLE; @@ -1762,8 +1560,7 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, spin_unlock_bh(&priv->tx_lock); break; default: - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, - "Unknown AMPDU action\n"); + ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); } return ret; @@ -1792,7 +1589,6 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) spin_lock_bh(&priv->beacon_lock); priv->op_flags &= ~OP_SCANNING; spin_unlock_bh(&priv->beacon_lock); - priv->op_flags |= OP_FULL_RESET; if (priv->op_flags & OP_ASSOCIATED) { ath9k_htc_beacon_config(priv, priv->vif); ath_start_ani(priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 29d80ca78393..33f36029fa4f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -20,8 +20,15 @@ /* TX */ /******/ +static const int subtype_txq_to_hwq[] = { + [WME_AC_BE] = ATH_TXQ_AC_BE, + [WME_AC_BK] = ATH_TXQ_AC_BK, + [WME_AC_VI] = ATH_TXQ_AC_VI, + [WME_AC_VO] = ATH_TXQ_AC_VO, +}; + #define ATH9K_HTC_INIT_TXQ(subtype) do { \ - qi.tqi_subtype = subtype; \ + qi.tqi_subtype = subtype_txq_to_hwq[subtype]; \ qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; \ qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; \ qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; \ @@ -62,8 +69,8 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, qi.tqi_readyTime = qinfo->tqi_readyTime; if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "Unable to update hardware queue %u!\n", qnum); + ath_err(ath9k_hw_common(ah), + "Unable to update hardware queue %u!\n", qnum); error = -EIO; } else { ath9k_hw_resettxqueue(ah, qnum); @@ -244,7 +251,7 @@ void ath9k_tx_tasklet(unsigned long data) ista = (struct ath9k_htc_sta *)sta->drv_priv; if (ath9k_htc_check_tx_aggr(priv, ista, tid)) { - ieee80211_start_tx_ba_session(sta, tid); + ieee80211_start_tx_ba_session(sta, tid, 0); spin_lock_bh(&priv->tx_lock); ista->tid_state[tid] = AGGR_PROGRESS; spin_unlock_bh(&priv->tx_lock); @@ -263,8 +270,8 @@ void ath9k_tx_tasklet(unsigned long data) if (priv->tx_queues_stop) { priv->tx_queues_stop = false; spin_unlock_bh(&priv->tx_lock); - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, - "Waking up TX queues\n"); + ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, + "Waking up TX queues\n"); ieee80211_wake_queues(priv->hw); return; } @@ -289,8 +296,7 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, (ep_id == priv->data_vo_ep)) { skb_pull(skb, sizeof(struct tx_frame_hdr)); } else { - ath_print(common, ATH_DBG_FATAL, - "Unsupported TX EPID: %d\n", ep_id); + ath_err(common, "Unsupported TX EPID: %d\n", ep_id); dev_kfree_skb_any(skb); return; } @@ -330,9 +336,8 @@ bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype) return false; if (qnum >= ARRAY_SIZE(priv->hwq_map)) { - ath_print(common, ATH_DBG_FATAL, - "qnum %u out of range, max %u!\n", - qnum, (unsigned int)ARRAY_SIZE(priv->hwq_map)); + ath_err(common, "qnum %u out of range, max %zu!\n", + qnum, ARRAY_SIZE(priv->hwq_map)); ath9k_hw_releasetxqueue(ah, qnum); return false; } @@ -483,8 +488,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, __le16 fc; if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) { - ath_print(common, ATH_DBG_FATAL, - "Corrupted RX frame, dropping\n"); + ath_err(common, "Corrupted RX frame, dropping\n"); goto rx_next; } @@ -492,10 +496,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, if (be16_to_cpu(rxstatus->rs_datalen) - (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) { - ath_print(common, ATH_DBG_FATAL, - "Corrupted RX data len, dropping " - "(dlen: %d, skblen: %d)\n", - rxstatus->rs_datalen, skb->len); + ath_err(common, + "Corrupted RX data len, dropping (dlen: %d, skblen: %d)\n", + rxstatus->rs_datalen, skb->len); goto rx_next; } @@ -678,8 +681,8 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, spin_unlock(&priv->rx.rxbuflock); if (rxbuf == NULL) { - ath_print(common, ATH_DBG_ANY, - "No free RX buffer\n"); + ath_dbg(common, ATH_DBG_ANY, + "No free RX buffer\n"); goto err; } @@ -721,8 +724,7 @@ int ath9k_rx_init(struct ath9k_htc_priv *priv) for (i = 0; i < ATH9K_HTC_RXBUF; i++) { rxbuf = kzalloc(sizeof(struct ath9k_htc_rxbuf), GFP_KERNEL); if (rxbuf == NULL) { - ath_print(common, ATH_DBG_FATAL, - "Unable to allocate RX buffers\n"); + ath_err(common, "Unable to allocate RX buffers\n"); goto err; } list_add_tail(&rxbuf->list, &priv->rx.rxbuf); diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 861ec9269309..c41ab8c30161 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -462,9 +462,10 @@ void ath9k_htc_hw_free(struct htc_target *htc) } int ath9k_htc_hw_init(struct htc_target *target, - struct device *dev, u16 devid, char *product) + struct device *dev, u16 devid, + char *product, u32 drv_info) { - if (ath9k_htc_probe_device(target, dev, devid, product)) { + if (ath9k_htc_probe_device(target, dev, devid, product, drv_info)) { printk(KERN_ERR "Failed to initialize the device\n"); return -ENODEV; } diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index 07b6509d5896..ecd018798c47 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -77,20 +77,6 @@ struct htc_config_pipe_msg { u8 credits; } __packed; -struct htc_packet { - void *pktcontext; - u8 *buf; - u8 *buf_payload; - u32 buflen; - u32 payload_len; - - int endpoint; - int status; - - void *context; - u32 reserved; -}; - struct htc_ep_callbacks { void *priv; void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok); @@ -123,11 +109,6 @@ struct htc_endpoint { #define HTC_CONTROL_BUFFER_SIZE \ (HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr)) -struct htc_control_buf { - struct htc_packet htc_pkt; - u8 buf[HTC_CONTROL_BUFFER_SIZE]; -}; - #define HTC_OP_START_WAIT BIT(0) #define HTC_OP_CONFIG_PIPE_CREDITS BIT(1) @@ -239,7 +220,8 @@ struct htc_target *ath9k_htc_hw_alloc(void *hif_handle, struct device *dev); void ath9k_htc_hw_free(struct htc_target *htc); int ath9k_htc_hw_init(struct htc_target *target, - struct device *dev, u16 devid, char *product); + struct device *dev, u16 devid, char *product, + u32 drv_info); void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug); #endif /* HTC_HST_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 0a4ad348b699..c8f254fe0f0b 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -223,11 +223,6 @@ static inline void ath9k_hw_rfbus_done(struct ath_hw *ah) return ath9k_hw_private_ops(ah)->rfbus_done(ah); } -static inline void ath9k_enable_rfkill(struct ath_hw *ah) -{ - return ath9k_hw_private_ops(ah)->enable_rfkill(ah); -} - static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah) { if (!ath9k_hw_private_ops(ah)->restore_chainmask) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index c7fbe25cc128..fde978665e07 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -54,13 +54,6 @@ static void ath9k_hw_init_mode_regs(struct ath_hw *ah) ath9k_hw_private_ops(ah)->init_mode_regs(ah); } -static bool ath9k_hw_macversion_supported(struct ath_hw *ah) -{ - struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); - - return priv_ops->macversion_supported(ah->hw_version.macVersion); -} - static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah, struct ath9k_channel *chan) { @@ -129,9 +122,9 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) udelay(AH_TIME_QUANTUM); } - ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, - "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", - timeout, reg, REG_READ(ah, reg), mask, val); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_ANY, + "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", + timeout, reg, REG_READ(ah, reg), mask, val); return false; } @@ -211,8 +204,8 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah, } break; default: - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "Unknown phy %u (rate ix %u)\n", phy, rateix); + ath_err(ath9k_hw_common(ah), + "Unknown phy %u (rate ix %u)\n", phy, rateix); txTime = 0; break; } @@ -284,11 +277,9 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) static void ath9k_hw_disablepcie(struct ath_hw *ah) { - if (AR_SREV_9100(ah)) + if (!AR_SREV_5416(ah)) return; - ENABLE_REGWRITE_BUFFER(ah); - REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029); @@ -300,8 +291,6 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah) REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007); REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); - - REGWRITE_BUFFER_FLUSH(ah); } /* This should work for all families including legacy */ @@ -310,10 +299,9 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); u32 regAddr[2] = { AR_STA_ID0 }; u32 regHold[2]; - u32 patternData[4] = { 0x55555555, - 0xaaaaaaaa, - 0x66666666, - 0x99999999 }; + static const u32 patternData[4] = { + 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 + }; int i, j, loop_max; if (!AR_SREV_9300_20_OR_LATER(ah)) { @@ -332,11 +320,9 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) REG_WRITE(ah, addr, wrData); rdData = REG_READ(ah, addr); if (rdData != wrData) { - ath_print(common, ATH_DBG_FATAL, - "address test failed " - "addr: 0x%08x - wr:0x%08x != " - "rd:0x%08x\n", - addr, wrData, rdData); + ath_err(common, + "address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", + addr, wrData, rdData); return false; } } @@ -345,11 +331,9 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) REG_WRITE(ah, addr, wrData); rdData = REG_READ(ah, addr); if (wrData != rdData) { - ath_print(common, ATH_DBG_FATAL, - "address test failed " - "addr: 0x%08x - wr:0x%08x != " - "rd:0x%08x\n", - addr, wrData, rdData); + ath_err(common, + "address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", + addr, wrData, rdData); return false; } } @@ -419,17 +403,12 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) ah->hw_version.magic = AR5416_MAGIC; ah->hw_version.subvendorid = 0; - ah->ah_flags = 0; - if (!AR_SREV_9100(ah)) - ah->ah_flags = AH_USE_EEPROM; - ah->atim_window = 0; ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE | AR_STA_ID1_MCAST_KSRCH; - ah->beacon_interval = 100; ah->enable_32kHz_clock = DONT_USE_32KHZ; - ah->slottime = (u32) -1; + ah->slottime = 20; ah->globaltxtimeout = (u32) -1; ah->power_mode = ATH9K_PM_UNDEFINED; } @@ -440,7 +419,7 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) u32 sum; int i; u16 eeval; - u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW }; + static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW }; sum = 0; for (i = 0; i < 3; i++) { @@ -474,16 +453,15 @@ static int ath9k_hw_post_init(struct ath_hw *ah) if (ecode != 0) return ecode; - ath_print(ath9k_hw_common(ah), ATH_DBG_CONFIG, - "Eeprom VER: %d, REV: %d\n", - ah->eep_ops->get_eeprom_ver(ah), - ah->eep_ops->get_eeprom_rev(ah)); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_CONFIG, + "Eeprom VER: %d, REV: %d\n", + ah->eep_ops->get_eeprom_ver(ah), + ah->eep_ops->get_eeprom_rev(ah)); ecode = ath9k_hw_rf_alloc_ext_banks(ah); if (ecode) { - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "Failed allocating banks for " - "external radio\n"); + ath_err(ath9k_hw_common(ah), + "Failed allocating banks for external radio\n"); ath9k_hw_rf_free_ext_banks(ah); return ecode; } @@ -514,8 +492,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) ah->hw_version.macVersion = AR_SREV_VERSION_9100; if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { - ath_print(common, ATH_DBG_FATAL, - "Couldn't reset chip\n"); + ath_err(common, "Couldn't reset chip\n"); return -EIO; } @@ -525,7 +502,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) ath9k_hw_attach_ops(ah); if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { - ath_print(common, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); + ath_err(common, "Couldn't wakeup chip\n"); return -EIO; } @@ -541,7 +518,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) } } - ath_print(common, ATH_DBG_RESET, "serialize_regmode is %d\n", + ath_dbg(common, ATH_DBG_RESET, "serialize_regmode is %d\n", ah->config.serialize_regmode); if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) @@ -549,11 +526,22 @@ static int __ath9k_hw_init(struct ath_hw *ah) else ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD; - if (!ath9k_hw_macversion_supported(ah)) { - ath_print(common, ATH_DBG_FATAL, - "Mac Chip Rev 0x%02x.%x is not supported by " - "this driver\n", ah->hw_version.macVersion, - ah->hw_version.macRev); + switch (ah->hw_version.macVersion) { + case AR_SREV_VERSION_5416_PCI: + case AR_SREV_VERSION_5416_PCIE: + case AR_SREV_VERSION_9160: + case AR_SREV_VERSION_9100: + case AR_SREV_VERSION_9280: + case AR_SREV_VERSION_9285: + case AR_SREV_VERSION_9287: + case AR_SREV_VERSION_9271: + case AR_SREV_VERSION_9300: + case AR_SREV_VERSION_9485: + break; + default: + ath_err(common, + "Mac Chip Rev 0x%02x.%x is not supported by this driver\n", + ah->hw_version.macVersion, ah->hw_version.macRev); return -EOPNOTSUPP; } @@ -599,8 +587,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) r = ath9k_hw_init_macaddr(ah); if (r) { - ath_print(common, ATH_DBG_FATAL, - "Failed to initialize MAC address\n"); + ath_err(common, "Failed to initialize MAC address\n"); return r; } @@ -634,21 +621,21 @@ int ath9k_hw_init(struct ath_hw *ah) case AR9287_DEVID_PCIE: case AR2427_DEVID_PCIE: case AR9300_DEVID_PCIE: + case AR9300_DEVID_AR9485_PCIE: break; default: if (common->bus_ops->ath_bus_type == ATH_USB) break; - ath_print(common, ATH_DBG_FATAL, - "Hardware device ID 0x%04x not supported\n", - ah->hw_version.devid); + ath_err(common, "Hardware device ID 0x%04x not supported\n", + ah->hw_version.devid); return -EOPNOTSUPP; } ret = __ath9k_hw_init(ah); if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to initialize hardware; " - "initialization status: %d\n", ret); + ath_err(common, + "Unable to initialize hardware; initialization status: %d\n", + ret); return ret; } @@ -680,7 +667,12 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) static void ath9k_hw_init_pll(struct ath_hw *ah, struct ath9k_channel *chan) { - u32 pll = ath9k_hw_compute_pll_control(ah, chan); + u32 pll; + + if (AR_SREV_9485(ah)) + REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); + + pll = ath9k_hw_compute_pll_control(ah, chan); REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); @@ -772,8 +764,8 @@ static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) { if (tu > 0xFFFF) { - ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT, - "bad global tx timeout %u\n", tu); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT, + "bad global tx timeout %u\n", tu); ah->globaltxtimeout = (u32) -1; return false; } else { @@ -790,8 +782,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) int slottime; int sifstime; - ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", - ah->misc_mode); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", + ah->misc_mode); if (ah->misc_mode != 0) REG_WRITE(ah, AR_PCU_MISC, @@ -816,7 +808,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) acktimeout += 64 - sifstime - ah->slottime; - ath9k_hw_setslottime(ah, slottime); + ath9k_hw_setslottime(ah, ah->slottime); ath9k_hw_set_ack_timeout(ah, acktimeout); ath9k_hw_set_cts_timeout(ah, acktimeout); if (ah->globaltxtimeout != (u32) -1) @@ -1034,8 +1026,8 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) REG_WRITE(ah, AR_RTC_RC, 0); if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { - ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, - "RTC stuck in MAC reset\n"); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, + "RTC stuck in MAC reset\n"); return false; } @@ -1081,8 +1073,8 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) AR_RTC_STATUS_M, AR_RTC_STATUS_ON, AH_WAIT_TIMEOUT)) { - ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, - "RTC not waking up\n"); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, + "RTC not waking up\n"); return false; } @@ -1142,16 +1134,14 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { if (ath9k_hw_numtxpending(ah, qnum)) { - ath_print(common, ATH_DBG_QUEUE, - "Transmit frames pending on " - "queue %d\n", qnum); + ath_dbg(common, ATH_DBG_QUEUE, + "Transmit frames pending on queue %d\n", qnum); return false; } } if (!ath9k_hw_rfbus_req(ah)) { - ath_print(common, ATH_DBG_FATAL, - "Could not kill baseband RX\n"); + ath_err(common, "Could not kill baseband RX\n"); return false; } @@ -1159,8 +1149,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, r = ath9k_hw_rf_set_freq(ah, chan); if (r) { - ath_print(common, ATH_DBG_FATAL, - "Failed to set channel\n"); + ath_err(common, "Failed to set channel\n"); return false; } ath9k_hw_set_clockrate(ah); @@ -1170,7 +1159,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit)); + (u32) regulatory->power_limit), false); ath9k_hw_rfbus_done(ah); @@ -1227,7 +1216,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (!ah->chip_fullsleep) { ath9k_hw_abortpcurecv(ah); if (!ath9k_hw_stopdmarecv(ah)) { - ath_print(common, ATH_DBG_XMIT, + ath_dbg(common, ATH_DBG_XMIT, "Failed to stop receive dma\n"); bChannelChange = false; } @@ -1283,6 +1272,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_mark_phy_inactive(ah); + ah->paprd_table_write_done = false; + /* Only required on the first reset */ if (AR_SREV_9271(ah) && ah->htc_reset_init) { REG_WRITE(ah, @@ -1292,7 +1283,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, } if (!ath9k_hw_chip_reset(ah, chan)) { - ath_print(common, ATH_DBG_FATAL, "Chip reset failed\n"); + ath_err(common, "Chip reset failed\n"); return -EINVAL; } @@ -1394,7 +1385,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_init_qos(ah); if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - ath9k_enable_rfkill(ah); + ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); ath9k_hw_init_global_settings(ah); @@ -1439,13 +1430,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, u32 mask; mask = REG_READ(ah, AR_CFG); if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { - ath_print(common, ATH_DBG_RESET, + ath_dbg(common, ATH_DBG_RESET, "CFG Byte Swap Set 0x%x\n", mask); } else { mask = INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; REG_WRITE(ah, AR_CFG, mask); - ath_print(common, ATH_DBG_RESET, + ath_dbg(common, ATH_DBG_RESET, "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); } } else { @@ -1573,9 +1564,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) AR_RTC_FORCE_WAKE_EN); } if (i == 0) { - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "Failed to wakeup in %uus\n", - POWER_UP_TIME / 20); + ath_err(ath9k_hw_common(ah), + "Failed to wakeup in %uus\n", + POWER_UP_TIME / 20); return false; } } @@ -1599,8 +1590,8 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) if (ah->power_mode == mode) return status; - ath_print(common, ATH_DBG_RESET, "%s -> %s\n", - modes[ah->power_mode], modes[mode]); + ath_dbg(common, ATH_DBG_RESET, "%s -> %s\n", + modes[ah->power_mode], modes[mode]); switch (mode) { case ATH9K_PM_AWAKE: @@ -1614,12 +1605,20 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) ath9k_set_power_network_sleep(ah, setChip); break; default: - ath_print(common, ATH_DBG_FATAL, - "Unknown power mode %u\n", mode); + ath_err(common, "Unknown power mode %u\n", mode); return false; } ah->power_mode = mode; + /* + * XXX: If this warning never comes up after a while then + * simply keep the ATH_DBG_WARN_ON_ONCE() but make + * ath9k_hw_setpower() return type void. + */ + + if (!(ah->ah_flags & AH_UNPLUGGED)) + ATH_DBG_WARN_ON_ONCE(!status); + return status; } EXPORT_SYMBOL(ath9k_hw_setpower); @@ -1632,17 +1631,9 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) { int flags = 0; - ah->beacon_interval = beacon_period; - ENABLE_REGWRITE_BUFFER(ah); switch (ah->opmode) { - case NL80211_IFTYPE_STATION: - REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); - REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff); - REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff); - flags |= AR_TBTT_TIMER_EN; - break; case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: REG_SET_BIT(ah, AR_TXCFG, @@ -1666,17 +1657,9 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; break; default: - if (ah->is_monitoring) { - REG_WRITE(ah, AR_NEXT_TBTT_TIMER, - TU_TO_USEC(next_beacon)); - REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff); - REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff); - flags |= AR_TBTT_TIMER_EN; - break; - } - ath_print(ath9k_hw_common(ah), ATH_DBG_BEACON, - "%s: unsupported opmode: %d\n", - __func__, ah->opmode); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_BEACON, + "%s: unsupported opmode: %d\n", + __func__, ah->opmode); return; break; } @@ -1732,10 +1715,10 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, else nextTbtt = bs->bs_nexttbtt; - ath_print(common, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim); - ath_print(common, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt); - ath_print(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval); - ath_print(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); + ath_dbg(common, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim); + ath_dbg(common, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt); + ath_dbg(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval); + ath_dbg(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); ENABLE_REGWRITE_BUFFER(ah); @@ -1781,7 +1764,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; u16 capField = 0, eeval; - u8 ant_div_ctl1; + u8 ant_div_ctl1, tx_chainmask, rx_chainmask; eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); regulatory->current_rd = eeval; @@ -1800,14 +1783,14 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) regulatory->current_rd += 5; else if (regulatory->current_rd == 0x41) regulatory->current_rd = 0x43; - ath_print(common, ATH_DBG_REGULATORY, - "regdomain mapped to 0x%x\n", regulatory->current_rd); + ath_dbg(common, ATH_DBG_REGULATORY, + "regdomain mapped to 0x%x\n", regulatory->current_rd); } eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) { - ath_print(common, ATH_DBG_FATAL, - "no band has been marked as supported in EEPROM.\n"); + ath_err(common, + "no band has been marked as supported in EEPROM\n"); return -EINVAL; } @@ -1833,6 +1816,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; + /* enable key search for every frame in an aggregate */ + if (AR_SREV_9300_20_OR_LATER(ah)) + ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH; + pCap->low_2ghz_chan = 2312; pCap->high_2ghz_chan = 2732; @@ -1921,13 +1908,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) AR_SREV_5416(ah)) pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; - pCap->num_antcfg_5ghz = - ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ); - pCap->num_antcfg_2ghz = - ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); - - if (AR_SREV_9280_20_OR_LATER(ah) && - ath9k_hw_btcoex_supported(ah)) { + if (AR_SREV_9280_20_OR_LATER(ah) && common->btcoex_enabled) { btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO; @@ -1942,8 +1923,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) } if (AR_SREV_9300_20_OR_LATER(ah)) { - pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_LDPC | - ATH9K_HW_CAP_FASTCLOCK; + pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK; + if (!AR_SREV_9485(ah)) + pCap->hw_caps |= ATH9K_HW_CAP_LDPC; + pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH; pCap->rx_status_len = sizeof(struct ar9003_rxs); @@ -1963,6 +1946,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if (AR_SREV_9300_20_OR_LATER(ah)) pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED; + if (AR_SREV_9300_20_OR_LATER(ah)) + ah->ent_mode = REG_READ(ah, AR_ENT_OTP); + if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah)) pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; @@ -1973,6 +1959,29 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; } + if (AR_SREV_9300_20_OR_LATER(ah)) { + if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE)) + pCap->hw_caps |= ATH9K_HW_CAP_APM; + } + + + + if (AR_SREV_9485_10(ah)) { + pCap->pcie_lcr_extsync_en = true; + pCap->pcie_lcr_offset = 0x80; + } + + tx_chainmask = pCap->tx_chainmask; + rx_chainmask = pCap->rx_chainmask; + while (tx_chainmask || rx_chainmask) { + if (tx_chainmask & BIT(0)) + pCap->max_txchains++; + if (rx_chainmask & BIT(0)) + pCap->max_rxchains++; + + tx_chainmask >>= 1; + rx_chainmask >>= 1; + } return 0; } @@ -2177,7 +2186,7 @@ bool ath9k_hw_disable(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_disable); -void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) +void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) { struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath9k_channel *chan = ah->curchan; @@ -2190,7 +2199,7 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit)); + (u32) regulatory->power_limit), test); } EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); @@ -2250,8 +2259,8 @@ void ath9k_hw_reset_tsf(struct ath_hw *ah) { if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0, AH_TSF_WRITE_TIMEOUT)) - ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, - "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, + "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); } @@ -2324,11 +2333,10 @@ static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask) return timer_table->gen_timer_index[b]; } -u32 ath9k_hw_gettsf32(struct ath_hw *ah) +static u32 ath9k_hw_gettsf32(struct ath_hw *ah) { return REG_READ(ah, AR_TSF_L32); } -EXPORT_SYMBOL(ath9k_hw_gettsf32); struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, void (*trigger)(void *), @@ -2342,9 +2350,9 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); if (timer == NULL) { - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "Failed to allocate memory" - "for hw timer[%d]\n", timer_index); + ath_err(ath9k_hw_common(ah), + "Failed to allocate memory for hw timer[%d]\n", + timer_index); return NULL; } @@ -2373,9 +2381,9 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah, tsf = ath9k_hw_gettsf32(ah); - ath_print(ath9k_hw_common(ah), ATH_DBG_HWTIMER, - "curent tsf %x period %x" - "timer_next %x\n", tsf, timer_period, timer_next); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_HWTIMER, + "current tsf %x period %x timer_next %x\n", + tsf, timer_period, timer_next); /* * Pull timer_next forward if the current TSF already passed it @@ -2455,8 +2463,8 @@ void ath_gen_timer_isr(struct ath_hw *ah) index = rightmost_index(timer_table, &thresh_mask); timer = timer_table->timers[index]; BUG_ON(!timer); - ath_print(common, ATH_DBG_HWTIMER, - "TSF overflow for Gen timer %d\n", index); + ath_dbg(common, ATH_DBG_HWTIMER, + "TSF overflow for Gen timer %d\n", index); timer->overflow(timer->arg); } @@ -2464,8 +2472,8 @@ void ath_gen_timer_isr(struct ath_hw *ah) index = rightmost_index(timer_table, &trigger_mask); timer = timer_table->timers[index]; BUG_ON(!timer); - ath_print(common, ATH_DBG_HWTIMER, - "Gen timer[%d] trigger\n", index); + ath_dbg(common, ATH_DBG_HWTIMER, + "Gen timer[%d] trigger\n", index); timer->trigger(timer->arg); } } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index d47d1b4b6002..5a3dfec45e96 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -30,7 +30,6 @@ #include "btcoex.h" #include "../regd.h" -#include "../debug.h" #define ATHEROS_VENDOR_ID 0x168c @@ -44,6 +43,7 @@ #define AR9287_DEVID_PCI 0x002d #define AR9287_DEVID_PCIE 0x002e #define AR9300_DEVID_PCIE 0x0030 +#define AR9300_DEVID_AR9485_PCIE 0x0032 #define AR5416_AR9100_DEVID 0x000b @@ -157,6 +157,13 @@ #define PAPRD_GAIN_TABLE_ENTRIES 32 #define PAPRD_TABLE_SZ 24 +enum ath_hw_txq_subtype { + ATH_TXQ_AC_BE = 0, + ATH_TXQ_AC_BK = 1, + ATH_TXQ_AC_VI = 2, + ATH_TXQ_AC_VO = 3, +}; + enum ath_ini_subsys { ATH_INI_PRE = 0, ATH_INI_CORE, @@ -180,6 +187,7 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12), ATH9K_HW_CAP_2GHZ = BIT(13), ATH9K_HW_CAP_5GHZ = BIT(14), + ATH9K_HW_CAP_APM = BIT(15), }; struct ath9k_hw_capabilities { @@ -191,16 +199,18 @@ struct ath9k_hw_capabilities { u16 rts_aggr_limit; u8 tx_chainmask; u8 rx_chainmask; + u8 max_txchains; + u8 max_rxchains; u16 tx_triglevel_max; u16 reg_cap; u8 num_gpio_pins; - u8 num_antcfg_2ghz; - u8 num_antcfg_5ghz; u8 rx_hp_qdepth; u8 rx_lp_qdepth; u8 rx_status_len; u8 tx_desc_len; u8 txs_len; + u16 pcie_lcr_offset; + bool pcie_lcr_extsync_en; }; struct ath9k_ops_config { @@ -226,7 +236,6 @@ struct ath9k_ops_config { #define SPUR_DISABLE 0 #define SPUR_ENABLE_IOCTL 1 #define SPUR_ENABLE_EEPROM 2 -#define AR_EEPROM_MODAL_SPURS 5 #define AR_SPUR_5413_1 1640 #define AR_SPUR_5413_2 1200 #define AR_NO_SPUR 0x8000 @@ -434,6 +443,7 @@ struct ath9k_hw_version { u16 analog5GhzRev; u16 analog2GhzRev; u16 subsysid; + enum ath_usb_dev usbdev; }; /* Generic TSF timer definitions */ @@ -478,6 +488,40 @@ struct ath_hw_antcomb_conf { }; /** + * struct ath_hw_radar_conf - radar detection initialization parameters + * + * @pulse_inband: threshold for checking the ratio of in-band power + * to total power for short radar pulses (half dB steps) + * @pulse_inband_step: threshold for checking an in-band power to total + * power ratio increase for short radar pulses (half dB steps) + * @pulse_height: threshold for detecting the beginning of a short + * radar pulse (dB step) + * @pulse_rssi: threshold for detecting if a short radar pulse is + * gone (dB step) + * @pulse_maxlen: maximum pulse length (0.8 us steps) + * + * @radar_rssi: RSSI threshold for starting long radar detection (dB steps) + * @radar_inband: threshold for checking the ratio of in-band power + * to total power for long radar pulses (half dB steps) + * @fir_power: threshold for detecting the end of a long radar pulse (dB) + * + * @ext_channel: enable extension channel radar detection + */ +struct ath_hw_radar_conf { + unsigned int pulse_inband; + unsigned int pulse_inband_step; + unsigned int pulse_height; + unsigned int pulse_rssi; + unsigned int pulse_maxlen; + + unsigned int radar_rssi; + unsigned int radar_inband; + int fir_power; + + bool ext_channel; +}; + +/** * struct ath_hw_private_ops - callbacks used internally by hardware code * * This structure contains private callbacks designed to only be used internally @@ -488,7 +532,6 @@ struct ath_hw_antcomb_conf { * * @init_mode_regs: Initializes mode registers * @init_mode_gain_regs: Initialize TX/RX gain registers - * @macversion_supported: If this specific mac revision is supported * * @rf_set_freq: change frequency * @spur_mitigate_freq: spur mitigation @@ -510,7 +553,6 @@ struct ath_hw_private_ops { void (*init_mode_regs)(struct ath_hw *ah); void (*init_mode_gain_regs)(struct ath_hw *ah); - bool (*macversion_supported)(u32 macversion); void (*setup_calibration)(struct ath_hw *ah, struct ath9k_cal_list *currCal); @@ -534,7 +576,6 @@ struct ath_hw_private_ops { void (*set_delta_slope)(struct ath_hw *ah, struct ath9k_channel *chan); bool (*rfbus_req)(struct ath_hw *ah); void (*rfbus_done)(struct ath_hw *ah); - void (*enable_rfkill)(struct ath_hw *ah); void (*restore_chainmask)(struct ath_hw *ah); void (*set_diversity)(struct ath_hw *ah, bool value); u32 (*compute_pll_control)(struct ath_hw *ah, @@ -542,6 +583,8 @@ struct ath_hw_private_ops { bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd, int param); void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); + void (*set_radar_params)(struct ath_hw *ah, + struct ath_hw_radar_conf *conf); /* ANI */ void (*ani_cache_ini_regs)(struct ath_hw *ah); @@ -603,6 +646,10 @@ struct ath_nf_limits { s16 nominal; }; +/* ah_flags */ +#define AH_USE_EEPROM 0x1 +#define AH_UNPLUGGED 0x2 /* The card has been physically removed. */ + struct ath_hw { struct ieee80211_hw *hw; struct ath_common common; @@ -718,9 +765,7 @@ struct ath_hw { u32 *bank6Temp; u8 txpower_limit; - int16_t txpower_indexoffset; int coverage_class; - u32 beacon_interval; u32 slottime; u32 globaltxtimeout; @@ -740,6 +785,8 @@ struct ath_hw { u8 txchainmask; u8 rxchainmask; + struct ath_hw_radar_conf radar_conf; + u32 originalGain[22]; int initPDADC; int PDADCdelta; @@ -789,6 +836,11 @@ struct ath_hw { u32 bb_watchdog_last_status; u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */ + unsigned int paprd_target_power; + unsigned int paprd_training_power; + unsigned int paprd_ratemask; + unsigned int paprd_ratemask_ht40; + bool paprd_table_write_done; u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES]; u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES]; /* @@ -797,6 +849,9 @@ struct ath_hw { * this register when in sleep states. */ u32 WARegVal; + + /* Enterprise mode cap */ + u32 ent_mode; }; static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) @@ -819,10 +874,9 @@ static inline struct ath_hw_ops *ath9k_hw_ops(struct ath_hw *ah) return &ah->ops; } -static inline int sign_extend(int val, const int nbits) +static inline u8 get_streams(int mask) { - int order = BIT(nbits-1); - return (val ^ order) - order; + return !!(mask & BIT(0)) + !!(mask & BIT(1)) + !!(mask & BIT(2)); } /* Initialization, Detach, Reset */ @@ -861,7 +915,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *ah); void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); bool ath9k_hw_phy_disable(struct ath_hw *ah); bool ath9k_hw_disable(struct ath_hw *ah); -void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); +void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test); void ath9k_hw_setopmode(struct ath_hw *ah); void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); void ath9k_hw_setbssidmask(struct ath_hw *ah); @@ -893,7 +947,6 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer); void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); void ath_gen_timer_isr(struct ath_hw *hw); -u32 ath9k_hw_gettsf32(struct ath_hw *ah); void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 14b8ab386daf..767d8b86f1e1 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -29,17 +29,27 @@ static unsigned int ath9k_debug = ATH_DBG_DEFAULT; module_param_named(debug, ath9k_debug, uint, 0); MODULE_PARM_DESC(debug, "Debugging mask"); -int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); +int ath9k_modparam_nohwcrypt; +module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); int led_blink; module_param_named(blink, led_blink, int, 0444); MODULE_PARM_DESC(blink, "Enable LED blink on activity"); +static int ath9k_btcoex_enable; +module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444); +MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence"); + +int ath9k_pm_qos_value = ATH9K_PM_QOS_DEFAULT_VALUE; +module_param_named(pmqos, ath9k_pm_qos_value, int, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(pmqos, "User specified PM-QOS value"); + +bool is_ath9k_unloaded; /* We use the hw_value as an index into our private channel structure */ #define CHAN2G(_freq, _idx) { \ + .band = IEEE80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_idx), \ .max_power = 20, \ @@ -206,7 +216,9 @@ static void setup_ht_cap(struct ath_softc *sc, ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; - if (AR_SREV_9300_20_OR_LATER(ah)) + if (AR_SREV_9485(ah)) + max_streams = 1; + else if (AR_SREV_9300_20_OR_LATER(ah)) max_streams = 3; else max_streams = 2; @@ -222,9 +234,9 @@ static void setup_ht_cap(struct ath_softc *sc, tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams); rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams); - ath_print(common, ATH_DBG_CONFIG, - "TX streams %d, RX streams: %d\n", - tx_streams, rx_streams); + ath_dbg(common, ATH_DBG_CONFIG, + "TX streams %d, RX streams: %d\n", + tx_streams, rx_streams); if (tx_streams != rx_streams) { ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; @@ -267,8 +279,8 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, struct ath_buf *bf; int i, bsize, error, desc_len; - ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", - name, nbuf, ndesc); + ath_dbg(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", + name, nbuf, ndesc); INIT_LIST_HEAD(head); @@ -279,8 +291,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, /* ath_desc must be a multiple of DWORDs */ if ((desc_len % 4) != 0) { - ath_print(common, ATH_DBG_FATAL, - "ath_desc not DWORD aligned\n"); + ath_err(common, "ath_desc not DWORD aligned\n"); BUG_ON((desc_len % 4) != 0); error = -ENOMEM; goto fail; @@ -314,9 +325,9 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, goto fail; } ds = (u8 *) dd->dd_desc; - ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", - name, ds, (u32) dd->dd_desc_len, - ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); + ath_dbg(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", + name, ds, (u32) dd->dd_desc_len, + ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); /* allocate buffers */ bsize = sizeof(struct ath_buf) * nbuf; @@ -362,7 +373,7 @@ fail: #undef DS2PHYS } -static void ath9k_init_crypto(struct ath_softc *sc) +void ath9k_init_crypto(struct ath_softc *sc) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); int i = 0; @@ -370,9 +381,9 @@ static void ath9k_init_crypto(struct ath_softc *sc) /* Get the hardware key cache size. */ common->keymax = sc->sc_ah->caps.keycache_size; if (common->keymax > ATH_KEYMAX) { - ath_print(common, ATH_DBG_ANY, - "Warning, using only %u entries in %u key cache\n", - ATH_KEYMAX, common->keymax); + ath_dbg(common, ATH_DBG_ANY, + "Warning, using only %u entries in %u key cache\n", + ATH_KEYMAX, common->keymax); common->keymax = ATH_KEYMAX; } @@ -395,7 +406,8 @@ static void ath9k_init_crypto(struct ath_softc *sc) static int ath9k_init_btcoex(struct ath_softc *sc) { - int r, qnum; + struct ath_txq *txq; + int r; switch (sc->sc_ah->btcoex_hw.scheme) { case ATH_BTCOEX_CFG_NONE: @@ -408,8 +420,8 @@ static int ath9k_init_btcoex(struct ath_softc *sc) r = ath_init_btcoex_timer(sc); if (r) return -1; - qnum = sc->tx.hwq_map[WME_AC_BE]; - ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum); + txq = sc->tx.txq_map[WME_AC_BE]; + ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum); sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; break; default: @@ -422,59 +434,18 @@ static int ath9k_init_btcoex(struct ath_softc *sc) static int ath9k_init_queues(struct ath_softc *sc) { - struct ath_common *common = ath9k_hw_common(sc->sc_ah); int i = 0; - for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) - sc->tx.hwq_map[i] = -1; - sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); - if (sc->beacon.beaconq == -1) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup a beacon xmit queue\n"); - goto err; - } - sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); - if (sc->beacon.cabq == NULL) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup CAB xmit queue\n"); - goto err; - } sc->config.cabqReadytime = ATH_CABQ_READY_TIME; ath_cabq_update(sc); - if (!ath_tx_setup(sc, WME_AC_BK)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for BK traffic\n"); - goto err; - } - - if (!ath_tx_setup(sc, WME_AC_BE)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for BE traffic\n"); - goto err; - } - if (!ath_tx_setup(sc, WME_AC_VI)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for VI traffic\n"); - goto err; - } - if (!ath_tx_setup(sc, WME_AC_VO)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for VO traffic\n"); - goto err; - } + for (i = 0; i < WME_NUM_AC; i++) + sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i); return 0; - -err: - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); - - return -EIO; } static int ath9k_init_channels_rates(struct ath_softc *sc) @@ -570,6 +541,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, ah->hw_version.subsysid = subsysid; sc->sc_ah = ah; + if (!sc->dev->platform_data) + ah->ah_flags |= AH_USE_EEPROM; + common = ath9k_hw_common(ah); common->ops = &ath9k_common_ops; common->bus_ops = bus_ops; @@ -577,10 +551,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, common->hw = sc->hw; common->priv = sc; common->debug_mask = ath9k_debug; + common->btcoex_enabled = ath9k_btcoex_enable == 1; spin_lock_init(&common->cc_lock); spin_lock_init(&sc->wiphy_lock); - spin_lock_init(&sc->sc_resetlock); spin_lock_init(&sc->sc_serial_rw); spin_lock_init(&sc->sc_pm_lock); mutex_init(&sc->mutex); @@ -600,13 +574,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, if (ret) goto err_hw; - ret = ath9k_init_debug(ah); - if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to create debugfs files\n"); - goto err_debug; - } - ret = ath9k_init_queues(sc); if (ret) goto err_queues; @@ -629,8 +596,6 @@ err_btcoex: if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); err_queues: - ath9k_exit_debug(ah); -err_debug: ath9k_hw_deinit(ah); err_hw: tasklet_kill(&sc->intr_tq); @@ -642,6 +607,37 @@ err_hw: return ret; } +static void ath9k_init_band_txpower(struct ath_softc *sc, int band) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + struct ath_hw *ah = sc->sc_ah; + struct ath_regulatory *reg = ath9k_hw_regulatory(ah); + int i; + + sband = &sc->sbands[band]; + for (i = 0; i < sband->n_channels; i++) { + chan = &sband->channels[i]; + ah->curchan = &ah->channels[chan->hw_value]; + ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20); + ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true); + chan->max_power = reg->max_power_level / 2; + } +} + +static void ath9k_init_txpower_limits(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath9k_channel *curchan = ah->curchan; + + if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) + ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ); + if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) + ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ); + + ah->curchan = curchan; +} + void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); @@ -657,7 +653,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; - if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) + if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) hw->flags |= IEEE80211_HW_MFP_CAPABLE; hw->wiphy->interface_modes = @@ -705,6 +701,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, const struct ath_bus_ops *bus_ops) { struct ieee80211_hw *hw = sc->hw; + struct ath_wiphy *aphy = hw->priv; struct ath_common *common; struct ath_hw *ah; int error = 0; @@ -737,11 +734,19 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, if (error != 0) goto error_rx; + ath9k_init_txpower_limits(sc); + /* Register with mac80211 */ error = ieee80211_register_hw(hw); if (error) goto error_register; + error = ath9k_init_debug(ah); + if (error) { + ath_err(common, "Unable to create debugfs files\n"); + goto error_world; + } + /* Handle world regulatory */ if (!ath_is_world_regd(reg)) { error = regulatory_hint(hw->wiphy, reg->alpha2); @@ -754,6 +759,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); sc->wiphy_scheduler_int = msecs_to_jiffies(500); + aphy->last_rssi = ATH_RSSI_DUMMY_MARKER; ath_init_leds(sc); ath_start_rfkill_poll(sc); @@ -799,7 +805,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); - ath9k_exit_debug(sc->sc_ah); ath9k_hw_deinit(sc->sc_ah); tasklet_kill(&sc->intr_tq); @@ -866,20 +871,12 @@ static int __init ath9k_init(void) goto err_out; } - error = ath9k_debug_create_root(); - if (error) { - printk(KERN_ERR - "ath9k: Unable to create debugfs root: %d\n", - error); - goto err_rate_unregister; - } - error = ath_pci_init(); if (error < 0) { printk(KERN_ERR "ath9k: No PCI devices found, driver not installed.\n"); error = -ENODEV; - goto err_remove_root; + goto err_rate_unregister; } error = ath_ahb_init(); @@ -893,8 +890,6 @@ static int __init ath9k_init(void) err_pci_exit: ath_pci_exit(); - err_remove_root: - ath9k_debug_remove_root(); err_rate_unregister: ath_rate_control_unregister(); err_out: @@ -904,9 +899,9 @@ module_init(ath9k_init); static void __exit ath9k_exit(void) { + is_ath9k_unloaded = true; ath_ahb_exit(); ath_pci_exit(); - ath9k_debug_remove_root(); ath_rate_control_unregister(); printk(KERN_INFO "%s: Driver unloaded\n", dev_info); } diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index c996963ab339..180170d3ce25 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -20,11 +20,11 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, struct ath9k_tx_queue_info *qi) { - ath_print(ath9k_hw_common(ah), ATH_DBG_INTERRUPT, - "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", - ah->txok_interrupt_mask, ah->txerr_interrupt_mask, - ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, - ah->txurn_interrupt_mask); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_INTERRUPT, + "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", + ah->txok_interrupt_mask, ah->txerr_interrupt_mask, + ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, + ah->txurn_interrupt_mask); ENABLE_REGWRITE_BUFFER(ah); @@ -56,8 +56,8 @@ EXPORT_SYMBOL(ath9k_hw_puttxbuf); void ath9k_hw_txstart(struct ath_hw *ah, u32 q) { - ath_print(ath9k_hw_common(ah), ATH_DBG_QUEUE, - "Enable TXE on queue: %u\n", q); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_QUEUE, + "Enable TXE on queue: %u\n", q); REG_WRITE(ah, AR_Q_TXE, 1 << q); } EXPORT_SYMBOL(ath9k_hw_txstart); @@ -117,12 +117,11 @@ EXPORT_SYMBOL(ath9k_hw_numtxpending); bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) { u32 txcfg, curLevel, newLevel; - enum ath9k_int omask; if (ah->tx_trig_level >= ah->config.max_txtrig_level) return false; - omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL); + ath9k_hw_disable_interrupts(ah); txcfg = REG_READ(ah, AR_TXCFG); curLevel = MS(txcfg, AR_FTRIG); @@ -136,7 +135,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) REG_WRITE(ah, AR_TXCFG, (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); - ath9k_hw_set_interrupts(ah, omask); + ath9k_hw_enable_interrupts(ah); ah->tx_trig_level = newLevel; @@ -155,15 +154,15 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; if (q >= pCap->total_queues) { - ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " - "invalid queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Stopping TX DMA, invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " - "inactive queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Stopping TX DMA, inactive queue: %u\n", q); return false; } @@ -176,9 +175,9 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) } if (ath9k_hw_numtxpending(ah, q)) { - ath_print(common, ATH_DBG_QUEUE, - "%s: Num of pending TX Frames %d on Q %d\n", - __func__, ath9k_hw_numtxpending(ah, q), q); + ath_dbg(common, ATH_DBG_QUEUE, + "%s: Num of pending TX Frames %d on Q %d\n", + __func__, ath9k_hw_numtxpending(ah, q), q); for (j = 0; j < 2; j++) { tsfLow = REG_READ(ah, AR_TSF_L32); @@ -192,9 +191,9 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) break; - ath_print(common, ATH_DBG_QUEUE, - "TSF has moved while trying to set " - "quiet time TSF: 0x%08x\n", tsfLow); + ath_dbg(common, ATH_DBG_QUEUE, + "TSF has moved while trying to set quiet time TSF: 0x%08x\n", + tsfLow); } REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); @@ -205,9 +204,8 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) wait = wait_time; while (ath9k_hw_numtxpending(ah, q)) { if ((--wait) == 0) { - ath_print(common, ATH_DBG_FATAL, - "Failed to stop TX DMA in 100 " - "msec after killing last frame\n"); + ath_err(common, + "Failed to stop TX DMA in 100 msec after killing last frame\n"); break; } udelay(ATH9K_TIME_QUANTUM); @@ -240,19 +238,19 @@ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, struct ath9k_tx_queue_info *qi; if (q >= pCap->total_queues) { - ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, " - "invalid queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Set TXQ properties, invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, " - "inactive queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Set TXQ properties, inactive queue: %u\n", q); return false; } - ath_print(common, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); qi->tqi_ver = qinfo->tqi_ver; qi->tqi_subtype = qinfo->tqi_subtype; @@ -311,15 +309,15 @@ bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, struct ath9k_tx_queue_info *qi; if (q >= pCap->total_queues) { - ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, " - "invalid queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Get TXQ properties, invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, " - "inactive queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Get TXQ properties, inactive queue: %u\n", q); return false; } @@ -369,23 +367,20 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, ATH9K_TX_QUEUE_INACTIVE) break; if (q == pCap->total_queues) { - ath_print(common, ATH_DBG_FATAL, - "No available TX queue\n"); + ath_err(common, "No available TX queue\n"); return -1; } break; default: - ath_print(common, ATH_DBG_FATAL, - "Invalid TX queue type: %u\n", type); + ath_err(common, "Invalid TX queue type: %u\n", type); return -1; } - ath_print(common, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); qi = &ah->txq[q]; if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { - ath_print(common, ATH_DBG_FATAL, - "TX queue: %u already active\n", q); + ath_err(common, "TX queue: %u already active\n", q); return -1; } memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); @@ -417,18 +412,18 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) struct ath9k_tx_queue_info *qi; if (q >= pCap->total_queues) { - ath_print(common, ATH_DBG_QUEUE, "Release TXQ, " - "invalid queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Release TXQ, invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_print(common, ATH_DBG_QUEUE, "Release TXQ, " - "inactive queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Release TXQ, inactive queue: %u\n", q); return false; } - ath_print(common, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; ah->txok_interrupt_mask &= ~(1 << q); @@ -451,19 +446,19 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) u32 cwMin, chanCwMin, value; if (q >= pCap->total_queues) { - ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, " - "invalid queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Reset TXQ, invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, " - "inactive queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Reset TXQ, inactive queue: %u\n", q); return true; } - ath_print(common, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { if (chan && IS_CHAN_B(chan)) @@ -697,15 +692,16 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { if (ads.ds_rxstatus8 & AR_CRCErr) rs->rs_status |= ATH9K_RXERR_CRC; - else if (ads.ds_rxstatus8 & AR_PHYErr) { + if (ads.ds_rxstatus8 & AR_PHYErr) { rs->rs_status |= ATH9K_RXERR_PHY; phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); rs->rs_phyerr = phyerr; - } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) + } + if (ads.ds_rxstatus8 & AR_DecryptCRCErr) rs->rs_status |= ATH9K_RXERR_DECRYPT; - else if (ads.ds_rxstatus8 & AR_MichaelErr) + if (ads.ds_rxstatus8 & AR_MichaelErr) rs->rs_status |= ATH9K_RXERR_MIC; - else if (ads.ds_rxstatus8 & AR_KeyMiss) + if (ads.ds_rxstatus8 & AR_KeyMiss) rs->rs_status |= ATH9K_RXERR_DECRYPT; } @@ -735,9 +731,9 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) AR_DIAG_RX_ABORT)); reg = REG_READ(ah, AR_OBS_BUS_1); - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "RX failed to go idle in 10 ms RXSM=0x%x\n", - reg); + ath_err(ath9k_hw_common(ah), + "RX failed to go idle in 10 ms RXSM=0x%x\n", + reg); return false; } @@ -766,14 +762,6 @@ void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning) } EXPORT_SYMBOL(ath9k_hw_startpcureceive); -void ath9k_hw_stoppcurecv(struct ath_hw *ah) -{ - REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); - - ath9k_hw_disable_mib_counters(ah); -} -EXPORT_SYMBOL(ath9k_hw_stoppcurecv); - void ath9k_hw_abortpcurecv(struct ath_hw *ah) { REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); @@ -799,12 +787,11 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah) } if (i == 0) { - ath_print(common, ATH_DBG_FATAL, - "DMA failed to stop in %d ms " - "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", - AH_RX_STOP_DMA_TIMEOUT / 1000, - REG_READ(ah, AR_CR), - REG_READ(ah, AR_DIAG_SW)); + ath_err(common, + "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", + AH_RX_STOP_DMA_TIMEOUT / 1000, + REG_READ(ah, AR_CR), + REG_READ(ah, AR_DIAG_SW)); return false; } else { return true; @@ -848,28 +835,59 @@ bool ath9k_hw_intrpend(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_intrpend); -enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, - enum ath9k_int ints) +void ath9k_hw_disable_interrupts(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + + ath_dbg(common, ATH_DBG_INTERRUPT, "disable IER\n"); + REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + (void) REG_READ(ah, AR_IER); + if (!AR_SREV_9100(ah)) { + REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); + (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); + + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); + (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); + } +} +EXPORT_SYMBOL(ath9k_hw_disable_interrupts); + +void ath9k_hw_enable_interrupts(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + + if (!(ah->imask & ATH9K_INT_GLOBAL)) + return; + + ath_dbg(common, ATH_DBG_INTERRUPT, "enable IER\n"); + REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + if (!AR_SREV_9100(ah)) { + REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, + AR_INTR_MAC_IRQ); + REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); + + + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, + AR_INTR_SYNC_DEFAULT); + REG_WRITE(ah, AR_INTR_SYNC_MASK, + AR_INTR_SYNC_DEFAULT); + } + ath_dbg(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", + REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); +} +EXPORT_SYMBOL(ath9k_hw_enable_interrupts); + +void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) { enum ath9k_int omask = ah->imask; u32 mask, mask2; struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_common *common = ath9k_hw_common(ah); - ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); + if (!(ints & ATH9K_INT_GLOBAL)) + ath9k_hw_enable_interrupts(ah); - if (omask & ATH9K_INT_GLOBAL) { - ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n"); - REG_WRITE(ah, AR_IER, AR_IER_DISABLE); - (void) REG_READ(ah, AR_IER); - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); - (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); - - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); - (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); - } - } + ath_dbg(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); /* TODO: global int Ref count */ mask = ints & ATH9K_INT_COMMON; @@ -930,7 +948,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, mask2 |= AR_IMR_S2_CST; } - ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); + ath_dbg(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); REG_WRITE(ah, AR_IMR, mask); ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | @@ -945,24 +963,8 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); } - if (ints & ATH9K_INT_GLOBAL) { - ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n"); - REG_WRITE(ah, AR_IER, AR_IER_ENABLE); - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, - AR_INTR_MAC_IRQ); - REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); - - - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, - AR_INTR_SYNC_DEFAULT); - REG_WRITE(ah, AR_INTR_SYNC_MASK, - AR_INTR_SYNC_DEFAULT); - } - ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", - REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); - } + ath9k_hw_enable_interrupts(ah); - return omask; + return; } EXPORT_SYMBOL(ath9k_hw_set_interrupts); diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 7c1a34d64f6d..7512f97e8f49 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -104,13 +104,11 @@ struct ath_tx_status { u32 ts_tstamp; u16 ts_seqnum; u8 ts_status; - u8 ts_ratecode; u8 ts_rateindex; int8_t ts_rssi; u8 ts_shortretry; u8 ts_longretry; u8 ts_virtcol; - u8 ts_antenna; u8 ts_flags; int8_t ts_rssi_ctl0; int8_t ts_rssi_ctl1; @@ -121,7 +119,6 @@ struct ath_tx_status { u8 qid; u16 desc_id; u8 tid; - u8 pad[2]; u32 ba_low; u32 ba_high; u32 evm0; @@ -240,7 +237,7 @@ struct ath_desc { u32 ds_ctl1; u32 ds_hw[20]; void *ds_vdata; -} __packed; +} __packed __aligned(4); #define ATH9K_TXDESC_CLRDMASK 0x0001 #define ATH9K_TXDESC_NOACK 0x0002 @@ -310,7 +307,7 @@ struct ar5416_desc { u32 status8; } rx; } u; -} __packed; +} __packed __aligned(4); #define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds)) #define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds)) @@ -669,6 +666,7 @@ enum ath9k_key_type { struct ath_hw; struct ath9k_channel; +enum ath9k_int; u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); @@ -693,15 +691,15 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning); -void ath9k_hw_stoppcurecv(struct ath_hw *ah); void ath9k_hw_abortpcurecv(struct ath_hw *ah); bool ath9k_hw_stopdmarecv(struct ath_hw *ah); int ath9k_hw_beaconq_setup(struct ath_hw *ah); /* Interrupt Handling */ bool ath9k_hw_intrpend(struct ath_hw *ah); -enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, - enum ath9k_int ints); +void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints); +void ath9k_hw_enable_interrupts(struct ath_hw *ah); +void ath9k_hw_disable_interrupts(struct ath_hw *ah); void ar9002_hw_attach_mac_ops(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c0c3464d3a86..f90a6ca94a76 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -23,7 +23,7 @@ static void ath_update_txpow(struct ath_softc *sc) struct ath_hw *ah = sc->sc_ah; if (sc->curtxpow != sc->config.txpowlimit) { - ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); + ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); /* read back in case value is clamped */ sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; } @@ -234,6 +234,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, ath9k_ps_wakeup(sc); + spin_lock_bh(&sc->sc_pcu_lock); + /* * This is only performed if the channel settings have * actually changed. @@ -243,11 +245,9 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, * hardware at the new frequency, and then re-enable * the relevant bits of the h/w. */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); stopped = ath_drain_all_txq(sc, false); - spin_lock_bh(&sc->rx.pcu_lock); - if (!ath_stoprecv(sc)) stopped = false; @@ -261,46 +261,39 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) caldata = &aphy->caldata; - ath_print(common, ATH_DBG_CONFIG, - "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n", - sc->sc_ah->curchan->channel, - channel->center_freq, conf_is_ht40(conf), - fastcc); - - spin_lock_bh(&sc->sc_resetlock); + ath_dbg(common, ATH_DBG_CONFIG, + "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n", + sc->sc_ah->curchan->channel, + channel->center_freq, conf_is_ht40(conf), + fastcc); r = ath9k_hw_reset(ah, hchan, caldata, fastcc); if (r) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset channel (%u MHz), " - "reset status %d\n", - channel->center_freq, r); - spin_unlock_bh(&sc->sc_resetlock); - spin_unlock_bh(&sc->rx.pcu_lock); + ath_err(common, + "Unable to reset channel (%u MHz), reset status %d\n", + channel->center_freq, r); goto ps_restore; } - spin_unlock_bh(&sc->sc_resetlock); if (ath_startrecv(sc) != 0) { - ath_print(common, ATH_DBG_FATAL, - "Unable to restart recv logic\n"); + ath_err(common, "Unable to restart recv logic\n"); r = -EIO; - spin_unlock_bh(&sc->rx.pcu_lock); goto ps_restore; } - spin_unlock_bh(&sc->rx.pcu_lock); - ath_update_txpow(sc); ath9k_hw_set_interrupts(ah, ah->imask); if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { - ath_beacon_config(sc, NULL); + if (sc->sc_flags & SC_OP_BEACONS) + ath_beacon_config(sc, NULL); ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); ath_start_ani(common); } ps_restore: + spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_ps_restore(sc); return r; } @@ -328,6 +321,42 @@ static void ath_paprd_activate(struct ath_softc *sc) ath9k_ps_restore(sc); } +static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain) +{ + struct ieee80211_hw *hw = sc->hw; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ath_tx_control txctl; + int time_left; + + memset(&txctl, 0, sizeof(txctl)); + txctl.txq = sc->tx.txq_map[WME_AC_BE]; + + memset(tx_info, 0, sizeof(*tx_info)); + tx_info->band = hw->conf.channel->band; + tx_info->flags |= IEEE80211_TX_CTL_NO_ACK; + tx_info->control.rates[0].idx = 0; + tx_info->control.rates[0].count = 1; + tx_info->control.rates[0].flags = IEEE80211_TX_RC_MCS; + tx_info->control.rates[1].idx = -1; + + init_completion(&sc->paprd_complete); + sc->paprd_pending = true; + txctl.paprd = BIT(chain); + if (ath_tx_start(hw, skb, &txctl) != 0) + return false; + + time_left = wait_for_completion_timeout(&sc->paprd_complete, + msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); + sc->paprd_pending = false; + + if (!time_left) + ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CALIBRATE, + "Timeout waiting for paprd training on TX chain %d\n", + chain); + + return !!time_left; +} + void ath_paprd_calibrate(struct work_struct *work) { struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work); @@ -335,28 +364,23 @@ void ath_paprd_calibrate(struct work_struct *work) struct ath_hw *ah = sc->sc_ah; struct ieee80211_hdr *hdr; struct sk_buff *skb = NULL; - struct ieee80211_tx_info *tx_info; - int band = hw->conf.channel->band; - struct ieee80211_supported_band *sband = &sc->sbands[band]; - struct ath_tx_control txctl; struct ath9k_hw_cal_data *caldata = ah->caldata; struct ath_common *common = ath9k_hw_common(ah); - int qnum, ftype; + int ftype; int chain_ok = 0; int chain; int len = 1800; - int time_left; - int i; if (!caldata) return; + if (ar9003_paprd_init_table(ah) < 0) + return; + skb = alloc_skb(len, GFP_KERNEL); if (!skb) return; - tx_info = IEEE80211_SKB_CB(skb); - skb_put(skb, len); memset(skb->data, 0, len); hdr = (struct ieee80211_hdr *)skb->data; @@ -367,40 +391,25 @@ void ath_paprd_calibrate(struct work_struct *work) memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); - memset(&txctl, 0, sizeof(txctl)); - qnum = sc->tx.hwq_map[WME_AC_BE]; - txctl.txq = &sc->tx.txq[qnum]; - ath9k_ps_wakeup(sc); - ar9003_paprd_init_table(ah); for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { if (!(common->tx_chainmask & BIT(chain))) continue; chain_ok = 0; - memset(tx_info, 0, sizeof(*tx_info)); - tx_info->band = band; - for (i = 0; i < 4; i++) { - tx_info->control.rates[i].idx = sband->n_bitrates - 1; - tx_info->control.rates[i].count = 6; - } + ath_dbg(common, ATH_DBG_CALIBRATE, + "Sending PAPRD frame for thermal measurement " + "on chain %d\n", chain); + if (!ath_paprd_send_frame(sc, skb, chain)) + goto fail_paprd; - init_completion(&sc->paprd_complete); ar9003_paprd_setup_gain_table(ah, chain); - txctl.paprd = BIT(chain); - if (ath_tx_start(hw, skb, &txctl) != 0) - break; - time_left = wait_for_completion_timeout(&sc->paprd_complete, - msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); - if (!time_left) { - ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, - "Timeout waiting for paprd training on " - "TX chain %d\n", - chain); + ath_dbg(common, ATH_DBG_CALIBRATE, + "Sending PAPRD training frame on chain %d\n", chain); + if (!ath_paprd_send_frame(sc, skb, chain)) goto fail_paprd; - } if (!ar9003_paprd_is_done(ah)) break; @@ -457,7 +466,7 @@ void ath_ani_calibrate(unsigned long data) /* Long calibration runs independently of short calibration. */ if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { longcal = true; - ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); + ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); common->ani.longcal_timer = timestamp; } @@ -465,8 +474,8 @@ void ath_ani_calibrate(unsigned long data) if (!common->ani.caldone) { if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { shortcal = true; - ath_print(common, ATH_DBG_ANI, - "shortcal @%lu\n", jiffies); + ath_dbg(common, ATH_DBG_ANI, + "shortcal @%lu\n", jiffies); common->ani.shortcal_timer = timestamp; common->ani.resetcal_timer = timestamp; } @@ -525,49 +534,25 @@ set_timer: if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { if (!ah->caldata->paprd_done) ieee80211_queue_work(sc->hw, &sc->paprd_work); - else + else if (!ah->paprd_table_write_done) ath_paprd_activate(sc); } } -/* - * Update tx/rx chainmask. For legacy association, - * hard code chainmask to 1x1, for 11n association, use - * the chainmask configuration, for bt coexistence, use - * the chainmask configuration even in legacy mode. - */ -void ath_update_chainmask(struct ath_softc *sc, int is_ht) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - - if ((sc->sc_flags & SC_OP_OFFCHANNEL) || is_ht || - (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) { - common->tx_chainmask = ah->caps.tx_chainmask; - common->rx_chainmask = ah->caps.rx_chainmask; - } else { - common->tx_chainmask = 1; - common->rx_chainmask = 1; - } - - ath_print(common, ATH_DBG_CONFIG, - "tx chmask: %d, rx chmask: %d\n", - common->tx_chainmask, - common->rx_chainmask); -} - static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) { struct ath_node *an; - + struct ath_hw *ah = sc->sc_ah; an = (struct ath_node *)sta->drv_priv; + if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM) + sc->sc_flags |= SC_OP_ENABLE_APM; + if (sc->sc_flags & SC_OP_TXAGGR) { ath_tx_node_init(sc, an); an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + sta->ht_cap.ampdu_factor); an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); - an->last_rssi = ATH_RSSI_DUMMY_MARKER; } } @@ -615,6 +600,8 @@ void ath9k_tasklet(unsigned long data) return; } + spin_lock(&sc->sc_pcu_lock); + if (!ath9k_hw_check_alive(ah)) ieee80211_queue_work(sc->hw, &sc->hw_check_work); @@ -625,15 +612,12 @@ void ath9k_tasklet(unsigned long data) rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN); if (status & rxmask) { - spin_lock_bh(&sc->rx.pcu_lock); - /* Check for high priority Rx first */ if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && (status & ATH9K_INT_RXHP)) ath_rx_tasklet(sc, 0, true); ath_rx_tasklet(sc, 0, false); - spin_unlock_bh(&sc->rx.pcu_lock); } if (status & ATH9K_INT_TX) { @@ -648,8 +632,8 @@ void ath9k_tasklet(unsigned long data) * TSF sync does not look correct; remain awake to sync with * the next Beacon. */ - ath_print(common, ATH_DBG_PS, - "TSFOOR - Sync with next Beacon\n"); + ath_dbg(common, ATH_DBG_PS, + "TSFOOR - Sync with next Beacon\n"); sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC; } @@ -658,7 +642,9 @@ void ath9k_tasklet(unsigned long data) ath_gen_timer_isr(sc->sc_ah); /* re-enable hardware interrupt */ - ath9k_hw_set_interrupts(ah, ah->imask); + ath9k_hw_enable_interrupts(ah); + + spin_unlock(&sc->sc_pcu_lock); ath9k_ps_restore(sc); } @@ -757,7 +743,7 @@ irqreturn_t ath_isr(int irq, void *dev) * interrupt; otherwise it will continue to * fire. */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); /* * Let the hal handle the event. We assume * it will clear whatever condition caused @@ -766,11 +752,13 @@ irqreturn_t ath_isr(int irq, void *dev) spin_lock(&common->cc_lock); ath9k_hw_proc_mib_event(ah); spin_unlock(&common->cc_lock); - ath9k_hw_set_interrupts(ah, ah->imask); + ath9k_hw_enable_interrupts(ah); } if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) if (status & ATH9K_INT_TIM_TIMER) { + if (ATH_DBG_WARN_ON_ONCE(sc->ps_idle)) + goto chip_reset; /* Clear RxAbort bit so that we can * receive frames */ ath9k_setpower(sc, ATH9K_PM_AWAKE); @@ -783,8 +771,8 @@ chip_reset: ath_debug_stat_interrupt(sc, status); if (sched) { - /* turn off every interrupt except SWBA */ - ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA)); + /* turn off every interrupt */ + ath9k_hw_disable_interrupts(ah); tasklet_schedule(&sc->intr_tq); } @@ -836,16 +824,18 @@ static u32 ath_get_extchanmode(struct ath_softc *sc, } static void ath9k_bss_assoc_info(struct ath_softc *sc, + struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf) { + struct ath_wiphy *aphy = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); if (bss_conf->assoc) { - ath_print(common, ATH_DBG_CONFIG, - "Bss Info ASSOC %d, bssid: %pM\n", - bss_conf->aid, common->curbssid); + ath_dbg(common, ATH_DBG_CONFIG, + "Bss Info ASSOC %d, bssid: %pM\n", + bss_conf->aid, common->curbssid); /* New association, store aid */ common->curaid = bss_conf->aid; @@ -862,12 +852,13 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, ath_beacon_config(sc, vif); /* Reset rssi stats */ + aphy->last_rssi = ATH_RSSI_DUMMY_MARKER; sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; sc->sc_flags |= SC_OP_ANI_RUN; ath_start_ani(common); } else { - ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); common->curaid = 0; /* Stop ANI */ sc->sc_flags &= ~SC_OP_ANI_RUN; @@ -883,31 +874,25 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) int r; ath9k_ps_wakeup(sc); + spin_lock_bh(&sc->sc_pcu_lock); + ath9k_hw_configpcipowersave(ah, 0, 0); if (!ah->curchan) ah->curchan = ath_get_curchannel(sc, sc->hw); - spin_lock_bh(&sc->rx.pcu_lock); - spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); if (r) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset channel (%u MHz), " - "reset status %d\n", - channel->center_freq, r); + ath_err(common, + "Unable to reset channel (%u MHz), reset status %d\n", + channel->center_freq, r); } - spin_unlock_bh(&sc->sc_resetlock); ath_update_txpow(sc); if (ath_startrecv(sc) != 0) { - ath_print(common, ATH_DBG_FATAL, - "Unable to restart recv logic\n"); - spin_unlock_bh(&sc->rx.pcu_lock); - return; + ath_err(common, "Unable to restart recv logic\n"); + goto out; } - spin_unlock_bh(&sc->rx.pcu_lock); - if (sc->sc_flags & SC_OP_BEACONS) ath_beacon_config(sc, NULL); /* restart beacons */ @@ -920,6 +905,9 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) ath9k_hw_set_gpio(ah, ah->led_pin, 0); ieee80211_wake_queues(hw); +out: + spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_ps_restore(sc); } @@ -930,6 +918,8 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) int r; ath9k_ps_wakeup(sc); + spin_lock_bh(&sc->sc_pcu_lock); + ieee80211_stop_queues(hw); /* @@ -942,34 +932,30 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) } /* Disable interrupts */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath_drain_all_txq(sc, false); /* clear pending tx frames */ - spin_lock_bh(&sc->rx.pcu_lock); - ath_stoprecv(sc); /* turn off frame recv */ ath_flushrecv(sc); /* flush recv queue */ if (!ah->curchan) ah->curchan = ath_get_curchannel(sc, hw); - spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); if (r) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "Unable to reset channel (%u MHz), " - "reset status %d\n", - channel->center_freq, r); + ath_err(ath9k_hw_common(sc->sc_ah), + "Unable to reset channel (%u MHz), reset status %d\n", + channel->center_freq, r); } - spin_unlock_bh(&sc->sc_resetlock); ath9k_hw_phy_disable(ah); - spin_unlock_bh(&sc->rx.pcu_lock); - ath9k_hw_configpcipowersave(ah, 1, 1); + + spin_unlock_bh(&sc->sc_pcu_lock); ath9k_ps_restore(sc); + ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); } @@ -983,28 +969,23 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) /* Stop ANI */ del_timer_sync(&common->ani.timer); + spin_lock_bh(&sc->sc_pcu_lock); + ieee80211_stop_queues(hw); - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath_drain_all_txq(sc, retry_tx); - spin_lock_bh(&sc->rx.pcu_lock); - ath_stoprecv(sc); ath_flushrecv(sc); - spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); if (r) - ath_print(common, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d\n", r); - spin_unlock_bh(&sc->sc_resetlock); + ath_err(common, + "Unable to reset hardware; reset status %d\n", r); if (ath_startrecv(sc) != 0) - ath_print(common, ATH_DBG_FATAL, - "Unable to start recv logic\n"); - - spin_unlock_bh(&sc->rx.pcu_lock); + ath_err(common, "Unable to start recv logic\n"); /* * We may be doing a reset in response to a request @@ -1030,6 +1011,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) } ieee80211_wake_queues(hw); + spin_unlock_bh(&sc->sc_pcu_lock); /* Start ANI */ ath_start_ani(common); @@ -1037,56 +1019,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) return r; } -static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) -{ - int qnum; - - switch (queue) { - case 0: - qnum = sc->tx.hwq_map[WME_AC_VO]; - break; - case 1: - qnum = sc->tx.hwq_map[WME_AC_VI]; - break; - case 2: - qnum = sc->tx.hwq_map[WME_AC_BE]; - break; - case 3: - qnum = sc->tx.hwq_map[WME_AC_BK]; - break; - default: - qnum = sc->tx.hwq_map[WME_AC_BE]; - break; - } - - return qnum; -} - -int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) -{ - int qnum; - - switch (queue) { - case WME_AC_VO: - qnum = 0; - break; - case WME_AC_VI: - qnum = 1; - break; - case WME_AC_BE: - qnum = 2; - break; - case WME_AC_BK: - qnum = 3; - break; - default: - qnum = -1; - break; - } - - return qnum; -} - /* XXX: Remove me once we don't depend on ath9k_channel for all * this redundant data */ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, @@ -1125,9 +1057,9 @@ static int ath9k_start(struct ieee80211_hw *hw) struct ath9k_channel *init_channel; int r; - ath_print(common, ATH_DBG_CONFIG, - "Starting driver with initial channel: %d MHz\n", - curchan->center_freq); + ath_dbg(common, ATH_DBG_CONFIG, + "Starting driver with initial channel: %d MHz\n", + curchan->center_freq); mutex_lock(&sc->mutex); @@ -1168,19 +1100,15 @@ static int ath9k_start(struct ieee80211_hw *hw) * be followed by initialization of the appropriate bits * and then setup of the interrupt mask. */ - spin_lock_bh(&sc->rx.pcu_lock); - spin_lock_bh(&sc->sc_resetlock); + spin_lock_bh(&sc->sc_pcu_lock); r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); if (r) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d " - "(freq %u MHz)\n", r, - curchan->center_freq); - spin_unlock_bh(&sc->sc_resetlock); - spin_unlock_bh(&sc->rx.pcu_lock); + ath_err(common, + "Unable to reset hardware; reset status %d (freq %u MHz)\n", + r, curchan->center_freq); + spin_unlock_bh(&sc->sc_pcu_lock); goto mutex_unlock; } - spin_unlock_bh(&sc->sc_resetlock); /* * This is needed only to setup initial state @@ -1196,13 +1124,12 @@ static int ath9k_start(struct ieee80211_hw *hw) * here except setup the interrupt mask. */ if (ath_startrecv(sc) != 0) { - ath_print(common, ATH_DBG_FATAL, - "Unable to start recv logic\n"); + ath_err(common, "Unable to start recv logic\n"); r = -EIO; - spin_unlock_bh(&sc->rx.pcu_lock); + spin_unlock_bh(&sc->sc_pcu_lock); goto mutex_unlock; } - spin_unlock_bh(&sc->rx.pcu_lock); + spin_unlock_bh(&sc->sc_pcu_lock); /* Setup our intr mask. */ ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | @@ -1244,7 +1171,14 @@ static int ath9k_start(struct ieee80211_hw *hw) ath9k_btcoex_timer_resume(sc); } - pm_qos_update_request(&sc->pm_qos_req, 55); + /* User has the option to provide pm-qos value as a module + * parameter rather than using the default value of + * 'ATH9K_PM_QOS_DEFAULT_VALUE'. + */ + pm_qos_update_request(&sc->pm_qos_req, ath9k_pm_qos_value); + + if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en) + common->bus_ops->extn_synch_en(common); mutex_unlock: mutex_unlock(&sc->mutex); @@ -1255,19 +1189,16 @@ mutex_unlock: static int ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_tx_control txctl; - int padpos, padsize; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - int qnum; if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { - ath_print(common, ATH_DBG_XMIT, - "ath9k: %s: TX in unexpected wiphy state " - "%d\n", wiphy_name(hw->wiphy), aphy->state); + ath_dbg(common, ATH_DBG_XMIT, + "ath9k: %s: TX in unexpected wiphy state %d\n", + wiphy_name(hw->wiphy), aphy->state); goto exit; } @@ -1279,8 +1210,8 @@ static int ath9k_tx(struct ieee80211_hw *hw, if (ieee80211_is_data(hdr->frame_control) && !ieee80211_is_nullfunc(hdr->frame_control) && !ieee80211_has_pm(hdr->frame_control)) { - ath_print(common, ATH_DBG_PS, "Add PM=1 for a TX frame " - "while in PS mode\n"); + ath_dbg(common, ATH_DBG_PS, + "Add PM=1 for a TX frame while in PS mode\n"); hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); } } @@ -1295,12 +1226,12 @@ static int ath9k_tx(struct ieee80211_hw *hw, if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) ath9k_hw_setrxabort(sc->sc_ah, 0); if (ieee80211_is_pspoll(hdr->frame_control)) { - ath_print(common, ATH_DBG_PS, - "Sending PS-Poll to pick a buffered frame\n"); + ath_dbg(common, ATH_DBG_PS, + "Sending PS-Poll to pick a buffered frame\n"); sc->ps_flags |= PS_WAIT_FOR_PSPOLL_DATA; } else { - ath_print(common, ATH_DBG_PS, - "Wake up to complete TX\n"); + ath_dbg(common, ATH_DBG_PS, + "Wake up to complete TX\n"); sc->ps_flags |= PS_WAIT_FOR_TX_ACK; } /* @@ -1312,36 +1243,12 @@ static int ath9k_tx(struct ieee80211_hw *hw, } memset(&txctl, 0, sizeof(struct ath_tx_control)); + txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)]; - /* - * As a temporary workaround, assign seq# here; this will likely need - * to be cleaned up to work better with Beacon transmission and virtual - * BSSes. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } - - /* Add the padding after the header if this is not already done */ - padpos = ath9k_cmn_padpos(hdr->frame_control); - padsize = padpos & 3; - if (padsize && skb->len>padpos) { - if (skb_headroom(skb) < padsize) - return -1; - skb_push(skb, padsize); - memmove(skb->data, skb->data + padsize, padpos); - } - - qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); - txctl.txq = &sc->tx.txq[qnum]; - - ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); + ath_dbg(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); if (ath_tx_start(hw, skb, &txctl) != 0) { - ath_print(common, ATH_DBG_XMIT, "TX failed\n"); + ath_dbg(common, ATH_DBG_XMIT, "TX failed\n"); goto exit; } @@ -1381,7 +1288,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) } if (sc->sc_flags & SC_OP_INVALID) { - ath_print(common, ATH_DBG_ANY, "Device not present\n"); + ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); mutex_unlock(&sc->mutex); return; } @@ -1400,26 +1307,30 @@ static void ath9k_stop(struct ieee80211_hw *hw) ath9k_btcoex_timer_pause(sc); } + spin_lock_bh(&sc->sc_pcu_lock); + /* make sure h/w will not generate any interrupt * before setting the invalid flag. */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); - spin_lock_bh(&sc->rx.pcu_lock); if (!(sc->sc_flags & SC_OP_INVALID)) { ath_drain_all_txq(sc, false); ath_stoprecv(sc); ath9k_hw_phy_disable(ah); } else sc->rx.rxlink = NULL; - spin_unlock_bh(&sc->rx.pcu_lock); /* disable HAL and put h/w to sleep */ ath9k_hw_disable(ah); ath9k_hw_configpcipowersave(ah, 1, 1); + + spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_ps_restore(sc); - /* Finally, put the chip in FULL SLEEP mode */ - ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); + sc->ps_idle = true; + ath9k_set_wiphy_idle(aphy, true); + ath_radio_disable(sc, hw); sc->sc_flags |= SC_OP_INVALID; @@ -1427,7 +1338,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) mutex_unlock(&sc->mutex); - ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n"); } static int ath9k_add_interface(struct ieee80211_hw *hw, @@ -1460,14 +1371,14 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ic_opmode = vif->type; break; default: - ath_print(common, ATH_DBG_FATAL, - "Interface type %d not yet supported\n", vif->type); + ath_err(common, "Interface type %d not yet supported\n", + vif->type); ret = -EOPNOTSUPP; goto out; } - ath_print(common, ATH_DBG_CONFIG, - "Attach a VIF of type: %d\n", ic_opmode); + ath_dbg(common, ATH_DBG_CONFIG, + "Attach a VIF of type: %d\n", ic_opmode); /* Set the VIF opmode */ avp->av_opmode = ic_opmode; @@ -1513,15 +1424,83 @@ out: return ret; } +static void ath9k_reclaim_beacon(struct ath_softc *sc, + struct ieee80211_vif *vif) +{ + struct ath_vif *avp = (void *)vif->drv_priv; + + /* Disable SWBA interrupt */ + sc->sc_ah->imask &= ~ATH9K_INT_SWBA; + ath9k_ps_wakeup(sc); + ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask); + ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); + tasklet_kill(&sc->bcon_tasklet); + ath9k_ps_restore(sc); + + ath_beacon_return(sc, avp); + sc->sc_flags &= ~SC_OP_BEACONS; + + if (sc->nbcnvifs > 0) { + /* Re-enable beaconing */ + sc->sc_ah->imask |= ATH9K_INT_SWBA; + ath9k_ps_wakeup(sc); + ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask); + ath9k_ps_restore(sc); + } +} + +static int ath9k_change_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum nl80211_iftype new_type, + bool p2p) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + int ret = 0; + + ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n"); + mutex_lock(&sc->mutex); + + switch (new_type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_ADHOC: + if (sc->nbcnvifs >= ATH_BCBUF) { + ath_err(common, "No beacon slot available\n"); + ret = -ENOBUFS; + goto out; + } + break; + case NL80211_IFTYPE_STATION: + /* Stop ANI */ + sc->sc_flags &= ~SC_OP_ANI_RUN; + del_timer_sync(&common->ani.timer); + if ((vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_ADHOC)) + ath9k_reclaim_beacon(sc, vif); + break; + default: + ath_err(common, "Interface type %d not yet supported\n", + vif->type); + ret = -ENOTSUPP; + goto out; + } + vif->type = new_type; + vif->p2p = p2p; + +out: + mutex_unlock(&sc->mutex); + return ret; +} + static void ath9k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_vif *avp = (void *)vif->drv_priv; - ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n"); mutex_lock(&sc->mutex); @@ -1532,26 +1511,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, /* Reclaim beacon resources */ if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || - (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { - /* Disable SWBA interrupt */ - sc->sc_ah->imask &= ~ATH9K_INT_SWBA; - ath9k_ps_wakeup(sc); - ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask); - ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - ath9k_ps_restore(sc); - tasklet_kill(&sc->bcon_tasklet); - } - - ath_beacon_return(sc, avp); - sc->sc_flags &= ~SC_OP_BEACONS; - - if (sc->nbcnvifs) { - /* Re-enable SWBA interrupt */ - sc->sc_ah->imask |= ATH9K_INT_SWBA; - ath9k_ps_wakeup(sc); - ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask); - ath9k_ps_restore(sc); - } + (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) + ath9k_reclaim_beacon(sc, vif); sc->nvifs--; @@ -1631,8 +1592,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (enable_radio) { sc->ps_idle = false; ath_radio_enable(sc, hw); - ath_print(common, ATH_DBG_CONFIG, - "not-idle: enabling radio\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "not-idle: enabling radio\n"); } } @@ -1654,12 +1615,12 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_MONITOR) { if (conf->flags & IEEE80211_CONF_MONITOR) { - ath_print(common, ATH_DBG_CONFIG, - "Monitor mode is enabled\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "Monitor mode is enabled\n"); sc->sc_ah->is_monitoring = true; } else { - ath_print(common, ATH_DBG_CONFIG, - "Monitor mode is disabled\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "Monitor mode is disabled\n"); sc->sc_ah->is_monitoring = false; } } @@ -1691,14 +1652,12 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) goto skip_chan_change; } - ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", - curchan->center_freq); + ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", + curchan->center_freq); /* XXX: remove me eventualy */ ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]); - ath_update_chainmask(sc, conf_is_ht(conf)); - /* update survey stats for the old channel before switching */ spin_lock_irqsave(&common->cc_lock, flags); ath_update_survey_stats(sc); @@ -1725,8 +1684,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) } if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { - ath_print(common, ATH_DBG_FATAL, - "Unable to set channel\n"); + ath_err(common, "Unable to set channel\n"); mutex_unlock(&sc->mutex); return -EINVAL; } @@ -1751,7 +1709,7 @@ skip_chan_change: spin_unlock_bh(&sc->wiphy_lock); if (disable_radio) { - ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); + ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); sc->ps_idle = true; ath_radio_disable(sc, hw); } @@ -1790,8 +1748,8 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, ath9k_hw_setrxfilter(sc->sc_ah, rfilt); ath9k_ps_restore(sc); - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, - "Set HW RX filter: 0x%x\n", rfilt); + ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, + "Set HW RX filter: 0x%x\n", rfilt); } static int ath9k_sta_add(struct ieee80211_hw *hw, @@ -1824,12 +1782,15 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_txq *txq; struct ath9k_tx_queue_info qi; - int ret = 0, qnum; + int ret = 0; if (queue >= WME_NUM_AC) return 0; + txq = sc->tx.txq_map[queue]; + mutex_lock(&sc->mutex); memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); @@ -1838,20 +1799,18 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, qi.tqi_cwmin = params->cw_min; qi.tqi_cwmax = params->cw_max; qi.tqi_burstTime = params->txop; - qnum = ath_get_hal_qnum(queue, sc); - ath_print(common, ATH_DBG_CONFIG, - "Configure tx [queue/halq] [%d/%d], " - "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", - queue, qnum, params->aifs, params->cw_min, - params->cw_max, params->txop); + ath_dbg(common, ATH_DBG_CONFIG, + "Configure tx [queue/halq] [%d/%d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", + queue, txq->axq_qnum, params->aifs, params->cw_min, + params->cw_max, params->txop); - ret = ath_txq_update(sc, qnum, &qi); + ret = ath_txq_update(sc, txq->axq_qnum, &qi); if (ret) - ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); + ath_err(common, "TXQ Update failed\n"); if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) - if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret) + if (queue == WME_AC_BE && !ret) ath_beaconq_config(sc); mutex_unlock(&sc->mutex); @@ -1870,12 +1829,12 @@ static int ath9k_set_key(struct ieee80211_hw *hw, struct ath_common *common = ath9k_hw_common(sc->sc_ah); int ret = 0; - if (modparam_nohwcrypt) + if (ath9k_modparam_nohwcrypt) return -ENOSPC; mutex_lock(&sc->mutex); ath9k_ps_wakeup(sc); - ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Set HW Key\n"); switch (cmd) { case SET_KEY: @@ -1930,13 +1889,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, /* Set aggregation protection mode parameters */ sc->config.ath_aggr_prot = 0; - /* Only legacy IBSS for now */ - if (vif->type == NL80211_IFTYPE_ADHOC) - ath_update_chainmask(sc, 0); - - ath_print(common, ATH_DBG_CONFIG, - "BSSID: %pM aid: 0x%x\n", - common->curbssid, common->curaid); + ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n", + common->curbssid, common->curaid); /* need to reconfigure the beacon */ sc->sc_flags &= ~SC_OP_BEACONS ; @@ -1992,8 +1946,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ERP_PREAMBLE) { - ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", - bss_conf->use_short_preamble); + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", + bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) sc->sc_flags |= SC_OP_PREAMBLE_SHORT; else @@ -2001,8 +1955,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ERP_CTS_PROT) { - ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", - bss_conf->use_cts_prot); + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", + bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && hw->conf.channel->band != IEEE80211_BAND_5GHZ) sc->sc_flags |= SC_OP_PROTECT_ENABLE; @@ -2011,9 +1965,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ASSOC) { - ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", bss_conf->assoc); - ath9k_bss_assoc_info(sc, vif, bss_conf); + ath9k_bss_assoc_info(sc, hw, vif, bss_conf); } mutex_unlock(&sc->mutex); @@ -2026,7 +1980,9 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw) struct ath_softc *sc = aphy->sc; mutex_lock(&sc->mutex); + ath9k_ps_wakeup(sc); tsf = ath9k_hw_gettsf64(sc->sc_ah); + ath9k_ps_restore(sc); mutex_unlock(&sc->mutex); return tsf; @@ -2038,7 +1994,9 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf) struct ath_softc *sc = aphy->sc; mutex_lock(&sc->mutex); + ath9k_ps_wakeup(sc); ath9k_hw_settsf64(sc->sc_ah, tsf); + ath9k_ps_restore(sc); mutex_unlock(&sc->mutex); } @@ -2076,6 +2034,9 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_RX_STOP: break; case IEEE80211_AMPDU_TX_START: + if (!(sc->sc_flags & SC_OP_TXAGGR)) + return -EOPNOTSUPP; + ath9k_ps_wakeup(sc); ret = ath_tx_aggr_start(sc, sta, tid, ssn); if (!ret) @@ -2094,8 +2055,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, ath9k_ps_restore(sc); break; default: - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "Unknown AMPDU action\n"); + ath_err(ath9k_hw_common(sc->sc_ah), "Unknown AMPDU action\n"); } local_bh_enable(); @@ -2195,6 +2155,7 @@ struct ieee80211_ops ath9k_ops = { .start = ath9k_start, .stop = ath9k_stop, .add_interface = ath9k_add_interface, + .change_interface = ath9k_change_interface, .remove_interface = ath9k_remove_interface, .config = ath9k_config, .configure_filter = ath9k_configure_filter, diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index b5b651413e77..78ef1f13386f 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -16,6 +16,7 @@ #include <linux/nl80211.h> #include <linux/pci.h> +#include <linux/ath9k_platform.h> #include "ath9k.h" static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { @@ -29,6 +30,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ + { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ { 0 } }; @@ -53,21 +55,35 @@ static void ath_pci_read_cachesize(struct ath_common *common, int *csz) static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) { - struct ath_hw *ah = (struct ath_hw *) common->ah; - - common->ops->read(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); - - if (!ath9k_hw_wait(ah, - AR_EEPROM_STATUS_DATA, - AR_EEPROM_STATUS_DATA_BUSY | - AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, - AH_WAIT_TIMEOUT)) { - return false; + struct ath_softc *sc = (struct ath_softc *) common->priv; + struct ath9k_platform_data *pdata = sc->dev->platform_data; + + if (pdata) { + if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { + ath_err(common, + "%s: eeprom read failed, offset %08x is out of range\n", + __func__, off); + } + + *data = pdata->eeprom_data[off]; + } else { + struct ath_hw *ah = (struct ath_hw *) common->ah; + + common->ops->read(ah, AR5416_EEPROM_OFFSET + + (off << AR5416_EEPROM_S)); + + if (!ath9k_hw_wait(ah, + AR_EEPROM_STATUS_DATA, + AR_EEPROM_STATUS_DATA_BUSY | + AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, + AH_WAIT_TIMEOUT)) { + return false; + } + + *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA), + AR_EEPROM_STATUS_DATA_VAL); } - *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA), - AR_EEPROM_STATUS_DATA_VAL); - return true; } @@ -80,7 +96,7 @@ static void ath_pci_bt_coex_prep(struct ath_common *common) struct pci_dev *pdev = to_pci_dev(sc->dev); u8 aspm; - if (!pdev->is_pcie) + if (!pci_is_pcie(pdev)) return; pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm); @@ -88,11 +104,23 @@ static void ath_pci_bt_coex_prep(struct ath_common *common) pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); } +static void ath_pci_extn_synch_enable(struct ath_common *common) +{ + struct ath_softc *sc = (struct ath_softc *) common->priv; + struct pci_dev *pdev = to_pci_dev(sc->dev); + u8 lnkctl; + + pci_read_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, &lnkctl); + lnkctl |= PCI_EXP_LNKCTL_ES; + pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl); +} + static const struct ath_bus_ops ath_pci_bus_ops = { .ath_bus_type = ATH_PCI, .read_cachesize = ath_pci_read_cachesize, .eeprom_read = ath_pci_eeprom_read, .bt_coex_prep = ath_pci_bt_coex_prep, + .extn_synch_en = ath_pci_extn_synch_enable, }; static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -236,6 +264,8 @@ static void ath_pci_remove(struct pci_dev *pdev) struct ath_softc *sc = aphy->sc; void __iomem *mem = sc->mem; + if (!is_ath9k_unloaded) + sc->sc_ah->ah_flags |= AH_UNPLUGGED; ath9k_deinit_device(sc); free_irq(sc->irq, sc); ieee80211_free_hw(sc->hw); @@ -247,34 +277,25 @@ static void ath_pci_remove(struct pci_dev *pdev) #ifdef CONFIG_PM -static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) +static int ath_pci_suspend(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - return 0; } -static int ath_pci_resume(struct pci_dev *pdev) +static int ath_pci_resume(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; u32 val; - int err; - - pci_restore_state(pdev); - - err = pci_enable_device(pdev); - if (err) - return err; /* * Suspend/Resume resets the PCI configuration space, so we have to @@ -290,10 +311,38 @@ static int ath_pci_resume(struct pci_dev *pdev) AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); + /* + * Reset key cache to sane defaults (all entries cleared) instead of + * semi-random values after suspend/resume. + */ + ath9k_ps_wakeup(sc); + ath9k_init_crypto(sc); + ath9k_ps_restore(sc); + + sc->ps_idle = true; + ath9k_set_wiphy_idle(aphy, true); + ath_radio_disable(sc, hw); + return 0; } -#endif /* CONFIG_PM */ +static const struct dev_pm_ops ath9k_pm_ops = { + .suspend = ath_pci_suspend, + .resume = ath_pci_resume, + .freeze = ath_pci_suspend, + .thaw = ath_pci_resume, + .poweroff = ath_pci_suspend, + .restore = ath_pci_resume, +}; + +#define ATH9K_PM_OPS (&ath9k_pm_ops) + +#else /* !CONFIG_PM */ + +#define ATH9K_PM_OPS NULL + +#endif /* !CONFIG_PM */ + MODULE_DEVICE_TABLE(pci, ath_pci_id_table); @@ -302,10 +351,7 @@ static struct pci_driver ath_pci_driver = { .id_table = ath_pci_id_table, .probe = ath_pci_probe, .remove = ath_pci_remove, -#ifdef CONFIG_PM - .suspend = ath_pci_suspend, - .resume = ath_pci_resume, -#endif /* CONFIG_PM */ + .driver.pm = ATH9K_PM_OPS, }; int ath_pci_init(void) diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 17969af842f6..5e3d7496986e 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -19,6 +19,7 @@ #define CHANSEL_DIV 15 #define CHANSEL_2G(_freq) (((_freq) * 0x10000) / CHANSEL_DIV) +#define CHANSEL_2G_9485(_freq) ((((_freq) * 0x10000) - 215) / CHANSEL_DIV) #define CHANSEL_5G(_freq) (((_freq) * 0x8000) / CHANSEL_DIV) #define AR_PHY_BASE 0x9800 diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 89978d71617f..e45147820eae 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -381,25 +381,6 @@ static const struct ath_rate_table ar5416_11g_ratetable = { static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, struct ieee80211_tx_rate *rate); -static inline int8_t median(int8_t a, int8_t b, int8_t c) -{ - if (a >= b) { - if (b >= c) - return b; - else if (a > c) - return c; - else - return a; - } else { - if (a >= c) - return a; - else if (b >= c) - return c; - else - return b; - } -} - static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, struct ath_rate_priv *ath_rc_priv) { @@ -419,7 +400,7 @@ static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, } } -static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv) +static void ath_rc_init_valid_rate_idx(struct ath_rate_priv *ath_rc_priv) { u8 i; @@ -427,7 +408,7 @@ static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv) ath_rc_priv->valid_rate_index[i] = 0; } -static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv, +static inline void ath_rc_set_valid_rate_idx(struct ath_rate_priv *ath_rc_priv, u8 index, int valid_tx_rate) { BUG_ON(index > ath_rc_priv->rate_table_size); @@ -508,7 +489,7 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i; ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_set_valid_txmask(ath_rc_priv, i, 1); + ath_rc_set_valid_rate_idx(ath_rc_priv, i, 1); hi = i; } } @@ -551,7 +532,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, ath_rc_priv->valid_phy_rateidx[phy] [valid_rate_count] = j; ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_set_valid_txmask(ath_rc_priv, j, 1); + ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1); hi = A_MAX(hi, j); } } @@ -587,7 +568,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, ath_rc_priv->valid_phy_rateidx[phy] [ath_rc_priv->valid_phy_ratecnt[phy]] = j; ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_set_valid_txmask(ath_rc_priv, j, 1); + ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1); hi = A_MAX(hi, j); } } @@ -883,7 +864,7 @@ static bool ath_rc_update_per(struct ath_softc *sc, bool state_change = false; int count, n_bad_frames; u8 last_per; - static u32 nretry_to_per_lookup[10] = { + static const u32 nretry_to_per_lookup[10] = { 100 * 0 / 1, 100 * 1 / 4, 100 * 1 / 2, @@ -1106,13 +1087,13 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, struct ieee80211_tx_rate *rate) { int rix = 0, i = 0; - int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 }; + static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 }; if (!(rate->flags & IEEE80211_TX_RC_MCS)) return rate->idx; while (rate->idx > mcs_rix_off[i] && - i < sizeof(mcs_rix_off)/sizeof(int)) { + i < ARRAY_SIZE(mcs_rix_off)) { rix++; i++; } @@ -1203,7 +1184,7 @@ struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, return &ar5416_11na_ratetable; return &ar5416_11a_ratetable; default: - ath_print(common, ATH_DBG_CONFIG, "Invalid band\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Invalid band\n"); return NULL; } } @@ -1229,7 +1210,7 @@ static void ath_rc_init(struct ath_softc *sc, } /* Determine the valid rates */ - ath_rc_init_valid_txmask(ath_rc_priv); + ath_rc_init_valid_rate_idx(ath_rc_priv); for (i = 0; i < WLAN_RC_PHY_MAX; i++) { for (j = 0; j < MAX_TX_RATE_PHY; j++) @@ -1278,9 +1259,9 @@ static void ath_rc_init(struct ath_softc *sc, ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; ath_rc_priv->rate_table = rate_table; - ath_print(common, ATH_DBG_CONFIG, - "RC Initialized with capabilities: 0x%x\n", - ath_rc_priv->ht_cap); + ath_dbg(common, ATH_DBG_CONFIG, + "RC Initialized with capabilities: 0x%x\n", + ath_rc_priv->ht_cap); } static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, @@ -1340,7 +1321,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, struct ath_rate_priv *ath_rc_priv = priv_sta; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr; - int final_ts_idx = 0, tx_status = 0, is_underrun = 0; + int final_ts_idx = 0, tx_status = 0; int long_retry = 0; __le16 fc; int i; @@ -1373,32 +1354,17 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, tx_info->status.ampdu_len = 1; } - /* - * If an underrun error is seen assume it as an excessive retry only - * if max frame trigger level has been reached (2 KB for singel stream, - * and 4 KB for dual stream). Adjust the long retry as if the frame was - * tried hw->max_rate_tries times to affect how ratectrl updates PER for - * the failed rate. In case of congestion on the bus penalizing these - * type of underruns should help hardware actually transmit new frames - * successfully by eventually preferring slower rates. This itself - * should also alleviate congestion on the bus. - */ - if ((tx_info->pad[0] & ATH_TX_INFO_UNDERRUN) && - (sc->sc_ah->tx_trig_level >= ath_rc_priv->tx_triglevel_max)) { - tx_status = 1; - is_underrun = 1; - } - - if (tx_info->pad[0] & ATH_TX_INFO_XRETRY) + if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) tx_status = 1; ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, - (is_underrun) ? sc->hw->max_rate_tries : long_retry); + long_retry); /* Check if aggregation has to be enabled for this tid */ if (conf_is_ht(&sc->hw->conf) && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { - if (ieee80211_is_data_qos(fc)) { + if (ieee80211_is_data_qos(fc) && + skb_get_queue_mapping(skb) != IEEE80211_AC_VO) { u8 *qc, tid; struct ath_node *an; @@ -1407,7 +1373,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, an = (struct ath_node *)sta->drv_priv; if(ath_tx_aggr_check(sc, an, tid)) - ieee80211_start_tx_ba_session(sta, tid); + ieee80211_start_tx_ba_session(sta, tid, 0); } } @@ -1444,12 +1410,12 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, ath_rc_priv->neg_ht_rates.rs_nrates = j; } - is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; + is_cw40 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); if (is_cw40) - is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; + is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40); else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) - is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; + is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20); /* Choose rate table first */ @@ -1468,10 +1434,8 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, struct ath_rate_priv *ath_rc_priv = priv_sta; const struct ath_rate_table *rate_table = NULL; bool oper_cw40 = false, oper_sgi; - bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ? - true : false; - bool local_sgi = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ? - true : false; + bool local_cw40 = !!(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG); + bool local_sgi = !!(ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG); /* FIXME: Handle AP mode later when we support CWM */ @@ -1499,9 +1463,9 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, oper_cw40, oper_sgi); ath_rc_init(sc, priv_sta, sband, sta, rate_table); - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, - "Operating HT Bandwidth changed to: %d\n", - sc->hw->conf.channel_type); + ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, + "Operating HT Bandwidth changed to: %d\n", + sc->hw->conf.channel_type); } } } @@ -1612,13 +1576,11 @@ static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp); if (!rate_priv) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "Unable to allocate private rc structure\n"); + ath_err(ath9k_hw_common(sc->sc_ah), + "Unable to allocate private rc structure\n"); return NULL; } - rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max; - return rate_priv; } diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 2f46a2266ba1..5d984b8acdb1 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -195,7 +195,6 @@ struct ath_rc_stats { * @rate_max_phy: phy index for the max rate * @per: PER for every valid rate in % * @probe_interval: interval for ratectrl to probe for other rates - * @prev_data_rix: rate idx of last data frame * @ht_cap: HT capabilities * @neg_rates: Negotatied rates * @neg_ht_rates: Negotiated HT rates @@ -214,22 +213,14 @@ struct ath_rate_priv { u32 probe_time; u32 per_down_time; u32 probe_interval; - u32 prev_data_rix; - u32 tx_triglevel_max; struct ath_rateset neg_rates; struct ath_rateset neg_ht_rates; - struct ath_rate_softc *asc; const struct ath_rate_table *rate_table; struct dentry *debugfs_rcstats; struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; }; -#define ATH_TX_INFO_FRAME_TYPE_INTERNAL (1 << 0) -#define ATH_TX_INFO_FRAME_TYPE_PAUSE (1 << 1) -#define ATH_TX_INFO_XRETRY (1 << 3) -#define ATH_TX_INFO_UNDERRUN (1 << 4) - enum ath9k_internal_frame_type { ATH9K_IFT_NOT_INTERNAL, ATH9K_IFT_PAUSE, diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index fdc2ec52b42f..b2497b8601e5 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -165,7 +165,7 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc, u32 nbuf = 0; if (list_empty(&sc->rx.rxbuf)) { - ath_print(common, ATH_DBG_QUEUE, "No free rx buf available\n"); + ath_dbg(common, ATH_DBG_QUEUE, "No free rx buf available\n"); return; } @@ -269,7 +269,7 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; bf->bf_buf_addr = 0; - ath_print(common, ATH_DBG_FATAL, + ath_err(common, "dma_mapping_error() on RX init\n"); error = -ENOMEM; goto rx_init_fail; @@ -317,7 +317,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) struct ath_buf *bf; int error = 0; - spin_lock_init(&sc->rx.pcu_lock); + spin_lock_init(&sc->sc_pcu_lock); sc->sc_flags &= ~SC_OP_RXFLUSH; spin_lock_init(&sc->rx.rxbuflock); @@ -327,17 +327,17 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN, min(common->cachelsz, (u16)64)); - ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", - common->cachelsz, common->rx_bufsize); + ath_dbg(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", + common->cachelsz, common->rx_bufsize); /* Initialize rx descriptors */ error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, "rx", nbufs, 1, 0); if (error != 0) { - ath_print(common, ATH_DBG_FATAL, - "failed to allocate rx descriptors: %d\n", - error); + ath_err(common, + "failed to allocate rx descriptors: %d\n", + error); goto err; } @@ -358,8 +358,8 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; bf->bf_buf_addr = 0; - ath_print(common, ATH_DBG_FATAL, - "dma_mapping_error() on RX init\n"); + ath_err(common, + "dma_mapping_error() on RX init\n"); error = -ENOMEM; goto err; } @@ -528,6 +528,13 @@ bool ath_stoprecv(struct ath_softc *sc) sc->rx.rxlink = NULL; spin_unlock_bh(&sc->rx.rxbuflock); + if (!(ah->ah_flags & AH_UNPLUGGED) && + unlikely(!stopped)) { + ath_err(ath9k_hw_common(sc->sc_ah), + "Could not stop RX, we could be " + "confusing the DMA engine when we start RX up\n"); + ATH_DBG_WARN_ON_ONCE(!stopped); + } return stopped; } @@ -588,9 +595,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) if (sc->ps_flags & PS_BEACON_SYNC) { sc->ps_flags &= ~PS_BEACON_SYNC; - ath_print(common, ATH_DBG_PS, - "Reconfigure Beacon timers based on " - "timestamp from the AP\n"); + ath_dbg(common, ATH_DBG_PS, + "Reconfigure Beacon timers based on timestamp from the AP\n"); ath_beacon_config(sc, NULL); } @@ -602,8 +608,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) * a backup trigger for returning into NETWORK SLEEP state, * so we are waiting for it as well. */ - ath_print(common, ATH_DBG_PS, "Received DTIM beacon indicating " - "buffered broadcast/multicast frame(s)\n"); + ath_dbg(common, ATH_DBG_PS, + "Received DTIM beacon indicating buffered broadcast/multicast frame(s)\n"); sc->ps_flags |= PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON; return; } @@ -615,8 +621,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) * been delivered. */ sc->ps_flags &= ~PS_WAIT_FOR_CAB; - ath_print(common, ATH_DBG_PS, - "PS wait for CAB frames timed out\n"); + ath_dbg(common, ATH_DBG_PS, + "PS wait for CAB frames timed out\n"); } } @@ -641,15 +647,14 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) * point. */ sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON); - ath_print(common, ATH_DBG_PS, - "All PS CAB frames received, back to sleep\n"); + ath_dbg(common, ATH_DBG_PS, + "All PS CAB frames received, back to sleep\n"); } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) && !is_multicast_ether_addr(hdr->addr1) && !ieee80211_has_morefrags(hdr->frame_control)) { sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA; - ath_print(common, ATH_DBG_PS, - "Going back to sleep after having received " - "PS-Poll data (0x%lx)\n", + ath_dbg(common, ATH_DBG_PS, + "Going back to sleep after having received PS-Poll data (0x%lx)\n", sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | PS_WAIT_FOR_PSPOLL_DATA | @@ -658,8 +663,7 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) } static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw, - struct ath_softc *sc, struct sk_buff *skb, - struct ieee80211_rx_status *rxs) + struct ath_softc *sc, struct sk_buff *skb) { struct ieee80211_hdr *hdr; @@ -958,8 +962,9 @@ static int ath9k_process_rate(struct ath_common *common, * No valid hardware bitrate found -- we should not get here * because hardware has already validated this frame as OK. */ - ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected " - "0x%02x using 1 Mbit\n", rx_stats->rs_rate); + ath_dbg(common, ATH_DBG_XMIT, + "unsupported hw bitrate detected 0x%02x using 1 Mbit\n", + rx_stats->rs_rate); return -EINVAL; } @@ -969,36 +974,23 @@ static void ath9k_process_rssi(struct ath_common *common, struct ieee80211_hdr *hdr, struct ath_rx_status *rx_stats) { + struct ath_wiphy *aphy = hw->priv; struct ath_hw *ah = common->ah; - struct ieee80211_sta *sta; - struct ath_node *an; - int last_rssi = ATH_RSSI_DUMMY_MARKER; + int last_rssi; __le16 fc; + if (ah->opmode != NL80211_IFTYPE_STATION) + return; + fc = hdr->frame_control; + if (!ieee80211_is_beacon(fc) || + compare_ether_addr(hdr->addr3, common->curbssid)) + return; - rcu_read_lock(); - /* - * XXX: use ieee80211_find_sta! This requires quite a bit of work - * under the current ath9k virtual wiphy implementation as we have - * no way of tying a vif to wiphy. Typically vifs are attached to - * at least one sdata of a wiphy on mac80211 but with ath9k virtual - * wiphy you'd have to iterate over every wiphy and each sdata. - */ - if (is_multicast_ether_addr(hdr->addr1)) - sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL); - else - sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1); - - if (sta) { - an = (struct ath_node *) sta->drv_priv; - if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && - !rx_stats->rs_moreaggr) - ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi); - last_rssi = an->last_rssi; - } - rcu_read_unlock(); + if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) + ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi); + last_rssi = aphy->last_rssi; if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) rx_stats->rs_rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); @@ -1006,8 +998,7 @@ static void ath9k_process_rssi(struct ath_common *common, rx_stats->rs_rssi = 0; /* Update Beacon RSSI, this is used by ANI. */ - if (ieee80211_is_beacon(fc)) - ah->stats.avgbrssi = rx_stats->rs_rssi; + ah->stats.avgbrssi = rx_stats->rs_rssi; } /* @@ -1637,7 +1628,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); /* - * The hw can techncically differ from common->hw when using ath9k + * The hw can technically differ from common->hw when using ath9k * virtual wiphy so to account for that we iterate over the active * wiphys and find the appropriate wiphy and therefore hw. */ @@ -1744,9 +1735,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) dev_kfree_skb_any(requeue_skb); bf->bf_mpdu = NULL; bf->bf_buf_addr = 0; - ath_print(common, ATH_DBG_FATAL, - "dma_mapping_error() on RX\n"); - ath_rx_send_to_mac80211(hw, sc, skb, rxs); + ath_err(common, "dma_mapping_error() on RX\n"); + ath_rx_send_to_mac80211(hw, sc, skb); break; } @@ -1762,17 +1752,18 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) } spin_lock_irqsave(&sc->sc_pm_lock, flags); - if (unlikely(ath9k_check_auto_sleep(sc) || - (sc->ps_flags & (PS_WAIT_FOR_BEACON | + + if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | - PS_WAIT_FOR_PSPOLL_DATA)))) + PS_WAIT_FOR_PSPOLL_DATA)) || + unlikely(ath9k_check_auto_sleep(sc))) ath_rx_ps(sc, skb); spin_unlock_irqrestore(&sc->sc_pm_lock, flags); if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) ath_ant_comb_scan(sc, &rs); - ath_rx_send_to_mac80211(hw, sc, skb, rxs); + ath_rx_send_to_mac80211(hw, sc, skb); requeue: if (edma) { diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 2c6a22fbb0f0..4df5659c6c16 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -787,6 +787,8 @@ #define AR_SREV_REVISION_9271_11 1 #define AR_SREV_VERSION_9300 0x1c0 #define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */ +#define AR_SREV_VERSION_9485 0x240 +#define AR_SREV_REVISION_9485_10 0 #define AR_SREV_5416(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ @@ -859,20 +861,24 @@ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9300_20))) +#define AR_SREV_9485(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) +#define AR_SREV_9485_10(_ah) \ + (AR_SREV_9485(_ah) && \ + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_10)) + #define AR_SREV_9285E_20(_ah) \ (AR_SREV_9285_12_OR_LATER(_ah) && \ ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) -#define AR_DEVID_7010(_ah) \ - (((_ah)->hw_version.devid == 0x7010) || \ - ((_ah)->hw_version.devid == 0x7015) || \ - ((_ah)->hw_version.devid == 0x9018) || \ - ((_ah)->hw_version.devid == 0xA704) || \ - ((_ah)->hw_version.devid == 0x1200)) +enum ath_usb_dev { + AR9280_USB = 1, /* AR7010 + AR9280, UB94 */ + AR9287_USB = 2, /* AR7010 + AR9287, UB95 */ +}; -#define AR9287_HTC_DEVID(_ah) \ - (((_ah)->hw_version.devid == 0x7015) || \ - ((_ah)->hw_version.devid == 0x1200)) +#define AR_DEVID_7010(_ah) \ + (((_ah)->hw_version.usbdev == AR9280_USB) || \ + ((_ah)->hw_version.usbdev == AR9287_USB)) #define AR_RADIO_SREV_MAJOR 0xf0 #define AR_RAD5133_SREV_MAJOR 0xc0 @@ -1074,6 +1080,9 @@ enum { #define AR_INTR_PRIO_ASYNC_MASK 0x40c8 #define AR_INTR_PRIO_SYNC_MASK 0x40cc #define AR_INTR_PRIO_ASYNC_ENABLE 0x40d4 +#define AR_ENT_OTP 0x40d8 +#define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 +#define AR_ENT_OTP_MPSD 0x00800000 #define AR_RTC_9300_PLL_DIV 0x000003ff #define AR_RTC_9300_PLL_DIV_S 0 @@ -1111,6 +1120,8 @@ enum { #define AR_RTC_PLL_CONTROL \ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014) +#define AR_RTC_PLL_CONTROL2 0x703c + #define AR_RTC_PLL_DIV 0x0000001f #define AR_RTC_PLL_DIV_S 0 #define AR_RTC_PLL_DIV2 0x00000020 @@ -1574,6 +1585,7 @@ enum { #define AR_PCU_TBTT_PROTECT 0x00200000 #define AR_PCU_CLEAR_VMF 0x01000000 #define AR_PCU_CLEAR_BA_VALID 0x04000000 +#define AR_PCU_ALWAYS_PERFORM_KEYSEARCH 0x10000000 #define AR_PCU_BT_ANT_PREVENT_RX 0x00100000 #define AR_PCU_BT_ANT_PREVENT_RX_S 20 diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index ec7cf5ee56bc..2dc7095e56d1 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c @@ -107,6 +107,7 @@ int ath9k_wiphy_add(struct ath_softc *sc) aphy->sc = sc; aphy->hw = hw; sc->sec_wiphy[i] = aphy; + aphy->last_rssi = ATH_RSSI_DUMMY_MARKER; spin_unlock_bh(&sc->wiphy_lock); memcpy(addr, common->macaddr, ETH_ALEN); @@ -186,7 +187,7 @@ static int ath9k_send_nullfunc(struct ath_wiphy *aphy, info->control.rates[1].idx = -1; memset(&txctl, 0, sizeof(struct ath_tx_control)); - txctl.txq = &sc->tx.txq[sc->tx.hwq_map[WME_AC_VO]]; + txctl.txq = sc->tx.txq_map[WME_AC_VO]; txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; if (ath_tx_start(aphy->hw, skb, &txctl) != 0) @@ -287,7 +288,6 @@ void ath9k_wiphy_chan_work(struct work_struct *work) /* sync hw configuration for hw code */ common->hw = aphy->hw; - ath_update_chainmask(sc, sc->chan_is_ht); if (ath_set_channel(sc, aphy->hw, &sc->sc_ah->channels[sc->chan_idx]) < 0) { printk(KERN_DEBUG "ath9k: Failed to set channel for new " @@ -304,13 +304,12 @@ void ath9k_wiphy_chan_work(struct work_struct *work) * ath9k version of ieee80211_tx_status() for TX frames that are generated * internally in the driver. */ -void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) +void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype) { struct ath_wiphy *aphy = hw->priv; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - if ((tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_PAUSE) && - aphy->state == ATH_WIPHY_PAUSING) { + if (ftype == ATH9K_IFT_PAUSE && aphy->state == ATH_WIPHY_PAUSING) { if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) { printk(KERN_DEBUG "ath9k: %s: no ACK for pause " "frame\n", wiphy_name(hw->wiphy)); @@ -656,10 +655,9 @@ void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle) struct ath_softc *sc = aphy->sc; aphy->idle = idle; - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, - "Marking %s as %s\n", - wiphy_name(aphy->hw->wiphy), - idle ? "idle" : "not-idle"); + ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, + "Marking %s as %sidle\n", + wiphy_name(aphy->hw->wiphy), idle ? "" : "not-"); } /* Only bother starting a queue on an active virtual wiphy */ bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue) diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 93a8bda09c25..dc862f5e1162 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -120,17 +120,27 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv) kfree(priv->wmi); } -void ath9k_wmi_tasklet(unsigned long data) +void ath9k_swba_tasklet(unsigned long data) { struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; struct ath_common *common = ath9k_hw_common(priv->ah); - ath_print(common, ATH_DBG_WMI, "SWBA Event received\n"); + ath_dbg(common, ATH_DBG_WMI, "SWBA Event received\n"); ath9k_htc_swba(priv, priv->wmi->beacon_pending); } +void ath9k_fatal_work(struct work_struct *work) +{ + struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, + fatal_work); + struct ath_common *common = ath9k_hw_common(priv->ah); + + ath_dbg(common, ATH_DBG_FATAL, "FATAL Event received, resetting device\n"); + ath9k_htc_reset(priv); +} + static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) { skb_pull(skb, sizeof(struct wmi_cmd_hdr)); @@ -163,7 +173,11 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, switch (cmd_id) { case WMI_SWBA_EVENTID: wmi->beacon_pending = *(u8 *)wmi_event; - tasklet_schedule(&wmi->drv_priv->wmi_tasklet); + tasklet_schedule(&wmi->drv_priv->swba_tasklet); + break; + case WMI_FATAL_EVENTID: + ieee80211_queue_work(wmi->drv_priv->hw, + &wmi->drv_priv->fatal_work); break; case WMI_TXRATE_EVENTID: #ifdef CONFIG_ATH9K_HTC_DEBUGFS @@ -250,7 +264,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, int time_left, ret = 0; unsigned long flags; - if (wmi->drv_priv->op_flags & OP_UNPLUGGED) + if (ah->ah_flags & AH_UNPLUGGED) return 0; skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC); @@ -286,9 +300,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout); if (!time_left) { - ath_print(common, ATH_DBG_WMI, - "Timeout waiting for WMI command: %s\n", - wmi_cmd_to_name(cmd_id)); + ath_dbg(common, ATH_DBG_WMI, + "Timeout waiting for WMI command: %s\n", + wmi_cmd_to_name(cmd_id)); mutex_unlock(&wmi->op_mutex); return -ETIMEDOUT; } @@ -298,8 +312,8 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, return 0; out: - ath_print(common, ATH_DBG_WMI, - "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id)); + ath_dbg(common, ATH_DBG_WMI, + "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id)); mutex_unlock(&wmi->op_mutex); kfree_skb(skb); diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index ac61074af8ac..42084277522d 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -117,7 +117,8 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, u8 *cmd_buf, u32 cmd_len, u8 *rsp_buf, u32 rsp_len, u32 timeout); -void ath9k_wmi_tasklet(unsigned long data); +void ath9k_swba_tasklet(unsigned long data); +void ath9k_fatal_work(struct work_struct *work); #define WMI_CMD(_wmi_cmd) \ do { \ diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index aff04789f794..332d1feb5c18 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -48,19 +48,17 @@ static u16 bits_per_symbol[][2] = { #define IS_HT_RATE(_rate) ((_rate) & 0x80) -static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head); +static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, + struct list_head *bf_head); static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, struct ath_txq *txq, struct list_head *bf_q, struct ath_tx_status *ts, int txok, int sendbar); static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, struct list_head *head); -static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); -static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, - struct ath_tx_status *ts, int txok); +static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len); static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, - int nbad, int txok, bool update_rc); + int nframes, int nbad, int txok, bool update_rc); static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, int seqno); @@ -124,7 +122,7 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; + struct ath_txq *txq = tid->ac->txq; WARN_ON(!tid->paused); @@ -140,12 +138,21 @@ unlock: spin_unlock_bh(&txq->axq_lock); } +static struct ath_frame_info *get_frame_info(struct sk_buff *skb) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + BUILD_BUG_ON(sizeof(struct ath_frame_info) > + sizeof(tx_info->rate_driver_data)); + return (struct ath_frame_info *) &tx_info->rate_driver_data[0]; +} + static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; + struct ath_txq *txq = tid->ac->txq; struct ath_buf *bf; struct list_head bf_head; struct ath_tx_status ts; + struct ath_frame_info *fi; INIT_LIST_HEAD(&bf_head); @@ -156,12 +163,15 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) bf = list_first_entry(&tid->buf_q, struct ath_buf, list); list_move_tail(&bf->list, &bf_head); - if (bf_isretried(bf)) { - ath_tx_update_baw(sc, tid, bf->bf_seqno); + spin_unlock_bh(&txq->axq_lock); + fi = get_frame_info(bf->bf_mpdu); + if (fi->retries) { + ath_tx_update_baw(sc, tid, fi->seqno); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); } else { - ath_tx_send_ht_normal(sc, txq, tid, &bf_head); + ath_tx_send_normal(sc, txq, tid, &bf_head); } + spin_lock_bh(&txq->axq_lock); } spin_unlock_bh(&txq->axq_lock); @@ -184,14 +194,11 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, } static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, - struct ath_buf *bf) + u16 seqno) { int index, cindex; - if (bf_isretried(bf)) - return; - - index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); + index = ATH_BA_INDEX(tid->seq_start, seqno); cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); __set_bit(cindex, tid->tx_buf); @@ -215,6 +222,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf; struct list_head bf_head; struct ath_tx_status ts; + struct ath_frame_info *fi; memset(&ts, 0, sizeof(ts)); INIT_LIST_HEAD(&bf_head); @@ -226,8 +234,9 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, bf = list_first_entry(&tid->buf_q, struct ath_buf, list); list_move_tail(&bf->list, &bf_head); - if (bf_isretried(bf)) - ath_tx_update_baw(sc, tid, bf->bf_seqno); + fi = get_frame_info(bf->bf_mpdu); + if (fi->retries) + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock(&txq->axq_lock); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); @@ -239,16 +248,15 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, } static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf) + struct sk_buff *skb) { - struct sk_buff *skb; + struct ath_frame_info *fi = get_frame_info(skb); struct ieee80211_hdr *hdr; - bf->bf_state.bf_type |= BUF_RETRY; - bf->bf_retries++; TX_STAT_INC(txq->axq_qnum, a_retries); + if (fi->retries++ > 0) + return; - skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); } @@ -298,9 +306,41 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) return tbf; } +static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf, + struct ath_tx_status *ts, int txok, + int *nframes, int *nbad) +{ + struct ath_frame_info *fi; + u16 seq_st = 0; + u32 ba[WME_BA_BMP_SIZE >> 5]; + int ba_index; + int isaggr = 0; + + *nbad = 0; + *nframes = 0; + + isaggr = bf_isaggr(bf); + if (isaggr) { + seq_st = ts->ts_seqnum; + memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); + } + + while (bf) { + fi = get_frame_info(bf->bf_mpdu); + ba_index = ATH_BA_INDEX(seq_st, fi->seqno); + + (*nframes)++; + if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) + (*nbad)++; + + bf = bf->bf_next; + } +} + + static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf, struct list_head *bf_q, - struct ath_tx_status *ts, int txok) + struct ath_tx_status *ts, int txok, bool retry) { struct ath_node *an = NULL; struct sk_buff *skb; @@ -316,7 +356,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; bool rc_update = true; struct ieee80211_tx_rate rates[4]; + struct ath_frame_info *fi; int nframes; + u8 tidno; skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; @@ -325,7 +367,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, hw = bf->aphy->hw; memcpy(rates, tx_info->control.rates, sizeof(rates)); - nframes = bf->bf_nframes; rcu_read_lock(); @@ -342,7 +383,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, !bf->bf_stale || bf_next != NULL) list_move_tail(&bf->list, &bf_head); - ath_tx_rc_status(bf, ts, 1, 0, false); + ath_tx_rc_status(bf, ts, 1, 1, 0, false); ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0, 0); @@ -352,14 +393,15 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, } an = (struct ath_node *)sta->drv_priv; - tid = ATH_AN_2_TID(an, bf->bf_tidno); + tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; + tid = ATH_AN_2_TID(an, tidno); /* * The hardware occasionally sends a tx status for the wrong TID. * In this case, the BA status cannot be considered valid and all * subframes need to be retransmitted */ - if (bf->bf_tidno != ts->tid) + if (tidno != ts->tid) txok = false; isaggr = bf_isaggr(bf); @@ -385,15 +427,16 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, INIT_LIST_HEAD(&bf_pending); INIT_LIST_HEAD(&bf_head); - nbad = ath_tx_num_badfrms(sc, bf, ts, txok); + ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad); while (bf) { txfail = txpending = 0; bf_next = bf->bf_next; skb = bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); + fi = get_frame_info(skb); - if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { + if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) { /* transmit completion, subframe is * acked by block ack */ acked_cnt++; @@ -401,10 +444,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, /* transmit completion */ acked_cnt++; } else { - if (!(tid->state & AGGR_CLEANUP) && - !bf_last->bf_tx_aborted) { - if (bf->bf_retries < ATH_MAX_SW_RETRIES) { - ath_tx_set_retry(sc, txq, bf); + if (!(tid->state & AGGR_CLEANUP) && retry) { + if (fi->retries < ATH_MAX_SW_RETRIES) { + ath_tx_set_retry(sc, txq, bf->bf_mpdu); txpending = 1; } else { bf->bf_state.bf_type |= BUF_XRETRY; @@ -442,16 +484,15 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, * block-ack window */ spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, bf->bf_seqno); + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock_bh(&txq->axq_lock); if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { memcpy(tx_info->control.rates, rates, sizeof(rates)); - bf->bf_nframes = nframes; - ath_tx_rc_status(bf, ts, nbad, txok, true); + ath_tx_rc_status(bf, ts, nframes, nbad, txok, true); rc_update = false; } else { - ath_tx_rc_status(bf, ts, nbad, txok, false); + ath_tx_rc_status(bf, ts, nframes, nbad, txok, false); } ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, @@ -470,14 +511,13 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, */ if (!tbf) { spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, - bf->bf_seqno); + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock_bh(&txq->axq_lock); bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, ts, nbad, - 0, false); + ath_tx_rc_status(bf, ts, nframes, + nbad, 0, false); ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0, 0); @@ -611,6 +651,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, u16 minlen; u8 flags, rix; int width, streams, half_gi, ndelim, mindelim; + struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); /* Select standard number of delimiters based on frame length alone */ ndelim = ATH_AGGR_GET_NDELIM(frmlen); @@ -621,7 +662,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, * TODO - this could be improved to be dependent on the rate. * The hardware can keep up at lower rates, but not higher rates */ - if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) + if (fi->keyix != ATH9K_TXKEYIX_INVALID) ndelim += ATH_AGGR_ENCRYPTDELIM; /* @@ -665,7 +706,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, - struct list_head *bf_q) + struct list_head *bf_q, + int *aggr_len) { #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) struct ath_buf *bf, *bf_first, *bf_prev = NULL; @@ -674,14 +716,16 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, al_delta, h_baw = tid->baw_size / 2; enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; struct ieee80211_tx_info *tx_info; + struct ath_frame_info *fi; bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); do { bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + fi = get_frame_info(bf->bf_mpdu); /* do not step over block-ack window */ - if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) { + if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) { status = ATH_AGGR_BAW_CLOSED; break; } @@ -692,7 +736,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, } /* do not exceed aggregation limit */ - al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen; + al_delta = ATH_AGGR_DELIM_SZ + fi->framelen; if (nframes && (aggr_limit < (al + bpad + al_delta + prev_al))) { @@ -719,14 +763,15 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, * Get the delimiters needed to meet the MPDU * density for this node. */ - ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen); + ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen); bpad = PADBYTES(al_delta) + (ndelim << 2); bf->bf_next = NULL; ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0); /* link buffers of this frame to the aggregate */ - ath_tx_addto_baw(sc, tid, bf); + if (!fi->retries) + ath_tx_addto_baw(sc, tid, fi->seqno); ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); list_move_tail(&bf->list, bf_q); if (bf_prev) { @@ -738,8 +783,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, } while (!list_empty(&tid->buf_q)); - bf_first->bf_al = al; - bf_first->bf_nframes = nframes; + *aggr_len = al; return status; #undef PADBYTES @@ -750,7 +794,9 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, { struct ath_buf *bf; enum ATH_AGGR_STATUS status; + struct ath_frame_info *fi; struct list_head bf_q; + int aggr_len; do { if (list_empty(&tid->buf_q)) @@ -758,7 +804,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, INIT_LIST_HEAD(&bf_q); - status = ath_tx_form_aggr(sc, txq, tid, &bf_q); + status = ath_tx_form_aggr(sc, txq, tid, &bf_q, &aggr_len); /* * no frames picked up to be aggregated; @@ -771,18 +817,20 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); /* if only one frame, send as non-aggregate */ - if (bf->bf_nframes == 1) { + if (bf == bf->bf_lastbf) { + fi = get_frame_info(bf->bf_mpdu); + bf->bf_state.bf_type &= ~BUF_AGGR; ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc); - ath_buf_set_rate(sc, bf); + ath_buf_set_rate(sc, bf, fi->framelen); ath_tx_txqaddbuf(sc, txq, &bf_q); continue; } /* setup first desc of aggregate */ bf->bf_state.bf_type |= BUF_AGGR; - ath_buf_set_rate(sc, bf); - ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al); + ath_buf_set_rate(sc, bf, aggr_len); + ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, aggr_len); /* anchor last desc of aggregate */ ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc); @@ -790,7 +838,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, ath_tx_txqaddbuf(sc, txq, &bf_q); TX_STAT_INC(txq->axq_qnum, a_aggr); - } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH && + } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH && status != ATH_AGGR_BAW_CLOSED); } @@ -817,7 +865,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) { struct ath_node *an = (struct ath_node *)sta->drv_priv; struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); - struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; + struct ath_txq *txq = txtid->ac->txq; if (txtid->state & AGGR_CLEANUP) return; @@ -888,10 +936,16 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_tx_queue_info qi; + static const int subtype_txq_to_hwq[] = { + [WME_AC_BE] = ATH_TXQ_AC_BE, + [WME_AC_BK] = ATH_TXQ_AC_BK, + [WME_AC_VI] = ATH_TXQ_AC_VI, + [WME_AC_VO] = ATH_TXQ_AC_VO, + }; int qnum, i; memset(&qi, 0, sizeof(qi)); - qi.tqi_subtype = subtype; + qi.tqi_subtype = subtype_txq_to_hwq[subtype]; qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; @@ -931,22 +985,21 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) return NULL; } if (qnum >= ARRAY_SIZE(sc->tx.txq)) { - ath_print(common, ATH_DBG_FATAL, - "qnum %u out of range, max %u!\n", - qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq)); + ath_err(common, "qnum %u out of range, max %zu!\n", + qnum, ARRAY_SIZE(sc->tx.txq)); ath9k_hw_releasetxqueue(ah, qnum); return NULL; } if (!ATH_TXQ_SETUP(sc, qnum)) { struct ath_txq *txq = &sc->tx.txq[qnum]; - txq->axq_class = subtype; txq->axq_qnum = qnum; txq->axq_link = NULL; INIT_LIST_HEAD(&txq->axq_q); INIT_LIST_HEAD(&txq->axq_acq); spin_lock_init(&txq->axq_lock); txq->axq_depth = 0; + txq->axq_ampdu_depth = 0; txq->axq_tx_inprogress = false; sc->tx.txqsetup |= 1<<qnum; @@ -985,8 +1038,8 @@ int ath_txq_update(struct ath_softc *sc, int qnum, qi.tqi_readyTime = qinfo->tqi_readyTime; if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "Unable to update hardware queue %u!\n", qnum); + ath_err(ath9k_hw_common(sc->sc_ah), + "Unable to update hardware queue %u!\n", qnum); error = -EIO; } else { ath9k_hw_resettxqueue(ah, qnum); @@ -1016,6 +1069,12 @@ int ath_cabq_update(struct ath_softc *sc) return 0; } +static bool bf_is_ampdu_not_probing(struct ath_buf *bf) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu); + return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); +} + /* * Drain a given TX queue (could be Beacon or Data) * @@ -1062,8 +1121,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) } lastbf = bf->bf_lastbf; - if (!retry_tx) - lastbf->bf_tx_aborted = true; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { list_cut_position(&bf_head, @@ -1076,11 +1133,13 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) } txq->axq_depth--; - + if (bf_is_ampdu_not_probing(bf)) + txq->axq_ampdu_depth--; spin_unlock_bh(&txq->axq_lock); if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0, + retry_tx); else ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); } @@ -1101,7 +1160,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) if (bf_isampdu(bf)) ath_tx_complete_aggr(sc, txq, bf, &bf_head, - &ts, 0); + &ts, 0, retry_tx); else ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); @@ -1143,7 +1202,7 @@ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) } if (npend) - ath_print(common, ATH_DBG_FATAL, "Failed to stop TX DMA!\n"); + ath_err(common, "Failed to stop TX DMA!\n"); for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i)) @@ -1202,24 +1261,6 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) } } -int ath_tx_setup(struct ath_softc *sc, int haltype) -{ - struct ath_txq *txq; - - if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "HAL AC %u out of range, max %zu!\n", - haltype, ARRAY_SIZE(sc->tx.hwq_map)); - return 0; - } - txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype); - if (txq != NULL) { - sc->tx.hwq_map[haltype] = txq->axq_qnum; - return 1; - } else - return 0; -} - /***********/ /* TX, DMA */ /***********/ @@ -1245,8 +1286,8 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, bf = list_first_entry(head, struct ath_buf, list); - ath_print(common, ATH_DBG_QUEUE, - "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); + ath_dbg(common, ATH_DBG_QUEUE, + "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { if (txq->axq_depth >= ATH_TXFIFO_DEPTH) { @@ -1254,47 +1295,45 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, return; } if (!list_empty(&txq->txq_fifo[txq->txq_headidx])) - ath_print(common, ATH_DBG_XMIT, - "Initializing tx fifo %d which " - "is non-empty\n", - txq->txq_headidx); + ath_dbg(common, ATH_DBG_XMIT, + "Initializing tx fifo %d which is non-empty\n", + txq->txq_headidx); INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]); list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]); INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH); ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); - ath_print(common, ATH_DBG_XMIT, - "TXDP[%u] = %llx (%p)\n", - txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); + ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n", + txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); } else { list_splice_tail_init(head, &txq->axq_q); if (txq->axq_link == NULL) { ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); - ath_print(common, ATH_DBG_XMIT, - "TXDP[%u] = %llx (%p)\n", - txq->axq_qnum, ito64(bf->bf_daddr), - bf->bf_desc); + ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n", + txq->axq_qnum, ito64(bf->bf_daddr), + bf->bf_desc); } else { *txq->axq_link = bf->bf_daddr; - ath_print(common, ATH_DBG_XMIT, - "link[%u] (%p)=%llx (%p)\n", - txq->axq_qnum, txq->axq_link, - ito64(bf->bf_daddr), bf->bf_desc); + ath_dbg(common, ATH_DBG_XMIT, + "link[%u] (%p)=%llx (%p)\n", + txq->axq_qnum, txq->axq_link, + ito64(bf->bf_daddr), bf->bf_desc); } ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc, &txq->axq_link); ath9k_hw_txstart(ah, txq->axq_qnum); } txq->axq_depth++; + if (bf_is_ampdu_not_probing(bf)) + txq->axq_ampdu_depth++; } static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, - struct list_head *bf_head, - struct ath_tx_control *txctl) + struct ath_buf *bf, struct ath_tx_control *txctl) { - struct ath_buf *bf; + struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); + struct list_head bf_head; - bf = list_first_entry(bf_head, struct ath_buf, list); bf->bf_state.bf_type |= BUF_AMPDU; TX_STAT_INC(txctl->txq->axq_qnum, a_queued); @@ -1306,56 +1345,47 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, * - h/w queue depth exceeds low water mark */ if (!list_empty(&tid->buf_q) || tid->paused || - !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) || - txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) { + !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) || + txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) { /* * Add this frame to software queue for scheduling later * for aggregation. */ - list_move_tail(&bf->list, &tid->buf_q); + list_add_tail(&bf->list, &tid->buf_q); ath_tx_queue_tid(txctl->txq, tid); return; } + INIT_LIST_HEAD(&bf_head); + list_add(&bf->list, &bf_head); + /* Add sub-frame to BAW */ - ath_tx_addto_baw(sc, tid, bf); + if (!fi->retries) + ath_tx_addto_baw(sc, tid, fi->seqno); /* Queue to h/w without aggregation */ - bf->bf_nframes = 1; bf->bf_lastbf = bf; - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txctl->txq, bf_head); + ath_buf_set_rate(sc, bf, fi->framelen); + ath_tx_txqaddbuf(sc, txctl->txq, &bf_head); } -static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head) +static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, + struct list_head *bf_head) { + struct ath_frame_info *fi; struct ath_buf *bf; bf = list_first_entry(bf_head, struct ath_buf, list); bf->bf_state.bf_type &= ~BUF_AMPDU; /* update starting sequence number for subsequent ADDBA request */ - INCR(tid->seq_start, IEEE80211_SEQ_MAX); - - bf->bf_nframes = 1; - bf->bf_lastbf = bf; - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txq, bf_head); - TX_STAT_INC(txq->axq_qnum, queued); -} - -static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, - struct list_head *bf_head) -{ - struct ath_buf *bf; - - bf = list_first_entry(bf_head, struct ath_buf, list); + if (tid) + INCR(tid->seq_start, IEEE80211_SEQ_MAX); bf->bf_lastbf = bf; - bf->bf_nframes = 1; - ath_buf_set_rate(sc, bf); + fi = get_frame_info(bf->bf_mpdu); + ath_buf_set_rate(sc, bf, fi->framelen); ath_tx_txqaddbuf(sc, txq, bf_head); TX_STAT_INC(txq->axq_qnum, queued); } @@ -1383,40 +1413,52 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) return htype; } -static void assign_aggr_tid_seqno(struct sk_buff *skb, - struct ath_buf *bf) +static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, + int framelen) { + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = tx_info->control.sta; + struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; struct ieee80211_hdr *hdr; + struct ath_frame_info *fi = get_frame_info(skb); struct ath_node *an; struct ath_atx_tid *tid; - __le16 fc; - u8 *qc; + enum ath9k_key_type keytype; + u16 seqno = 0; + u8 tidno; - if (!tx_info->control.sta) - return; + keytype = ath9k_cmn_get_hw_crypto_keytype(skb); - an = (struct ath_node *)tx_info->control.sta->drv_priv; hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; + if (sta && ieee80211_is_data_qos(hdr->frame_control) && + conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - bf->bf_tidno = qc[0] & 0xf; + an = (struct ath_node *) sta->drv_priv; + tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; + + /* + * Override seqno set by upper layer with the one + * in tx aggregation state. + */ + tid = ATH_AN_2_TID(an, tidno); + seqno = tid->seq_next; + hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT); + INCR(tid->seq_next, IEEE80211_SEQ_MAX); } - /* - * For HT capable stations, we save tidno for later use. - * We also override seqno set by upper layer with the one - * in tx aggregation state. - */ - tid = ATH_AN_2_TID(an, bf->bf_tidno); - hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); - bf->bf_seqno = tid->seq_next; - INCR(tid->seq_next, IEEE80211_SEQ_MAX); + memset(fi, 0, sizeof(*fi)); + if (hw_key) + fi->keyix = hw_key->hw_key_idx; + else + fi->keyix = ATH9K_TXKEYIX_INVALID; + fi->keytype = keytype; + fi->framelen = framelen; + fi->seqno = seqno; } -static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc) +static int setup_tx_flags(struct sk_buff *skb) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); int flags = 0; @@ -1427,7 +1469,7 @@ static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc) if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= ATH9K_TXDESC_NOACK; - if (use_ldpc) + if (tx_info->flags & IEEE80211_TX_CTL_LDPC) flags |= ATH9K_TXDESC_LDPC; return flags; @@ -1439,13 +1481,11 @@ static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc) * width - 0 for 20 MHz, 1 for 40 MHz * half_gi - to use 4us v/s 3.6 us for symbol time */ -static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, +static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, int width, int half_gi, bool shortPreamble) { u32 nbits, nsymbits, duration, nsymbols; - int streams, pktlen; - - pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; + int streams; /* find number of symbols: PLCP + data */ streams = HT_RC_2_STREAMS(rix); @@ -1464,7 +1504,19 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, return duration; } -static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) +u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath9k_channel *curchan = ah->curchan; + if ((sc->sc_flags & SC_OP_ENABLE_APM) && + (curchan->channelFlags & CHANNEL_5GHZ) && + (chainmask == 0x7) && (rate < 0x90)) + return 0x3; + else + return chainmask; +} + +static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath9k_11n_rate_series series[4]; @@ -1504,7 +1556,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) rix = rates[i].idx; series[i].Tries = rates[i].count; - series[i].ChSel = common->tx_chainmask; if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) || (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) { @@ -1527,14 +1578,16 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) if (rates[i].flags & IEEE80211_TX_RC_MCS) { /* MCS rates */ series[i].Rate = rix | 0x80; - series[i].PktDuration = ath_pkt_duration(sc, rix, bf, + series[i].ChSel = ath_txchainmask_reduction(sc, + common->tx_chainmask, series[i].Rate); + series[i].PktDuration = ath_pkt_duration(sc, rix, len, is_40, is_sgi, is_sp); if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) series[i].RateFlags |= ATH9K_RATESERIES_STBC; continue; } - /* legcay rates */ + /* legacy rates */ if ((tx_info->band == IEEE80211_BAND_2GHZ) && !(rate->flags & IEEE80211_RATE_ERP_G)) phy = WLAN_RC_PHY_CCK; @@ -1550,12 +1603,18 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) is_sp = false; } + if (bf->bf_state.bfs_paprd) + series[i].ChSel = common->tx_chainmask; + else + series[i].ChSel = ath_txchainmask_reduction(sc, + common->tx_chainmask, series[i].Rate); + series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, - phy, rate->bitrate * 100, bf->bf_frmlen, rix, is_sp); + phy, rate->bitrate * 100, len, rix, is_sp); } /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ - if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit)) + if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit)) flags &= ~ATH9K_TXDESC_RTSENA; /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */ @@ -1572,67 +1631,29 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192); } -static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, - struct sk_buff *skb, - struct ath_tx_control *txctl) +static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, + struct ath_txq *txq, + struct sk_buff *skb) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - int hdrlen; - __le16 fc; - int padpos, padsize; - bool use_ldpc = false; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_frame_info *fi = get_frame_info(skb); + struct ath_buf *bf; + struct ath_desc *ds; + int frm_type; - tx_info->pad[0] = 0; - switch (txctl->frame_type) { - case ATH9K_IFT_NOT_INTERNAL: - break; - case ATH9K_IFT_PAUSE: - tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_PAUSE; - /* fall through */ - case ATH9K_IFT_UNPAUSE: - tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_INTERNAL; - break; + bf = ath_tx_get_buffer(sc); + if (!bf) { + ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n"); + return NULL; } - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - fc = hdr->frame_control; ATH_TXBUF_RESET(bf); bf->aphy = aphy; - bf->bf_frmlen = skb->len + FCS_LEN; - /* Remove the padding size from bf_frmlen, if any */ - padpos = ath9k_cmn_padpos(hdr->frame_control); - padsize = padpos & 3; - if (padsize && skb->len>padpos+padsize) { - bf->bf_frmlen -= padsize; - } - - if (!txctl->paprd && conf_is_ht(&hw->conf)) { - bf->bf_state.bf_type |= BUF_HT; - if (tx_info->flags & IEEE80211_TX_CTL_LDPC) - use_ldpc = true; - } - - bf->bf_state.bfs_paprd = txctl->paprd; - if (txctl->paprd) - bf->bf_state.bfs_paprd_timestamp = jiffies; - bf->bf_flags = setup_tx_flags(skb, use_ldpc); - - bf->bf_keytype = ath9k_cmn_get_hw_crypto_keytype(skb); - if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { - bf->bf_frmlen += tx_info->control.hw_key->icv_len; - bf->bf_keyix = tx_info->control.hw_key->hw_key_idx; - } else { - bf->bf_keyix = ATH9K_TXKEYIX_INVALID; - } - - if (ieee80211_is_data_qos(fc) && bf_isht(bf) && - (sc->sc_flags & SC_OP_TXAGGR)) - assign_aggr_tid_seqno(skb, bf); - + bf->bf_flags = setup_tx_flags(skb); bf->bf_mpdu = skb; bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, @@ -1640,42 +1661,19 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { bf->bf_mpdu = NULL; bf->bf_buf_addr = 0; - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "dma_mapping_error() on TX\n"); - return -ENOMEM; + ath_err(ath9k_hw_common(sc->sc_ah), + "dma_mapping_error() on TX\n"); + ath_tx_return_buffer(sc, bf); + return NULL; } - bf->bf_tx_aborted = false; - - return 0; -} - -/* FIXME: tx power */ -static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, - struct ath_tx_control *txctl) -{ - struct sk_buff *skb = bf->bf_mpdu; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ath_node *an = NULL; - struct list_head bf_head; - struct ath_desc *ds; - struct ath_atx_tid *tid; - struct ath_hw *ah = sc->sc_ah; - int frm_type; - __le16 fc; - frm_type = get_hw_packet_type(skb); - fc = hdr->frame_control; - - INIT_LIST_HEAD(&bf_head); - list_add_tail(&bf->list, &bf_head); ds = bf->bf_desc; ath9k_hw_set_desc_link(ah, ds, 0); - ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER, - bf->bf_keyix, bf->bf_keytype, bf->bf_flags); + ath9k_hw_set11n_txdesc(ah, ds, fi->framelen, frm_type, MAX_RATE_POWER, + fi->keyix, fi->keytype, bf->bf_flags); ath9k_hw_filltxdesc(ah, ds, skb->len, /* segment length */ @@ -1683,42 +1681,53 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, true, /* last segment */ ds, /* first descriptor */ bf->bf_buf_addr, - txctl->txq->axq_qnum); + txq->axq_qnum); + + + return bf; +} - if (bf->bf_state.bfs_paprd) - ar9003_hw_set_paprd_txdesc(ah, ds, bf->bf_state.bfs_paprd); +/* FIXME: tx power */ +static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, + struct ath_tx_control *txctl) +{ + struct sk_buff *skb = bf->bf_mpdu; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct list_head bf_head; + struct ath_atx_tid *tid = NULL; + u8 tidno; spin_lock_bh(&txctl->txq->axq_lock); - if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) && - tx_info->control.sta) { - an = (struct ath_node *)tx_info->control.sta->drv_priv; - tid = ATH_AN_2_TID(an, bf->bf_tidno); + if (ieee80211_is_data_qos(hdr->frame_control) && txctl->an) { + tidno = ieee80211_get_qos_ctl(hdr)[0] & + IEEE80211_QOS_CTL_TID_MASK; + tid = ATH_AN_2_TID(txctl->an, tidno); - if (!ieee80211_is_data_qos(fc)) { - ath_tx_send_normal(sc, txctl->txq, &bf_head); - goto tx_done; - } + WARN_ON(tid->ac->txq != txctl->txq); + } - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { - /* - * Try aggregation if it's a unicast data frame - * and the destination is HT capable. - */ - ath_tx_send_ampdu(sc, tid, &bf_head, txctl); - } else { - /* - * Send this frame as regular when ADDBA - * exchange is neither complete nor pending. - */ - ath_tx_send_ht_normal(sc, txctl->txq, - tid, &bf_head); - } + if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) { + /* + * Try aggregation if it's a unicast data frame + * and the destination is HT capable. + */ + ath_tx_send_ampdu(sc, tid, bf, txctl); } else { - ath_tx_send_normal(sc, txctl->txq, &bf_head); + INIT_LIST_HEAD(&bf_head); + list_add_tail(&bf->list, &bf_head); + + bf->bf_state.bfs_ftype = txctl->frame_type; + bf->bf_state.bfs_paprd = txctl->paprd; + + if (bf->bf_state.bfs_paprd) + ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc, + bf->bf_state.bfs_paprd); + + ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); } -tx_done: spin_unlock_bh(&txctl->txq->axq_lock); } @@ -1726,66 +1735,23 @@ tx_done: int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath_tx_control *txctl) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = info->control.sta; struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_txq *txq = txctl->txq; struct ath_buf *bf; - int q, r; - - bf = ath_tx_get_buffer(sc); - if (!bf) { - ath_print(common, ATH_DBG_XMIT, "TX buffers are full\n"); - return -1; - } - - r = ath_tx_setup_buffer(hw, bf, skb, txctl); - if (unlikely(r)) { - ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n"); - - /* upon ath_tx_processq() this TX queue will be resumed, we - * guarantee this will happen by knowing beforehand that - * we will at least have to run TX completionon one buffer - * on the queue */ - spin_lock_bh(&txq->axq_lock); - if (!txq->stopped && txq->axq_depth > 1) { - ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); - txq->stopped = 1; - } - spin_unlock_bh(&txq->axq_lock); - - ath_tx_return_buffer(sc, bf); - - return r; - } - - q = skb_get_queue_mapping(skb); - if (q >= 4) - q = 0; - - spin_lock_bh(&txq->axq_lock); - if (++sc->tx.pending_frames[q] > ATH_MAX_QDEPTH && !txq->stopped) { - ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); - txq->stopped = 1; - } - spin_unlock_bh(&txq->axq_lock); - - ath_tx_start_dma(sc, bf, txctl); - - return 0; -} - -void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; int padpos, padsize; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ath_tx_control txctl; + int frmlen = skb->len + FCS_LEN; + int q; + + /* NOTE: sta can be NULL according to net/mac80211.h */ + if (sta) + txctl->an = (struct ath_node *)sta->drv_priv; - memset(&txctl, 0, sizeof(struct ath_tx_control)); + if (info->control.hw_key) + frmlen += info->control.hw_key->icv_len; /* * As a temporary workaround, assign seq# here; this will likely need @@ -1802,30 +1768,37 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) /* Add the padding after the header if this is not already done */ padpos = ath9k_cmn_padpos(hdr->frame_control); padsize = padpos & 3; - if (padsize && skb->len>padpos) { - if (skb_headroom(skb) < padsize) { - ath_print(common, ATH_DBG_XMIT, - "TX CABQ padding failed\n"); - dev_kfree_skb_any(skb); - return; - } + if (padsize && skb->len > padpos) { + if (skb_headroom(skb) < padsize) + return -ENOMEM; + skb_push(skb, padsize); memmove(skb->data, skb->data + padsize, padpos); } - txctl.txq = sc->beacon.cabq; + setup_frame_info(hw, skb, frmlen); - ath_print(common, ATH_DBG_XMIT, - "transmitting CABQ packet, skb: %p\n", skb); + /* + * At this point, the vif, hw_key and sta pointers in the tx control + * info are no longer valid (overwritten by the ath_frame_info data. + */ + + bf = ath_tx_setup_buffer(hw, txctl->txq, skb); + if (unlikely(!bf)) + return -ENOMEM; - if (ath_tx_start(hw, skb, &txctl) != 0) { - ath_print(common, ATH_DBG_XMIT, "CABQ TX failed\n"); - goto exit; + q = skb_get_queue_mapping(skb); + spin_lock_bh(&txq->axq_lock); + if (txq == sc->tx.txq_map[q] && + ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) { + ath_mac80211_stop_queue(sc, q); + txq->stopped = 1; } + spin_unlock_bh(&txq->axq_lock); - return; -exit: - dev_kfree_skb_any(skb); + ath_tx_start_dma(sc, bf, txctl); + + return 0; } /*****************/ @@ -1833,7 +1806,8 @@ exit: /*****************/ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, - struct ath_wiphy *aphy, int tx_flags) + struct ath_wiphy *aphy, int tx_flags, int ftype, + struct ath_txq *txq) { struct ieee80211_hw *hw = sc->hw; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); @@ -1841,7 +1815,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; int q, padpos, padsize; - ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); + ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); if (aphy) hw = aphy->hw; @@ -1867,24 +1841,24 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; - ath_print(common, ATH_DBG_PS, - "Going back to sleep after having " - "received TX status (0x%lx)\n", + ath_dbg(common, ATH_DBG_PS, + "Going back to sleep after having received TX status (0x%lx)\n", sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | PS_WAIT_FOR_PSPOLL_DATA | PS_WAIT_FOR_TX_ACK)); } - if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL)) - ath9k_tx_status(hw, skb); + if (unlikely(ftype)) + ath9k_tx_status(hw, skb, ftype); else { q = skb_get_queue_mapping(skb); - if (q >= 4) - q = 0; - - if (--sc->tx.pending_frames[q] < 0) - sc->tx.pending_frames[q] = 0; + if (txq == sc->tx.txq_map[q]) { + spin_lock_bh(&txq->axq_lock); + if (WARN_ON(--txq->pending_frames < 0)) + txq->pending_frames = 0; + spin_unlock_bh(&txq->axq_lock); + } ieee80211_tx_status(hw, skb); } @@ -1912,15 +1886,14 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, bf->bf_buf_addr = 0; if (bf->bf_state.bfs_paprd) { - if (time_after(jiffies, - bf->bf_state.bfs_paprd_timestamp + - msecs_to_jiffies(ATH_PAPRD_TIMEOUT))) + if (!sc->paprd_pending) dev_kfree_skb_any(skb); else complete(&sc->paprd_complete); } else { - ath_debug_stat_tx(sc, txq, bf, ts); - ath_tx_complete(sc, skb, bf->aphy, tx_flags); + ath_debug_stat_tx(sc, bf, ts); + ath_tx_complete(sc, skb, bf->aphy, tx_flags, + bf->bf_state.bfs_ftype, txq); } /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't * accidentally reference it later. @@ -1935,42 +1908,15 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, spin_unlock_irqrestore(&sc->tx.txbuflock, flags); } -static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, - struct ath_tx_status *ts, int txok) -{ - u16 seq_st = 0; - u32 ba[WME_BA_BMP_SIZE >> 5]; - int ba_index; - int nbad = 0; - int isaggr = 0; - - if (bf->bf_lastbf->bf_tx_aborted) - return 0; - - isaggr = bf_isaggr(bf); - if (isaggr) { - seq_st = ts->ts_seqnum; - memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); - } - - while (bf) { - ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno); - if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) - nbad++; - - bf = bf->bf_next; - } - - return nbad; -} - static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, - int nbad, int txok, bool update_rc) + int nframes, int nbad, int txok, bool update_rc) { struct sk_buff *skb = bf->bf_mpdu; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hw *hw = bf->aphy->hw; + struct ath_softc *sc = bf->aphy->sc; + struct ath_hw *ah = sc->sc_ah; u8 i, tx_rateindex; if (txok) @@ -1984,22 +1930,32 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) { tx_info->flags |= IEEE80211_TX_STAT_AMPDU; - BUG_ON(nbad > bf->bf_nframes); + BUG_ON(nbad > nframes); - tx_info->status.ampdu_len = bf->bf_nframes; - tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad; + tx_info->status.ampdu_len = nframes; + tx_info->status.ampdu_ack_len = nframes - nbad; } if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { - if (ieee80211_is_data(hdr->frame_control)) { - if (ts->ts_flags & - (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN)) - tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN; - if ((ts->ts_status & ATH9K_TXERR_XRETRY) || - (ts->ts_status & ATH9K_TXERR_FIFO)) - tx_info->pad[0] |= ATH_TX_INFO_XRETRY; - } + /* + * If an underrun error is seen assume it as an excessive + * retry only if max frame trigger level has been reached + * (2 KB for single stream, and 4 KB for dual stream). + * Adjust the long retry as if the frame was tried + * hw->max_rate_tries times to affect how rate control updates + * PER for the failed rate. + * In case of congestion on the bus penalizing this type of + * underruns should help hardware actually transmit new frames + * successfully by eventually preferring slower rates. + * This itself should also alleviate congestion on the bus. + */ + if (ieee80211_is_data(hdr->frame_control) && + (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN | + ATH9K_TX_DELIM_UNDERRUN)) && + ah->tx_trig_level >= sc->sc_ah->caps.tx_triglevel_max) + tx_info->status.rates[tx_rateindex].count = + hw->max_rate_tries; } for (i = tx_rateindex + 1; i < hw->max_rates; i++) { @@ -2010,16 +1966,13 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; } -static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) +static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum) { - int qnum; - - qnum = ath_get_mac80211_qnum(txq->axq_class, sc); - if (qnum == -1) - return; + struct ath_txq *txq; + txq = sc->tx.txq_map[qnum]; spin_lock_bh(&txq->axq_lock); - if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) { + if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) { if (ath_mac80211_start_queue(sc, qnum)) txq->stopped = 0; } @@ -2036,10 +1989,11 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) struct ath_tx_status ts; int txok; int status; + int qnum; - ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", - txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), - txq->axq_link); + ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", + txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), + txq->axq_link); for (;;) { spin_lock_bh(&txq->axq_lock); @@ -2096,6 +2050,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) txq->axq_tx_inprogress = false; if (bf_held) list_del(&bf_held->list); + + if (bf_is_ampdu_not_probing(bf)) + txq->axq_ampdu_depth--; spin_unlock_bh(&txq->axq_lock); if (bf_held) @@ -2108,15 +2065,19 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) */ if (ts.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true); + ath_tx_rc_status(bf, &ts, 1, txok ? 0 : 1, txok, true); } + qnum = skb_get_queue_mapping(bf->bf_mpdu); + if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok, + true); else ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); - ath_wake_mac80211_queue(sc, txq); + if (txq == sc->tx.txq_map[qnum]) + ath_wake_mac80211_queue(sc, qnum); spin_lock_bh(&txq->axq_lock); if (sc->sc_flags & SC_OP_TXAGGR) @@ -2150,8 +2111,8 @@ static void ath_tx_complete_poll_work(struct work_struct *work) } if (needreset) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, - "tx hung, resetting the chip\n"); + ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, + "tx hung, resetting the chip\n"); ath9k_ps_wakeup(sc); ath_reset(sc, true); ath9k_ps_restore(sc); @@ -2186,14 +2147,15 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) struct list_head bf_head; int status; int txok; + int qnum; for (;;) { status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs); if (status == -EINPROGRESS) break; if (status == -EIO) { - ath_print(common, ATH_DBG_XMIT, - "Error processing tx status\n"); + ath_dbg(common, ATH_DBG_XMIT, + "Error processing tx status\n"); break; } @@ -2219,6 +2181,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); txq->axq_depth--; txq->axq_tx_inprogress = false; + if (bf_is_ampdu_not_probing(bf)) + txq->axq_ampdu_depth--; spin_unlock_bh(&txq->axq_lock); txok = !(txs.ts_status & ATH9K_TXERR_MASK); @@ -2226,16 +2190,20 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) if (!bf_isampdu(bf)) { if (txs.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true); + ath_tx_rc_status(bf, &txs, 1, txok ? 0 : 1, txok, true); } + qnum = skb_get_queue_mapping(bf->bf_mpdu); + if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, + txok, true); else ath_tx_complete_buf(sc, bf, txq, &bf_head, &txs, txok, 0); - ath_wake_mac80211_queue(sc, txq); + if (txq == sc->tx.txq_map[qnum]) + ath_wake_mac80211_queue(sc, qnum); spin_lock_bh(&txq->axq_lock); if (!list_empty(&txq->txq_fifo_pending)) { @@ -2300,16 +2268,16 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, "tx", nbufs, 1, 1); if (error != 0) { - ath_print(common, ATH_DBG_FATAL, - "Failed to allocate tx descriptors: %d\n", error); + ath_err(common, + "Failed to allocate tx descriptors: %d\n", error); goto err; } error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, "beacon", ATH_BCBUF, 1, 1); if (error != 0) { - ath_print(common, ATH_DBG_FATAL, - "Failed to allocate beacon descriptors: %d\n", error); + ath_err(common, + "Failed to allocate beacon descriptors: %d\n", error); goto err; } @@ -2367,7 +2335,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) for (acno = 0, ac = &an->ac[acno]; acno < WME_NUM_AC; acno++, ac++) { ac->sched = false; - ac->qnum = sc->tx.hwq_map[acno]; + ac->txq = sc->tx.txq_map[acno]; INIT_LIST_HEAD(&ac->tid_q); } } @@ -2377,17 +2345,13 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) struct ath_atx_ac *ac; struct ath_atx_tid *tid; struct ath_txq *txq; - int i, tidno; + int tidno; for (tidno = 0, tid = &an->tid[tidno]; tidno < WME_NUM_TID; tidno++, tid++) { - i = tid->ac->qnum; - - if (!ATH_TXQ_SETUP(sc, i)) - continue; - txq = &sc->tx.txq[i]; ac = tid->ac; + txq = ac->txq; spin_lock_bh(&txq->axq_lock); diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 6cf0c9ef47aa..d07ff7f2fd92 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -48,7 +48,7 @@ #include <linux/usb.h> #ifdef CONFIG_CARL9170_LEDS #include <linux/leds.h> -#endif /* CONFIG_CARL170_LEDS */ +#endif /* CONFIG_CARL9170_LEDS */ #ifdef CONFIG_CARL9170_WPC #include <linux/input.h> #endif /* CONFIG_CARL9170_WPC */ @@ -215,7 +215,7 @@ enum carl9170_restart_reasons { CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS, CARL9170_RR_WATCHDOG, CARL9170_RR_STUCK_TX, - CARL9170_RR_SLOW_SYSTEM, + CARL9170_RR_UNRESPONSIVE_DEVICE, CARL9170_RR_COMMAND_TIMEOUT, CARL9170_RR_TOO_MANY_PHY_ERRORS, CARL9170_RR_LOST_RSP, @@ -287,6 +287,7 @@ struct ar9170 { /* reset / stuck frames/queue detection */ struct work_struct restart_work; + struct work_struct ping_work; unsigned int restart_counter; unsigned long queue_stop_timeout[__AR9170_NUM_TXQ]; unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ]; diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c index c21f3364bfec..cdfc94c371b4 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.c +++ b/drivers/net/wireless/ath/carl9170/cmd.c @@ -41,7 +41,7 @@ int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) { - __le32 buf[2] = { + const __le32 buf[2] = { cpu_to_le32(reg), cpu_to_le32(val), }; diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index d552166db505..3680dfc70f46 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h @@ -97,13 +97,13 @@ struct carl9170_set_key_cmd { __le16 type; u8 macAddr[6]; u32 key[4]; -} __packed; +} __packed __aligned(4); #define CARL9170_SET_KEY_CMD_SIZE 28 struct carl9170_disable_key_cmd { __le16 user; __le16 padding; -} __packed; +} __packed __aligned(4); #define CARL9170_DISABLE_KEY_CMD_SIZE 4 struct carl9170_u32_list { @@ -206,7 +206,7 @@ struct carl9170_cmd { struct carl9170_rx_filter_cmd rx_filter; u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; } __packed; -} __packed; +} __packed __aligned(4); #define CARL9170_TX_STATUS_QUEUE 3 #define CARL9170_TX_STATUS_QUEUE_S 0 @@ -216,6 +216,7 @@ struct carl9170_cmd { #define CARL9170_TX_STATUS_TRIES (7 << CARL9170_TX_STATUS_TRIES_S) #define CARL9170_TX_STATUS_SUCCESS 0x80 +#ifdef __CARL9170FW__ /* * NOTE: * Both structs [carl9170_tx_status and _carl9170_tx_status] @@ -232,6 +233,8 @@ struct carl9170_tx_status { u8 tries:3; u8 success:1; } __packed; +#endif /* __CARL9170FW__ */ + struct _carl9170_tx_status { /* * This version should be immune to all alignment bugs. @@ -272,13 +275,15 @@ struct carl9170_rsp { struct carl9170_rf_init_result rf_init_res; struct carl9170_u32_list rreg_res; struct carl9170_u32_list echo; +#ifdef __CARL9170FW__ struct carl9170_tx_status tx_status[0]; +#endif /* __CARL9170FW__ */ struct _carl9170_tx_status _tx_status[0]; struct carl9170_gpio gpio; struct carl9170_tsf_rsp tsf; struct carl9170_psm psm; u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; } __packed; -} __packed; +} __packed __aligned(4); #endif /* __CARL9170_SHARED_FWCMD_H */ diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h index 2f471b3f05af..e85df6edfed3 100644 --- a/drivers/net/wireless/ath/carl9170/hw.h +++ b/drivers/net/wireless/ath/carl9170/hw.h @@ -712,7 +712,8 @@ struct ar9170_stream { __le16 tag; u8 payload[0]; -}; +} __packed __aligned(4); +#define AR9170_STREAM_LEN 4 #define AR9170_MAX_ACKTABLE_ENTRIES 8 #define AR9170_MAX_VIRTUAL_MAC 7 @@ -736,4 +737,8 @@ struct ar9170_stream { #define MOD_VAL(reg, value, newvalue) \ (((value) & ~reg) | (((newvalue) << reg##_S) & reg)) + +#define GET_VAL(reg, value) \ + (((value) & reg) >> reg##_S) + #endif /* __CARL9170_SHARED_HW_H */ diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c index 2305bc27151c..385cf508479b 100644 --- a/drivers/net/wireless/ath/carl9170/mac.c +++ b/drivers/net/wireless/ath/carl9170/mac.c @@ -205,8 +205,8 @@ int carl9170_init_mac(struct ar9170 *ar) carl9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105); /* Aggregation MAX number and timeout */ - carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0xa); - carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a00); + carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0x8000a); + carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a07); carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, AR9170_MAC_FTF_DEFAULTS); @@ -457,8 +457,9 @@ int carl9170_set_beacon_timers(struct ar9170 *ar) int carl9170_update_beacon(struct ar9170 *ar, const bool submit) { - struct sk_buff *skb; + struct sk_buff *skb = NULL; struct carl9170_vif_info *cvif; + struct ieee80211_tx_info *txinfo; __le32 *data, *old = NULL; u32 word, off, addr, len; int i = 0, err = 0; @@ -487,7 +488,13 @@ found: if (!skb) { err = -ENOMEM; - goto out_unlock; + goto err_free; + } + + txinfo = IEEE80211_SKB_CB(skb); + if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) { + err = -EINVAL; + goto err_free; } spin_lock_bh(&ar->beacon_lock); @@ -504,11 +511,8 @@ found: wiphy_err(ar->hw->wiphy, "beacon does not " "fit into device memory!\n"); } - - spin_unlock_bh(&ar->beacon_lock); - dev_kfree_skb_any(skb); err = -EINVAL; - goto out_unlock; + goto err_unlock; } if (len > AR9170_MAC_BCN_LENGTH_MAX) { @@ -518,22 +522,22 @@ found: AR9170_MAC_BCN_LENGTH_MAX, len); } - spin_unlock_bh(&ar->beacon_lock); - dev_kfree_skb_any(skb); err = -EMSGSIZE; - goto out_unlock; + goto err_unlock; } - carl9170_async_regwrite_begin(ar); + i = txinfo->control.rates[0].idx; + if (txinfo->band != IEEE80211_BAND_2GHZ) + i += 4; - /* XXX: use skb->cb info */ - if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { - carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, - ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400); - } else { - carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, - ((skb->len + FCS_LEN) << 16) + 0x001b); - } + word = __carl9170_ratetable[i].hw_value & 0xf; + if (i < 4) + word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400; + else + word |= ((skb->len + FCS_LEN) << 16) + 0x0010; + + carl9170_async_regwrite_begin(ar); + carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word); for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { /* @@ -557,7 +561,7 @@ found: cvif->beacon = skb; spin_unlock_bh(&ar->beacon_lock); if (err) - goto out_unlock; + goto err_free; if (submit) { err = carl9170_bcn_ctrl(ar, cvif->id, @@ -565,10 +569,18 @@ found: addr, skb->len + FCS_LEN); if (err) - goto out_unlock; + goto err_free; } out_unlock: rcu_read_unlock(); + return 0; + +err_unlock: + spin_unlock_bh(&ar->beacon_lock); + +err_free: + rcu_read_unlock(); + dev_kfree_skb_any(skb); return err; } diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index dc7b30b170d0..870df8c42622 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -428,6 +428,7 @@ static void carl9170_cancel_worker(struct ar9170 *ar) cancel_delayed_work_sync(&ar->led_work); #endif /* CONFIG_CARL9170_LEDS */ cancel_work_sync(&ar->ps_work); + cancel_work_sync(&ar->ping_work); cancel_work_sync(&ar->ampdu_work); } @@ -533,6 +534,21 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r) */ } +static void carl9170_ping_work(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, ping_work); + int err; + + if (!IS_STARTED(ar)) + return; + + mutex_lock(&ar->mutex); + err = carl9170_echo_test(ar, 0xdeadbeef); + if (err) + carl9170_restart(ar, CARL9170_RR_UNRESPONSIVE_DEVICE); + mutex_unlock(&ar->mutex); +} + static int carl9170_init_interface(struct ar9170 *ar, struct ieee80211_vif *vif) { @@ -1614,6 +1630,7 @@ void *carl9170_alloc(size_t priv_size) skb_queue_head_init(&ar->tx_pending[i]); } INIT_WORK(&ar->ps_work, carl9170_ps_work); + INIT_WORK(&ar->ping_work, carl9170_ping_work); INIT_WORK(&ar->restart_work, carl9170_restart_work); INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work); INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor); @@ -1829,7 +1846,7 @@ int carl9170_register(struct ar9170 *ar) err = carl9170_led_register(ar); if (err) goto err_unreg; -#endif /* CONFIG_CAR9L170_LEDS */ +#endif /* CONFIG_CARL9170_LEDS */ #ifdef CONFIG_CARL9170_WPC err = carl9170_register_wps_button(ar); diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index 89deca37a988..b6b0de600506 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c @@ -1029,8 +1029,6 @@ static int carl9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, if (err) return err; - msleep(20); - return 0; } @@ -1554,15 +1552,6 @@ static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq, return carl9170_regwrite_result(); } -/* TODO: replace this with sign_extend32(noise, 8) */ -static int carl9170_calc_noise_dbm(u32 raw_noise) -{ - if (raw_noise & 0x100) - return ~0x1ff | raw_noise; - else - return raw_noise; -} - int carl9170_get_noisefloor(struct ar9170 *ar) { static const u32 phy_regs[] = { @@ -1578,11 +1567,11 @@ int carl9170_get_noisefloor(struct ar9170 *ar) return err; for (i = 0; i < 2; i++) { - ar->noise[i] = carl9170_calc_noise_dbm( - (phy_res[i] >> 19) & 0x1ff); + ar->noise[i] = sign_extend32(GET_VAL( + AR9170_PHY_CCA_MIN_PWR, phy_res[i]), 8); - ar->noise[i + 2] = carl9170_calc_noise_dbm( - (phy_res[i + 2] >> 23) & 0x1ff); + ar->noise[i + 2] = sign_extend32(GET_VAL( + AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8); } return 0; @@ -1669,12 +1658,6 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, return err; cmd = CARL9170_CMD_RF_INIT; - - msleep(100); - - err = carl9170_echo_test(ar, 0xaabbccdd); - if (err) - return err; } else { cmd = CARL9170_CMD_FREQUENCY; } @@ -1685,6 +1668,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE, 0x200); + if (err) + return err; err = carl9170_init_rf_bank4_pwr(ar, channel->band == IEEE80211_BAND_5GHZ, diff --git a/drivers/net/wireless/ath/carl9170/phy.h b/drivers/net/wireless/ath/carl9170/phy.h index 02c34eb4ebde..024fb42bc787 100644 --- a/drivers/net/wireless/ath/carl9170/phy.h +++ b/drivers/net/wireless/ath/carl9170/phy.h @@ -139,8 +139,8 @@ #define AR9170_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 #define AR9170_PHY_REG_CCA (AR9170_PHY_REG_BASE + 0x0064) -#define AR9170_PHY_CCA_MINCCA_PWR 0x0ff80000 -#define AR9170_PHY_CCA_MINCCA_PWR_S 19 +#define AR9170_PHY_CCA_MIN_PWR 0x0ff80000 +#define AR9170_PHY_CCA_MIN_PWR_S 19 #define AR9170_PHY_CCA_THRESH62 0x0007f000 #define AR9170_PHY_CCA_THRESH62_S 12 @@ -338,8 +338,8 @@ #define AR9170_PHY_EXT_CCA_CYCPWR_THR1_S 9 #define AR9170_PHY_EXT_CCA_THRESH62 0x007f0000 #define AR9170_PHY_EXT_CCA_THRESH62_S 16 -#define AR9170_PHY_EXT_MINCCA_PWR 0xff800000 -#define AR9170_PHY_EXT_MINCCA_PWR_S 23 +#define AR9170_PHY_EXT_CCA_MIN_PWR 0xff800000 +#define AR9170_PHY_EXT_CCA_MIN_PWR_S 23 #define AR9170_PHY_REG_SFCORR_EXT (AR9170_PHY_REG_BASE + 0x01c0) #define AR9170_PHY_SFCORR_EXT_M1_THRESH 0x0000007f @@ -546,19 +546,19 @@ #define AR9170_PHY_FORCE_XPA_CFG_S 0 #define AR9170_PHY_REG_CH1_CCA (AR9170_PHY_REG_BASE + 0x1064) -#define AR9170_PHY_CH1_MINCCA_PWR 0x0ff80000 -#define AR9170_PHY_CH1_MINCCA_PWR_S 19 +#define AR9170_PHY_CH1_CCA_MIN_PWR 0x0ff80000 +#define AR9170_PHY_CH1_CCA_MIN_PWR_S 19 #define AR9170_PHY_REG_CH2_CCA (AR9170_PHY_REG_BASE + 0x2064) -#define AR9170_PHY_CH2_MINCCA_PWR 0x0ff80000 -#define AR9170_PHY_CH2_MINCCA_PWR_S 19 +#define AR9170_PHY_CH2_CCA_MIN_PWR 0x0ff80000 +#define AR9170_PHY_CH2_CCA_MIN_PWR_S 19 #define AR9170_PHY_REG_CH1_EXT_CCA (AR9170_PHY_REG_BASE + 0x11bc) -#define AR9170_PHY_CH1_EXT_MINCCA_PWR 0xff800000 -#define AR9170_PHY_CH1_EXT_MINCCA_PWR_S 23 +#define AR9170_PHY_CH1_EXT_CCA_MIN_PWR 0xff800000 +#define AR9170_PHY_CH1_EXT_CCA_MIN_PWR_S 23 #define AR9170_PHY_REG_CH2_EXT_CCA (AR9170_PHY_REG_BASE + 0x21bc) -#define AR9170_PHY_CH2_EXT_MINCCA_PWR 0xff800000 -#define AR9170_PHY_CH2_EXT_MINCCA_PWR_S 23 +#define AR9170_PHY_CH2_EXT_CCA_MIN_PWR 0xff800000 +#define AR9170_PHY_CH2_EXT_CCA_MIN_PWR_S 23 #endif /* __CARL9170_SHARED_PHY_H */ diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index 7e6506a77bbb..6cc58e052d10 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c @@ -242,9 +242,11 @@ static void carl9170_tx_release(struct kref *ref) ar->tx_ampdu_schedule = true; if (txinfo->flags & IEEE80211_TX_STAT_AMPDU) { - txinfo->status.ampdu_len = txinfo->pad[0]; - txinfo->status.ampdu_ack_len = txinfo->pad[1]; - txinfo->pad[0] = txinfo->pad[1] = 0; + struct _carl9170_tx_superframe *super; + + super = (void *)skb->data; + txinfo->status.ampdu_len = super->s.rix; + txinfo->status.ampdu_ack_len = super->s.cnt; } else if (txinfo->flags & IEEE80211_TX_STAT_ACK) { /* * drop redundant tx_status reports: @@ -337,7 +339,8 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, u8 tid; if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || - txinfo->flags & IEEE80211_TX_CTL_INJECTED) + txinfo->flags & IEEE80211_TX_CTL_INJECTED || + (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) return; tx_info = IEEE80211_SKB_CB(skb); @@ -389,8 +392,8 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, sta_info->stats[tid].ampdu_ack_len++; if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) { - txinfo->pad[0] = sta_info->stats[tid].ampdu_len; - txinfo->pad[1] = sta_info->stats[tid].ampdu_ack_len; + super->s.rix = sta_info->stats[tid].ampdu_len; + super->s.cnt = sta_info->stats[tid].ampdu_ack_len; txinfo->flags |= IEEE80211_TX_STAT_AMPDU; sta_info->stats[tid].clear = true; } @@ -524,6 +527,59 @@ next: } } +static void carl9170_tx_ampdu_timeout(struct ar9170 *ar) +{ + struct carl9170_sta_tid *iter; + struct sk_buff *skb; + struct ieee80211_tx_info *txinfo; + struct carl9170_tx_info *arinfo; + struct _carl9170_tx_superframe *super; + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; + struct ieee80211_hdr *hdr; + unsigned int vif_id; + + rcu_read_lock(); + list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) { + if (iter->state < CARL9170_TID_STATE_IDLE) + continue; + + spin_lock_bh(&iter->lock); + skb = skb_peek(&iter->queue); + if (!skb) + goto unlock; + + txinfo = IEEE80211_SKB_CB(skb); + arinfo = (void *)txinfo->rate_driver_data; + if (time_is_after_jiffies(arinfo->timeout + + msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT))) + goto unlock; + + super = (void *) skb->data; + hdr = (void *) super->frame_data; + + vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> + CARL9170_TX_SUPER_MISC_VIF_ID_S; + + if (WARN_ON(vif_id >= AR9170_MAX_VIRTUAL_MAC)) + goto unlock; + + vif = rcu_dereference(ar->vif_priv[vif_id].vif); + if (WARN_ON(!vif)) + goto unlock; + + sta = ieee80211_find_sta(vif, hdr->addr1); + if (WARN_ON(!sta)) + goto unlock; + + ieee80211_stop_tx_ba_session(sta, iter->tid); +unlock: + spin_unlock_bh(&iter->lock); + + } + rcu_read_unlock(); +} + void carl9170_tx_janitor(struct work_struct *work) { struct ar9170 *ar = container_of(work, struct ar9170, @@ -534,6 +590,7 @@ void carl9170_tx_janitor(struct work_struct *work) ar->tx_janitor_last_run = jiffies; carl9170_check_queue_stop_timeout(ar); + carl9170_tx_ampdu_timeout(ar); if (!atomic_read(&ar->tx_total_queued)) return; @@ -842,10 +899,8 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) if (unlikely(!sta || !cvif)) goto err_out; - factor = min_t(unsigned int, 1u, - info->control.sta->ht_cap.ampdu_factor); - - density = info->control.sta->ht_cap.ampdu_density; + factor = min_t(unsigned int, 1u, sta->ht_cap.ampdu_factor); + density = sta->ht_cap.ampdu_density; if (density) { /* @@ -1206,6 +1261,7 @@ static void carl9170_tx(struct ar9170 *ar) static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, struct ieee80211_sta *sta, struct sk_buff *skb) { + struct _carl9170_tx_superframe *super = (void *) skb->data; struct carl9170_sta_info *sta_info; struct carl9170_sta_tid *agg; struct sk_buff *iter; @@ -1274,6 +1330,7 @@ err_unlock: err_unlock_rcu: rcu_read_unlock(); + super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR); carl9170_tx_status(ar, skb, false); ar->tx_dropped++; return false; @@ -1302,9 +1359,6 @@ int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) */ if (info->flags & IEEE80211_TX_CTL_AMPDU) { - if (WARN_ON_ONCE(!sta)) - goto err_free; - run = carl9170_tx_ampdu_queue(ar, sta, skb); if (run) carl9170_tx_ampdu(ar); diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c index 7504ed14c725..537732e5964f 100644 --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c @@ -160,8 +160,7 @@ err_acc: static void carl9170_usb_tx_data_complete(struct urb *urb) { - struct ar9170 *ar = (struct ar9170 *) - usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + struct ar9170 *ar = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); if (WARN_ON_ONCE(!ar)) { dev_kfree_skb_irq(urb->context); @@ -433,7 +432,7 @@ static void carl9170_usb_rx_complete(struct urb *urb) * device. */ - carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM); + ieee80211_queue_work(ar->hw, &ar->ping_work); } } else { /* @@ -835,7 +834,7 @@ static int carl9170_usb_load_firmware(struct ar9170 *ar) if (err) goto err_out; - /* firmware restarts cmd counter */ + /* now, start the command response counter */ ar->cmd_seq = -1; return 0; @@ -852,7 +851,12 @@ int carl9170_usb_restart(struct ar9170 *ar) if (ar->intf->condition != USB_INTERFACE_BOUND) return 0; - /* Disable command response sequence counter. */ + /* + * Disable the command response sequence counter check. + * We already know that the device/firmware is in a bad state. + * So, no extra points are awarded to anyone who reminds the + * driver about that. + */ ar->cmd_seq = -2; err = carl9170_reboot(ar); @@ -904,6 +908,15 @@ static int carl9170_usb_init_device(struct ar9170 *ar) { int err; + /* + * The carl9170 firmware let's the driver know when it's + * ready for action. But we have to be prepared to gracefully + * handle all spurious [flushed] messages after each (re-)boot. + * Thus the command response counter remains disabled until it + * can be safely synchronized. + */ + ar->cmd_seq = -2; + err = carl9170_usb_send_rx_irq_urb(ar); if (err) goto err_out; @@ -912,14 +925,21 @@ static int carl9170_usb_init_device(struct ar9170 *ar) if (err) goto err_unrx; + err = carl9170_usb_open(ar); + if (err) + goto err_unrx; + mutex_lock(&ar->mutex); err = carl9170_usb_load_firmware(ar); mutex_unlock(&ar->mutex); if (err) - goto err_unrx; + goto err_stop; return 0; +err_stop: + carl9170_usb_stop(ar); + err_unrx: carl9170_usb_cancel_urbs(ar); @@ -965,10 +985,6 @@ static void carl9170_usb_firmware_finish(struct ar9170 *ar) if (err) goto err_freefw; - err = carl9170_usb_open(ar); - if (err) - goto err_unrx; - err = carl9170_register(ar); carl9170_usb_stop(ar); @@ -1044,7 +1060,6 @@ static int carl9170_usb_probe(struct usb_interface *intf, atomic_set(&ar->rx_work_urbs, 0); atomic_set(&ar->rx_anch_urbs, 0); atomic_set(&ar->rx_pool_urbs, 0); - ar->cmd_seq = -2; usb_get_dev(ar->udev); @@ -1091,10 +1106,6 @@ static int carl9170_usb_suspend(struct usb_interface *intf, carl9170_usb_cancel_urbs(ar); - /* - * firmware automatically reboots for usb suspend. - */ - return 0; } @@ -1107,12 +1118,20 @@ static int carl9170_usb_resume(struct usb_interface *intf) return -ENODEV; usb_unpoison_anchored_urbs(&ar->rx_anch); + carl9170_set_state(ar, CARL9170_STOPPED); - err = carl9170_usb_init_device(ar); - if (err) - goto err_unrx; + /* + * The USB documentation demands that [for suspend] all traffic + * to and from the device has to stop. This would be fine, but + * there's a catch: the device[usb phy] does not come back. + * + * Upon resume the firmware will "kill" itself and the + * boot-code sorts out the magic voodoo. + * Not very nice, but there's not much what could go wrong. + */ + msleep(1100); - err = carl9170_usb_open(ar); + err = carl9170_usb_init_device(ar); if (err) goto err_unrx; @@ -1134,6 +1153,7 @@ static struct usb_driver carl9170_driver = { #ifdef CONFIG_PM .suspend = carl9170_usb_suspend, .resume = carl9170_usb_resume, + .reset_resume = carl9170_usb_resume, #endif /* CONFIG_PM */ }; diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h index ff53f078a0b5..ee0f84f2a2f6 100644 --- a/drivers/net/wireless/ath/carl9170/version.h +++ b/drivers/net/wireless/ath/carl9170/version.h @@ -1,7 +1,7 @@ #ifndef __CARL9170_SHARED_VERSION_H #define __CARL9170_SHARED_VERSION_H #define CARL9170FW_VERSION_YEAR 10 -#define CARL9170FW_VERSION_MONTH 9 -#define CARL9170FW_VERSION_DAY 28 -#define CARL9170FW_VERSION_GIT "1.8.8.3" +#define CARL9170FW_VERSION_MONTH 10 +#define CARL9170FW_VERSION_DAY 29 +#define CARL9170FW_VERSION_GIT "1.9.0" #endif /* __CARL9170_SHARED_VERSION_H */ diff --git a/drivers/net/wireless/ath/debug.c b/drivers/net/wireless/ath/debug.c index dacfb234f491..5367b1086e09 100644 --- a/drivers/net/wireless/ath/debug.c +++ b/drivers/net/wireless/ath/debug.c @@ -15,21 +15,6 @@ */ #include "ath.h" -#include "debug.h" - -void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...) -{ - va_list args; - - if (likely(!(common->debug_mask & dbg_mask))) - return; - - va_start(args, fmt); - printk(KERN_DEBUG "ath: "); - vprintk(fmt, args); - va_end(args); -} -EXPORT_SYMBOL(ath_print); const char *ath_opmode_to_string(enum nl80211_iftype opmode) { diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h deleted file mode 100644 index 64e4af2c2887..000000000000 --- a/drivers/net/wireless/ath/debug.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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. - */ - -#ifndef ATH_DEBUG_H -#define ATH_DEBUG_H - -#include "ath.h" - -/** - * enum ath_debug_level - atheros wireless debug level - * - * @ATH_DBG_RESET: reset processing - * @ATH_DBG_QUEUE: hardware queue management - * @ATH_DBG_EEPROM: eeprom processing - * @ATH_DBG_CALIBRATE: periodic calibration - * @ATH_DBG_INTERRUPT: interrupt processing - * @ATH_DBG_REGULATORY: regulatory processing - * @ATH_DBG_ANI: adaptive noise immunitive processing - * @ATH_DBG_XMIT: basic xmit operation - * @ATH_DBG_BEACON: beacon handling - * @ATH_DBG_CONFIG: configuration of the hardware - * @ATH_DBG_FATAL: fatal errors, this is the default, DBG_DEFAULT - * @ATH_DBG_PS: power save processing - * @ATH_DBG_HWTIMER: hardware timer handling - * @ATH_DBG_BTCOEX: bluetooth coexistance - * @ATH_DBG_BSTUCK: stuck beacons - * @ATH_DBG_ANY: enable all debugging - * - * The debug level is used to control the amount and type of debugging output - * we want to see. Each driver has its own method for enabling debugging and - * modifying debug level states -- but this is typically done through a - * module parameter 'debug' along with a respective 'debug' debugfs file - * entry. - */ -enum ATH_DEBUG { - ATH_DBG_RESET = 0x00000001, - ATH_DBG_QUEUE = 0x00000002, - ATH_DBG_EEPROM = 0x00000004, - ATH_DBG_CALIBRATE = 0x00000008, - ATH_DBG_INTERRUPT = 0x00000010, - ATH_DBG_REGULATORY = 0x00000020, - ATH_DBG_ANI = 0x00000040, - ATH_DBG_XMIT = 0x00000080, - ATH_DBG_BEACON = 0x00000100, - ATH_DBG_CONFIG = 0x00000200, - ATH_DBG_FATAL = 0x00000400, - ATH_DBG_PS = 0x00000800, - ATH_DBG_HWTIMER = 0x00001000, - ATH_DBG_BTCOEX = 0x00002000, - ATH_DBG_WMI = 0x00004000, - ATH_DBG_BSTUCK = 0x00008000, - ATH_DBG_ANY = 0xffffffff -}; - -#define ATH_DBG_DEFAULT (ATH_DBG_FATAL) - -#ifdef CONFIG_ATH_DEBUG -void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...) - __attribute__ ((format (printf, 3, 4))); -#else -static inline void __attribute__ ((format (printf, 3, 4))) -ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...) -{ -} -#endif /* CONFIG_ATH_DEBUG */ - -/** Returns string describing opmode, or NULL if unknown mode. */ -#ifdef CONFIG_ATH_DEBUG -const char *ath_opmode_to_string(enum nl80211_iftype opmode); -#else -static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode) -{ - return "UNKNOWN"; -} -#endif - -#endif /* ATH_DEBUG_H */ diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c index bd21a4d82085..5d465e5fcf24 100644 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c @@ -20,7 +20,6 @@ #include "ath.h" #include "reg.h" -#include "debug.h" #define REG_READ (common->ops->read) #define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg) @@ -37,8 +36,7 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry) void *ah = common->ah; if (entry >= common->keymax) { - ath_print(common, ATH_DBG_FATAL, - "keychache entry %u out of range\n", entry); + ath_err(common, "keycache entry %u out of range\n", entry); return false; } @@ -60,6 +58,8 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry) REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); + if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) + REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); } @@ -67,15 +67,15 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry) } EXPORT_SYMBOL(ath_hw_keyreset); -bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac) +static bool ath_hw_keysetmac(struct ath_common *common, + u16 entry, const u8 *mac) { u32 macHi, macLo; u32 unicast_flag = AR_KEYTABLE_VALID; void *ah = common->ah; if (entry >= common->keymax) { - ath_print(common, ATH_DBG_FATAL, - "keychache entry %u out of range\n", entry); + ath_err(common, "keycache entry %u out of range\n", entry); return false; } @@ -107,17 +107,16 @@ bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac) return true; } -bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, - const struct ath_keyval *k, - const u8 *mac) +static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, + const struct ath_keyval *k, + const u8 *mac) { void *ah = common->ah; u32 key0, key1, key2, key3, key4; u32 keyType; if (entry >= common->keymax) { - ath_print(common, ATH_DBG_FATAL, - "keycache entry %u out of range\n", entry); + ath_err(common, "keycache entry %u out of range\n", entry); return false; } @@ -127,8 +126,8 @@ bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, break; case ATH_CIPHER_AES_CCM: if (!(common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)) { - ath_print(common, ATH_DBG_ANY, - "AES-CCM not supported by this mac rev\n"); + ath_dbg(common, ATH_DBG_ANY, + "AES-CCM not supported by this mac rev\n"); return false; } keyType = AR_KEYTABLE_TYPE_CCM; @@ -136,15 +135,15 @@ bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, case ATH_CIPHER_TKIP: keyType = AR_KEYTABLE_TYPE_TKIP; if (entry + 64 >= common->keymax) { - ath_print(common, ATH_DBG_ANY, - "entry %u inappropriate for TKIP\n", entry); + ath_dbg(common, ATH_DBG_ANY, + "entry %u inappropriate for TKIP\n", entry); return false; } break; case ATH_CIPHER_WEP: if (k->kv_len < WLAN_KEY_LEN_WEP40) { - ath_print(common, ATH_DBG_ANY, - "WEP key length %u too small\n", k->kv_len); + ath_dbg(common, ATH_DBG_ANY, + "WEP key length %u too small\n", k->kv_len); return false; } if (k->kv_len <= WLAN_KEY_LEN_WEP40) @@ -158,8 +157,7 @@ bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, keyType = AR_KEYTABLE_TYPE_CLR; break; default: - ath_print(common, ATH_DBG_FATAL, - "cipher %u not supported\n", k->kv_type); + ath_err(common, "cipher %u not supported\n", k->kv_type); return false; } @@ -340,8 +338,7 @@ static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); if (!ath_hw_set_keycache_entry(common, keyix, hk, NULL)) { /* TX MIC entry failed. No need to proceed further */ - ath_print(common, ATH_DBG_FATAL, - "Setting TX MIC Key Failed\n"); + ath_err(common, "Setting TX MIC Key Failed\n"); return 0; } diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c index 487193f1de1a..c325202fdc5f 100644 --- a/drivers/net/wireless/ath/main.c +++ b/drivers/net/wireless/ath/main.c @@ -56,3 +56,23 @@ struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, return skb; } EXPORT_SYMBOL(ath_rxbuf_alloc); + +int ath_printk(const char *level, struct ath_common *common, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + int rtn; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + rtn = printk("%sath: %pV", level, &vaf); + + va_end(args); + + return rtn; +} +EXPORT_SYMBOL(ath_printk); diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 3f4244f56ce5..2b14775e6bc6 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -342,6 +342,14 @@ int ath_reg_notifier_apply(struct wiphy *wiphy, /* We always apply this */ ath_reg_apply_radar_flags(wiphy); + /* + * This would happen when we have sent a custom regulatory request + * a world regulatory domain and the scheduler hasn't yet processed + * any pending requests in the queue. + */ + if (!request) + return 0; + switch (request->initiator) { case NL80211_REGDOM_SET_BY_DRIVER: case NL80211_REGDOM_SET_BY_CORE: diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index c8f7090b27d3..46e382ed46aa 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -1161,7 +1161,7 @@ static irqreturn_t service_interrupt(int irq, void *dev_id) struct atmel_private *priv = netdev_priv(dev); u8 isr; int i = -1; - static u8 irq_order[] = { + static const u8 irq_order[] = { ISR_OUT_OF_RANGE, ISR_RxCOMPLETE, ISR_TxCOMPLETE, @@ -3771,7 +3771,9 @@ static int probe_atmel_card(struct net_device *dev) if (rc) { if (dev->dev_addr[0] == 0xFF) { - u8 default_mac[] = {0x00, 0x04, 0x25, 0x00, 0x00, 0x00}; + static const u8 default_mac[] = { + 0x00, 0x04, 0x25, 0x00, 0x00, 0x00 + }; printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name); memcpy(dev->dev_addr, default_mac, 6); } diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 0a00d42642cd..47033f6a1c2b 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -86,15 +86,16 @@ config B43_PIO select SSB_BLOCKIO default y -config B43_NPHY - bool "Pre IEEE 802.11n support (BROKEN)" - depends on B43 && EXPERIMENTAL && BROKEN +config B43_PHY_N + bool "Support for 802.11n (N-PHY) devices (EXPERIMENTAL)" + depends on B43 && EXPERIMENTAL ---help--- - Support for the IEEE 802.11n draft. + Support for the N-PHY. - THIS IS BROKEN AND DOES NOT WORK YET. + This enables support for devices with N-PHY revision up to 2. - SAY N. + Say N if you expect high stability and performance. Saying Y will not + affect other devices support and may provide support for basic needs. config B43_PHY_LP bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)" diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 69d4af09a6cb..cef334a8c669 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -1,12 +1,12 @@ b43-y += main.o b43-y += tables.o -b43-$(CONFIG_B43_NPHY) += tables_nphy.o -b43-$(CONFIG_B43_NPHY) += radio_2055.o -b43-$(CONFIG_B43_NPHY) += radio_2056.o +b43-$(CONFIG_B43_PHY_N) += tables_nphy.o +b43-$(CONFIG_B43_PHY_N) += radio_2055.o +b43-$(CONFIG_B43_PHY_N) += radio_2056.o b43-y += phy_common.o b43-y += phy_g.o b43-y += phy_a.o -b43-$(CONFIG_B43_NPHY) += phy_n.o +b43-$(CONFIG_B43_PHY_N) += phy_n.o b43-$(CONFIG_B43_PHY_LP) += phy_lp.o b43-$(CONFIG_B43_PHY_LP) += tables_lpphy.o b43-y += sysfs.o diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 72821c456b02..bd4cb75b6ca3 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -153,6 +153,19 @@ #define B43_BFH_FEM_BT 0x0040 /* has FEM and switch to share antenna * with bluetooth */ +/* SPROM boardflags2_lo values */ +#define B43_BFL2_RXBB_INT_REG_DIS 0x0001 /* external RX BB regulator present */ +#define B43_BFL2_APLL_WAR 0x0002 /* alternative A-band PLL settings implemented */ +#define B43_BFL2_TXPWRCTRL_EN 0x0004 /* permits enabling TX Power Control */ +#define B43_BFL2_2X4_DIV 0x0008 /* 2x4 diversity switch */ +#define B43_BFL2_5G_PWRGAIN 0x0010 /* supports 5G band power gain */ +#define B43_BFL2_PCIEWAR_OVR 0x0020 /* overrides ASPM and Clkreq settings */ +#define B43_BFL2_CAESERS_BRD 0x0040 /* is Caesers board (unused) */ +#define B43_BFL2_BTC3WIRE 0x0080 /* used 3-wire bluetooth coexist */ +#define B43_BFL2_SKWRKFEM_BRD 0x0100 /* 4321mcm93 uses Skyworks FEM */ +#define B43_BFL2_SPUR_WAR 0x0200 /* has a workaround for clock-harmonic spurs */ +#define B43_BFL2_GPLL_WAR 0x0400 /* altenative G-band PLL settings implemented */ + /* GPIO register offset, in both ChipCommon and PCI core. */ #define B43_GPIO_CONTROL 0x6c @@ -403,10 +416,10 @@ enum { /* 802.11 core specific TM State Low (SSB_TMSLOW) flags */ #define B43_TMSLOW_GMODE 0x20000000 /* G Mode Enable */ -#define B43_TMSLOW_PHYCLKSPEED 0x00C00000 /* PHY clock speed mask (N-PHY only) */ -#define B43_TMSLOW_PHYCLKSPEED_40MHZ 0x00000000 /* 40 MHz PHY */ -#define B43_TMSLOW_PHYCLKSPEED_80MHZ 0x00400000 /* 80 MHz PHY */ -#define B43_TMSLOW_PHYCLKSPEED_160MHZ 0x00800000 /* 160 MHz PHY */ +#define B43_TMSLOW_PHY_BANDWIDTH 0x00C00000 /* PHY band width and clock speed mask (N-PHY only) */ +#define B43_TMSLOW_PHY_BANDWIDTH_10MHZ 0x00000000 /* 10 MHz bandwidth, 40 MHz PHY */ +#define B43_TMSLOW_PHY_BANDWIDTH_20MHZ 0x00400000 /* 20 MHz bandwidth, 80 MHz PHY */ +#define B43_TMSLOW_PHY_BANDWIDTH_40MHZ 0x00800000 /* 40 MHz bandwidth, 160 MHz PHY */ #define B43_TMSLOW_PLLREFSEL 0x00200000 /* PLL Frequency Reference Select (rev >= 5) */ #define B43_TMSLOW_MACPHYCLKEN 0x00100000 /* MAC PHY Clock Control Enable (rev >= 5) */ #define B43_TMSLOW_PHYRESET 0x00080000 /* PHY Reset */ diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 10d0aaf754c5..3d5566e7af0a 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -415,11 +415,6 @@ static int alloc_ringmemory(struct b43_dmaring *ring) static void free_ringmemory(struct b43_dmaring *ring) { - gfp_t flags = GFP_KERNEL; - - if (ring->type == B43_DMA_64BIT) - flags |= GFP_DMA; - dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE, ring->descbase, ring->dmabase); } diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index a1186525c70d..22bc9f17f634 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -322,59 +322,83 @@ static int b43_ratelimit(struct b43_wl *wl) void b43info(struct b43_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (b43_modparam_verbose < B43_VERBOSITY_INFO) return; if (!b43_ratelimit(wl)) return; + va_start(args, fmt); - printk(KERN_INFO "b43-%s: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_INFO "b43-%s: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } void b43err(struct b43_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (b43_modparam_verbose < B43_VERBOSITY_ERROR) return; if (!b43_ratelimit(wl)) return; + va_start(args, fmt); - printk(KERN_ERR "b43-%s ERROR: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_ERR "b43-%s ERROR: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } void b43warn(struct b43_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (b43_modparam_verbose < B43_VERBOSITY_WARN) return; if (!b43_ratelimit(wl)) return; + va_start(args, fmt); - printk(KERN_WARNING "b43-%s warning: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_WARNING "b43-%s warning: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } void b43dbg(struct b43_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (b43_modparam_verbose < B43_VERBOSITY_DEBUG) return; + va_start(args, fmt); - printk(KERN_DEBUG "b43-%s debug: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_DEBUG "b43-%s debug: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } @@ -1126,6 +1150,8 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags) flags |= B43_TMSLOW_PHYCLKEN; flags |= B43_TMSLOW_PHYRESET; + if (dev->phy.type == B43_PHYTYPE_N) + flags |= B43_TMSLOW_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */ ssb_device_enable(dev->dev, flags); msleep(2); /* Wait for the PLL to turn on. */ @@ -2095,8 +2121,10 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) filename = "ucode13"; else if (rev == 14) filename = "ucode14"; - else if (rev >= 15) + else if (rev == 15) filename = "ucode15"; + else if ((rev >= 16) && (rev <= 20)) + filename = "ucode16_mimo"; else goto err_no_ucode; err = b43_do_request_fw(ctx, filename, &fw->ucode); @@ -2139,7 +2167,9 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) goto err_no_initvals; break; case B43_PHYTYPE_N: - if ((rev >= 11) && (rev <= 12)) + if (rev >= 16) + filename = "n0initvals16"; + else if ((rev >= 11) && (rev <= 12)) filename = "n0initvals11"; else goto err_no_initvals; @@ -2183,7 +2213,9 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) goto err_no_initvals; break; case B43_PHYTYPE_N: - if ((rev >= 11) && (rev <= 12)) + if (rev >= 16) + filename = "n0bsinitvals16"; + else if ((rev >= 11) && (rev <= 12)) filename = "n0bsinitvals11"; else goto err_no_initvals; @@ -4022,9 +4054,9 @@ static int b43_phy_versioning(struct b43_wldev *dev) if (phy_rev > 9) unsupported = 1; break; -#ifdef CONFIG_B43_NPHY +#ifdef CONFIG_B43_PHY_N case B43_PHYTYPE_N: - if (phy_rev > 4) + if (phy_rev > 9) unsupported = 1; break; #endif @@ -5067,7 +5099,7 @@ static void b43_print_driverinfo(void) #ifdef CONFIG_B43_PCMCIA feat_pcmcia = "M"; #endif -#ifdef CONFIG_B43_NPHY +#ifdef CONFIG_B43_PHY_N feat_nphy = "N"; #endif #ifdef CONFIG_B43_LEDS diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index 7b2ea6781457..b5c5ce94d3fd 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -50,7 +50,7 @@ int b43_phy_allocate(struct b43_wldev *dev) phy->ops = &b43_phyops_g; break; case B43_PHYTYPE_N: -#ifdef CONFIG_B43_NPHY +#ifdef CONFIG_B43_PHY_N phy->ops = &b43_phyops_n; #endif break; @@ -231,6 +231,7 @@ void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) u16 b43_phy_read(struct b43_wldev *dev, u16 reg) { assert_mac_suspended(dev); + dev->phy.writes_counter = 0; return dev->phy.ops->phy_read(dev, reg); } @@ -238,6 +239,10 @@ void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) { assert_mac_suspended(dev); dev->phy.ops->phy_write(dev, reg, value); + if (++dev->phy.writes_counter == B43_MAX_WRITES_IN_ROW) { + b43_read16(dev, B43_MMIO_PHY_VER); + dev->phy.writes_counter = 0; + } } void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg) @@ -424,12 +429,21 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on) b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4); } + +bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type) +{ + return (channel_type == NL80211_CHAN_HT40MINUS || + channel_type == NL80211_CHAN_HT40PLUS); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/Cordic */ struct b43_c32 b43_cordic(int theta) { - u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304, - 58666, 29335, 14668, 7334, 3667, 1833, 917, 458, - 229, 115, 57, 29, }; + static const u32 arctg[] = { + 2949120, 1740967, 919879, 466945, 234379, 117304, + 58666, 29335, 14668, 7334, 3667, 1833, + 917, 458, 229, 115, 57, 29, + }; u8 i; s32 tmp; s8 signx = 1; diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index 0e6194228845..2401bee8b081 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -39,6 +39,9 @@ struct b43_c32 { s32 i, q; }; #define B43_PHYVER_TYPE_SHIFT 8 #define B43_PHYVER_VERSION 0x00FF +/* PHY writes need to be flushed if we reach limit */ +#define B43_MAX_WRITES_IN_ROW 24 + /** * enum b43_interference_mitigation - Interference Mitigation mode * @@ -232,6 +235,9 @@ struct b43_phy { /* PHY revision number. */ u8 rev; + /* Count writes since last read */ + u8 writes_counter; + /* Radio versioning */ u16 radio_manuf; /* Radio manufacturer */ u16 radio_ver; /* Radio version */ @@ -430,6 +436,8 @@ int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset); */ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on); +bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type); + struct b43_c32 b43_cordic(int theta); #endif /* LINUX_B43_PHY_COMMON_H_ */ diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index e0f2d122e124..ab81ed8b19d7 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -67,6 +67,18 @@ enum b43_nphy_rf_sequence { B43_RFSEQ_UPDATE_GAINU, }; +enum b43_nphy_rssi_type { + B43_NPHY_RSSI_X = 0, + B43_NPHY_RSSI_Y, + B43_NPHY_RSSI_Z, + B43_NPHY_RSSI_PWRDET, + B43_NPHY_RSSI_TSSI_I, + B43_NPHY_RSSI_TSSI_Q, + B43_NPHY_RSSI_TBD, +}; + +static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, + bool enable); static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd, u8 *events, u8 *delays, u8 length); static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, @@ -76,13 +88,6 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, u16 value, u8 core); -static inline bool b43_channel_type_is_40mhz( - enum nl80211_channel_type channel_type) -{ - return (channel_type == NL80211_CHAN_HT40MINUS || - channel_type == NL80211_CHAN_HT40PLUS); -} - void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) {//TODO } @@ -134,6 +139,99 @@ static void b43_chantab_radio_upload(struct b43_wldev *dev, b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); } +static void b43_chantab_radio_2056_upload(struct b43_wldev *dev, + const struct b43_nphy_channeltab_entry_rev3 *e) +{ + b43_radio_write(dev, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1); + b43_radio_write(dev, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2); + b43_radio_write(dev, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv); + b43_radio_write(dev, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2); + b43_radio_write(dev, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1); + b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, + e->radio_syn_pll_loopfilter1); + b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, + e->radio_syn_pll_loopfilter2); + b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER3, + e->radio_syn_pll_loopfilter3); + b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, + e->radio_syn_pll_loopfilter4); + b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER5, + e->radio_syn_pll_loopfilter5); + b43_radio_write(dev, B2056_SYN_RESERVED_ADDR27, + e->radio_syn_reserved_addr27); + b43_radio_write(dev, B2056_SYN_RESERVED_ADDR28, + e->radio_syn_reserved_addr28); + b43_radio_write(dev, B2056_SYN_RESERVED_ADDR29, + e->radio_syn_reserved_addr29); + b43_radio_write(dev, B2056_SYN_LOGEN_VCOBUF1, + e->radio_syn_logen_vcobuf1); + b43_radio_write(dev, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2); + b43_radio_write(dev, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3); + b43_radio_write(dev, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4); + + b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA_TUNE, + e->radio_rx0_lnaa_tune); + b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG_TUNE, + e->radio_rx0_lnag_tune); + + b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE, + e->radio_tx0_intpaa_boost_tune); + b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE, + e->radio_tx0_intpag_boost_tune); + b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE, + e->radio_tx0_pada_boost_tune); + b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE, + e->radio_tx0_padg_boost_tune); + b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE, + e->radio_tx0_pgaa_boost_tune); + b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE, + e->radio_tx0_pgag_boost_tune); + b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE, + e->radio_tx0_mixa_boost_tune); + b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE, + e->radio_tx0_mixg_boost_tune); + + b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA_TUNE, + e->radio_rx1_lnaa_tune); + b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG_TUNE, + e->radio_rx1_lnag_tune); + + b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE, + e->radio_tx1_intpaa_boost_tune); + b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE, + e->radio_tx1_intpag_boost_tune); + b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE, + e->radio_tx1_pada_boost_tune); + b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE, + e->radio_tx1_padg_boost_tune); + b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE, + e->radio_tx1_pgaa_boost_tune); + b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE, + e->radio_tx1_pgag_boost_tune); + b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE, + e->radio_tx1_mixa_boost_tune); + b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE, + e->radio_tx1_mixg_boost_tune); +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */ +static void b43_radio_2056_setup(struct b43_wldev *dev, + const struct b43_nphy_channeltab_entry_rev3 *e) +{ + B43_WARN_ON(dev->phy.rev < 3); + + b43_chantab_radio_2056_upload(dev, e); + /* TODO */ + udelay(50); + /* VCO calibration */ + b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00); + b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38); + b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x18); + b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38); + b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x39); + udelay(300); +} + static void b43_chantab_phy_upload(struct b43_wldev *dev, const struct b43_phy_n_sfo_cfg *e) { @@ -145,9 +243,154 @@ static void b43_chantab_phy_upload(struct b43_wldev *dev, b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */ +static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) +{ + struct b43_phy_n *nphy = dev->phy.n; + u8 i; + u16 tmp; + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 1); + + nphy->txpwrctrl = enable; + if (!enable) { + if (dev->phy.rev >= 3) + ; /* TODO */ + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840); + for (i = 0; i < 84; i++) + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0); + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40); + for (i = 0; i < 84; i++) + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0); + + tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN; + if (dev->phy.rev >= 3) + tmp |= B43_NPHY_TXPCTL_CMD_PCTLEN; + b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp); + + if (dev->phy.rev >= 3) { + b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100); + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100); + } else { + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000); + } + + if (dev->phy.rev == 2) + b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, + ~B43_NPHY_BPHY_CTL3_SCALE, 0x53); + else if (dev->phy.rev < 2) + b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, + ~B43_NPHY_BPHY_CTL3_SCALE, 0x5A); + + if (dev->phy.rev < 2 && 0) + ; /* TODO */ + } else { + b43err(dev->wl, "enabling tx pwr ctrl not implemented yet\n"); + } + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 0); +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) { - //TODO + struct b43_phy_n *nphy = dev->phy.n; + struct ssb_sprom *sprom = &(dev->dev->bus->sprom); + + u8 txpi[2], bbmult, i; + u16 tmp, radio_gain, dac_gain; + u16 freq = dev->phy.channel_freq; + u32 txgain; + /* u32 gaintbl; rev3+ */ + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 1); + + if (dev->phy.rev >= 3) { + txpi[0] = 40; + txpi[1] = 40; + } else if (sprom->revision < 4) { + txpi[0] = 72; + txpi[1] = 72; + } else { + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + txpi[0] = sprom->txpid2g[0]; + txpi[1] = sprom->txpid2g[1]; + } else if (freq >= 4900 && freq < 5100) { + txpi[0] = sprom->txpid5gl[0]; + txpi[1] = sprom->txpid5gl[1]; + } else if (freq >= 5100 && freq < 5500) { + txpi[0] = sprom->txpid5g[0]; + txpi[1] = sprom->txpid5g[1]; + } else if (freq >= 5500) { + txpi[0] = sprom->txpid5gh[0]; + txpi[1] = sprom->txpid5gh[1]; + } else { + txpi[0] = 91; + txpi[1] = 91; + } + } + + /* + for (i = 0; i < 2; i++) { + nphy->txpwrindex[i].index_internal = txpi[i]; + nphy->txpwrindex[i].index_internal_save = txpi[i]; + } + */ + + for (i = 0; i < 2; i++) { + if (dev->phy.rev >= 3) { + /* FIXME: support 5GHz */ + txgain = b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]]; + radio_gain = (txgain >> 16) & 0x1FFFF; + } else { + txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]]; + radio_gain = (txgain >> 16) & 0x1FFF; + } + + dac_gain = (txgain >> 8) & 0x3F; + bbmult = txgain & 0xFF; + + if (dev->phy.rev >= 3) { + if (i == 0) + b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100); + else + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100); + } else { + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000); + } + + if (i == 0) + b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain); + else + b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain); + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D10 + i); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, radio_gain); + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57); + tmp = b43_phy_read(dev, B43_NPHY_TABLE_DATALO); + + if (i == 0) + tmp = (tmp & 0x00FF) | (bbmult << 8); + else + tmp = (tmp & 0xFF00) | bbmult; + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, tmp); + + if (0) + ; /* TODO */ + } + + b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT); + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 0); } @@ -191,7 +434,8 @@ static void b43_radio_init2055_post(struct b43_wldev *dev) binfo->type != 0x46D || binfo->rev < 0x41); else - workaround = ((sprom->boardflags_hi & B43_BFH_NOPA) == 0); + workaround = + !(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS); b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); if (workaround) { @@ -240,23 +484,55 @@ static void b43_radio_init2055_post(struct b43_wldev *dev) static void b43_radio_init2055(struct b43_wldev *dev) { b43_radio_init2055_pre(dev); - if (b43_status(dev) < B43_STAT_INITIALIZED) - b2055_upload_inittab(dev, 0, 1); - else - b2055_upload_inittab(dev, 0/*FIXME on 5ghz band*/, 0); + if (b43_status(dev) < B43_STAT_INITIALIZED) { + /* Follow wl, not specs. Do not force uploading all regs */ + b2055_upload_inittab(dev, 0, 0); + } else { + bool ghz5 = b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ; + b2055_upload_inittab(dev, ghz5, 0); + } b43_radio_init2055_post(dev); } +static void b43_radio_init2056_pre(struct b43_wldev *dev) +{ + b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, + ~B43_NPHY_RFCTL_CMD_CHIP0PU); + /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */ + b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, + B43_NPHY_RFCTL_CMD_OEPORFORCE); + b43_phy_set(dev, B43_NPHY_RFCTL_CMD, + ~B43_NPHY_RFCTL_CMD_OEPORFORCE); + b43_phy_set(dev, B43_NPHY_RFCTL_CMD, + B43_NPHY_RFCTL_CMD_CHIP0PU); +} + +static void b43_radio_init2056_post(struct b43_wldev *dev) +{ + b43_radio_set(dev, B2056_SYN_COM_CTRL, 0xB); + b43_radio_set(dev, B2056_SYN_COM_PU, 0x2); + b43_radio_set(dev, B2056_SYN_COM_RESET, 0x2); + msleep(1); + b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2); + b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC); + b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1); + /* + if (nphy->init_por) + Call Radio 2056 Recalibrate + */ +} + /* * Initialize a Broadcom 2056 N-radio * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init */ static void b43_radio_init2056(struct b43_wldev *dev) { - /* TODO */ + b43_radio_init2056_pre(dev); + b2056_upload_inittabs(dev, 0, 0); + b43_radio_init2056_post(dev); } - /* * Upload the N-PHY tables. * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables @@ -453,6 +729,8 @@ static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write, } } +#if 0 +/* Ready but not used anywhere */ /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */ static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core) { @@ -534,6 +812,7 @@ static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core) b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1)); b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core)); } +#endif /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */ static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask) @@ -569,7 +848,6 @@ static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask) ii = est.i1_pwr; qq = est.q1_pwr; } else { - B43_WARN_ON(1); continue; } @@ -651,7 +929,8 @@ static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev) } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ -static void b43_nphy_write_clip_detection(struct b43_wldev *dev, u16 *clip_st) +static void b43_nphy_write_clip_detection(struct b43_wldev *dev, + const u16 *clip_st) { b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]); b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]); @@ -727,7 +1006,7 @@ static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable) struct b43_phy_n *nphy = phy->n; if (enable) { - u16 clip[] = { 0xFFFF, 0xFFFF }; + static const u16 clip[] = { 0xFFFF, 0xFFFF }; if (nphy->deaf_count++ == 0) { nphy->classifier_state = b43_nphy_classifier(dev, 0, 0); b43_nphy_classifier(dev, 0x7, 0); @@ -839,7 +1118,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) u16 data[4]; s16 gain[2]; u16 minmax[2]; - u16 lna_gain[4] = { -2, 10, 19, 25 }; + static const u16 lna_gain[4] = { -2, 10, 19, 25 }; if (nphy->hang_avoid) b43_nphy_stay_in_carrier_search(dev, 1); @@ -871,7 +1150,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) data[2] = lna_gain[2] + gain[i]; data[3] = lna_gain[3] + gain[i]; } - b43_ntab_write_bulk(dev, B43_NTAB16(10, 8), 4, data); + b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data); minmax[i] = 23 + gain[i]; } @@ -891,6 +1170,7 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) struct b43_phy_n *nphy = dev->phy.n; u8 i, j; u8 code; + u16 tmp; /* TODO: for PHY >= 3 s8 *lna1_gain, *lna2_gain; @@ -913,15 +1193,15 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) B43_NPHY_C2_CGAINI_CL2DETECT); /* Set narrowband clip threshold */ - b43_phy_set(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84); - b43_phy_set(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84); + b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84); + b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84); if (!dev->phy.is_40mhz) { /* Set dwell lengths */ - b43_phy_set(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B); - b43_phy_set(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B); - b43_phy_set(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009); - b43_phy_set(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009); + b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B); + b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B); + b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009); + b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009); } /* Set wideband clip 2 threshold */ @@ -943,7 +1223,7 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) ~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1); } - b43_phy_set(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C); + b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C); if (nphy->gain_boost) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ && @@ -964,10 +1244,10 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT); b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, - (code << 8 | 0x7C)); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, - (code << 8 | 0x7C)); + /* specs say about 2 loops, but wl does 4 */ + for (i = 0; i < 4; i++) + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, + (code << 8 | 0x7C)); b43_nphy_adjust_lna_gain_table(dev); @@ -985,19 +1265,21 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, - (code << 8 | 0x74)); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, - (code << 8 | 0x74)); + /* specs say about 2 loops, but wl does 4 */ + for (i = 0; i < 4; i++) + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, + (code << 8 | 0x74)); } if (dev->phy.rev == 2) { for (i = 0; i < 4; i++) { b43_phy_write(dev, B43_NPHY_TABLE_ADDR, (0x0400 * i) + 0x0020); - for (j = 0; j < 21; j++) + for (j = 0; j < 21; j++) { + tmp = j * (i < 2 ? 3 : 1); b43_phy_write(dev, - B43_NPHY_TABLE_DATALO, 3 * j); + B43_NPHY_TABLE_DATALO, tmp); + } } b43_nphy_set_rf_sequence(dev, 5, @@ -1026,7 +1308,7 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 }; u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 }; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) b43_nphy_classifier(dev, 1, 0); else b43_nphy_classifier(dev, 1, 1); @@ -1049,29 +1331,18 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8); } - /* TODO: convert to b43_ntab_write? */ - b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2000); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A); - b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2010); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A); - b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2002); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA); - b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2012); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA); + b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A); + b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A); + b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA); + b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA); if (dev->phy.rev < 2) { - b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2008); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000); - b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2018); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000); - b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2007); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB); - b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2017); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB); - b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2006); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800); - b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2016); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800); + b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000); + b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000); + b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB); + b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB); + b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800); + b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800); } b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); @@ -1565,19 +1836,20 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */ static void b43_nphy_bphy_init(struct b43_wldev *dev) { unsigned int i; u16 val; val = 0x1E1F; - for (i = 0; i < 14; i++) { + for (i = 0; i < 16; i++) { b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); val -= 0x202; } val = 0x3E3F; for (i = 0; i < 16; i++) { - b43_phy_write(dev, B43_PHY_N_BMODE(0x97 + i), val); + b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val); val -= 0x202; } b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); @@ -1585,7 +1857,8 @@ static void b43_nphy_bphy_init(struct b43_wldev *dev) /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */ static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale, - s8 offset, u8 core, u8 rail, u8 type) + s8 offset, u8 core, u8 rail, + enum b43_nphy_rssi_type type) { u16 tmp; bool core1or5 = (core == 1) || (core == 5); @@ -1594,53 +1867,59 @@ static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale, offset = clamp_val(offset, -32, 31); tmp = ((scale & 0x3F) << 8) | (offset & 0x3F); - if (core1or5 && (rail == 0) && (type == 2)) + if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z)) b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp); - if (core1or5 && (rail == 1) && (type == 2)) + if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z)) b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp); - if (core2or5 && (rail == 0) && (type == 2)) + if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z)) b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp); - if (core2or5 && (rail == 1) && (type == 2)) + if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z)) b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp); - if (core1or5 && (rail == 0) && (type == 0)) + + if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_X)) b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp); - if (core1or5 && (rail == 1) && (type == 0)) + if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_X)) b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp); - if (core2or5 && (rail == 0) && (type == 0)) + if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_X)) b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp); - if (core2or5 && (rail == 1) && (type == 0)) + if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_X)) b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp); - if (core1or5 && (rail == 0) && (type == 1)) + + if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y)) b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp); - if (core1or5 && (rail == 1) && (type == 1)) + if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y)) b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp); - if (core2or5 && (rail == 0) && (type == 1)) + if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y)) b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp); - if (core2or5 && (rail == 1) && (type == 1)) + if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y)) b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp); - if (core1or5 && (rail == 0) && (type == 6)) + + if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD)) b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp); - if (core1or5 && (rail == 1) && (type == 6)) + if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD)) b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp); - if (core2or5 && (rail == 0) && (type == 6)) + if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD)) b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp); - if (core2or5 && (rail == 1) && (type == 6)) + if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD)) b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp); - if (core1or5 && (rail == 0) && (type == 3)) + + if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET)) b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp); - if (core1or5 && (rail == 1) && (type == 3)) + if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET)) b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp); - if (core2or5 && (rail == 0) && (type == 3)) + if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET)) b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp); - if (core2or5 && (rail == 1) && (type == 3)) + if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET)) b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp); - if (core1or5 && (type == 4)) + + if (core1or5 && (type == B43_NPHY_RSSI_TSSI_I)) b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp); - if (core2or5 && (type == 4)) + if (core2or5 && (type == B43_NPHY_RSSI_TSSI_I)) b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp); - if (core1or5 && (type == 5)) + + if (core1or5 && (type == B43_NPHY_RSSI_TSSI_Q)) b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp); - if (core2or5 && (type == 5)) + if (core2or5 && (type == B43_NPHY_RSSI_TSSI_Q)) b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp); } @@ -1668,27 +1947,39 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type) (type + 1) << 4); } - /* TODO use some definitions */ if (code == 0) { - b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0); + b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000); if (type < 3) { - b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFEC7, 0); - b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xEFDC, 0); - b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0); + b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, + ~(B43_NPHY_RFCTL_CMD_RXEN | + B43_NPHY_RFCTL_CMD_CORESEL)); + b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, + ~(0x1 << 12 | + 0x1 << 5 | + 0x1 << 1 | + 0x1)); + b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, + ~B43_NPHY_RFCTL_CMD_START); udelay(20); - b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0); + b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1); } } else { - b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, - 0x3000); + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000); if (type < 3) { b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, - 0xFEC7, 0x0180); - b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, - 0xEFDC, (code << 1 | 0x1021)); - b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0x1); + ~(B43_NPHY_RFCTL_CMD_RXEN | + B43_NPHY_RFCTL_CMD_CORESEL), + (B43_NPHY_RFCTL_CMD_RXEN | + code << B43_NPHY_RFCTL_CMD_CORESEL_SHIFT)); + b43_phy_set(dev, B43_NPHY_RFCTL_OVER, + (0x1 << 12 | + 0x1 << 5 | + 0x1 << 1 | + 0x1)); + b43_phy_set(dev, B43_NPHY_RFCTL_CMD, + B43_NPHY_RFCTL_CMD_START); udelay(20); - b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0); + b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1); } } } @@ -1837,6 +2128,14 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1); + } else if (dev->phy.rev == 2) { + save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); + save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); + save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); + save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD); + save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER); + save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1); + save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2); } b43_nphy_rssi_select(dev, 5, type); @@ -1880,6 +2179,14 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]); b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]); + } else if (dev->phy.rev == 2) { + b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]); + b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]); + b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]); + b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]); + b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]); + b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]); + b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]); } return out; @@ -1894,7 +2201,10 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) u16 class, override; u8 regs_save_radio[2]; u16 regs_save_phy[2]; + s8 offset[4]; + u8 core; + u8 rail; u16 clip_state[2]; u16 clip_off[2] = { 0xFFFF, 0xFFFF }; @@ -1995,16 +2305,15 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) if (results_min[i] == 248) offset[i] = code - 32; - if (i % 2 == 0) - b43_nphy_scale_offset_rssi(dev, 0, offset[i], 1, 0, - type); - else - b43_nphy_scale_offset_rssi(dev, 0, offset[i], 2, 1, - type); + core = (i / 2) ? 2 : 1; + rail = (i % 2) ? 1 : 0; + + b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail, + type); } b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]); - b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[1]); + b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]); switch (state[2]) { case 1: @@ -2042,6 +2351,9 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) b43_nphy_classifier(dev, 7, class); b43_nphy_write_clip_detection(dev, clip_state); + /* Specs don't say about reset here, but it makes wl and b43 dumps + identical, it really seems wl performs this */ + b43_nphy_reset_cca(dev); } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ @@ -2059,9 +2371,9 @@ static void b43_nphy_rssi_cal(struct b43_wldev *dev) if (dev->phy.rev >= 3) { b43_nphy_rev3_rssi_cal(dev); } else { - b43_nphy_rev2_rssi_cal(dev, 2); - b43_nphy_rev2_rssi_cal(dev, 0); - b43_nphy_rev2_rssi_cal(dev, 1); + b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z); + b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X); + b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y); } } @@ -2295,7 +2607,7 @@ static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev) { int i, j; /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */ - u16 offset[] = { 0x186, 0x195, 0x2C5 }; + static const u16 offset[] = { 0x186, 0x195, 0x2C5 }; for (i = 0; i < 3; i++) for (j = 0; j < 15; j++) @@ -2327,7 +2639,7 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) struct nphy_txgains target; const u32 *table = NULL; - if (nphy->txpwrctrl == 0) { + if (!nphy->txpwrctrl) { int i; if (nphy->hang_avoid) @@ -2884,7 +3196,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, u8 rfctl[2]; u8 afectl_core; u16 tmp[6]; - u16 cur_hpf1, cur_hpf2, cur_lna; + u16 uninitialized_var(cur_hpf1), uninitialized_var(cur_hpf2), cur_lna; u32 real, imag; enum ieee80211_band band; @@ -3077,9 +3389,9 @@ static void b43_nphy_mac_phy_clock_set(struct b43_wldev *dev, bool on) { u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW); if (on) - tmslow |= SSB_TMSLOW_PHYCLK; + tmslow |= B43_TMSLOW_MACPHYCLKEN; else - tmslow &= ~SSB_TMSLOW_PHYCLK; + tmslow &= ~B43_TMSLOW_MACPHYCLKEN; ssb_write32(dev->dev, SSB_TMSLOW, tmslow); } @@ -3088,7 +3400,7 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) { struct b43_phy *phy = &dev->phy; struct b43_phy_n *nphy = phy->n; - u16 buf[16]; + /* u16 buf[16]; it's rev3+ */ nphy->phyrxchain = mask; @@ -3232,10 +3544,12 @@ int b43_phy_initn(struct b43_wldev *dev) b43_nphy_classifier(dev, 0, 0); b43_nphy_read_clip_detection(dev, clip); + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + b43_nphy_bphy_init(dev); + tx_pwr_state = nphy->txpwrctrl; - /* TODO N PHY TX power control with argument 0 - (turning off power control) */ - /* TODO Fix the TX Power Settings */ + b43_nphy_tx_power_ctrl(dev, false); + b43_nphy_tx_power_fix(dev); /* TODO N PHY TX Power Control Idle TSSI */ /* TODO N PHY TX Power Control Setup */ @@ -3292,21 +3606,18 @@ int b43_phy_initn(struct b43_wldev *dev) /* TODO N PHY Pre Calibrate TX Gain */ target = b43_nphy_get_tx_gains(dev); } - } + if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) + if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0) + b43_nphy_save_cal(dev); + } else if (nphy->mphase_cal_phase_id == 0) + ;/* N PHY Periodic Calibration with arg 3 */ + } else { + b43_nphy_restore_cal(dev); } } - if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) { - if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0) - b43_nphy_save_cal(dev); - else if (nphy->mphase_cal_phase_id == 0) - ;/* N PHY Periodic Calibration with argument 3 */ - } else { - b43_nphy_restore_cal(dev); - } - b43_nphy_tx_pwr_ctrl_coef_setup(dev); - /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */ + b43_nphy_tx_power_ctrl(dev, tx_pwr_state); b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015); b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320); if (phy->rev >= 3 && phy->rev <= 6) @@ -3315,7 +3626,6 @@ int b43_phy_initn(struct b43_wldev *dev) if (phy->rev >= 3) b43_nphy_spur_workaround(dev); - b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); return 0; } @@ -3357,7 +3667,7 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev, b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840); } - if (nphy->txpwrctrl) + if (!nphy->txpwrctrl) b43_nphy_tx_power_fix(dev); if (dev->phy.rev < 3) @@ -3381,7 +3691,6 @@ static int b43_nphy_set_channel(struct b43_wldev *dev, enum nl80211_channel_type channel_type) { struct b43_phy *phy = &dev->phy; - struct b43_phy_n *nphy = dev->phy.n; const struct b43_nphy_channeltab_entry_rev2 *tabent_r2; const struct b43_nphy_channeltab_entry_rev3 *tabent_r3; @@ -3391,7 +3700,6 @@ static int b43_nphy_set_channel(struct b43_wldev *dev, if (dev->phy.rev >= 3) { tabent_r3 = b43_nphy_get_chantabent_rev3(dev, channel->center_freq); - tabent_r3 = NULL; if (!tabent_r3) return -ESRCH; } else { @@ -3420,7 +3728,7 @@ static int b43_nphy_set_channel(struct b43_wldev *dev, if (dev->phy.rev >= 3) { tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0; b43_radio_maskset(dev, 0x08, 0xFFFB, tmp); - /* TODO: PHY Radio2056 Setup (dev, tabent_r3); */ + b43_radio_2056_setup(dev, tabent_r3); b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel); } else { tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050; @@ -3451,7 +3759,11 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev) memset(nphy, 0, sizeof(*nphy)); - //TODO init struct b43_phy_n + nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4); + nphy->gain_boost = true; /* this way we follow wl, assume it is true */ + nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */ + nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */ + nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */ } static void b43_nphy_op_free(struct b43_wldev *dev) @@ -3500,6 +3812,15 @@ static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) b43_write16(dev, B43_MMIO_PHY_DATA, value); } +static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, + u16 set) +{ + check_phyreg(dev, reg); + b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); + b43_write16(dev, B43_MMIO_PHY_DATA, + (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); +} + static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) { /* Register 1 is a 32-bit register. */ @@ -3524,8 +3845,6 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, bool blocked) { - struct b43_phy_n *nphy = dev->phy.n; - if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) b43err(dev->wl, "MAC not suspended\n"); @@ -3596,6 +3915,7 @@ const struct b43_phy_operations b43_phyops_n = { .init = b43_nphy_op_init, .phy_read = b43_nphy_op_read, .phy_write = b43_nphy_op_write, + .phy_maskset = b43_nphy_op_maskset, .radio_read = b43_nphy_op_radio_read, .radio_write = b43_nphy_op_radio_write, .software_rfkill = b43_nphy_op_software_rfkill, diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index c144e59a708b..001e841f118c 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -782,7 +782,7 @@ struct b43_phy_n { u16 mphase_txcal_numcmds; u16 mphase_txcal_bestcoeffs[11]; - u8 txpwrctrl; + bool txpwrctrl; u16 txcal_bbmult; u16 txiqlocal_bestc[11]; bool txiqlocal_coeffsvalid; diff --git a/drivers/net/wireless/b43/radio_2055.c b/drivers/net/wireless/b43/radio_2055.c index 1b5316586cbf..44c6dea66882 100644 --- a/drivers/net/wireless/b43/radio_2055.c +++ b/drivers/net/wireless/b43/radio_2055.c @@ -244,7 +244,7 @@ static const struct b2055_inittab_entry b2055_inittab [] = { [0xCB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [0xCC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [B2055_C1_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xCE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xCE] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, [0xCF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [0xD0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [0xD1] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, @@ -256,7 +256,7 @@ static const struct b2055_inittab_entry b2055_inittab [] = { [0xD7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [0xD8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [B2055_C2_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xDA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xDA] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, [0xDB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [0xDC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [0xDD] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, @@ -304,178 +304,178 @@ static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab_rev2[] = { .channel = 184, .freq = 4920, /* MHz */ .unk2 = 3280, - RADIOREGS(0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xEC, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xB407, 0xB007, 0xAC07, 0x1402, 0x1502, 0x1602), + PHYREGS(0x07B4, 0x07B0, 0x07AC, 0x0214, 0x0215, 0x0216), }, { .channel = 186, .freq = 4930, /* MHz */ .unk2 = 3287, - RADIOREGS(0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xED, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xB807, 0xB407, 0xB007, 0x1302, 0x1402, 0x1502), + PHYREGS(0x07B8, 0x07B4, 0x07B0, 0x0213, 0x0214, 0x0215), }, { .channel = 188, .freq = 4940, /* MHz */ .unk2 = 3293, - RADIOREGS(0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xEE, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xBC07, 0xB807, 0xB407, 0x1202, 0x1302, 0x1402), + PHYREGS(0x07BC, 0x07B8, 0x07B4, 0x0212, 0x0213, 0x0214), }, { .channel = 190, .freq = 4950, /* MHz */ .unk2 = 3300, - RADIOREGS(0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xEF, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xC007, 0xBC07, 0xB807, 0x1102, 0x1202, 0x1302), + PHYREGS(0x07C0, 0x07BC, 0x07B8, 0x0211, 0x0212, 0x0213), }, { .channel = 192, .freq = 4960, /* MHz */ .unk2 = 3307, - RADIOREGS(0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF0, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xC407, 0xC007, 0xBC07, 0x0F02, 0x1102, 0x1202), + PHYREGS(0x07C4, 0x07C0, 0x07BC, 0x020F, 0x0211, 0x0212), }, { .channel = 194, .freq = 4970, /* MHz */ .unk2 = 3313, - RADIOREGS(0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF1, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xC807, 0xC407, 0xC007, 0x0E02, 0x0F02, 0x1102), + PHYREGS(0x07C8, 0x07C4, 0x07C0, 0x020E, 0x020F, 0x0211), }, { .channel = 196, .freq = 4980, /* MHz */ .unk2 = 3320, - RADIOREGS(0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF2, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xCC07, 0xC807, 0xC407, 0x0D02, 0x0E02, 0x0F02), + PHYREGS(0x07CC, 0x07C8, 0x07C4, 0x020D, 0x020E, 0x020F), }, { .channel = 198, .freq = 4990, /* MHz */ .unk2 = 3327, - RADIOREGS(0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF3, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xD007, 0xCC07, 0xC807, 0x0C02, 0x0D02, 0x0E02), + PHYREGS(0x07D0, 0x07CC, 0x07C8, 0x020C, 0x020D, 0x020E), }, { .channel = 200, .freq = 5000, /* MHz */ .unk2 = 3333, - RADIOREGS(0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF4, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xD407, 0xD007, 0xCC07, 0x0B02, 0x0C02, 0x0D02), + PHYREGS(0x07D4, 0x07D0, 0x07CC, 0x020B, 0x020C, 0x020D), }, { .channel = 202, .freq = 5010, /* MHz */ .unk2 = 3340, - RADIOREGS(0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF5, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xD807, 0xD407, 0xD007, 0x0A02, 0x0B02, 0x0C02), + PHYREGS(0x07D8, 0x07D4, 0x07D0, 0x020A, 0x020B, 0x020C), }, { .channel = 204, .freq = 5020, /* MHz */ .unk2 = 3347, - RADIOREGS(0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF6, 0x01, 0x0E, 0xF7, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xDC07, 0xD807, 0xD407, 0x0902, 0x0A02, 0x0B02), + PHYREGS(0x07DC, 0x07D8, 0x07D4, 0x0209, 0x020A, 0x020B), }, { .channel = 206, .freq = 5030, /* MHz */ .unk2 = 3353, - RADIOREGS(0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF7, 0x01, 0x0E, 0xF7, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xE007, 0xDC07, 0xD807, 0x0802, 0x0902, 0x0A02), + PHYREGS(0x07E0, 0x07DC, 0x07D8, 0x0208, 0x0209, 0x020A), }, { .channel = 208, .freq = 5040, /* MHz */ .unk2 = 3360, - RADIOREGS(0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF8, 0x01, 0x0D, 0xEF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xE407, 0xE007, 0xDC07, 0x0702, 0x0802, 0x0902), + PHYREGS(0x07E4, 0x07E0, 0x07DC, 0x0207, 0x0208, 0x0209), }, { .channel = 210, .freq = 5050, /* MHz */ .unk2 = 3367, - RADIOREGS(0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF9, 0x01, 0x0D, 0xEF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xE807, 0xE407, 0xE007, 0x0602, 0x0702, 0x0802), + PHYREGS(0x07E8, 0x07E4, 0x07E0, 0x0206, 0x0207, 0x0208), }, { .channel = 212, .freq = 5060, /* MHz */ .unk2 = 3373, - RADIOREGS(0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xFA, 0x01, 0x0D, 0xE6, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E), - PHYREGS(0xEC07, 0xE807, 0xE407, 0x0502, 0x0602, 0x0702), + PHYREGS(0x07EC, 0x07E8, 0x07E4, 0x0205, 0x0206, 0x0207), }, { .channel = 214, .freq = 5070, /* MHz */ .unk2 = 3380, - RADIOREGS(0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xFB, 0x01, 0x0D, 0xE6, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E), - PHYREGS(0xF007, 0xEC07, 0xE807, 0x0402, 0x0502, 0x0602), + PHYREGS(0x07F0, 0x07EC, 0x07E8, 0x0204, 0x0205, 0x0206), }, { .channel = 216, .freq = 5080, /* MHz */ .unk2 = 3387, - RADIOREGS(0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xFC, 0x01, 0x0D, 0xDE, 0x01, 0x04, 0x0A, 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D), - PHYREGS(0xF407, 0xF007, 0xEC07, 0x0302, 0x0402, 0x0502), + PHYREGS(0x07F4, 0x07F0, 0x07EC, 0x0203, 0x0204, 0x0205), }, { .channel = 218, .freq = 5090, /* MHz */ .unk2 = 3393, - RADIOREGS(0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xFD, 0x01, 0x0D, 0xDE, 0x01, 0x04, 0x0A, 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D), - PHYREGS(0xF807, 0xF407, 0xF007, 0x0202, 0x0302, 0x0402), + PHYREGS(0x07F8, 0x07F4, 0x07F0, 0x0202, 0x0203, 0x0204), }, { .channel = 220, .freq = 5100, /* MHz */ .unk2 = 3400, - RADIOREGS(0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xFE, 0x01, 0x0C, 0xD6, 0x01, 0x04, 0x0A, 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D), - PHYREGS(0xFC07, 0xF807, 0xF407, 0x0102, 0x0202, 0x0302), + PHYREGS(0x07FC, 0x07F8, 0x07F4, 0x0201, 0x0202, 0x0203), }, { .channel = 222, .freq = 5110, /* MHz */ .unk2 = 3407, - RADIOREGS(0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xFF, 0x01, 0x0C, 0xD6, 0x01, 0x04, 0x0A, 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D), - PHYREGS(0x0008, 0xFC07, 0xF807, 0x0002, 0x0102, 0x0202), + PHYREGS(0x0800, 0x07FC, 0x07F8, 0x0200, 0x0201, 0x0202), }, { .channel = 224, .freq = 5120, /* MHz */ .unk2 = 3413, - RADIOREGS(0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x00, 0x02, 0x0C, 0xCE, 0x01, 0x04, 0x0A, 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C), - PHYREGS(0x0408, 0x0008, 0xFC07, 0xFF01, 0x0002, 0x0102), + PHYREGS(0x0804, 0x0800, 0x07FC, 0x01FF, 0x0200, 0x0201), }, { .channel = 226, .freq = 5130, /* MHz */ .unk2 = 3420, - RADIOREGS(0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x01, 0x02, 0x0C, 0xCE, 0x01, 0x04, 0x0A, 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C), - PHYREGS(0x0808, 0x0408, 0x0008, 0xFE01, 0xFF01, 0x0002), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01FE, 0x01FF, 0x0200), }, { .channel = 228, .freq = 5140, /* MHz */ @@ -483,815 +483,815 @@ static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab_rev2[] = RADIOREGS(0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A, 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, 0x8B, 0xDD, 0x00, 0x0C, 0x0E, 0x8B), - PHYREGS(0x0C08, 0x0808, 0x0408, 0xFD01, 0xFE01, 0xFF01), + PHYREGS(0x080C, 0x0808, 0x0804, 0x01FD, 0x01FE, 0x01FF), }, { .channel = 32, .freq = 5160, /* MHz */ .unk2 = 3440, - RADIOREGS(0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x04, 0x02, 0x0B, 0xBE, 0x01, 0x04, 0x0A, 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A), - PHYREGS(0x1408, 0x1008, 0x0C08, 0xFB01, 0xFC01, 0xFD01), + PHYREGS(0x0814, 0x0810, 0x080C, 0x01FB, 0x01FC, 0x01FD), }, { .channel = 34, .freq = 5170, /* MHz */ .unk2 = 3447, - RADIOREGS(0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x05, 0x02, 0x0B, 0xBE, 0x01, 0x04, 0x0A, 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A), - PHYREGS(0x1808, 0x1408, 0x1008, 0xFA01, 0xFB01, 0xFC01), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01FA, 0x01FB, 0x01FC), }, { .channel = 36, .freq = 5180, /* MHz */ .unk2 = 3453, - RADIOREGS(0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x06, 0x02, 0x0B, 0xB6, 0x01, 0x04, 0x0A, 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89), - PHYREGS(0x1C08, 0x1808, 0x1408, 0xF901, 0xFA01, 0xFB01), + PHYREGS(0x081C, 0x0818, 0x0814, 0x01F9, 0x01FA, 0x01FB), }, { .channel = 38, .freq = 5190, /* MHz */ .unk2 = 3460, - RADIOREGS(0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x07, 0x02, 0x0B, 0xB6, 0x01, 0x04, 0x0A, 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89), - PHYREGS(0x2008, 0x1C08, 0x1808, 0xF801, 0xF901, 0xFA01), + PHYREGS(0x0820, 0x081C, 0x0818, 0x01F8, 0x01F9, 0x01FA), }, { .channel = 40, .freq = 5200, /* MHz */ .unk2 = 3467, - RADIOREGS(0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x08, 0x02, 0x0B, 0xAF, 0x01, 0x04, 0x0A, 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89), - PHYREGS(0x2408, 0x2008, 0x1C08, 0xF701, 0xF801, 0xF901), + PHYREGS(0x0824, 0x0820, 0x081C, 0x01F7, 0x01F8, 0x01F9), }, { .channel = 42, .freq = 5210, /* MHz */ .unk2 = 3473, - RADIOREGS(0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x09, 0x02, 0x0B, 0xAF, 0x01, 0x04, 0x0A, 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89), - PHYREGS(0x2808, 0x2408, 0x2008, 0xF601, 0xF701, 0xF801), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01F6, 0x01F7, 0x01F8), }, { .channel = 44, .freq = 5220, /* MHz */ .unk2 = 3480, - RADIOREGS(0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x0A, 0x02, 0x0A, 0xA7, 0x01, 0x04, 0x0A, 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88), - PHYREGS(0x2C08, 0x2808, 0x2408, 0xF501, 0xF601, 0xF701), + PHYREGS(0x082C, 0x0828, 0x0824, 0x01F5, 0x01F6, 0x01F7), }, { .channel = 46, .freq = 5230, /* MHz */ .unk2 = 3487, - RADIOREGS(0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x0B, 0x02, 0x0A, 0xA7, 0x01, 0x04, 0x0A, 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88), - PHYREGS(0x3008, 0x2C08, 0x2808, 0xF401, 0xF501, 0xF601), + PHYREGS(0x0830, 0x082C, 0x0828, 0x01F4, 0x01F5, 0x01F6), }, { .channel = 48, .freq = 5240, /* MHz */ .unk2 = 3493, - RADIOREGS(0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x0C, 0x02, 0x0A, 0xA0, 0x01, 0x04, 0x0A, 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87), - PHYREGS(0x3408, 0x3008, 0x2C08, 0xF301, 0xF401, 0xF501), + PHYREGS(0x0834, 0x0830, 0x082C, 0x01F3, 0x01F4, 0x01F5), }, { .channel = 50, .freq = 5250, /* MHz */ .unk2 = 3500, - RADIOREGS(0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x0D, 0x02, 0x0A, 0xA0, 0x01, 0x04, 0x0A, 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87), - PHYREGS(0x3808, 0x3408, 0x3008, 0xF201, 0xF301, 0xF401), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01F2, 0x01F3, 0x01F4), }, { .channel = 52, .freq = 5260, /* MHz */ .unk2 = 3507, - RADIOREGS(0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x0E, 0x02, 0x0A, 0x98, 0x01, 0x04, 0x0A, 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87), - PHYREGS(0x3C08, 0x3808, 0x3408, 0xF101, 0xF201, 0xF301), + PHYREGS(0x083C, 0x0838, 0x0834, 0x01F1, 0x01F2, 0x01F3), }, { .channel = 54, .freq = 5270, /* MHz */ .unk2 = 3513, - RADIOREGS(0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x0F, 0x02, 0x0A, 0x98, 0x01, 0x04, 0x0A, 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87), - PHYREGS(0x4008, 0x3C08, 0x3808, 0xF001, 0xF101, 0xF201), + PHYREGS(0x0840, 0x083C, 0x0838, 0x01F0, 0x01F1, 0x01F2), }, { .channel = 56, .freq = 5280, /* MHz */ .unk2 = 3520, - RADIOREGS(0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x10, 0x02, 0x09, 0x91, 0x01, 0x04, 0x0A, 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08, 0x08, 0x86), - PHYREGS(0x4408, 0x4008, 0x3C08, 0xF001, 0xF001, 0xF101), + PHYREGS(0x0844, 0x0840, 0x083C, 0x01F0, 0x01F0, 0x01F1), }, { .channel = 58, .freq = 5290, /* MHz */ .unk2 = 3527, - RADIOREGS(0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x11, 0x02, 0x09, 0x91, 0x01, 0x04, 0x0A, 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08, 0x08, 0x86), - PHYREGS(0x4808, 0x4408, 0x4008, 0xEF01, 0xF001, 0xF001), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01EF, 0x01F0, 0x01F0), }, { .channel = 60, .freq = 5300, /* MHz */ .unk2 = 3533, - RADIOREGS(0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x12, 0x02, 0x09, 0x8A, 0x01, 0x04, 0x0A, 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08, 0x07, 0x85), - PHYREGS(0x4C08, 0x4808, 0x4408, 0xEE01, 0xEF01, 0xF001), + PHYREGS(0x084C, 0x0848, 0x0844, 0x01EE, 0x01EF, 0x01F0), }, { .channel = 62, .freq = 5310, /* MHz */ .unk2 = 3540, - RADIOREGS(0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x13, 0x02, 0x09, 0x8A, 0x01, 0x04, 0x0A, 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08, 0x07, 0x85), - PHYREGS(0x5008, 0x4C08, 0x4808, 0xED01, 0xEE01, 0xEF01), + PHYREGS(0x0850, 0x084C, 0x0848, 0x01ED, 0x01EE, 0x01EF), }, { .channel = 64, .freq = 5320, /* MHz */ .unk2 = 3547, - RADIOREGS(0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x14, 0x02, 0x09, 0x83, 0x01, 0x04, 0x0A, 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07, 0x07, 0x84), - PHYREGS(0x5408, 0x5008, 0x4C08, 0xEC01, 0xED01, 0xEE01), + PHYREGS(0x0854, 0x0850, 0x084C, 0x01EC, 0x01ED, 0x01EE), }, { .channel = 66, .freq = 5330, /* MHz */ .unk2 = 3553, - RADIOREGS(0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x15, 0x02, 0x09, 0x83, 0x01, 0x04, 0x0A, 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07, 0x07, 0x84), - PHYREGS(0x5808, 0x5408, 0x5008, 0xEB01, 0xEC01, 0xED01), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01EB, 0x01EC, 0x01ED), }, { .channel = 68, .freq = 5340, /* MHz */ .unk2 = 3560, - RADIOREGS(0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x16, 0x02, 0x08, 0x7C, 0x01, 0x04, 0x0A, 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07, 0x06, 0x84), - PHYREGS(0x5C08, 0x5808, 0x5408, 0xEA01, 0xEB01, 0xEC01), + PHYREGS(0x085C, 0x0858, 0x0854, 0x01EA, 0x01EB, 0x01EC), }, { .channel = 70, .freq = 5350, /* MHz */ .unk2 = 3567, - RADIOREGS(0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x17, 0x02, 0x08, 0x7C, 0x01, 0x04, 0x0A, 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07, 0x06, 0x84), - PHYREGS(0x6008, 0x5C08, 0x5808, 0xE901, 0xEA01, 0xEB01), + PHYREGS(0x0860, 0x085C, 0x0858, 0x01E9, 0x01EA, 0x01EB), }, { .channel = 72, .freq = 5360, /* MHz */ .unk2 = 3573, - RADIOREGS(0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x18, 0x02, 0x08, 0x75, 0x01, 0x04, 0x0A, 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06, 0x05, 0x83), - PHYREGS(0x6408, 0x6008, 0x5C08, 0xE801, 0xE901, 0xEA01), + PHYREGS(0x0864, 0x0860, 0x085C, 0x01E8, 0x01E9, 0x01EA), }, { .channel = 74, .freq = 5370, /* MHz */ .unk2 = 3580, - RADIOREGS(0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x19, 0x02, 0x08, 0x75, 0x01, 0x04, 0x0A, 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06, 0x05, 0x83), - PHYREGS(0x6808, 0x6408, 0x6008, 0xE701, 0xE801, 0xE901), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01E7, 0x01E8, 0x01E9), }, { .channel = 76, .freq = 5380, /* MHz */ .unk2 = 3587, - RADIOREGS(0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x1A, 0x02, 0x08, 0x6E, 0x01, 0x04, 0x0A, 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06, 0x04, 0x82), - PHYREGS(0x6C08, 0x6808, 0x6408, 0xE601, 0xE701, 0xE801), + PHYREGS(0x086C, 0x0868, 0x0864, 0x01E6, 0x01E7, 0x01E8), }, { .channel = 78, .freq = 5390, /* MHz */ .unk2 = 3593, - RADIOREGS(0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x1B, 0x02, 0x08, 0x6E, 0x01, 0x04, 0x0A, 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06, 0x04, 0x82), - PHYREGS(0x7008, 0x6C08, 0x6808, 0xE501, 0xE601, 0xE701), + PHYREGS(0x0870, 0x086C, 0x0868, 0x01E5, 0x01E6, 0x01E7), }, { .channel = 80, .freq = 5400, /* MHz */ .unk2 = 3600, - RADIOREGS(0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x1C, 0x02, 0x07, 0x67, 0x01, 0x04, 0x0A, 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05, 0x04, 0x81), - PHYREGS(0x7408, 0x7008, 0x6C08, 0xE501, 0xE501, 0xE601), + PHYREGS(0x0874, 0x0870, 0x086C, 0x01E5, 0x01E5, 0x01E6), }, { .channel = 82, .freq = 5410, /* MHz */ .unk2 = 3607, - RADIOREGS(0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x1D, 0x02, 0x07, 0x67, 0x01, 0x04, 0x0A, 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05, 0x04, 0x81), - PHYREGS(0x7808, 0x7408, 0x7008, 0xE401, 0xE501, 0xE501), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01E4, 0x01E5, 0x01E5), }, { .channel = 84, .freq = 5420, /* MHz */ .unk2 = 3613, - RADIOREGS(0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x1E, 0x02, 0x07, 0x61, 0x01, 0x04, 0x0A, 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05, 0x03, 0x80), - PHYREGS(0x7C08, 0x7808, 0x7408, 0xE301, 0xE401, 0xE501), + PHYREGS(0x087C, 0x0878, 0x0874, 0x01E3, 0x01E4, 0x01E5), }, { .channel = 86, .freq = 5430, /* MHz */ .unk2 = 3620, - RADIOREGS(0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x1F, 0x02, 0x07, 0x61, 0x01, 0x04, 0x0A, 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05, 0x03, 0x80), - PHYREGS(0x8008, 0x7C08, 0x7808, 0xE201, 0xE301, 0xE401), + PHYREGS(0x0880, 0x087C, 0x0878, 0x01E2, 0x01E3, 0x01E4), }, { .channel = 88, .freq = 5440, /* MHz */ .unk2 = 3627, - RADIOREGS(0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x20, 0x02, 0x07, 0x5A, 0x01, 0x04, 0x0A, 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04, 0x02, 0x80), - PHYREGS(0x8408, 0x8008, 0x7C08, 0xE101, 0xE201, 0xE301), + PHYREGS(0x0884, 0x0880, 0x087C, 0x01E1, 0x01E2, 0x01E3), }, { .channel = 90, .freq = 5450, /* MHz */ .unk2 = 3633, - RADIOREGS(0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x21, 0x02, 0x07, 0x5A, 0x01, 0x04, 0x0A, 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04, 0x02, 0x80), - PHYREGS(0x8808, 0x8408, 0x8008, 0xE001, 0xE101, 0xE201), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01E0, 0x01E1, 0x01E2), }, { .channel = 92, .freq = 5460, /* MHz */ .unk2 = 3640, - RADIOREGS(0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x22, 0x02, 0x06, 0x53, 0x01, 0x04, 0x0A, 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04, 0x01, 0x80), - PHYREGS(0x8C08, 0x8808, 0x8408, 0xDF01, 0xE001, 0xE101), + PHYREGS(0x088C, 0x0888, 0x0884, 0x01DF, 0x01E0, 0x01E1), }, { .channel = 94, .freq = 5470, /* MHz */ .unk2 = 3647, - RADIOREGS(0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x23, 0x02, 0x06, 0x53, 0x01, 0x04, 0x0A, 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04, 0x01, 0x80), - PHYREGS(0x9008, 0x8C08, 0x8808, 0xDE01, 0xDF01, 0xE001), + PHYREGS(0x0890, 0x088C, 0x0888, 0x01DE, 0x01DF, 0x01E0), }, { .channel = 96, .freq = 5480, /* MHz */ .unk2 = 3653, - RADIOREGS(0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x24, 0x02, 0x06, 0x4D, 0x01, 0x04, 0x0A, 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0x9408, 0x9008, 0x8C08, 0xDD01, 0xDE01, 0xDF01), + PHYREGS(0x0894, 0x0890, 0x088C, 0x01DD, 0x01DE, 0x01DF), }, { .channel = 98, .freq = 5490, /* MHz */ .unk2 = 3660, - RADIOREGS(0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x25, 0x02, 0x06, 0x4D, 0x01, 0x04, 0x0A, 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0x9808, 0x9408, 0x9008, 0xDD01, 0xDD01, 0xDE01), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01DD, 0x01DD, 0x01DE), }, { .channel = 100, .freq = 5500, /* MHz */ .unk2 = 3667, - RADIOREGS(0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x26, 0x02, 0x06, 0x47, 0x01, 0x04, 0x0A, 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0x9C08, 0x9808, 0x9408, 0xDC01, 0xDD01, 0xDD01), + PHYREGS(0x089C, 0x0898, 0x0894, 0x01DC, 0x01DD, 0x01DD), }, { .channel = 102, .freq = 5510, /* MHz */ .unk2 = 3673, - RADIOREGS(0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x27, 0x02, 0x06, 0x47, 0x01, 0x04, 0x0A, 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0xA008, 0x9C08, 0x9808, 0xDB01, 0xDC01, 0xDD01), + PHYREGS(0x08A0, 0x089C, 0x0898, 0x01DB, 0x01DC, 0x01DD), }, { .channel = 104, .freq = 5520, /* MHz */ .unk2 = 3680, - RADIOREGS(0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x28, 0x02, 0x05, 0x40, 0x01, 0x04, 0x0A, 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xA408, 0xA008, 0x9C08, 0xDA01, 0xDB01, 0xDC01), + PHYREGS(0x08A4, 0x08A0, 0x089C, 0x01DA, 0x01DB, 0x01DC), }, { .channel = 106, .freq = 5530, /* MHz */ .unk2 = 3687, - RADIOREGS(0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x29, 0x02, 0x05, 0x40, 0x01, 0x04, 0x0A, 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xA808, 0xA408, 0xA008, 0xD901, 0xDA01, 0xDB01), + PHYREGS(0x08A8, 0x08A4, 0x08A0, 0x01D9, 0x01DA, 0x01DB), }, { .channel = 108, .freq = 5540, /* MHz */ .unk2 = 3693, - RADIOREGS(0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x2A, 0x02, 0x05, 0x3A, 0x01, 0x04, 0x0A, 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xAC08, 0xA808, 0xA408, 0xD801, 0xD901, 0xDA01), + PHYREGS(0x08AC, 0x08A8, 0x08A4, 0x01D8, 0x01D9, 0x01DA), }, { .channel = 110, .freq = 5550, /* MHz */ .unk2 = 3700, - RADIOREGS(0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x2B, 0x02, 0x05, 0x3A, 0x01, 0x04, 0x0A, 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xB008, 0xAC08, 0xA808, 0xD701, 0xD801, 0xD901), + PHYREGS(0x08B0, 0x08AC, 0x08A8, 0x01D7, 0x01D8, 0x01D9), }, { .channel = 112, .freq = 5560, /* MHz */ .unk2 = 3707, - RADIOREGS(0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x2C, 0x02, 0x05, 0x34, 0x01, 0x04, 0x0A, 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xB408, 0xB008, 0xAC08, 0xD701, 0xD701, 0xD801), + PHYREGS(0x08B4, 0x08B0, 0x08AC, 0x01D7, 0x01D7, 0x01D8), }, { .channel = 114, .freq = 5570, /* MHz */ .unk2 = 3713, - RADIOREGS(0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x2D, 0x02, 0x05, 0x34, 0x01, 0x04, 0x0A, 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xB808, 0xB408, 0xB008, 0xD601, 0xD701, 0xD701), + PHYREGS(0x08B8, 0x08B4, 0x08B0, 0x01D6, 0x01D7, 0x01D7), }, { .channel = 116, .freq = 5580, /* MHz */ .unk2 = 3720, - RADIOREGS(0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x2E, 0x02, 0x04, 0x2E, 0x01, 0x04, 0x0A, 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xBC08, 0xB808, 0xB408, 0xD501, 0xD601, 0xD701), + PHYREGS(0x08BC, 0x08B8, 0x08B4, 0x01D5, 0x01D6, 0x01D7), }, { .channel = 118, .freq = 5590, /* MHz */ .unk2 = 3727, - RADIOREGS(0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x2F, 0x02, 0x04, 0x2E, 0x01, 0x04, 0x0A, 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xC008, 0xBC08, 0xB808, 0xD401, 0xD501, 0xD601), + PHYREGS(0x08C0, 0x08BC, 0x08B8, 0x01D4, 0x01D5, 0x01D6), }, { .channel = 120, .freq = 5600, /* MHz */ .unk2 = 3733, - RADIOREGS(0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x30, 0x02, 0x04, 0x28, 0x01, 0x04, 0x0A, 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xC408, 0xC008, 0xBC08, 0xD301, 0xD401, 0xD501), + PHYREGS(0x08C4, 0x08C0, 0x08BC, 0x01D3, 0x01D4, 0x01D5), }, { .channel = 122, .freq = 5610, /* MHz */ .unk2 = 3740, - RADIOREGS(0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x31, 0x02, 0x04, 0x28, 0x01, 0x04, 0x0A, 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xC808, 0xC408, 0xC008, 0xD201, 0xD301, 0xD401), + PHYREGS(0x08C8, 0x08C4, 0x08C0, 0x01D2, 0x01D3, 0x01D4), }, { .channel = 124, .freq = 5620, /* MHz */ .unk2 = 3747, - RADIOREGS(0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x32, 0x02, 0x04, 0x21, 0x01, 0x04, 0x0A, 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xCC08, 0xC808, 0xC408, 0xD201, 0xD201, 0xD301), + PHYREGS(0x08CC, 0x08C8, 0x08C4, 0x01D2, 0x01D2, 0x01D3), }, { .channel = 126, .freq = 5630, /* MHz */ .unk2 = 3753, - RADIOREGS(0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x33, 0x02, 0x04, 0x21, 0x01, 0x04, 0x0A, 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xD008, 0xCC08, 0xC808, 0xD101, 0xD201, 0xD201), + PHYREGS(0x08D0, 0x08CC, 0x08C8, 0x01D1, 0x01D2, 0x01D2), }, { .channel = 128, .freq = 5640, /* MHz */ .unk2 = 3760, - RADIOREGS(0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x34, 0x02, 0x03, 0x1C, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xD408, 0xD008, 0xCC08, 0xD001, 0xD101, 0xD201), + PHYREGS(0x08D4, 0x08D0, 0x08CC, 0x01D0, 0x01D1, 0x01D2), }, { .channel = 130, .freq = 5650, /* MHz */ .unk2 = 3767, - RADIOREGS(0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x35, 0x02, 0x03, 0x1C, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xD808, 0xD408, 0xD008, 0xCF01, 0xD001, 0xD101), + PHYREGS(0x08D8, 0x08D4, 0x08D0, 0x01CF, 0x01D0, 0x01D1), }, { .channel = 132, .freq = 5660, /* MHz */ .unk2 = 3773, - RADIOREGS(0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x36, 0x02, 0x03, 0x16, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xDC08, 0xD808, 0xD408, 0xCE01, 0xCF01, 0xD001), + PHYREGS(0x08DC, 0x08D8, 0x08D4, 0x01CE, 0x01CF, 0x01D0), }, { .channel = 134, .freq = 5670, /* MHz */ .unk2 = 3780, - RADIOREGS(0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x37, 0x02, 0x03, 0x16, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xE008, 0xDC08, 0xD808, 0xCE01, 0xCE01, 0xCF01), + PHYREGS(0x08E0, 0x08DC, 0x08D8, 0x01CE, 0x01CE, 0x01CF), }, { .channel = 136, .freq = 5680, /* MHz */ .unk2 = 3787, - RADIOREGS(0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x38, 0x02, 0x03, 0x10, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xE408, 0xE008, 0xDC08, 0xCD01, 0xCE01, 0xCE01), + PHYREGS(0x08E4, 0x08E0, 0x08DC, 0x01CD, 0x01CE, 0x01CE), }, { .channel = 138, .freq = 5690, /* MHz */ .unk2 = 3793, - RADIOREGS(0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x39, 0x02, 0x03, 0x10, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xE808, 0xE408, 0xE008, 0xCC01, 0xCD01, 0xCE01), + PHYREGS(0x08E8, 0x08E4, 0x08E0, 0x01CC, 0x01CD, 0x01CE), }, { .channel = 140, .freq = 5700, /* MHz */ .unk2 = 3800, - RADIOREGS(0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x3A, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xEC08, 0xE808, 0xE408, 0xCB01, 0xCC01, 0xCD01), + PHYREGS(0x08EC, 0x08E8, 0x08E4, 0x01CB, 0x01CC, 0x01CD), }, { .channel = 142, .freq = 5710, /* MHz */ .unk2 = 3807, - RADIOREGS(0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x3B, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF008, 0xEC08, 0xE808, 0xCA01, 0xCB01, 0xCC01), + PHYREGS(0x08F0, 0x08EC, 0x08E8, 0x01CA, 0x01CB, 0x01CC), }, { .channel = 144, .freq = 5720, /* MHz */ .unk2 = 3813, - RADIOREGS(0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x3C, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF408, 0xF008, 0xEC08, 0xC901, 0xCA01, 0xCB01), + PHYREGS(0x08F4, 0x08F0, 0x08EC, 0x01C9, 0x01CA, 0x01CB), }, { .channel = 145, .freq = 5725, /* MHz */ .unk2 = 3817, - RADIOREGS(0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14, + RADIOREGS(0x72, 0x79, 0x04, 0x02, 0x03, 0x01, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF608, 0xF208, 0xEE08, 0xC901, 0xCA01, 0xCB01), + PHYREGS(0x08F6, 0x08F2, 0x08EE, 0x01C9, 0x01CA, 0x01CB), }, { .channel = 146, .freq = 5730, /* MHz */ .unk2 = 3820, - RADIOREGS(0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x3D, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF808, 0xF408, 0xF008, 0xC901, 0xC901, 0xCA01), + PHYREGS(0x08F8, 0x08F4, 0x08F0, 0x01C9, 0x01C9, 0x01CA), }, { .channel = 147, .freq = 5735, /* MHz */ .unk2 = 3823, - RADIOREGS(0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14, + RADIOREGS(0x72, 0x7B, 0x04, 0x02, 0x03, 0x01, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xFA08, 0xF608, 0xF208, 0xC801, 0xC901, 0xCA01), + PHYREGS(0x08FA, 0x08F6, 0x08F2, 0x01C8, 0x01C9, 0x01CA), }, { .channel = 148, .freq = 5740, /* MHz */ .unk2 = 3827, - RADIOREGS(0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x3E, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xFC08, 0xF808, 0xF408, 0xC801, 0xC901, 0xC901), + PHYREGS(0x08FC, 0x08F8, 0x08F4, 0x01C8, 0x01C9, 0x01C9), }, { .channel = 149, .freq = 5745, /* MHz */ .unk2 = 3830, - RADIOREGS(0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x7D, 0x04, 0x02, 0xFE, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xFE08, 0xFA08, 0xF608, 0xC801, 0xC801, 0xC901), + PHYREGS(0x08FE, 0x08FA, 0x08F6, 0x01C8, 0x01C8, 0x01C9), }, { .channel = 150, .freq = 5750, /* MHz */ .unk2 = 3833, - RADIOREGS(0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x3F, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0009, 0xFC08, 0xF808, 0xC701, 0xC801, 0xC901), + PHYREGS(0x0900, 0x08FC, 0x08F8, 0x01C7, 0x01C8, 0x01C9), }, { .channel = 151, .freq = 5755, /* MHz */ .unk2 = 3837, - RADIOREGS(0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x7F, 0x04, 0x02, 0xFE, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0209, 0xFE08, 0xFA08, 0xC701, 0xC801, 0xC801), + PHYREGS(0x0902, 0x08FE, 0x08FA, 0x01C7, 0x01C8, 0x01C8), }, { .channel = 152, .freq = 5760, /* MHz */ .unk2 = 3840, - RADIOREGS(0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x40, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0409, 0x0009, 0xFC08, 0xC601, 0xC701, 0xC801), + PHYREGS(0x0904, 0x0900, 0x08FC, 0x01C6, 0x01C7, 0x01C8), }, { .channel = 153, .freq = 5765, /* MHz */ .unk2 = 3843, - RADIOREGS(0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x81, 0x04, 0x02, 0xF8, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0609, 0x0209, 0xFE08, 0xC601, 0xC701, 0xC801), + PHYREGS(0x0906, 0x0902, 0x08FE, 0x01C6, 0x01C7, 0x01C8), }, { .channel = 154, .freq = 5770, /* MHz */ .unk2 = 3847, - RADIOREGS(0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x41, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0809, 0x0409, 0x0009, 0xC601, 0xC601, 0xC701), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01C6, 0x01C6, 0x01C7), }, { .channel = 155, .freq = 5775, /* MHz */ .unk2 = 3850, - RADIOREGS(0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x83, 0x04, 0x02, 0xF8, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0A09, 0x0609, 0x0209, 0xC501, 0xC601, 0xC701), + PHYREGS(0x090A, 0x0906, 0x0902, 0x01C5, 0x01C6, 0x01C7), }, { .channel = 156, .freq = 5780, /* MHz */ .unk2 = 3853, - RADIOREGS(0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x42, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0C09, 0x0809, 0x0409, 0xC501, 0xC601, 0xC601), + PHYREGS(0x090C, 0x0908, 0x0904, 0x01C5, 0x01C6, 0x01C6), }, { .channel = 157, .freq = 5785, /* MHz */ .unk2 = 3857, - RADIOREGS(0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x85, 0x04, 0x02, 0xF2, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0E09, 0x0A09, 0x0609, 0xC401, 0xC501, 0xC601), + PHYREGS(0x090E, 0x090A, 0x0906, 0x01C4, 0x01C5, 0x01C6), }, { .channel = 158, .freq = 5790, /* MHz */ .unk2 = 3860, - RADIOREGS(0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x43, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1009, 0x0C09, 0x0809, 0xC401, 0xC501, 0xC601), + PHYREGS(0x0910, 0x090C, 0x0908, 0x01C4, 0x01C5, 0x01C6), }, { .channel = 159, .freq = 5795, /* MHz */ .unk2 = 3863, - RADIOREGS(0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x87, 0x04, 0x02, 0xF2, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1209, 0x0E09, 0x0A09, 0xC401, 0xC401, 0xC501), + PHYREGS(0x0912, 0x090E, 0x090A, 0x01C4, 0x01C4, 0x01C5), }, { .channel = 160, .freq = 5800, /* MHz */ .unk2 = 3867, - RADIOREGS(0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x44, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1409, 0x1009, 0x0C09, 0xC301, 0xC401, 0xC501), + PHYREGS(0x0914, 0x0910, 0x090C, 0x01C3, 0x01C4, 0x01C5), }, { .channel = 161, .freq = 5805, /* MHz */ .unk2 = 3870, - RADIOREGS(0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x89, 0x04, 0x01, 0xED, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1609, 0x1209, 0x0E09, 0xC301, 0xC401, 0xC401), + PHYREGS(0x0916, 0x0912, 0x090E, 0x01C3, 0x01C4, 0x01C4), }, { .channel = 162, .freq = 5810, /* MHz */ .unk2 = 3873, - RADIOREGS(0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x45, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1809, 0x1409, 0x1009, 0xC201, 0xC301, 0xC401), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01C2, 0x01C3, 0x01C4), }, { .channel = 163, .freq = 5815, /* MHz */ .unk2 = 3877, - RADIOREGS(0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x8B, 0x04, 0x01, 0xED, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1A09, 0x1609, 0x1209, 0xC201, 0xC301, 0xC401), + PHYREGS(0x091A, 0x0916, 0x0912, 0x01C2, 0x01C3, 0x01C4), }, { .channel = 164, .freq = 5820, /* MHz */ .unk2 = 3880, - RADIOREGS(0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x46, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1C09, 0x1809, 0x1409, 0xC201, 0xC201, 0xC301), + PHYREGS(0x091C, 0x0918, 0x0914, 0x01C2, 0x01C2, 0x01C3), }, { .channel = 165, .freq = 5825, /* MHz */ .unk2 = 3883, - RADIOREGS(0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x8D, 0x04, 0x01, 0xED, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1E09, 0x1A09, 0x1609, 0xC101, 0xC201, 0xC301), + PHYREGS(0x091E, 0x091A, 0x0916, 0x01C1, 0x01C2, 0x01C3), }, { .channel = 166, .freq = 5830, /* MHz */ .unk2 = 3887, - RADIOREGS(0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x47, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2009, 0x1C09, 0x1809, 0xC101, 0xC201, 0xC201), + PHYREGS(0x0920, 0x091C, 0x0918, 0x01C1, 0x01C2, 0x01C2), }, { .channel = 168, .freq = 5840, /* MHz */ .unk2 = 3893, - RADIOREGS(0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x48, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2409, 0x2009, 0x1C09, 0xC001, 0xC101, 0xC201), + PHYREGS(0x0924, 0x0920, 0x091C, 0x01C0, 0x01C1, 0x01C2), }, { .channel = 170, .freq = 5850, /* MHz */ .unk2 = 3900, - RADIOREGS(0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x49, 0x02, 0x01, 0xE0, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2809, 0x2409, 0x2009, 0xBF01, 0xC001, 0xC101), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01BF, 0x01C0, 0x01C1), }, { .channel = 172, .freq = 5860, /* MHz */ .unk2 = 3907, - RADIOREGS(0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x4A, 0x02, 0x01, 0xDE, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2C09, 0x2809, 0x2409, 0xBF01, 0xBF01, 0xC001), + PHYREGS(0x092C, 0x0928, 0x0924, 0x01BF, 0x01BF, 0x01C0), }, { .channel = 174, .freq = 5870, /* MHz */ .unk2 = 3913, - RADIOREGS(0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x4B, 0x02, 0x00, 0xDB, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3009, 0x2C09, 0x2809, 0xBE01, 0xBF01, 0xBF01), + PHYREGS(0x0930, 0x092C, 0x0928, 0x01BE, 0x01BF, 0x01BF), }, { .channel = 176, .freq = 5880, /* MHz */ .unk2 = 3920, - RADIOREGS(0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x4C, 0x02, 0x00, 0xD8, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3409, 0x3009, 0x2C09, 0xBD01, 0xBE01, 0xBF01), + PHYREGS(0x0934, 0x0930, 0x092C, 0x01BD, 0x01BE, 0x01BF), }, { .channel = 178, .freq = 5890, /* MHz */ .unk2 = 3927, - RADIOREGS(0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x4D, 0x02, 0x00, 0xD6, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3809, 0x3409, 0x3009, 0xBC01, 0xBD01, 0xBE01), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01BC, 0x01BD, 0x01BE), }, { .channel = 180, .freq = 5900, /* MHz */ .unk2 = 3933, - RADIOREGS(0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x4E, 0x02, 0x00, 0xD3, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3C09, 0x3809, 0x3409, 0xBC01, 0xBC01, 0xBD01), + PHYREGS(0x093C, 0x0938, 0x0934, 0x01BC, 0x01BC, 0x01BD), }, { .channel = 182, .freq = 5910, /* MHz */ .unk2 = 3940, - RADIOREGS(0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x4F, 0x02, 0x00, 0xD6, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x4009, 0x3C09, 0x3809, 0xBB01, 0xBC01, 0xBC01), + PHYREGS(0x0940, 0x093C, 0x0938, 0x01BB, 0x01BC, 0x01BC), }, { .channel = 1, .freq = 2412, /* MHz */ .unk2 = 3216, - RADIOREGS(0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x6C, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, 0x80, 0xFF, 0x88, 0x0D, 0x0C, 0x80), - PHYREGS(0xC903, 0xC503, 0xC103, 0x3A04, 0x3F04, 0x4304), + PHYREGS(0x03C9, 0x03C5, 0x03C1, 0x043A, 0x043F, 0x0443), }, { .channel = 2, .freq = 2417, /* MHz */ .unk2 = 3223, - RADIOREGS(0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x71, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, 0x80, 0xFF, 0x88, 0x0C, 0x0B, 0x80), - PHYREGS(0xCB03, 0xC703, 0xC303, 0x3804, 0x3D04, 0x4104), + PHYREGS(0x03CB, 0x03C7, 0x03C3, 0x0438, 0x043D, 0x0441), }, { .channel = 3, .freq = 2422, /* MHz */ .unk2 = 3229, - RADIOREGS(0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x76, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80), - PHYREGS(0xCD03, 0xC903, 0xC503, 0x3604, 0x3A04, 0x3F04), + PHYREGS(0x03CD, 0x03C9, 0x03C5, 0x0436, 0x043A, 0x043F), }, { .channel = 4, .freq = 2427, /* MHz */ .unk2 = 3236, - RADIOREGS(0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x7B, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80), - PHYREGS(0xCF03, 0xCB03, 0xC703, 0x3404, 0x3804, 0x3D04), + PHYREGS(0x03CF, 0x03CB, 0x03C7, 0x0434, 0x0438, 0x043D), }, { .channel = 5, .freq = 2432, /* MHz */ .unk2 = 3243, - RADIOREGS(0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x80, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, 0x80, 0xFF, 0x88, 0x0C, 0x09, 0x80), - PHYREGS(0xD103, 0xCD03, 0xC903, 0x3104, 0x3604, 0x3A04), + PHYREGS(0x03D1, 0x03CD, 0x03C9, 0x0431, 0x0436, 0x043A), }, { .channel = 6, .freq = 2437, /* MHz */ .unk2 = 3249, - RADIOREGS(0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x85, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, 0x80, 0xFF, 0x88, 0x0B, 0x08, 0x80), - PHYREGS(0xD303, 0xCF03, 0xCB03, 0x2F04, 0x3404, 0x3804), + PHYREGS(0x03D3, 0x03CF, 0x03CB, 0x042F, 0x0434, 0x0438), }, { .channel = 7, .freq = 2442, /* MHz */ .unk2 = 3256, - RADIOREGS(0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x8A, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, 0x80, 0xFF, 0x88, 0x0A, 0x07, 0x80), - PHYREGS(0xD503, 0xD103, 0xCD03, 0x2D04, 0x3104, 0x3604), + PHYREGS(0x03D5, 0x03D1, 0x03CD, 0x042D, 0x0431, 0x0436), }, { .channel = 8, .freq = 2447, /* MHz */ .unk2 = 3263, - RADIOREGS(0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x8F, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, 0x80, 0xFF, 0x88, 0x0A, 0x06, 0x80), - PHYREGS(0xD703, 0xD303, 0xCF03, 0x2B04, 0x2F04, 0x3404), + PHYREGS(0x03D7, 0x03D3, 0x03CF, 0x042B, 0x042F, 0x0434), }, { .channel = 9, .freq = 2452, /* MHz */ .unk2 = 3269, - RADIOREGS(0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x94, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, 0x80, 0xFF, 0x88, 0x09, 0x06, 0x80), - PHYREGS(0xD903, 0xD503, 0xD103, 0x2904, 0x2D04, 0x3104), + PHYREGS(0x03D9, 0x03D5, 0x03D1, 0x0429, 0x042D, 0x0431), }, { .channel = 10, .freq = 2457, /* MHz */ .unk2 = 3276, - RADIOREGS(0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x99, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, 0x80, 0xFF, 0x88, 0x08, 0x05, 0x80), - PHYREGS(0xDB03, 0xD703, 0xD303, 0x2704, 0x2B04, 0x2F04), + PHYREGS(0x03DB, 0x03D7, 0x03D3, 0x0427, 0x042B, 0x042F), }, { .channel = 11, .freq = 2462, /* MHz */ .unk2 = 3283, - RADIOREGS(0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x9E, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, 0x80, 0xFF, 0x88, 0x08, 0x04, 0x80), - PHYREGS(0xDD03, 0xD903, 0xD503, 0x2404, 0x2904, 0x2D04), + PHYREGS(0x03DD, 0x03D9, 0x03D5, 0x0424, 0x0429, 0x042D), }, { .channel = 12, .freq = 2467, /* MHz */ .unk2 = 3289, - RADIOREGS(0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0xA3, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, 0x80, 0xFF, 0x88, 0x08, 0x03, 0x80), - PHYREGS(0xDF03, 0xDB03, 0xD703, 0x2204, 0x2704, 0x2B04), + PHYREGS(0x03DF, 0x03DB, 0x03D7, 0x0422, 0x0427, 0x042B), }, { .channel = 13, .freq = 2472, /* MHz */ .unk2 = 3296, - RADIOREGS(0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0xA8, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, 0x80, 0xFF, 0x88, 0x07, 0x03, 0x80), - PHYREGS(0xE103, 0xDD03, 0xD903, 0x2004, 0x2404, 0x2904), + PHYREGS(0x03E1, 0x03DD, 0x03D9, 0x0420, 0x0424, 0x0429), }, { .channel = 14, .freq = 2484, /* MHz */ .unk2 = 3312, - RADIOREGS(0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0xB4, 0x09, 0x0F, 0xFF, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, 0x80, 0xFF, 0x88, 0x07, 0x01, 0x80), - PHYREGS(0xE603, 0xE203, 0xDE03, 0x1B04, 0x1F04, 0x2404), + PHYREGS(0x03E6, 0x03E2, 0x03DE, 0x041B, 0x041F, 0x0424), }, }; @@ -1299,7 +1299,7 @@ void b2055_upload_inittab(struct b43_wldev *dev, bool ghz5, bool ignore_uploadflag) { const struct b2055_inittab_entry *e; - unsigned int i; + unsigned int i, writes = 0; u16 value; for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) { @@ -1312,6 +1312,8 @@ void b2055_upload_inittab(struct b43_wldev *dev, else value = e->ghz2; b43_radio_write16(dev, i, value); + if (++writes % 4 == 0) + b43_read32(dev, B43_MMIO_MACCTL); /* flush */ } } } diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c index d8563192ce56..8890df067029 100644 --- a/drivers/net/wireless/b43/radio_2056.c +++ b/drivers/net/wireless/b43/radio_2056.c @@ -24,17 +24,9073 @@ #include "radio_2056.h" #include "phy_common.h" +struct b2056_inittab_entry { + /* Value to write if we use the 5GHz band. */ + u16 ghz5; + /* Value to write if we use the 2.4GHz band. */ + u16 ghz2; + /* Flags */ + u8 flags; +}; +#define B2056_INITTAB_ENTRY_OK 0x01 +#define B2056_INITTAB_UPLOAD 0x02 +#define UPLOAD .flags = B2056_INITTAB_ENTRY_OK | B2056_INITTAB_UPLOAD +#define NOUPLOAD .flags = B2056_INITTAB_ENTRY_OK + +struct b2056_inittabs_pts { + const struct b2056_inittab_entry *syn; + unsigned int syn_length; + const struct b2056_inittab_entry *tx; + unsigned int tx_length; + const struct b2056_inittab_entry *rx; + unsigned int rx_length; +}; + +static const struct b2056_inittab_entry b2056_inittab_rev3_syn[] = { + [B2056_SYN_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_PU] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_GPIO_MASTER1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_GPIO_MASTER2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TOPBIAS_MASTER] = { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, }, + [B2056_SYN_TOPBIAS_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_AFEREG] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSEIDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSERCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LPO] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_VDDCAL_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_VDDCAL_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_VDDCAL_STATUS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCAL_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCAL_CODE_OUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL0] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL1] = { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL2] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL3] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_ZCAL_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_ZCAL_SPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_MAST1] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_SYN_PLL_MAST2] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_PLL_MAST3] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, + [B2056_SYN_PLL_BIAS_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL1] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL3] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL5] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL6] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_SYN_PLL_REFDIV] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_PLL_PFD] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_CP1] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_PLL_CP2] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, }, + [B2056_SYN_PLL_CP3] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER1] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER2] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER3] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER4] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER5] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_PLL_MMD1] = { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, }, + [B2056_SYN_PLL_MMD2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCO1] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCO2] = { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, }, + [B2056_SYN_PLL_MONITOR1] = { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, }, + [B2056_SYN_PLL_MONITOR2] = { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL4] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL5] = { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL6] = { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL7] = { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL8] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL9] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL11] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL12] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, + [B2056_SYN_PLL_VCOCAL13] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_SYN_PLL_VREG] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU2] = { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU8] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_LOGEN_BIAS_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RCCR1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF1] = { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER1] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER2] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF1] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGENBUF2] = { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, }, + [B2056_SYN_LOGEN_BUF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF4] = { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV1] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV2] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV3] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLOUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_CALEN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PEAKDET1] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, }, + [B2056_SYN_LOGEN_CORE_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_DIFF_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_DIFF_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_CMOS_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_CMOS_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER3_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF5_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF6_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL_WAITCNT] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_SYN_LOGEN_CORE_CALVALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_CMOS_CALVALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_CMOS_VALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev3_tx[] = { + [B2056_TX_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_IQCAL_GAIN_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_LOFT_FINE_I] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_FINE_Q] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_COARSE_I] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_COARSE_Q] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_TX_COM_MASTER1] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_TX_COM_MASTER2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RXIQCAL_TXMUX] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_TX_SSI_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_IQCAL_VCM_HG] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_IQCAL_IDAC] = { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, }, + [B2056_TX_TSSI_VCM] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_TX_AMP_DET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TX_SSI_MUX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSIA] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_TSSIG] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_TSSI_MISC1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSI_MISC2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSI_MISC3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PA_SPARE1] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_TX_PA_SPARE2] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_TX_INTPAA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_BOOST_TUNE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAA_IAUX_STAT] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_TX_INTPAA_IAUX_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_IMAIN_STAT] = { .ghz5 = 0x002d, .ghz2 = 0x002d, NOUPLOAD, }, + [B2056_TX_INTPAA_IMAIN_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_CASCBIAS] = { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, }, + [B2056_TX_INTPAA_PASLOPE] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_TX_INTPAA_PA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_BOOST_TUNE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAG_IAUX_STAT] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAG_IAUX_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_IMAIN_STAT] = { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, }, + [B2056_TX_INTPAG_IMAIN_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_CASCBIAS] = { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, }, + [B2056_TX_INTPAG_PASLOPE] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_TX_INTPAG_PA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADA_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PADA_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_TX_PADA_CASCBIAS] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_PADA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADA_BOOST_TUNE] = { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, }, + [B2056_TX_PADA_SLOPE] = { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, }, + [B2056_TX_PADG_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PADG_IDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_PADG_CASCBIAS] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_PADG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADG_BOOST_TUNE] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_TX_PADG_SLOPE] = { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, }, + [B2056_TX_PGAA_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PGAA_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_TX_PGAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAA_BOOST_TUNE] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, }, + [B2056_TX_PGAA_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, }, + [B2056_TX_PGAA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAG_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PGAG_IDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_PGAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAG_BOOST_TUNE] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_TX_PGAG_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, }, + [B2056_TX_PGAG_MISC] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_MIXA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_MIXA_BOOST_TUNE] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_TX_MIXG] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_MIXG_BOOST_TUNE] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_TX_BB_GM_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_GM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC] = { .ghz5 = 0x0074, .ghz2 = 0x0074, UPLOAD, }, + [B2056_TX_TXLPF_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_BW] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_TXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_0] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_1] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_2] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_4] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_5] = { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_6] = { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, }, + [B2056_TX_TXLPF_OPAMP_IDAC] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_TX_TXLPF_MISC] = { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, }, + [B2056_TX_TXSPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_INTPA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_PAD_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_PGA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_GM_TXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_TXLPF_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_TXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev3_rx[] = { + [B2056_RX_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXIQCAL_RXMUX] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_RX_RSSI_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RSSI_SEL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RSSI_GAIN] = { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, }, + [B2056_RX_RSSI_NB_IDAC] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_RX_RSSI_WB2I_IDAC_1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_RX_RSSI_WB2I_IDAC_2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, }, + [B2056_RX_RSSI_WB2Q_IDAC_1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_RX_RSSI_WB2Q_IDAC_2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, }, + [B2056_RX_RSSI_POLE] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_RSSI_WB1_IDAC] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_RX_RSSI_MISC] = { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, }, + [B2056_RX_LNAA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_LNAA_TUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_RX_LNAA_GAIN] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_RX_LNA_A_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_RX_BIASPOLE_LNAA1_IDAC] = { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, }, + [B2056_RX_LNAA2_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_RX_LNA1A_MISC] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_LNAG_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_LNAG_TUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_RX_LNAG_GAIN] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_RX_LNA_G_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_RX_BIASPOLE_LNAG1_IDAC] = { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, }, + [B2056_RX_LNAG2_IDAC] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_RX_LNA1G_MISC] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_MIXA_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_MIXA_VCM] = { .ghz5 = 0x0099, .ghz2 = 0x0099, NOUPLOAD, }, + [B2056_RX_MIXA_CTRLPTAT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXA_LOB_BIAS] = { .ghz5 = 0x0044, .ghz2 = 0x0044, UPLOAD, }, + [B2056_RX_MIXA_CORE_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXA_CMFB_IDAC] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_MIXA_BIAS_AUX] = { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, }, + [B2056_RX_MIXA_BIAS_MAIN] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_RX_MIXA_BIAS_MISC] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_RX_MIXA_MAST_BIAS] = { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, }, + [B2056_RX_MIXG_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_MIXG_VCM] = { .ghz5 = 0x0099, .ghz2 = 0x0099, NOUPLOAD, }, + [B2056_RX_MIXG_CTRLPTAT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_LOB_BIAS] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_RX_MIXG_CORE_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_CMFB_IDAC] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_AUX] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_MAIN] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_MISC] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_RX_MIXG_MAST_BIAS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_IOPAMP] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_RX_TIA_QOPAMP] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_RX_TIA_IMISC] = { .ghz5 = 0x0057, .ghz2 = 0x0057, NOUPLOAD, }, + [B2056_RX_TIA_QMISC] = { .ghz5 = 0x0057, .ghz2 = 0x0057, NOUPLOAD, }, + [B2056_RX_TIA_GAIN] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_TIA_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_SPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_BB_LPF_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_AACI_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_RXLPF_IDAC] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_RXLPF_OPAMPBIAS_LOWQ] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_RXLPF_BIAS_DCCANCEL] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_RX_RXLPF_OUTVCM] = { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, }, + [B2056_RX_RXLPF_INVCM_BODY] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_RXLPF_CC_OP] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_RX_RXLPF_GAIN] = { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, }, + [B2056_RX_RXLPF_Q_BW] = { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, }, + [B2056_RX_RXLPF_HP_CORNER_BW] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_RX_RXLPF_RCCAL_HPC] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_RCCAL_LPC] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_UNUSED] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_VGA_MASTER] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGA_BIAS] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGA_BIAS_DCCANCEL] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_RX_VGA_GAIN] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_RX_VGA_HP_CORNER_BW] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_RX_VGABUF_BIAS] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGABUF_GAIN_BW] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, }, + [B2056_RX_TXFBMIX_A] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TXFBMIX_G] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_LNAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_LNAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_MIXTIA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_VGA_BUF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_Q] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_BUF_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_VGA_HPC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_HPC_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev4_syn[] = { + [B2056_SYN_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_PU] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_GPIO_MASTER1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_GPIO_MASTER2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TOPBIAS_MASTER] = { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, }, + [B2056_SYN_TOPBIAS_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_AFEREG] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSEIDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSERCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LPO] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_VDDCAL_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_VDDCAL_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_VDDCAL_STATUS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCAL_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCAL_CODE_OUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL0] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL1] = { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL2] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL3] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_ZCAL_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_ZCAL_SPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_MAST1] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_SYN_PLL_MAST2] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_PLL_MAST3] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, + [B2056_SYN_PLL_BIAS_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL1] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL3] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL5] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL6] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_SYN_PLL_REFDIV] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_PLL_PFD] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_CP1] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_PLL_CP2] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, }, + [B2056_SYN_PLL_CP3] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER1] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER2] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER3] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER4] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER5] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_PLL_MMD1] = { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, }, + [B2056_SYN_PLL_MMD2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCO1] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCO2] = { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, }, + [B2056_SYN_PLL_MONITOR1] = { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, }, + [B2056_SYN_PLL_MONITOR2] = { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL4] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL5] = { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL6] = { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL7] = { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL8] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL9] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL11] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL12] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, + [B2056_SYN_PLL_VCOCAL13] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_SYN_PLL_VREG] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU2] = { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU8] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_LOGEN_BIAS_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RCCR1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF1] = { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER1] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER2] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF1] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGENBUF2] = { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, }, + [B2056_SYN_LOGEN_BUF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF4] = { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV1] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV2] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV3] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLOUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_CALEN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PEAKDET1] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, }, + [B2056_SYN_LOGEN_CORE_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_DIFF_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_DIFF_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_CMOS_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_CMOS_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER3_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF5_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF6_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL_WAITCNT] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_SYN_LOGEN_CORE_CALVALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_CMOS_CALVALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_CMOS_VALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev4_tx[] = { + [B2056_TX_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_IQCAL_GAIN_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_LOFT_FINE_I] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_FINE_Q] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_COARSE_I] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_COARSE_Q] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_TX_COM_MASTER1] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_TX_COM_MASTER2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RXIQCAL_TXMUX] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_TX_SSI_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_IQCAL_VCM_HG] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_IQCAL_IDAC] = { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, }, + [B2056_TX_TSSI_VCM] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_TX_AMP_DET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TX_SSI_MUX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSIA] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_TSSIG] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_TSSI_MISC1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSI_MISC2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSI_MISC3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PA_SPARE1] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_TX_PA_SPARE2] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_TX_INTPAA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_BOOST_TUNE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAA_IAUX_STAT] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_TX_INTPAA_IAUX_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_IMAIN_STAT] = { .ghz5 = 0x002d, .ghz2 = 0x002d, NOUPLOAD, }, + [B2056_TX_INTPAA_IMAIN_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_CASCBIAS] = { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, }, + [B2056_TX_INTPAA_PASLOPE] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_TX_INTPAA_PA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_BOOST_TUNE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAG_IAUX_STAT] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAG_IAUX_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_IMAIN_STAT] = { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, }, + [B2056_TX_INTPAG_IMAIN_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_CASCBIAS] = { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, }, + [B2056_TX_INTPAG_PASLOPE] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_TX_INTPAG_PA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADA_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PADA_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_TX_PADA_CASCBIAS] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_PADA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADA_BOOST_TUNE] = { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, }, + [B2056_TX_PADA_SLOPE] = { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, }, + [B2056_TX_PADG_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PADG_IDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_PADG_CASCBIAS] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_PADG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADG_BOOST_TUNE] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_TX_PADG_SLOPE] = { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, }, + [B2056_TX_PGAA_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PGAA_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_TX_PGAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAA_BOOST_TUNE] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, }, + [B2056_TX_PGAA_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, }, + [B2056_TX_PGAA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAG_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PGAG_IDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_PGAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAG_BOOST_TUNE] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_TX_PGAG_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, }, + [B2056_TX_PGAG_MISC] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_MIXA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_MIXA_BOOST_TUNE] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_TX_MIXG] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_MIXG_BOOST_TUNE] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_TX_BB_GM_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_GM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC] = { .ghz5 = 0x0072, .ghz2 = 0x0072, UPLOAD, }, + [B2056_TX_TXLPF_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_BW] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_TXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_0] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_1] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_2] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_4] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_5] = { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_6] = { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, }, + [B2056_TX_TXLPF_OPAMP_IDAC] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_TX_TXLPF_MISC] = { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, }, + [B2056_TX_TXSPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_INTPA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_PAD_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_PGA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_GM_TXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_TXLPF_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_TXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev4_rx[] = { + [B2056_RX_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXIQCAL_RXMUX] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_RX_RSSI_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RSSI_SEL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RSSI_GAIN] = { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, }, + [B2056_RX_RSSI_NB_IDAC] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_RX_RSSI_WB2I_IDAC_1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_RX_RSSI_WB2I_IDAC_2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, }, + [B2056_RX_RSSI_WB2Q_IDAC_1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_RX_RSSI_WB2Q_IDAC_2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, }, + [B2056_RX_RSSI_POLE] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_RSSI_WB1_IDAC] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_RX_RSSI_MISC] = { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, }, + [B2056_RX_LNAA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_LNAA_TUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_RX_LNAA_GAIN] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_RX_LNA_A_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_RX_BIASPOLE_LNAA1_IDAC] = { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, }, + [B2056_RX_LNAA2_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_RX_LNA1A_MISC] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_LNAG_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_LNAG_TUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_RX_LNAG_GAIN] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_RX_LNA_G_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_RX_BIASPOLE_LNAG1_IDAC] = { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, }, + [B2056_RX_LNAG2_IDAC] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_RX_LNA1G_MISC] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_MIXA_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_MIXA_VCM] = { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, }, + [B2056_RX_MIXA_CTRLPTAT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXA_LOB_BIAS] = { .ghz5 = 0x0044, .ghz2 = 0x0044, UPLOAD, }, + [B2056_RX_MIXA_CORE_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXA_CMFB_IDAC] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_MIXA_BIAS_AUX] = { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, }, + [B2056_RX_MIXA_BIAS_MAIN] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_RX_MIXA_BIAS_MISC] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_RX_MIXA_MAST_BIAS] = { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, }, + [B2056_RX_MIXG_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_MIXG_VCM] = { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, }, + [B2056_RX_MIXG_CTRLPTAT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_LOB_BIAS] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_RX_MIXG_CORE_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_CMFB_IDAC] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_AUX] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_MAIN] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_MISC] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_RX_MIXG_MAST_BIAS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_IOPAMP] = { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, }, + [B2056_RX_TIA_QOPAMP] = { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, }, + [B2056_RX_TIA_IMISC] = { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, }, + [B2056_RX_TIA_QMISC] = { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, }, + [B2056_RX_TIA_GAIN] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_TIA_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_SPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_BB_LPF_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_AACI_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_RXLPF_IDAC] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_RXLPF_OPAMPBIAS_LOWQ] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_RXLPF_BIAS_DCCANCEL] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_RX_RXLPF_OUTVCM] = { .ghz5 = 0x002f, .ghz2 = 0x002f, UPLOAD, }, + [B2056_RX_RXLPF_INVCM_BODY] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_RXLPF_CC_OP] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_RX_RXLPF_GAIN] = { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, }, + [B2056_RX_RXLPF_Q_BW] = { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, }, + [B2056_RX_RXLPF_HP_CORNER_BW] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_RX_RXLPF_RCCAL_HPC] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_RCCAL_LPC] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_UNUSED] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_VGA_MASTER] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGA_BIAS] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGA_BIAS_DCCANCEL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, }, + [B2056_RX_VGA_GAIN] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_RX_VGA_HP_CORNER_BW] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_RX_VGABUF_BIAS] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGABUF_GAIN_BW] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, }, + [B2056_RX_TXFBMIX_A] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TXFBMIX_G] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_LNAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_LNAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_MIXTIA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_VGA_BUF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_Q] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_BUF_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_VGA_HPC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_HPC_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev5_syn[] = { + [B2056_SYN_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_PU] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_GPIO_MASTER1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_GPIO_MASTER2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TOPBIAS_MASTER] = { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, }, + [B2056_SYN_TOPBIAS_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_AFEREG] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSEIDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSERCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LPO] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_VDDCAL_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_VDDCAL_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_VDDCAL_STATUS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCAL_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCAL_CODE_OUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL1] = { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL2] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL3] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_ZCAL_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_ZCAL_SPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_MAST1] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_SYN_PLL_MAST2] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_PLL_MAST3] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, + [B2056_SYN_PLL_BIAS_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL1] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL3] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL5] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL6] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_SYN_PLL_REFDIV] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_PLL_PFD] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_CP1] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_PLL_CP2] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, }, + [B2056_SYN_PLL_CP3] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER1] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER2] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER3] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER4] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER5] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_PLL_MMD1] = { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, }, + [B2056_SYN_PLL_MMD2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCO1] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCO2] = { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, }, + [B2056_SYN_PLL_MONITOR1] = { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, }, + [B2056_SYN_PLL_MONITOR2] = { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL4] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL5] = { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL6] = { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL7] = { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL8] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL9] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL11] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL12] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, + [B2056_SYN_PLL_VCOCAL13] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_SYN_PLL_VREG] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU2] = { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU8] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_LOGEN_BIAS_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RCCR1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF1] = { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER1] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER2] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF1] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGENBUF2] = { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, }, + [B2056_SYN_LOGEN_BUF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF4] = { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV1] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV2] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV3] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLOUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_CALEN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PEAKDET1] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, }, + [B2056_SYN_LOGEN_CORE_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_DIFF_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_DIFF_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_CMOS_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_CMOS_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER3_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF5_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF6_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL_WAITCNT] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_SYN_LOGEN_CORE_CALVALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_CMOS_CALVALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_CMOS_VALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev5_tx[] = { + [B2056_TX_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_IQCAL_GAIN_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_LOFT_FINE_I] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_FINE_Q] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_COARSE_I] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_COARSE_Q] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_TX_COM_MASTER1] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_TX_COM_MASTER2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RXIQCAL_TXMUX] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_TX_SSI_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_IQCAL_VCM_HG] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_IQCAL_IDAC] = { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, }, + [B2056_TX_TSSI_VCM] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_TX_AMP_DET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TX_SSI_MUX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSIA] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_TSSIG] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_TSSI_MISC1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSI_MISC2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSI_MISC3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PA_SPARE1] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_TX_PA_SPARE2] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_TX_INTPAA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_BOOST_TUNE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAA_IAUX_STAT] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_TX_INTPAA_IAUX_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_IMAIN_STAT] = { .ghz5 = 0x002d, .ghz2 = 0x002d, NOUPLOAD, }, + [B2056_TX_INTPAA_IMAIN_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_CASCBIAS] = { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, }, + [B2056_TX_INTPAA_PASLOPE] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_TX_INTPAA_PA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_BOOST_TUNE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAG_IAUX_STAT] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAG_IAUX_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_IMAIN_STAT] = { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, }, + [B2056_TX_INTPAG_IMAIN_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_CASCBIAS] = { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, }, + [B2056_TX_INTPAG_PASLOPE] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_TX_INTPAG_PA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADA_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PADA_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_TX_PADA_CASCBIAS] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_PADA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADA_BOOST_TUNE] = { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, }, + [B2056_TX_PADA_SLOPE] = { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, }, + [B2056_TX_PADG_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PADG_IDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_PADG_CASCBIAS] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_PADG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADG_BOOST_TUNE] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_TX_PADG_SLOPE] = { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, }, + [B2056_TX_PGAA_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PGAA_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_TX_PGAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAA_BOOST_TUNE] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, }, + [B2056_TX_PGAA_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, }, + [B2056_TX_PGAA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAG_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PGAG_IDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_PGAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAG_BOOST_TUNE] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_TX_PGAG_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, }, + [B2056_TX_PGAG_MISC] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_MIXA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_MIXA_BOOST_TUNE] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_TX_MIXG] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_MIXG_BOOST_TUNE] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_TX_BB_GM_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_GM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, }, + [B2056_TX_TXLPF_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_BW] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_TXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_0] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_1] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_2] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_4] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_5] = { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_6] = { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, }, + [B2056_TX_TXLPF_OPAMP_IDAC] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_TX_TXLPF_MISC] = { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, }, + [B2056_TX_TXSPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_INTPA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_PAD_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_PGA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_GM_TXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_TXLPF_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_TXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC0] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC1] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC2] = { .ghz5 = 0x0071, .ghz2 = 0x0071, UPLOAD, }, + [B2056_TX_GMBB_IDAC3] = { .ghz5 = 0x0071, .ghz2 = 0x0071, UPLOAD, }, + [B2056_TX_GMBB_IDAC4] = { .ghz5 = 0x0072, .ghz2 = 0x0072, UPLOAD, }, + [B2056_TX_GMBB_IDAC5] = { .ghz5 = 0x0073, .ghz2 = 0x0073, UPLOAD, }, + [B2056_TX_GMBB_IDAC6] = { .ghz5 = 0x0074, .ghz2 = 0x0074, UPLOAD, }, + [B2056_TX_GMBB_IDAC7] = { .ghz5 = 0x0075, .ghz2 = 0x0075, UPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev5_rx[] = { + [B2056_RX_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXIQCAL_RXMUX] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_RX_RSSI_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RSSI_SEL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RSSI_GAIN] = { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, }, + [B2056_RX_RSSI_NB_IDAC] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_RX_RSSI_WB2I_IDAC_1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_RX_RSSI_WB2I_IDAC_2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, }, + [B2056_RX_RSSI_WB2Q_IDAC_1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_RX_RSSI_WB2Q_IDAC_2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, }, + [B2056_RX_RSSI_POLE] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_RSSI_WB1_IDAC] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_RX_RSSI_MISC] = { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, }, + [B2056_RX_LNAA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_LNAA_TUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_RX_LNAA_GAIN] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_RX_LNA_A_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_RX_BIASPOLE_LNAA1_IDAC] = { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, }, + [B2056_RX_LNAA2_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_RX_LNA1A_MISC] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_LNAG_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_LNAG_TUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_RX_LNAG_GAIN] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_RX_LNA_G_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_RX_BIASPOLE_LNAG1_IDAC] = { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, }, + [B2056_RX_LNAG2_IDAC] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_RX_LNA1G_MISC] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_MIXA_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_MIXA_VCM] = { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, }, + [B2056_RX_MIXA_CTRLPTAT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXA_LOB_BIAS] = { .ghz5 = 0x0088, .ghz2 = 0x0088, UPLOAD, }, + [B2056_RX_MIXA_CORE_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXA_CMFB_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, }, + [B2056_RX_MIXA_BIAS_AUX] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, + [B2056_RX_MIXA_BIAS_MAIN] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_RX_MIXA_BIAS_MISC] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_RX_MIXA_MAST_BIAS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_MIXG_VCM] = { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, }, + [B2056_RX_MIXG_CTRLPTAT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_LOB_BIAS] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_RX_MIXG_CORE_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_CMFB_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, }, + [B2056_RX_MIXG_BIAS_AUX] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_MAIN] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_MISC] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_RX_MIXG_MAST_BIAS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_IOPAMP] = { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, }, + [B2056_RX_TIA_QOPAMP] = { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, }, + [B2056_RX_TIA_IMISC] = { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, }, + [B2056_RX_TIA_QMISC] = { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, }, + [B2056_RX_TIA_GAIN] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_TIA_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_SPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_BB_LPF_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_AACI_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_RXLPF_IDAC] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_RXLPF_OPAMPBIAS_LOWQ] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_RXLPF_BIAS_DCCANCEL] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_RX_RXLPF_OUTVCM] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, }, + [B2056_RX_RXLPF_INVCM_BODY] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_RXLPF_CC_OP] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_RX_RXLPF_GAIN] = { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, }, + [B2056_RX_RXLPF_Q_BW] = { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, }, + [B2056_RX_RXLPF_HP_CORNER_BW] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_RX_RXLPF_RCCAL_HPC] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_RCCAL_LPC] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_UNUSED] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_VGA_MASTER] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGA_BIAS] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGA_BIAS_DCCANCEL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, }, + [B2056_RX_VGA_GAIN] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_RX_VGA_HP_CORNER_BW] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_RX_VGABUF_BIAS] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGABUF_GAIN_BW] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, }, + [B2056_RX_TXFBMIX_A] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TXFBMIX_G] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_LNAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_LNAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_MIXTIA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_VGA_BUF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_Q] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_BUF_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_VGA_HPC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_HPC_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev6_syn[] = { + [B2056_SYN_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_PU] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_GPIO_MASTER1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_GPIO_MASTER2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TOPBIAS_MASTER] = { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, }, + [B2056_SYN_TOPBIAS_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_AFEREG] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSEIDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSERCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LPO] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_VDDCAL_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_VDDCAL_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_VDDCAL_STATUS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCAL_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCAL_CODE_OUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL1] = { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL2] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL3] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_ZCAL_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_ZCAL_SPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_MAST1] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_SYN_PLL_MAST2] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_PLL_MAST3] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, + [B2056_SYN_PLL_BIAS_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL1] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL3] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL5] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL6] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_SYN_PLL_REFDIV] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_PLL_PFD] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_CP1] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_PLL_CP2] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, }, + [B2056_SYN_PLL_CP3] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER1] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER2] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER3] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER4] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER5] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_PLL_MMD1] = { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, }, + [B2056_SYN_PLL_MMD2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCO1] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCO2] = { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, }, + [B2056_SYN_PLL_MONITOR1] = { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, }, + [B2056_SYN_PLL_MONITOR2] = { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL4] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL5] = { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL6] = { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL7] = { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL8] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL9] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL11] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL12] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, + [B2056_SYN_PLL_VCOCAL13] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_SYN_PLL_VREG] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU2] = { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU8] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_LOGEN_BIAS_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RCCR1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF1] = { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER1] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER2] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF1] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGENBUF2] = { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, }, + [B2056_SYN_LOGEN_BUF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF4] = { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV1] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV2] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV3] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLOUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_CALEN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PEAKDET1] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, }, + [B2056_SYN_LOGEN_CORE_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_DIFF_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_DIFF_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_CMOS_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_CMOS_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER3_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF5_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF6_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL_WAITCNT] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_SYN_LOGEN_CORE_CALVALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_CMOS_CALVALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_CMOS_VALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev6_tx[] = { + [B2056_TX_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_IQCAL_GAIN_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_LOFT_FINE_I] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_FINE_Q] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_COARSE_I] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_COARSE_Q] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_TX_COM_MASTER1] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_TX_COM_MASTER2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RXIQCAL_TXMUX] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_TX_SSI_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_IQCAL_VCM_HG] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_IQCAL_IDAC] = { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, }, + [B2056_TX_TSSI_VCM] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_TX_AMP_DET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TX_SSI_MUX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSIA] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_TSSIG] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_TSSI_MISC1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSI_MISC2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSI_MISC3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PA_SPARE1] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_TX_PA_SPARE2] = { .ghz5 = 0x00ee, .ghz2 = 0x00ee, UPLOAD, }, + [B2056_TX_INTPAA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_BOOST_TUNE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAA_IAUX_STAT] = { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, }, + [B2056_TX_INTPAA_IAUX_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_IMAIN_STAT] = { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, }, + [B2056_TX_INTPAA_IMAIN_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_CASCBIAS] = { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, }, + [B2056_TX_INTPAA_PASLOPE] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_TX_INTPAA_PA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_BOOST_TUNE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAG_IAUX_STAT] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAG_IAUX_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_IMAIN_STAT] = { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, }, + [B2056_TX_INTPAG_IMAIN_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_CASCBIAS] = { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, }, + [B2056_TX_INTPAG_PASLOPE] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_TX_INTPAG_PA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADA_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PADA_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_TX_PADA_CASCBIAS] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_PADA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADA_BOOST_TUNE] = { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, }, + [B2056_TX_PADA_SLOPE] = { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, }, + [B2056_TX_PADG_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PADG_IDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_PADG_CASCBIAS] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_PADG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADG_BOOST_TUNE] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_TX_PADG_SLOPE] = { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, }, + [B2056_TX_PGAA_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PGAA_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_TX_PGAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAA_BOOST_TUNE] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, }, + [B2056_TX_PGAA_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, }, + [B2056_TX_PGAA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAG_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PGAG_IDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_PGAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAG_BOOST_TUNE] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_TX_PGAG_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, }, + [B2056_TX_PGAG_MISC] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_MIXA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_MIXA_BOOST_TUNE] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_TX_MIXG] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_MIXG_BOOST_TUNE] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_TX_BB_GM_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_GM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, }, + [B2056_TX_TXLPF_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_BW] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_TXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_0] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_1] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_2] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_4] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_5] = { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_6] = { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, }, + [B2056_TX_TXLPF_OPAMP_IDAC] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_TX_TXLPF_MISC] = { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, }, + [B2056_TX_TXSPARE1] = { .ghz5 = 0x0030, .ghz2 = 0x0030, UPLOAD, }, + [B2056_TX_TXSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_INTPA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_PAD_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_PGA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_GM_TXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_TXLPF_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_TXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC0] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC1] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC2] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC3] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC4] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC5] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC6] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC7] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev6_rx[] = { + [B2056_RX_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXIQCAL_RXMUX] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_RX_RSSI_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RSSI_SEL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RSSI_GAIN] = { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, }, + [B2056_RX_RSSI_NB_IDAC] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_RX_RSSI_WB2I_IDAC_1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_RX_RSSI_WB2I_IDAC_2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, }, + [B2056_RX_RSSI_WB2Q_IDAC_1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_RX_RSSI_WB2Q_IDAC_2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, }, + [B2056_RX_RSSI_POLE] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_RSSI_WB1_IDAC] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_RX_RSSI_MISC] = { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, }, + [B2056_RX_LNAA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_LNAA_TUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_RX_LNAA_GAIN] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_RX_LNA_A_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_RX_BIASPOLE_LNAA1_IDAC] = { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, }, + [B2056_RX_LNAA2_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_RX_LNA1A_MISC] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_LNAG_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_LNAG_TUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_RX_LNAG_GAIN] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_RX_LNA_G_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_RX_BIASPOLE_LNAG1_IDAC] = { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, }, + [B2056_RX_LNAG2_IDAC] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_RX_LNA1G_MISC] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_MIXA_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_MIXA_VCM] = { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, }, + [B2056_RX_MIXA_CTRLPTAT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXA_LOB_BIAS] = { .ghz5 = 0x0088, .ghz2 = 0x0088, UPLOAD, }, + [B2056_RX_MIXA_CORE_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXA_CMFB_IDAC] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_MIXA_BIAS_AUX] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, + [B2056_RX_MIXA_BIAS_MAIN] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_RX_MIXA_BIAS_MISC] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_RX_MIXA_MAST_BIAS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_MIXG_VCM] = { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, }, + [B2056_RX_MIXG_CTRLPTAT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_LOB_BIAS] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_RX_MIXG_CORE_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_CMFB_IDAC] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_AUX] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_MAIN] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_MISC] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_RX_MIXG_MAST_BIAS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_IOPAMP] = { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, }, + [B2056_RX_TIA_QOPAMP] = { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, }, + [B2056_RX_TIA_IMISC] = { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, }, + [B2056_RX_TIA_QMISC] = { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, }, + [B2056_RX_TIA_GAIN] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_TIA_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_SPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_BB_LPF_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_AACI_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_RXLPF_IDAC] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_RXLPF_OPAMPBIAS_LOWQ] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_RXLPF_BIAS_DCCANCEL] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_RX_RXLPF_OUTVCM] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, }, + [B2056_RX_RXLPF_INVCM_BODY] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_RXLPF_CC_OP] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_RX_RXLPF_GAIN] = { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, }, + [B2056_RX_RXLPF_Q_BW] = { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, }, + [B2056_RX_RXLPF_HP_CORNER_BW] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_RX_RXLPF_RCCAL_HPC] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_RCCAL_LPC] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_UNUSED] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_VGA_MASTER] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGA_BIAS] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGA_BIAS_DCCANCEL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, }, + [B2056_RX_VGA_GAIN] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_RX_VGA_HP_CORNER_BW] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_RX_VGABUF_BIAS] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGABUF_GAIN_BW] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, }, + [B2056_RX_TXFBMIX_A] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TXFBMIX_G] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE3] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, }, + [B2056_RX_RXSPARE4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_LNAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_LNAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_MIXTIA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_VGA_BUF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_Q] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_BUF_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_VGA_HPC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_HPC_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev7_syn[] = { + [B2056_SYN_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_PU] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_GPIO_MASTER1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_GPIO_MASTER2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TOPBIAS_MASTER] = { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, }, + [B2056_SYN_TOPBIAS_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_AFEREG] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSEIDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSERCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LPO] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_VDDCAL_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_VDDCAL_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_VDDCAL_STATUS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCAL_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCAL_CODE_OUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL1] = { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL2] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL3] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_ZCAL_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_ZCAL_SPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_MAST1] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_SYN_PLL_MAST2] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_PLL_MAST3] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, + [B2056_SYN_PLL_BIAS_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL1] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL3] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL5] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL6] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_SYN_PLL_REFDIV] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_PLL_PFD] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_CP1] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_PLL_CP2] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, }, + [B2056_SYN_PLL_CP3] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER1] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER2] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER3] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER4] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER5] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_PLL_MMD1] = { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, }, + [B2056_SYN_PLL_MMD2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCO1] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCO2] = { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, }, + [B2056_SYN_PLL_MONITOR1] = { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, }, + [B2056_SYN_PLL_MONITOR2] = { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL4] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL5] = { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL6] = { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL7] = { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL8] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL9] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL11] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL12] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, + [B2056_SYN_PLL_VCOCAL13] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_SYN_PLL_VREG] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU2] = { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU8] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_LOGEN_BIAS_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RCCR1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF1] = { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER1] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER2] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF1] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGENBUF2] = { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, }, + [B2056_SYN_LOGEN_BUF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF4] = { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV1] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV2] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV3] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLOUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_CALEN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PEAKDET1] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, }, + [B2056_SYN_LOGEN_CORE_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_DIFF_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_DIFF_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_CMOS_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_CMOS_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER3_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF5_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF6_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL_WAITCNT] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_SYN_LOGEN_CORE_CALVALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_CMOS_CALVALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_CMOS_VALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev7_tx[] = { + [B2056_TX_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_IQCAL_GAIN_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_LOFT_FINE_I] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_FINE_Q] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_COARSE_I] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_COARSE_Q] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_TX_COM_MASTER1] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_TX_COM_MASTER2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RXIQCAL_TXMUX] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_TX_SSI_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_IQCAL_VCM_HG] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_IQCAL_IDAC] = { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, }, + [B2056_TX_TSSI_VCM] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_TX_AMP_DET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TX_SSI_MUX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSIA] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_TSSIG] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_TSSI_MISC1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSI_MISC2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSI_MISC3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PA_SPARE1] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_TX_PA_SPARE2] = { .ghz5 = 0x00ee, .ghz2 = 0x00ee, UPLOAD, }, + [B2056_TX_INTPAA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_BOOST_TUNE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAA_IAUX_STAT] = { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, }, + [B2056_TX_INTPAA_IAUX_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_IMAIN_STAT] = { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, }, + [B2056_TX_INTPAA_IMAIN_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_CASCBIAS] = { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, }, + [B2056_TX_INTPAA_PASLOPE] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_TX_INTPAA_PA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_BOOST_TUNE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAG_IAUX_STAT] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAG_IAUX_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_IMAIN_STAT] = { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, }, + [B2056_TX_INTPAG_IMAIN_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_CASCBIAS] = { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, }, + [B2056_TX_INTPAG_PASLOPE] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_TX_INTPAG_PA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADA_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PADA_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_TX_PADA_CASCBIAS] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_PADA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADA_BOOST_TUNE] = { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, }, + [B2056_TX_PADA_SLOPE] = { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, }, + [B2056_TX_PADG_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PADG_IDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_PADG_CASCBIAS] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_PADG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADG_BOOST_TUNE] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_TX_PADG_SLOPE] = { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, }, + [B2056_TX_PGAA_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PGAA_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_TX_PGAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAA_BOOST_TUNE] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, }, + [B2056_TX_PGAA_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, }, + [B2056_TX_PGAA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAG_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PGAG_IDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_PGAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAG_BOOST_TUNE] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_TX_PGAG_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, }, + [B2056_TX_PGAG_MISC] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_MIXA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_MIXA_BOOST_TUNE] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_TX_MIXG] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_MIXG_BOOST_TUNE] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_TX_BB_GM_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_GM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, }, + [B2056_TX_TXLPF_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_BW] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_TXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_0] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_1] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_2] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_4] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_5] = { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_6] = { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, }, + [B2056_TX_TXLPF_OPAMP_IDAC] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_TX_TXLPF_MISC] = { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, }, + [B2056_TX_TXSPARE1] = { .ghz5 = 0x0030, .ghz2 = 0x0030, UPLOAD, }, + [B2056_TX_TXSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_INTPA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_PAD_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_PGA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_GM_TXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_TXLPF_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_TXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC0] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC1] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC2] = { .ghz5 = 0x0071, .ghz2 = 0x0071, UPLOAD, }, + [B2056_TX_GMBB_IDAC3] = { .ghz5 = 0x0071, .ghz2 = 0x0071, UPLOAD, }, + [B2056_TX_GMBB_IDAC4] = { .ghz5 = 0x0072, .ghz2 = 0x0072, UPLOAD, }, + [B2056_TX_GMBB_IDAC5] = { .ghz5 = 0x0073, .ghz2 = 0x0073, UPLOAD, }, + [B2056_TX_GMBB_IDAC6] = { .ghz5 = 0x0074, .ghz2 = 0x0074, UPLOAD, }, + [B2056_TX_GMBB_IDAC7] = { .ghz5 = 0x0075, .ghz2 = 0x0075, UPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev7_rx[] = { + [B2056_RX_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXIQCAL_RXMUX] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_RX_RSSI_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RSSI_SEL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RSSI_GAIN] = { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, }, + [B2056_RX_RSSI_NB_IDAC] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_RX_RSSI_WB2I_IDAC_1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_RX_RSSI_WB2I_IDAC_2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, }, + [B2056_RX_RSSI_WB2Q_IDAC_1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_RX_RSSI_WB2Q_IDAC_2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, }, + [B2056_RX_RSSI_POLE] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_RSSI_WB1_IDAC] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_RX_RSSI_MISC] = { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, }, + [B2056_RX_LNAA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_LNAA_TUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_RX_LNAA_GAIN] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_RX_LNA_A_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_RX_BIASPOLE_LNAA1_IDAC] = { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, }, + [B2056_RX_LNAA2_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_RX_LNA1A_MISC] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_LNAG_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_LNAG_TUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_RX_LNAG_GAIN] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_RX_LNA_G_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_RX_BIASPOLE_LNAG1_IDAC] = { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, }, + [B2056_RX_LNAG2_IDAC] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_RX_LNA1G_MISC] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_MIXA_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_MIXA_VCM] = { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, }, + [B2056_RX_MIXA_CTRLPTAT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXA_LOB_BIAS] = { .ghz5 = 0x0088, .ghz2 = 0x0088, UPLOAD, }, + [B2056_RX_MIXA_CORE_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXA_CMFB_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, }, + [B2056_RX_MIXA_BIAS_AUX] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, + [B2056_RX_MIXA_BIAS_MAIN] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_RX_MIXA_BIAS_MISC] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_RX_MIXA_MAST_BIAS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_MIXG_VCM] = { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, }, + [B2056_RX_MIXG_CTRLPTAT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_LOB_BIAS] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_RX_MIXG_CORE_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_CMFB_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, }, + [B2056_RX_MIXG_BIAS_AUX] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_MAIN] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_MISC] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_RX_MIXG_MAST_BIAS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_IOPAMP] = { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, }, + [B2056_RX_TIA_QOPAMP] = { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, }, + [B2056_RX_TIA_IMISC] = { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, }, + [B2056_RX_TIA_QMISC] = { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, }, + [B2056_RX_TIA_GAIN] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_TIA_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_SPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_BB_LPF_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_AACI_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_RXLPF_IDAC] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_RXLPF_OPAMPBIAS_LOWQ] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_RXLPF_BIAS_DCCANCEL] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_RX_RXLPF_OUTVCM] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, }, + [B2056_RX_RXLPF_INVCM_BODY] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_RXLPF_CC_OP] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_RX_RXLPF_GAIN] = { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, }, + [B2056_RX_RXLPF_Q_BW] = { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, }, + [B2056_RX_RXLPF_HP_CORNER_BW] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_RX_RXLPF_RCCAL_HPC] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_RCCAL_LPC] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_UNUSED] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_VGA_MASTER] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGA_BIAS] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGA_BIAS_DCCANCEL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, }, + [B2056_RX_VGA_GAIN] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_RX_VGA_HP_CORNER_BW] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_RX_VGABUF_BIAS] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGABUF_GAIN_BW] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, }, + [B2056_RX_TXFBMIX_A] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TXFBMIX_G] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_LNAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_LNAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_MIXTIA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_VGA_BUF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_Q] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_BUF_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_VGA_HPC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_HPC_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev8_syn[] = { + [B2056_SYN_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_PU] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_GPIO_MASTER1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_GPIO_MASTER2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TOPBIAS_MASTER] = { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, }, + [B2056_SYN_TOPBIAS_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_AFEREG] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSEIDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_TEMPPROCSENSERCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LPO] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_VDDCAL_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_VDDCAL_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_VDDCAL_STATUS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCAL_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCAL_CODE_OUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL1] = { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL2] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL3] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_RCCAL_CTRL11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_ZCAL_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_ZCAL_SPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_MAST1] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_SYN_PLL_MAST2] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_PLL_MAST3] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, + [B2056_SYN_PLL_BIAS_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL1] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL3] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL5] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_SYN_PLL_XTAL6] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_SYN_PLL_REFDIV] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_PLL_PFD] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_CP1] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, + [B2056_SYN_PLL_CP2] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, }, + [B2056_SYN_PLL_CP3] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER1] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER2] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER3] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER4] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_PLL_LOOPFILTER5] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_PLL_MMD1] = { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, }, + [B2056_SYN_PLL_MMD2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCO1] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCO2] = { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, }, + [B2056_SYN_PLL_MONITOR1] = { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, }, + [B2056_SYN_PLL_MONITOR2] = { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL4] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL5] = { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL6] = { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL7] = { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL8] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL9] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL11] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_SYN_PLL_VCOCAL12] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, + [B2056_SYN_PLL_VCOCAL13] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_SYN_PLL_VREG] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_PLL_STATUS3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU2] = { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PU8] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_LOGEN_BIAS_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RCCR1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF1] = { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER1] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER2] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF1] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGENBUF2] = { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, }, + [B2056_SYN_LOGEN_BUF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF4] = { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV1] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV2] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_DIV3] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLOUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACLCAL3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_CALEN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_PEAKDET1] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, }, + [B2056_SYN_LOGEN_CORE_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_DIFF_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_DIFF_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_CMOS_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_CMOS_ACL_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_SYN_LOGEN_MIXER3_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF5_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_BUF6_OVRVAL] = { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, }, + [B2056_SYN_LOGEN_ACL_WAITCNT] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_SYN_LOGEN_CORE_CALVALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_RX_CMOS_CALVALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_SYN_LOGEN_TX_CMOS_VALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev8_tx[] = { + [B2056_TX_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_IQCAL_GAIN_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_LOFT_FINE_I] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_FINE_Q] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_COARSE_I] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_LOFT_COARSE_Q] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_TX_COM_MASTER1] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_TX_COM_MASTER2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_RXIQCAL_TXMUX] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_TX_SSI_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_IQCAL_VCM_HG] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_IQCAL_IDAC] = { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, }, + [B2056_TX_TSSI_VCM] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_TX_AMP_DET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TX_SSI_MUX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSIA] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_TSSIG] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_TSSI_MISC1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSI_MISC2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TSSI_MISC3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PA_SPARE1] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_TX_PA_SPARE2] = { .ghz5 = 0x00ee, .ghz2 = 0x00ee, UPLOAD, }, + [B2056_TX_INTPAA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_BOOST_TUNE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAA_IAUX_STAT] = { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, }, + [B2056_TX_INTPAA_IAUX_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_IMAIN_STAT] = { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, }, + [B2056_TX_INTPAA_IMAIN_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAA_CASCBIAS] = { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, }, + [B2056_TX_INTPAA_PASLOPE] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_TX_INTPAA_PA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_BOOST_TUNE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAG_IAUX_STAT] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_TX_INTPAG_IAUX_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_IMAIN_STAT] = { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, }, + [B2056_TX_INTPAG_IMAIN_DYN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_INTPAG_CASCBIAS] = { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, }, + [B2056_TX_INTPAG_PASLOPE] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_TX_INTPAG_PA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADA_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PADA_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_TX_PADA_CASCBIAS] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_PADA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADA_BOOST_TUNE] = { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, }, + [B2056_TX_PADA_SLOPE] = { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, }, + [B2056_TX_PADG_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PADG_IDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_PADG_CASCBIAS] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_TX_PADG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PADG_BOOST_TUNE] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_TX_PADG_SLOPE] = { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, }, + [B2056_TX_PGAA_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PGAA_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_TX_PGAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAA_BOOST_TUNE] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, }, + [B2056_TX_PGAA_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, }, + [B2056_TX_PGAA_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAG_MASTER] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_PGAG_IDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_TX_PGAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_PGAG_BOOST_TUNE] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_TX_PGAG_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, }, + [B2056_TX_PGAG_MISC] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_TX_MIXA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_MIXA_BOOST_TUNE] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_TX_MIXG] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_MIXG_BOOST_TUNE] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_TX_BB_GM_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_GM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, }, + [B2056_TX_TXLPF_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_RCCAL_OFF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_BW] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_TX_TXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_0] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_1] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_2] = { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_4] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_5] = { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, }, + [B2056_TX_TXLPF_IDAC_6] = { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, }, + [B2056_TX_TXLPF_OPAMP_IDAC] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_TX_TXLPF_MISC] = { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, }, + [B2056_TX_TXSPARE1] = { .ghz5 = 0x0030, .ghz2 = 0x0030, UPLOAD, }, + [B2056_TX_TXSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_TXSPARE16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_INTPA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_PAD_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_PGA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_GM_TXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_TXLPF_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_STATUS_TXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC0] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC1] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC2] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC3] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC4] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC5] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC6] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2056_TX_GMBB_IDAC7] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, +}; + +static const struct b2056_inittab_entry b2056_inittab_rev8_rx[] = { + [B2056_RX_RESERVED_ADDR2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_CTRL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_OVR] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RESET] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RCAL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_RXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_TXLPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_COM_RC_RXHPF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR17] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR18] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR19] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR20] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR21] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR22] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR23] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR24] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR25] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR26] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR27] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR28] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR29] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR30] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RESERVED_ADDR31] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXIQCAL_RXMUX] = { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, }, + [B2056_RX_RSSI_PU] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RSSI_SEL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RSSI_GAIN] = { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, }, + [B2056_RX_RSSI_NB_IDAC] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_RX_RSSI_WB2I_IDAC_1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_RX_RSSI_WB2I_IDAC_2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, }, + [B2056_RX_RSSI_WB2Q_IDAC_1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2056_RX_RSSI_WB2Q_IDAC_2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, }, + [B2056_RX_RSSI_POLE] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_RSSI_WB1_IDAC] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_RX_RSSI_MISC] = { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, }, + [B2056_RX_LNAA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_LNAA_TUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_RX_LNAA_GAIN] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_RX_LNA_A_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_RX_BIASPOLE_LNAA1_IDAC] = { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, }, + [B2056_RX_LNAA2_IDAC] = { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, }, + [B2056_RX_LNA1A_MISC] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_LNAG_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_LNAG_TUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2056_RX_LNAG_GAIN] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, + [B2056_RX_LNA_G_SLOPE] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2056_RX_BIASPOLE_LNAG1_IDAC] = { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, }, + [B2056_RX_LNAG2_IDAC] = { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, }, + [B2056_RX_LNA1G_MISC] = { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, }, + [B2056_RX_MIXA_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_MIXA_VCM] = { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, }, + [B2056_RX_MIXA_CTRLPTAT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXA_LOB_BIAS] = { .ghz5 = 0x0088, .ghz2 = 0x0088, UPLOAD, }, + [B2056_RX_MIXA_CORE_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXA_CMFB_IDAC] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_MIXA_BIAS_AUX] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, + [B2056_RX_MIXA_BIAS_MAIN] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_RX_MIXA_BIAS_MISC] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_RX_MIXA_MAST_BIAS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_MIXG_VCM] = { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, }, + [B2056_RX_MIXG_CTRLPTAT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_LOB_BIAS] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2056_RX_MIXG_CORE_IDAC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_MIXG_CMFB_IDAC] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_AUX] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_MAIN] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2056_RX_MIXG_BIAS_MISC] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, + [B2056_RX_MIXG_MAST_BIAS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_MASTER] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_IOPAMP] = { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, }, + [B2056_RX_TIA_QOPAMP] = { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, }, + [B2056_RX_TIA_IMISC] = { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, }, + [B2056_RX_TIA_QMISC] = { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, }, + [B2056_RX_TIA_GAIN] = { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, }, + [B2056_RX_TIA_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TIA_SPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_BB_LPF_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_AACI_MASTER] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2056_RX_RXLPF_IDAC] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_RXLPF_OPAMPBIAS_LOWQ] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_RXLPF_BIAS_DCCANCEL] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2056_RX_RXLPF_OUTVCM] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, }, + [B2056_RX_RXLPF_INVCM_BODY] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2056_RX_RXLPF_CC_OP] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2056_RX_RXLPF_GAIN] = { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, }, + [B2056_RX_RXLPF_Q_BW] = { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, }, + [B2056_RX_RXLPF_HP_CORNER_BW] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_RX_RXLPF_RCCAL_HPC] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXHPF_OFF7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_RCCAL_LPC] = { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXLPF_OFF_4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_UNUSED] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_VGA_MASTER] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGA_BIAS] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGA_BIAS_DCCANCEL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, }, + [B2056_RX_VGA_GAIN] = { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, }, + [B2056_RX_VGA_HP_CORNER_BW] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2056_RX_VGABUF_BIAS] = { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, }, + [B2056_RX_VGABUF_GAIN_BW] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, }, + [B2056_RX_TXFBMIX_A] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_TXFBMIX_G] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE3] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, }, + [B2056_RX_RXSPARE4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE6] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE10] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE11] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_RXSPARE16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_LNAA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_LNAG_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_MIXTIA_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_VGA_BUF_GAIN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_Q] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_BUF_BW] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_VGA_HPC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_RXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2056_RX_STATUS_HPC_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +#define INITTABSPTS(prefix) \ + .syn = prefix##_syn, \ + .syn_length = ARRAY_SIZE(prefix##_syn), \ + .tx = prefix##_tx, \ + .tx_length = ARRAY_SIZE(prefix##_tx), \ + .rx = prefix##_rx, \ + .rx_length = ARRAY_SIZE(prefix##_rx) + +struct b2056_inittabs_pts b2056_inittabs[] = { + [3] = { INITTABSPTS(b2056_inittab_rev3) }, + [4] = { INITTABSPTS(b2056_inittab_rev4) }, + [5] = { INITTABSPTS(b2056_inittab_rev5) }, + [6] = { INITTABSPTS(b2056_inittab_rev6) }, + [7] = { INITTABSPTS(b2056_inittab_rev7) }, + [8] = { INITTABSPTS(b2056_inittab_rev8) }, + [9] = { INITTABSPTS(b2056_inittab_rev7) }, +}; + +#define RADIOREGS3(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \ + r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \ + r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, \ + r30, r31, r32, r33, r34, r35, r36) \ + .radio_syn_pll_vcocal1 = r00, \ + .radio_syn_pll_vcocal2 = r01, \ + .radio_syn_pll_refdiv = r02, \ + .radio_syn_pll_mmd2 = r03, \ + .radio_syn_pll_mmd1 = r04, \ + .radio_syn_pll_loopfilter1 = r05, \ + .radio_syn_pll_loopfilter2 = r06, \ + .radio_syn_pll_loopfilter3 = r07, \ + .radio_syn_pll_loopfilter4 = r08, \ + .radio_syn_pll_loopfilter5 = r09, \ + .radio_syn_reserved_addr27 = r10, \ + .radio_syn_reserved_addr28 = r11, \ + .radio_syn_reserved_addr29 = r12, \ + .radio_syn_logen_vcobuf1 = r13, \ + .radio_syn_logen_mixer2 = r14, \ + .radio_syn_logen_buf3 = r15, \ + .radio_syn_logen_buf4 = r16, \ + .radio_rx0_lnaa_tune = r17, \ + .radio_rx0_lnag_tune = r18, \ + .radio_tx0_intpaa_boost_tune = r19, \ + .radio_tx0_intpag_boost_tune = r20, \ + .radio_tx0_pada_boost_tune = r21, \ + .radio_tx0_padg_boost_tune = r22, \ + .radio_tx0_pgaa_boost_tune = r23, \ + .radio_tx0_pgag_boost_tune = r24, \ + .radio_tx0_mixa_boost_tune = r25, \ + .radio_tx0_mixg_boost_tune = r26, \ + .radio_rx1_lnaa_tune = r27, \ + .radio_rx1_lnag_tune = r28, \ + .radio_tx1_intpaa_boost_tune = r29, \ + .radio_tx1_intpag_boost_tune = r30, \ + .radio_tx1_pada_boost_tune = r31, \ + .radio_tx1_padg_boost_tune = r32, \ + .radio_tx1_pgaa_boost_tune = r33, \ + .radio_tx1_pgag_boost_tune = r34, \ + .radio_tx1_mixa_boost_tune = r35, \ + .radio_tx1_mixg_boost_tune = r36 + +#define PHYREGS(r0, r1, r2, r3, r4, r5) \ + .phy_regs.phy_bw1a = r0, \ + .phy_regs.phy_bw2 = r1, \ + .phy_regs.phy_bw3 = r2, \ + .phy_regs.phy_bw4 = r3, \ + .phy_regs.phy_bw5 = r4, \ + .phy_regs.phy_bw6 = r5 + +/* http://bcm-v4.sipsolutions.net/802.11/Radio/2056/ChannelTable */ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] = { + { .freq = 4920, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216), + }, + { .freq = 4930, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215), + }, + { .freq = 4940, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214), + }, + { .freq = 4950, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213), + }, + { .freq = 4960, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212), + }, + { .freq = 4970, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211), + }, + { .freq = 4980, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f), + }, + { .freq = 4990, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e), + }, + { .freq = 5000, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d), + }, + { .freq = 5010, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c), + }, + { .freq = 5020, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b), + }, + { .freq = 5030, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a), + }, + { .freq = 5040, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209), + }, + { .freq = 5050, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208), + }, + { .freq = 5060, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207), + }, + { .freq = 5070, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206), + }, + { .freq = 5080, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205), + }, + { .freq = 5090, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204), + }, + { .freq = 5100, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203), + }, + { .freq = 5110, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202), + }, + { .freq = 5120, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201), + }, + { .freq = 5130, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200), + }, + { .freq = 5140, + RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff), + }, + { .freq = 5160, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd), + }, + { .freq = 5170, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc), + }, + { .freq = 5180, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), + }, + { .freq = 5190, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa), + }, + { .freq = 5200, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xef, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xef, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), + }, + { .freq = 5210, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8), + }, + { .freq = 5220, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), + }, + { .freq = 5230, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6), + }, + { .freq = 5240, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), + }, + { .freq = 5250, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4), + }, + { .freq = 5260, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3), + }, + { .freq = 5270, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2), + }, + { .freq = 5280, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1), + }, + { .freq = 5290, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0), + }, + { .freq = 5300, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfc, 0x00), + PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0), + }, + { .freq = 5310, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef), + }, + { .freq = 5320, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee), + }, + { .freq = 5330, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed), + }, + { .freq = 5340, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec), + }, + { .freq = 5350, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb), + }, + { .freq = 5360, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea), + }, + { .freq = 5370, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9), + }, + { .freq = 5380, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8), + }, + { .freq = 5390, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x8f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7), + }, + { .freq = 5400, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xfa, 0x00), + PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6), + }, + { .freq = 5410, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xfa, 0x00), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5), + }, + { .freq = 5420, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xfa, 0x00), + PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5), + }, + { .freq = 5430, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xfa, 0x00), + PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4), + }, + { .freq = 5440, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x7e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xfa, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xfa, 0x00), + PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3), + }, + { .freq = 5450, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x7d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xfa, 0x00, 0x7d, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xfa, 0x00), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2), + }, + { .freq = 5460, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xf8, 0x00), + PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1), + }, + { .freq = 5470, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xf8, 0x00), + PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0), + }, + { .freq = 5480, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x5d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xf8, 0x00), + PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df), + }, + { .freq = 5490, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x5c, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xf8, 0x00), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de), + }, + { .freq = 5500, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x5c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd), + }, + { .freq = 5510, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd), + }, + { .freq = 5520, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc), + }, + { .freq = 5530, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db), + }, + { .freq = 5540, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da), + }, + { .freq = 5550, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9), + }, + { .freq = 5560, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x2b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x2b, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8), + }, + { .freq = 5570, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x2a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7), + }, + { .freq = 5580, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7), + }, + { .freq = 5590, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6), + }, + { .freq = 5600, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5), + }, + { .freq = 5610, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4), + }, + { .freq = 5620, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3), + }, + { .freq = 5630, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2), + }, + { .freq = 5640, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2), + }, + { .freq = 5650, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1), + }, + { .freq = 5660, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf6, 0x00), + PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0), + }, + { .freq = 5670, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf6, 0x00), + PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf), + }, + { .freq = 5680, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf6, 0x00), + PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce), + }, + { .freq = 5690, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf6, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf6, 0x00), + PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce), + }, + { .freq = 5700, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf6, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf6, 0x00), + PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd), + }, + { .freq = 5710, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc), + }, + { .freq = 5720, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5725, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5730, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca), + }, + { .freq = 5735, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca), + }, + { .freq = 5740, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9), + }, + { .freq = 5745, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), + }, + { .freq = 5750, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9), + }, + { .freq = 5755, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8), + }, + { .freq = 5760, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5765, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5770, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7), + }, + { .freq = 5775, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7), + }, + { .freq = 5780, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6), + }, + { .freq = 5785, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5790, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5795, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5), + }, + { .freq = 5800, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5), + }, + { .freq = 5805, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), + }, + { .freq = 5810, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5815, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5820, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3), + }, + { .freq = 5825, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), + }, + { .freq = 5830, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2), + }, + { .freq = 5840, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2), + }, + { .freq = 5850, + RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1), + }, + { .freq = 5860, + RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf2, 0x00), + PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0), + }, + { .freq = 5870, + RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf2, 0x00), + PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf), + }, + { .freq = 5880, + RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf2, 0x00), + PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf), + }, + { .freq = 5890, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf2, 0x00), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be), + }, + { .freq = 5900, + RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05, + 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x05, 0x00, 0xf2, 0x00), + PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd), + }, + { .freq = 5910, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05, + 0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x05, 0x00, 0xf2, 0x00), + PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc), + }, + { .freq = 2412, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), + }, + { .freq = 2417, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), + }, + { .freq = 2422, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), + }, + { .freq = 2427, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xfd, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xfd, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), + }, + { .freq = 2432, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xfb, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xfb, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), + }, + { .freq = 2437, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xfa, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), + }, + { .freq = 2442, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf8, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), + }, + { .freq = 2447, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf7, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xf7, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), + }, + { .freq = 2452, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf6, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xf6, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), + }, + { .freq = 2457, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf5, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0d, 0x00, 0xf5, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0d), + PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), + }, + { .freq = 2462, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0d, 0x00, 0xf4, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0d), + PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), + }, + { .freq = 2467, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf3, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0d, 0x00, 0xf3, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0d), + PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), + }, + { .freq = 2472, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0d, 0x00, 0xf2, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0d), + PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), + }, + { .freq = 2484, + RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0d, 0x00, 0xf0, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0d), + PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424), + }, +}; + +static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev4[] = { + { .freq = 4920, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216), + }, + { .freq = 4930, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215), + }, + { .freq = 4940, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214), + }, + { .freq = 4950, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213), + }, + { .freq = 4960, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212), + }, + { .freq = 4970, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211), + }, + { .freq = 4980, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f), + }, + { .freq = 4990, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e), + }, + { .freq = 5000, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d), + }, + { .freq = 5010, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c), + }, + { .freq = 5020, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b), + }, + { .freq = 5030, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a), + }, + { .freq = 5040, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209), + }, + { .freq = 5050, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208), + }, + { .freq = 5060, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207), + }, + { .freq = 5070, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206), + }, + { .freq = 5080, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205), + }, + { .freq = 5090, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204), + }, + { .freq = 5100, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203), + }, + { .freq = 5110, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202), + }, + { .freq = 5120, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201), + }, + { .freq = 5130, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200), + }, + { .freq = 5140, + RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff), + }, + { .freq = 5160, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd), + }, + { .freq = 5170, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc), + }, + { .freq = 5180, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), + }, + { .freq = 5190, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa), + }, + { .freq = 5200, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xef, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xef, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), + }, + { .freq = 5210, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8), + }, + { .freq = 5220, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), + }, + { .freq = 5230, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6), + }, + { .freq = 5240, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), + }, + { .freq = 5250, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4), + }, + { .freq = 5260, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3), + }, + { .freq = 5270, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2), + }, + { .freq = 5280, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1), + }, + { .freq = 5290, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0), + }, + { .freq = 5300, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0), + }, + { .freq = 5310, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef), + }, + { .freq = 5320, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee), + }, + { .freq = 5330, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed), + }, + { .freq = 5340, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec), + }, + { .freq = 5350, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb), + }, + { .freq = 5360, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea), + }, + { .freq = 5370, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9), + }, + { .freq = 5380, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8), + }, + { .freq = 5390, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x8f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7), + }, + { .freq = 5400, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6), + }, + { .freq = 5410, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5), + }, + { .freq = 5420, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5), + }, + { .freq = 5430, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4), + }, + { .freq = 5440, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x7e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3), + }, + { .freq = 5450, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x7d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2), + }, + { .freq = 5460, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1), + }, + { .freq = 5470, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0), + }, + { .freq = 5480, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x5d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df), + }, + { .freq = 5490, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x5c, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de), + }, + { .freq = 5500, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x5c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x5c, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd), + }, + { .freq = 5510, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd), + }, + { .freq = 5520, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc), + }, + { .freq = 5530, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db), + }, + { .freq = 5540, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da), + }, + { .freq = 5550, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9), + }, + { .freq = 5560, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x2b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x2b, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8), + }, + { .freq = 5570, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x2a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7), + }, + { .freq = 5580, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7), + }, + { .freq = 5590, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6), + }, + { .freq = 5600, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x1a, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5), + }, + { .freq = 5610, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4), + }, + { .freq = 5620, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3), + }, + { .freq = 5630, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2), + }, + { .freq = 5640, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2), + }, + { .freq = 5650, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1), + }, + { .freq = 5660, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0), + }, + { .freq = 5670, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf), + }, + { .freq = 5680, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce), + }, + { .freq = 5690, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x07, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x07, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce), + }, + { .freq = 5700, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd), + }, + { .freq = 5710, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc), + }, + { .freq = 5720, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5725, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5730, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca), + }, + { .freq = 5735, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca), + }, + { .freq = 5740, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9), + }, + { .freq = 5745, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), + }, + { .freq = 5750, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9), + }, + { .freq = 5755, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8), + }, + { .freq = 5760, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5765, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5770, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7), + }, + { .freq = 5775, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7), + }, + { .freq = 5780, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6), + }, + { .freq = 5785, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5790, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5795, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5), + }, + { .freq = 5800, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5), + }, + { .freq = 5805, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), + }, + { .freq = 5810, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5815, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5820, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3), + }, + { .freq = 5825, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), + }, + { .freq = 5830, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2), + }, + { .freq = 5840, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2), + }, + { .freq = 5850, + RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1), + }, + { .freq = 5860, + RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0), + }, + { .freq = 5870, + RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf), + }, + { .freq = 5880, + RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf), + }, + { .freq = 5890, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be), + }, + { .freq = 5900, + RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf0, 0x00), + PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd), + }, + { .freq = 5910, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf0, 0x00), + PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc), + }, + { .freq = 2412, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), + }, + { .freq = 2417, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), + }, + { .freq = 2422, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), + }, + { .freq = 2427, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xfd, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xfd, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), + }, + { .freq = 2432, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xfb, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xfb, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), + }, + { .freq = 2437, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xfa, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), + }, + { .freq = 2442, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf8, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf8, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), + }, + { .freq = 2447, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf7, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf7, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), + }, + { .freq = 2452, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf6, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), + }, + { .freq = 2457, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf5, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf5, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), + }, + { .freq = 2462, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf4, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), + }, + { .freq = 2467, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf3, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf3, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), + }, + { .freq = 2472, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf2, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), + }, + { .freq = 2484, + RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf0, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424), + }, +}; + +static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev5[] = { + { .freq = 4920, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216), + }, + { .freq = 4930, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215), + }, + { .freq = 4940, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214), + }, + { .freq = 4950, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213), + }, + { .freq = 4960, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212), + }, + { .freq = 4970, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211), + }, + { .freq = 4980, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f), + }, + { .freq = 4990, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e), + }, + { .freq = 5000, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d), + }, + { .freq = 5010, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c), + }, + { .freq = 5020, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b), + }, + { .freq = 5030, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a), + }, + { .freq = 5040, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209), + }, + { .freq = 5050, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208), + }, + { .freq = 5060, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207), + }, + { .freq = 5070, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206), + }, + { .freq = 5080, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205), + }, + { .freq = 5090, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204), + }, + { .freq = 5100, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203), + }, + { .freq = 5110, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202), + }, + { .freq = 5120, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201), + }, + { .freq = 5130, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a, + 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200), + }, + { .freq = 5140, + RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a, + 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff), + }, + { .freq = 5160, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd), + }, + { .freq = 5170, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc), + }, + { .freq = 5180, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), + }, + { .freq = 5190, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa), + }, + { .freq = 5200, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), + }, + { .freq = 5210, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8), + }, + { .freq = 5220, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), + }, + { .freq = 5230, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6e, 0x00), + PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6), + }, + { .freq = 5240, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6d, 0x00), + PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), + }, + { .freq = 5250, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6d, 0x00), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4), + }, + { .freq = 5260, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6d, 0x00), + PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3), + }, + { .freq = 5270, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2), + }, + { .freq = 5280, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1), + }, + { .freq = 5290, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0), + }, + { .freq = 5300, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0), + }, + { .freq = 5310, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef), + }, + { .freq = 5320, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee), + }, + { .freq = 5330, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6b, 0x00), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed), + }, + { .freq = 5340, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6b, 0x00), + PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec), + }, + { .freq = 5350, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x6b, 0x00), + PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb), + }, + { .freq = 5360, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x6b, 0x00), + PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea), + }, + { .freq = 5370, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x5b, 0x00), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9), + }, + { .freq = 5380, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x5a, 0x00), + PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8), + }, + { .freq = 5390, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x5a, 0x00), + PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7), + }, + { .freq = 5400, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x5a, 0x00), + PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6), + }, + { .freq = 5410, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x5a, 0x00), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5), + }, + { .freq = 5420, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x5a, 0x00), + PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5), + }, + { .freq = 5430, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x59, 0x00), + PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4), + }, + { .freq = 5440, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x59, 0x00), + PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3), + }, + { .freq = 5450, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x59, 0x00), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2), + }, + { .freq = 5460, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1), + }, + { .freq = 5470, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0), + }, + { .freq = 5480, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df), + }, + { .freq = 5490, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de), + }, + { .freq = 5500, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd), + }, + { .freq = 5510, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd), + }, + { .freq = 5520, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc), + }, + { .freq = 5530, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x78, 0x00), + PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db), + }, + { .freq = 5540, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x77, 0x00), + PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da), + }, + { .freq = 5550, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x77, 0x00), + PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9), + }, + { .freq = 5560, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x77, 0x00), + PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8), + }, + { .freq = 5570, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7), + }, + { .freq = 5580, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7), + }, + { .freq = 5590, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6), + }, + { .freq = 5600, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5), + }, + { .freq = 5610, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4), + }, + { .freq = 5620, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3), + }, + { .freq = 5630, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2), + }, + { .freq = 5640, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x75, 0x00), + PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2), + }, + { .freq = 5650, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x75, 0x00), + PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1), + }, + { .freq = 5660, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x75, 0x00), + PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0), + }, + { .freq = 5670, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf), + }, + { .freq = 5680, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce), + }, + { .freq = 5690, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce), + }, + { .freq = 5700, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd), + }, + { .freq = 5710, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc), + }, + { .freq = 5720, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5725, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5730, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x84, 0x00), + PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca), + }, + { .freq = 5735, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x83, 0x00), + PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca), + }, + { .freq = 5740, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x83, 0x00), + PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9), + }, + { .freq = 5745, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x83, 0x00), + PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), + }, + { .freq = 5750, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x83, 0x00), + PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9), + }, + { .freq = 5755, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x83, 0x00), + PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8), + }, + { .freq = 5760, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x83, 0x00), + PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5765, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5770, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7), + }, + { .freq = 5775, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7), + }, + { .freq = 5780, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6), + }, + { .freq = 5785, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5790, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5795, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5), + }, + { .freq = 5800, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5), + }, + { .freq = 5805, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), + }, + { .freq = 5810, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5815, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5820, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3), + }, + { .freq = 5825, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), + }, + { .freq = 5830, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x72, 0x00), + PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2), + }, + { .freq = 5840, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x72, 0x00), + PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2), + }, + { .freq = 5850, + RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x72, 0x00), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1), + }, + { .freq = 5860, + RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x72, 0x00), + PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0), + }, + { .freq = 5870, + RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x71, 0x00), + PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf), + }, + { .freq = 5880, + RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x71, 0x00), + PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf), + }, + { .freq = 5890, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x71, 0x00), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be), + }, + { .freq = 5900, + RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x71, 0x00), + PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd), + }, + { .freq = 5910, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x71, 0x00), + PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc), + }, + { .freq = 2412, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0b), + PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), + }, + { .freq = 2417, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0a), + PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), + }, + { .freq = 2422, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0a), + PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), + }, + { .freq = 2427, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x0d, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), + }, + { .freq = 2432, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), + }, + { .freq = 2437, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), + }, + { .freq = 2442, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), + }, + { .freq = 2447, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x09, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x09), + PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), + }, + { .freq = 2452, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x09, 0x00, 0x07, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x09), + PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), + }, + { .freq = 2457, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x09, 0x00, 0x06, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x09), + PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), + }, + { .freq = 2462, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x09, 0x00, 0x05, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x09), + PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), + }, + { .freq = 2467, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x08), + PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), + }, + { .freq = 2472, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x08), + PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), + }, + { .freq = 2484, + RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x08), + PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424), + }, +}; + +static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev6[] = { + { .freq = 4920, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216), + }, + { .freq = 4930, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215), + }, + { .freq = 4940, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214), + }, + { .freq = 4950, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213), + }, + { .freq = 4960, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212), + }, + { .freq = 4970, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211), + }, + { .freq = 4980, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f), + }, + { .freq = 4990, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e), + }, + { .freq = 5000, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d), + }, + { .freq = 5010, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c), + }, + { .freq = 5020, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b), + }, + { .freq = 5030, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a), + }, + { .freq = 5040, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209), + }, + { .freq = 5050, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208), + }, + { .freq = 5060, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207), + }, + { .freq = 5070, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206), + }, + { .freq = 5080, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205), + }, + { .freq = 5090, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204), + }, + { .freq = 5100, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203), + }, + { .freq = 5110, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202), + }, + { .freq = 5120, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201), + }, + { .freq = 5130, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200), + }, + { .freq = 5140, + RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff), + }, + { .freq = 5160, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, + 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd), + }, + { .freq = 5170, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, + 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc), + }, + { .freq = 5180, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), + }, + { .freq = 5190, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa), + }, + { .freq = 5200, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), + }, + { .freq = 5210, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8), + }, + { .freq = 5220, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), + }, + { .freq = 5230, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6), + }, + { .freq = 5240, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), + }, + { .freq = 5250, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4), + }, + { .freq = 5260, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, + 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3), + }, + { .freq = 5270, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, + 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2), + }, + { .freq = 5280, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1), + }, + { .freq = 5290, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0), + }, + { .freq = 5300, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0), + }, + { .freq = 5310, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef), + }, + { .freq = 5320, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee), + }, + { .freq = 5330, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, + 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed), + }, + { .freq = 5340, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, + 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec), + }, + { .freq = 5350, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, + 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb), + }, + { .freq = 5360, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea), + }, + { .freq = 5370, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9), + }, + { .freq = 5380, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8), + }, + { .freq = 5390, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7), + }, + { .freq = 5400, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6), + }, + { .freq = 5410, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5), + }, + { .freq = 5420, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5), + }, + { .freq = 5430, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, + 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4), + }, + { .freq = 5440, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3), + }, + { .freq = 5450, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2), + }, + { .freq = 5460, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1), + }, + { .freq = 5470, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0), + }, + { .freq = 5480, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df), + }, + { .freq = 5490, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de), + }, + { .freq = 5500, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd), + }, + { .freq = 5510, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd), + }, + { .freq = 5520, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc), + }, + { .freq = 5530, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, + 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db), + }, + { .freq = 5540, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, + 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da), + }, + { .freq = 5550, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9), + }, + { .freq = 5560, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8), + }, + { .freq = 5570, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7), + }, + { .freq = 5580, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, + 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7), + }, + { .freq = 5590, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, + 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6), + }, + { .freq = 5600, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5), + }, + { .freq = 5610, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4), + }, + { .freq = 5620, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3), + }, + { .freq = 5630, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2), + }, + { .freq = 5640, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2), + }, + { .freq = 5650, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1), + }, + { .freq = 5660, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0), + }, + { .freq = 5670, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf), + }, + { .freq = 5680, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce), + }, + { .freq = 5690, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce), + }, + { .freq = 5700, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd), + }, + { .freq = 5710, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc), + }, + { .freq = 5720, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5725, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5730, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca), + }, + { .freq = 5735, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6d, 0x00), + PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca), + }, + { .freq = 5740, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6d, 0x00), + PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9), + }, + { .freq = 5745, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6d, 0x00), + PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), + }, + { .freq = 5750, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6d, 0x00), + PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9), + }, + { .freq = 5755, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6c, 0x00), + PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8), + }, + { .freq = 5760, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6c, 0x00), + PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5765, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6c, 0x00), + PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5770, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7), + }, + { .freq = 5775, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7), + }, + { .freq = 5780, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6), + }, + { .freq = 5785, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5790, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5795, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5), + }, + { .freq = 5800, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5), + }, + { .freq = 5805, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), + }, + { .freq = 5810, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5815, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5820, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3), + }, + { .freq = 5825, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x69, 0x00), + PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), + }, + { .freq = 5830, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x69, 0x00), + PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2), + }, + { .freq = 5840, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2), + }, + { .freq = 5850, + RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1), + }, + { .freq = 5860, + RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0), + }, + { .freq = 5870, + RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf), + }, + { .freq = 5880, + RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf), + }, + { .freq = 5890, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be), + }, + { .freq = 5900, + RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd), + }, + { .freq = 5910, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc), + }, + { .freq = 2412, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0b, 0x00, 0x0a), + PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), + }, + { .freq = 2417, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0b, 0x00, 0x0a), + PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), + }, + { .freq = 2422, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0b, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0b, 0x00, 0x0a), + PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), + }, + { .freq = 2427, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), + }, + { .freq = 2432, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), + }, + { .freq = 2437, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), + }, + { .freq = 2442, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), + }, + { .freq = 2447, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x09), + PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), + }, + { .freq = 2452, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x09, 0x00, 0x23, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x09), + PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), + }, + { .freq = 2457, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x09), + PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), + }, + { .freq = 2462, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), + }, + { .freq = 2467, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), + }, + { .freq = 2472, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), + }, + { .freq = 2484, + RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424), + }, +}; + +static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev7_9[] = { + { .freq = 4920, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216), + }, + { .freq = 4930, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215), + }, + { .freq = 4940, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214), + }, + { .freq = 4950, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213), + }, + { .freq = 4960, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212), + }, + { .freq = 4970, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211), + }, + { .freq = 4980, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f), + }, + { .freq = 4990, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e), + }, + { .freq = 5000, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d), + }, + { .freq = 5010, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c), + }, + { .freq = 5020, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b), + }, + { .freq = 5030, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a), + }, + { .freq = 5040, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209), + }, + { .freq = 5050, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208), + }, + { .freq = 5060, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207), + }, + { .freq = 5070, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206), + }, + { .freq = 5080, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205), + }, + { .freq = 5090, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204), + }, + { .freq = 5100, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203), + }, + { .freq = 5110, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202), + }, + { .freq = 5120, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201), + }, + { .freq = 5130, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a, + 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200), + }, + { .freq = 5140, + RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a, + 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff), + }, + { .freq = 5160, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd), + }, + { .freq = 5170, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc), + }, + { .freq = 5180, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), + }, + { .freq = 5190, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa), + }, + { .freq = 5200, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), + }, + { .freq = 5210, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8), + }, + { .freq = 5220, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xfe, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), + }, + { .freq = 5230, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xee, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6e, 0x00), + PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6), + }, + { .freq = 5240, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xee, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6d, 0x00), + PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), + }, + { .freq = 5250, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xed, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6d, 0x00), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4), + }, + { .freq = 5260, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, + 0xed, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6d, 0x00), + PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3), + }, + { .freq = 5270, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, + 0xed, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2), + }, + { .freq = 5280, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1), + }, + { .freq = 5290, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0), + }, + { .freq = 5300, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0), + }, + { .freq = 5310, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef), + }, + { .freq = 5320, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdb, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee), + }, + { .freq = 5330, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xcb, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6b, 0x00), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed), + }, + { .freq = 5340, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xca, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6b, 0x00), + PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec), + }, + { .freq = 5350, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xca, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x6b, 0x00), + PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb), + }, + { .freq = 5360, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x6b, 0x00), + PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea), + }, + { .freq = 5370, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x7b, 0x00), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9), + }, + { .freq = 5380, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x7a, 0x00), + PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8), + }, + { .freq = 5390, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x7a, 0x00), + PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7), + }, + { .freq = 5400, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x7a, 0x00), + PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6), + }, + { .freq = 5410, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb7, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x7a, 0x00), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5), + }, + { .freq = 5420, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xa7, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x7a, 0x00), + PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5), + }, + { .freq = 5430, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, + 0xa6, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x79, 0x00), + PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4), + }, + { .freq = 5440, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0xa6, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x79, 0x00), + PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3), + }, + { .freq = 5450, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x95, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x79, 0x00), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2), + }, + { .freq = 5460, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x95, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x79, 0x00), + PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1), + }, + { .freq = 5470, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x94, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x79, 0x00), + PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0), + }, + { .freq = 5480, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df), + }, + { .freq = 5490, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x83, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de), + }, + { .freq = 5500, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x82, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd), + }, + { .freq = 5510, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x82, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd), + }, + { .freq = 5520, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x72, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc), + }, + { .freq = 5530, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, + 0x72, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x78, 0x00), + PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db), + }, + { .freq = 5540, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, + 0x71, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x77, 0x00), + PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da), + }, + { .freq = 5550, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x77, 0x00), + PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9), + }, + { .freq = 5560, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x77, 0x00), + PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8), + }, + { .freq = 5570, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7), + }, + { .freq = 5580, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, + 0x60, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x86, 0x00), + PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7), + }, + { .freq = 5590, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x86, 0x00), + PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6), + }, + { .freq = 5600, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x86, 0x00), + PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5), + }, + { .freq = 5610, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x86, 0x00), + PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4), + }, + { .freq = 5620, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x86, 0x00), + PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3), + }, + { .freq = 5630, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x86, 0x00), + PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2), + }, + { .freq = 5640, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x85, 0x00), + PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2), + }, + { .freq = 5650, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x85, 0x00), + PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1), + }, + { .freq = 5660, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x85, 0x00), + PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0), + }, + { .freq = 5670, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x84, 0x00), + PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf), + }, + { .freq = 5680, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x84, 0x00), + PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce), + }, + { .freq = 5690, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x94, 0x00), + PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce), + }, + { .freq = 5700, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x94, 0x00), + PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd), + }, + { .freq = 5710, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x94, 0x00), + PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc), + }, + { .freq = 5720, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x94, 0x00), + PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5725, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x94, 0x00), + PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5730, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x94, 0x00), + PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca), + }, + { .freq = 5735, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x93, 0x00), + PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca), + }, + { .freq = 5740, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x93, 0x00), + PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9), + }, + { .freq = 5745, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x93, 0x00), + PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), + }, + { .freq = 5750, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x93, 0x00), + PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9), + }, + { .freq = 5755, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x10, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x93, 0x00), + PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8), + }, + { .freq = 5760, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x93, 0x00), + PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5765, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5770, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7), + }, + { .freq = 5775, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7), + }, + { .freq = 5780, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6), + }, + { .freq = 5785, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5790, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5795, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5), + }, + { .freq = 5800, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5), + }, + { .freq = 5805, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), + }, + { .freq = 5810, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5815, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5820, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3), + }, + { .freq = 5825, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), + }, + { .freq = 5830, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2), + }, + { .freq = 5840, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2), + }, + { .freq = 5850, + RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1), + }, + { .freq = 5860, + RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0), + }, + { .freq = 5870, + RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x91, 0x00), + PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf), + }, + { .freq = 5880, + RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x91, 0x00), + PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf), + }, + { .freq = 5890, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x91, 0x00), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be), + }, + { .freq = 5900, + RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x91, 0x00), + PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd), + }, + { .freq = 5910, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x91, 0x00), + PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc), + }, + { .freq = 2412, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0b, 0x00, 0x89, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0b), + PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), + }, + { .freq = 2417, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0a), + PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), + }, + { .freq = 2422, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0a), + PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), + }, + { .freq = 2427, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), + }, + { .freq = 2432, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), + }, + { .freq = 2437, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), + }, + { .freq = 2442, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x66, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), + }, + { .freq = 2447, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x09), + PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), + }, + { .freq = 2452, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x09), + PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), + }, + { .freq = 2457, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x09), + PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), + }, + { .freq = 2462, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x09), + PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), + }, + { .freq = 2467, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x08, 0x00, 0x22, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x08), + PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), + }, + { .freq = 2472, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x08, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x08), + PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), + }, + { .freq = 2484, + RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x08), + PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424), + }, }; +static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev8[] = { + { .freq = 4920, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216), + }, + { .freq = 4930, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215), + }, + { .freq = 4940, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214), + }, + { .freq = 4950, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213), + }, + { .freq = 4960, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212), + }, + { .freq = 4970, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211), + }, + { .freq = 4980, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f), + }, + { .freq = 4990, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e), + }, + { .freq = 5000, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d), + }, + { .freq = 5010, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c), + }, + { .freq = 5020, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b), + }, + { .freq = 5030, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a), + }, + { .freq = 5040, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209), + }, + { .freq = 5050, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208), + }, + { .freq = 5060, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207), + }, + { .freq = 5070, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206), + }, + { .freq = 5080, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205), + }, + { .freq = 5090, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204), + }, + { .freq = 5100, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203), + }, + { .freq = 5110, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202), + }, + { .freq = 5120, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201), + }, + { .freq = 5130, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200), + }, + { .freq = 5140, + RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff), + }, + { .freq = 5160, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, + 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd), + }, + { .freq = 5170, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, + 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc), + }, + { .freq = 5180, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), + }, + { .freq = 5190, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa), + }, + { .freq = 5200, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), + }, + { .freq = 5210, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8), + }, + { .freq = 5220, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), + }, + { .freq = 5230, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6), + }, + { .freq = 5240, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), + }, + { .freq = 5250, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4), + }, + { .freq = 5260, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, + 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3), + }, + { .freq = 5270, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, + 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2), + }, + { .freq = 5280, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1), + }, + { .freq = 5290, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0), + }, + { .freq = 5300, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0), + }, + { .freq = 5310, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef), + }, + { .freq = 5320, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee), + }, + { .freq = 5330, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, + 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed), + }, + { .freq = 5340, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, + 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec), + }, + { .freq = 5350, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, + 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb), + }, + { .freq = 5360, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea), + }, + { .freq = 5370, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9), + }, + { .freq = 5380, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8), + }, + { .freq = 5390, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7), + }, + { .freq = 5400, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6), + }, + { .freq = 5410, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5), + }, + { .freq = 5420, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5), + }, + { .freq = 5430, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, + 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4), + }, + { .freq = 5440, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3), + }, + { .freq = 5450, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2), + }, + { .freq = 5460, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1), + }, + { .freq = 5470, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0), + }, + { .freq = 5480, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df), + }, + { .freq = 5490, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de), + }, + { .freq = 5500, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd), + }, + { .freq = 5510, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd), + }, + { .freq = 5520, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc), + }, + { .freq = 5530, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, + 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db), + }, + { .freq = 5540, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, + 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da), + }, + { .freq = 5550, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9), + }, + { .freq = 5560, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8), + }, + { .freq = 5570, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7), + }, + { .freq = 5580, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, + 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7), + }, + { .freq = 5590, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, + 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6), + }, + { .freq = 5600, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5), + }, + { .freq = 5610, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4), + }, + { .freq = 5620, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3), + }, + { .freq = 5630, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2), + }, + { .freq = 5640, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2), + }, + { .freq = 5650, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1), + }, + { .freq = 5660, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0), + }, + { .freq = 5670, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf), + }, + { .freq = 5680, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce), + }, + { .freq = 5690, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce), + }, + { .freq = 5700, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd), + }, + { .freq = 5710, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc), + }, + { .freq = 5720, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5725, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5730, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca), + }, + { .freq = 5735, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6d, 0x00), + PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca), + }, + { .freq = 5740, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6d, 0x00), + PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9), + }, + { .freq = 5745, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6d, 0x00), + PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), + }, + { .freq = 5750, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6d, 0x00), + PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9), + }, + { .freq = 5755, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6c, 0x00), + PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8), + }, + { .freq = 5760, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6c, 0x00), + PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5765, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6c, 0x00), + PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5770, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7), + }, + { .freq = 5775, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7), + }, + { .freq = 5780, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6), + }, + { .freq = 5785, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5790, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5795, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5), + }, + { .freq = 5800, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5), + }, + { .freq = 5805, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), + }, + { .freq = 5810, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5815, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5820, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3), + }, + { .freq = 5825, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x69, 0x00), + PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), + }, + { .freq = 5830, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x69, 0x00), + PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2), + }, + { .freq = 5840, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2), + }, + { .freq = 5850, + RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1), + }, + { .freq = 5860, + RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0), + }, + { .freq = 5870, + RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf), + }, + { .freq = 5880, + RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf), + }, + { .freq = 5890, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be), + }, + { .freq = 5900, + RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd), + }, + { .freq = 5910, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc), + }, + { .freq = 2412, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0b, 0x00, 0x0a), + PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), + }, + { .freq = 2417, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0b, 0x00, 0x0a), + PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), + }, + { .freq = 2422, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0b, 0x00, 0x0a), + PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), + }, + { .freq = 2427, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), + }, + { .freq = 2432, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), + }, + { .freq = 2437, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), + }, + { .freq = 2442, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), + }, + { .freq = 2447, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x09), + PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), + }, + { .freq = 2452, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x09), + PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), + }, + { .freq = 2457, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x09), + PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), + }, + { .freq = 2462, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), + }, + { .freq = 2467, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), + }, + { .freq = 2472, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), + }, + { .freq = 2484, + RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424), + }, +}; + +static void b2056_upload_inittab(struct b43_wldev *dev, bool ghz5, + bool ignore_uploadflag, u16 routing, + const struct b2056_inittab_entry *e, + unsigned int length) +{ + unsigned int i; + u16 value; + + for (i = 0; i < length; i++, e++) { + if (!(e->flags & B2056_INITTAB_ENTRY_OK)) + continue; + if ((e->flags & B2056_INITTAB_UPLOAD) || ignore_uploadflag) { + if (ghz5) + value = e->ghz5; + else + value = e->ghz2; + b43_radio_write(dev, routing | i, value); + } + } +} + +void b2056_upload_inittabs(struct b43_wldev *dev, + bool ghz5, bool ignore_uploadflag) +{ + struct b2056_inittabs_pts *pts; + + if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) { + B43_WARN_ON(1); + return; + } + pts = &b2056_inittabs[dev->phy.rev]; + + b2056_upload_inittab(dev, ghz5, ignore_uploadflag, + B2056_SYN, pts->syn, pts->syn_length); + b2056_upload_inittab(dev, ghz5, ignore_uploadflag, + B2056_TX0, pts->tx, pts->tx_length); + b2056_upload_inittab(dev, ghz5, ignore_uploadflag, + B2056_TX1, pts->tx, pts->tx_length); + b2056_upload_inittab(dev, ghz5, ignore_uploadflag, + B2056_RX0, pts->rx, pts->rx_length); + b2056_upload_inittab(dev, ghz5, ignore_uploadflag, + B2056_RX1, pts->rx, pts->rx_length); +} + const struct b43_nphy_channeltab_entry_rev3 * b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq) { const struct b43_nphy_channeltab_entry_rev3 *e; - unsigned int i; + unsigned int length, i; + + switch (dev->phy.rev) { + case 3: + e = b43_nphy_channeltab_rev3; + length = ARRAY_SIZE(b43_nphy_channeltab_rev3); + break; + case 4: + e = b43_nphy_channeltab_rev4; + length = ARRAY_SIZE(b43_nphy_channeltab_rev4); + break; + case 5: + e = b43_nphy_channeltab_rev5; + length = ARRAY_SIZE(b43_nphy_channeltab_rev5); + break; + case 6: + e = b43_nphy_channeltab_rev6; + length = ARRAY_SIZE(b43_nphy_channeltab_rev6); + break; + case 7: + case 9: + e = b43_nphy_channeltab_rev7_9; + length = ARRAY_SIZE(b43_nphy_channeltab_rev7_9); + break; + case 8: + e = b43_nphy_channeltab_rev8; + length = ARRAY_SIZE(b43_nphy_channeltab_rev8); + break; + default: + B43_WARN_ON(1); + return NULL; + } - for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev3); i++) { - e = &(b43_nphy_channeltab_rev3[i]); + for (i = 0; i < length; i++, e++) { if (e->freq == freq) return e; } diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h index fda6dafecb8c..d601f6e7e313 100644 --- a/drivers/net/wireless/b43/radio_2056.h +++ b/drivers/net/wireless/b43/radio_2056.h @@ -4,6 +4,9 @@ Copyright (c) 2010 RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com> + Some parts of the code in this file are derived from the brcm80211 + driver Copyright (c) 2010 Broadcom Corporation + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -28,15 +31,1090 @@ #include "tables_nphy.h" +#define B2056_SYN (0x0 << 12) +#define B2056_TX0 (0x2 << 12) +#define B2056_TX1 (0x3 << 12) +#define B2056_RX0 (0x6 << 12) +#define B2056_RX1 (0x7 << 12) +#define B2056_ALLTX (0xE << 12) +#define B2056_ALLRX (0xF << 12) + +#define B2056_SYN_RESERVED_ADDR0 0x00 +#define B2056_SYN_IDCODE 0x01 +#define B2056_SYN_RESERVED_ADDR2 0x02 +#define B2056_SYN_RESERVED_ADDR3 0x03 +#define B2056_SYN_RESERVED_ADDR4 0x04 +#define B2056_SYN_RESERVED_ADDR5 0x05 +#define B2056_SYN_RESERVED_ADDR6 0x06 +#define B2056_SYN_RESERVED_ADDR7 0x07 +#define B2056_SYN_COM_CTRL 0x08 +#define B2056_SYN_COM_PU 0x09 +#define B2056_SYN_COM_OVR 0x0A +#define B2056_SYN_COM_RESET 0x0B +#define B2056_SYN_COM_RCAL 0x0C +#define B2056_SYN_COM_RC_RXLPF 0x0D +#define B2056_SYN_COM_RC_TXLPF 0x0E +#define B2056_SYN_COM_RC_RXHPF 0x0F +#define B2056_SYN_RESERVED_ADDR16 0x10 +#define B2056_SYN_RESERVED_ADDR17 0x11 +#define B2056_SYN_RESERVED_ADDR18 0x12 +#define B2056_SYN_RESERVED_ADDR19 0x13 +#define B2056_SYN_RESERVED_ADDR20 0x14 +#define B2056_SYN_RESERVED_ADDR21 0x15 +#define B2056_SYN_RESERVED_ADDR22 0x16 +#define B2056_SYN_RESERVED_ADDR23 0x17 +#define B2056_SYN_RESERVED_ADDR24 0x18 +#define B2056_SYN_RESERVED_ADDR25 0x19 +#define B2056_SYN_RESERVED_ADDR26 0x1A +#define B2056_SYN_RESERVED_ADDR27 0x1B +#define B2056_SYN_RESERVED_ADDR28 0x1C +#define B2056_SYN_RESERVED_ADDR29 0x1D +#define B2056_SYN_RESERVED_ADDR30 0x1E +#define B2056_SYN_RESERVED_ADDR31 0x1F +#define B2056_SYN_GPIO_MASTER1 0x20 +#define B2056_SYN_GPIO_MASTER2 0x21 +#define B2056_SYN_TOPBIAS_MASTER 0x22 +#define B2056_SYN_TOPBIAS_RCAL 0x23 +#define B2056_SYN_AFEREG 0x24 +#define B2056_SYN_TEMPPROCSENSE 0x25 +#define B2056_SYN_TEMPPROCSENSEIDAC 0x26 +#define B2056_SYN_TEMPPROCSENSERCAL 0x27 +#define B2056_SYN_LPO 0x28 +#define B2056_SYN_VDDCAL_MASTER 0x29 +#define B2056_SYN_VDDCAL_IDAC 0x2A +#define B2056_SYN_VDDCAL_STATUS 0x2B +#define B2056_SYN_RCAL_MASTER 0x2C +#define B2056_SYN_RCAL_CODE_OUT 0x2D +#define B2056_SYN_RCCAL_CTRL0 0x2E +#define B2056_SYN_RCCAL_CTRL1 0x2F +#define B2056_SYN_RCCAL_CTRL2 0x30 +#define B2056_SYN_RCCAL_CTRL3 0x31 +#define B2056_SYN_RCCAL_CTRL4 0x32 +#define B2056_SYN_RCCAL_CTRL5 0x33 +#define B2056_SYN_RCCAL_CTRL6 0x34 +#define B2056_SYN_RCCAL_CTRL7 0x35 +#define B2056_SYN_RCCAL_CTRL8 0x36 +#define B2056_SYN_RCCAL_CTRL9 0x37 +#define B2056_SYN_RCCAL_CTRL10 0x38 +#define B2056_SYN_RCCAL_CTRL11 0x39 +#define B2056_SYN_ZCAL_SPARE1 0x3A +#define B2056_SYN_ZCAL_SPARE2 0x3B +#define B2056_SYN_PLL_MAST1 0x3C +#define B2056_SYN_PLL_MAST2 0x3D +#define B2056_SYN_PLL_MAST3 0x3E +#define B2056_SYN_PLL_BIAS_RESET 0x3F +#define B2056_SYN_PLL_XTAL0 0x40 +#define B2056_SYN_PLL_XTAL1 0x41 +#define B2056_SYN_PLL_XTAL3 0x42 +#define B2056_SYN_PLL_XTAL4 0x43 +#define B2056_SYN_PLL_XTAL5 0x44 +#define B2056_SYN_PLL_XTAL6 0x45 +#define B2056_SYN_PLL_REFDIV 0x46 +#define B2056_SYN_PLL_PFD 0x47 +#define B2056_SYN_PLL_CP1 0x48 +#define B2056_SYN_PLL_CP2 0x49 +#define B2056_SYN_PLL_CP3 0x4A +#define B2056_SYN_PLL_LOOPFILTER1 0x4B +#define B2056_SYN_PLL_LOOPFILTER2 0x4C +#define B2056_SYN_PLL_LOOPFILTER3 0x4D +#define B2056_SYN_PLL_LOOPFILTER4 0x4E +#define B2056_SYN_PLL_LOOPFILTER5 0x4F +#define B2056_SYN_PLL_MMD1 0x50 +#define B2056_SYN_PLL_MMD2 0x51 +#define B2056_SYN_PLL_VCO1 0x52 +#define B2056_SYN_PLL_VCO2 0x53 +#define B2056_SYN_PLL_MONITOR1 0x54 +#define B2056_SYN_PLL_MONITOR2 0x55 +#define B2056_SYN_PLL_VCOCAL1 0x56 +#define B2056_SYN_PLL_VCOCAL2 0x57 +#define B2056_SYN_PLL_VCOCAL4 0x58 +#define B2056_SYN_PLL_VCOCAL5 0x59 +#define B2056_SYN_PLL_VCOCAL6 0x5A +#define B2056_SYN_PLL_VCOCAL7 0x5B +#define B2056_SYN_PLL_VCOCAL8 0x5C +#define B2056_SYN_PLL_VCOCAL9 0x5D +#define B2056_SYN_PLL_VCOCAL10 0x5E +#define B2056_SYN_PLL_VCOCAL11 0x5F +#define B2056_SYN_PLL_VCOCAL12 0x60 +#define B2056_SYN_PLL_VCOCAL13 0x61 +#define B2056_SYN_PLL_VREG 0x62 +#define B2056_SYN_PLL_STATUS1 0x63 +#define B2056_SYN_PLL_STATUS2 0x64 +#define B2056_SYN_PLL_STATUS3 0x65 +#define B2056_SYN_LOGEN_PU0 0x66 +#define B2056_SYN_LOGEN_PU1 0x67 +#define B2056_SYN_LOGEN_PU2 0x68 +#define B2056_SYN_LOGEN_PU3 0x69 +#define B2056_SYN_LOGEN_PU5 0x6A +#define B2056_SYN_LOGEN_PU6 0x6B +#define B2056_SYN_LOGEN_PU7 0x6C +#define B2056_SYN_LOGEN_PU8 0x6D +#define B2056_SYN_LOGEN_BIAS_RESET 0x6E +#define B2056_SYN_LOGEN_RCCR1 0x6F +#define B2056_SYN_LOGEN_VCOBUF1 0x70 +#define B2056_SYN_LOGEN_MIXER1 0x71 +#define B2056_SYN_LOGEN_MIXER2 0x72 +#define B2056_SYN_LOGEN_BUF1 0x73 +#define B2056_SYN_LOGENBUF2 0x74 +#define B2056_SYN_LOGEN_BUF3 0x75 +#define B2056_SYN_LOGEN_BUF4 0x76 +#define B2056_SYN_LOGEN_DIV1 0x77 +#define B2056_SYN_LOGEN_DIV2 0x78 +#define B2056_SYN_LOGEN_DIV3 0x79 +#define B2056_SYN_LOGEN_ACL1 0x7A +#define B2056_SYN_LOGEN_ACL2 0x7B +#define B2056_SYN_LOGEN_ACL3 0x7C +#define B2056_SYN_LOGEN_ACL4 0x7D +#define B2056_SYN_LOGEN_ACL5 0x7E +#define B2056_SYN_LOGEN_ACL6 0x7F +#define B2056_SYN_LOGEN_ACLOUT 0x80 +#define B2056_SYN_LOGEN_ACLCAL1 0x81 +#define B2056_SYN_LOGEN_ACLCAL2 0x82 +#define B2056_SYN_LOGEN_ACLCAL3 0x83 +#define B2056_SYN_CALEN 0x84 +#define B2056_SYN_LOGEN_PEAKDET1 0x85 +#define B2056_SYN_LOGEN_CORE_ACL_OVR 0x86 +#define B2056_SYN_LOGEN_RX_DIFF_ACL_OVR 0x87 +#define B2056_SYN_LOGEN_TX_DIFF_ACL_OVR 0x88 +#define B2056_SYN_LOGEN_RX_CMOS_ACL_OVR 0x89 +#define B2056_SYN_LOGEN_TX_CMOS_ACL_OVR 0x8A +#define B2056_SYN_LOGEN_VCOBUF2 0x8B +#define B2056_SYN_LOGEN_MIXER3 0x8C +#define B2056_SYN_LOGEN_BUF5 0x8D +#define B2056_SYN_LOGEN_BUF6 0x8E +#define B2056_SYN_LOGEN_CBUFRX1 0x8F +#define B2056_SYN_LOGEN_CBUFRX2 0x90 +#define B2056_SYN_LOGEN_CBUFRX3 0x91 +#define B2056_SYN_LOGEN_CBUFRX4 0x92 +#define B2056_SYN_LOGEN_CBUFTX1 0x93 +#define B2056_SYN_LOGEN_CBUFTX2 0x94 +#define B2056_SYN_LOGEN_CBUFTX3 0x95 +#define B2056_SYN_LOGEN_CBUFTX4 0x96 +#define B2056_SYN_LOGEN_CMOSRX1 0x97 +#define B2056_SYN_LOGEN_CMOSRX2 0x98 +#define B2056_SYN_LOGEN_CMOSRX3 0x99 +#define B2056_SYN_LOGEN_CMOSRX4 0x9A +#define B2056_SYN_LOGEN_CMOSTX1 0x9B +#define B2056_SYN_LOGEN_CMOSTX2 0x9C +#define B2056_SYN_LOGEN_CMOSTX3 0x9D +#define B2056_SYN_LOGEN_CMOSTX4 0x9E +#define B2056_SYN_LOGEN_VCOBUF2_OVRVAL 0x9F +#define B2056_SYN_LOGEN_MIXER3_OVRVAL 0xA0 +#define B2056_SYN_LOGEN_BUF5_OVRVAL 0xA1 +#define B2056_SYN_LOGEN_BUF6_OVRVAL 0xA2 +#define B2056_SYN_LOGEN_CBUFRX1_OVRVAL 0xA3 +#define B2056_SYN_LOGEN_CBUFRX2_OVRVAL 0xA4 +#define B2056_SYN_LOGEN_CBUFRX3_OVRVAL 0xA5 +#define B2056_SYN_LOGEN_CBUFRX4_OVRVAL 0xA6 +#define B2056_SYN_LOGEN_CBUFTX1_OVRVAL 0xA7 +#define B2056_SYN_LOGEN_CBUFTX2_OVRVAL 0xA8 +#define B2056_SYN_LOGEN_CBUFTX3_OVRVAL 0xA9 +#define B2056_SYN_LOGEN_CBUFTX4_OVRVAL 0xAA +#define B2056_SYN_LOGEN_CMOSRX1_OVRVAL 0xAB +#define B2056_SYN_LOGEN_CMOSRX2_OVRVAL 0xAC +#define B2056_SYN_LOGEN_CMOSRX3_OVRVAL 0xAD +#define B2056_SYN_LOGEN_CMOSRX4_OVRVAL 0xAE +#define B2056_SYN_LOGEN_CMOSTX1_OVRVAL 0xAF +#define B2056_SYN_LOGEN_CMOSTX2_OVRVAL 0xB0 +#define B2056_SYN_LOGEN_CMOSTX3_OVRVAL 0xB1 +#define B2056_SYN_LOGEN_CMOSTX4_OVRVAL 0xB2 +#define B2056_SYN_LOGEN_ACL_WAITCNT 0xB3 +#define B2056_SYN_LOGEN_CORE_CALVALID 0xB4 +#define B2056_SYN_LOGEN_RX_CMOS_CALVALID 0xB5 +#define B2056_SYN_LOGEN_TX_CMOS_VALID 0xB6 + +#define B2056_TX_RESERVED_ADDR0 0x00 +#define B2056_TX_IDCODE 0x01 +#define B2056_TX_RESERVED_ADDR2 0x02 +#define B2056_TX_RESERVED_ADDR3 0x03 +#define B2056_TX_RESERVED_ADDR4 0x04 +#define B2056_TX_RESERVED_ADDR5 0x05 +#define B2056_TX_RESERVED_ADDR6 0x06 +#define B2056_TX_RESERVED_ADDR7 0x07 +#define B2056_TX_COM_CTRL 0x08 +#define B2056_TX_COM_PU 0x09 +#define B2056_TX_COM_OVR 0x0A +#define B2056_TX_COM_RESET 0x0B +#define B2056_TX_COM_RCAL 0x0C +#define B2056_TX_COM_RC_RXLPF 0x0D +#define B2056_TX_COM_RC_TXLPF 0x0E +#define B2056_TX_COM_RC_RXHPF 0x0F +#define B2056_TX_RESERVED_ADDR16 0x10 +#define B2056_TX_RESERVED_ADDR17 0x11 +#define B2056_TX_RESERVED_ADDR18 0x12 +#define B2056_TX_RESERVED_ADDR19 0x13 +#define B2056_TX_RESERVED_ADDR20 0x14 +#define B2056_TX_RESERVED_ADDR21 0x15 +#define B2056_TX_RESERVED_ADDR22 0x16 +#define B2056_TX_RESERVED_ADDR23 0x17 +#define B2056_TX_RESERVED_ADDR24 0x18 +#define B2056_TX_RESERVED_ADDR25 0x19 +#define B2056_TX_RESERVED_ADDR26 0x1A +#define B2056_TX_RESERVED_ADDR27 0x1B +#define B2056_TX_RESERVED_ADDR28 0x1C +#define B2056_TX_RESERVED_ADDR29 0x1D +#define B2056_TX_RESERVED_ADDR30 0x1E +#define B2056_TX_RESERVED_ADDR31 0x1F +#define B2056_TX_IQCAL_GAIN_BW 0x20 +#define B2056_TX_LOFT_FINE_I 0x21 +#define B2056_TX_LOFT_FINE_Q 0x22 +#define B2056_TX_LOFT_COARSE_I 0x23 +#define B2056_TX_LOFT_COARSE_Q 0x24 +#define B2056_TX_TX_COM_MASTER1 0x25 +#define B2056_TX_TX_COM_MASTER2 0x26 +#define B2056_TX_RXIQCAL_TXMUX 0x27 +#define B2056_TX_TX_SSI_MASTER 0x28 +#define B2056_TX_IQCAL_VCM_HG 0x29 +#define B2056_TX_IQCAL_IDAC 0x2A +#define B2056_TX_TSSI_VCM 0x2B +#define B2056_TX_TX_AMP_DET 0x2C +#define B2056_TX_TX_SSI_MUX 0x2D +#define B2056_TX_TSSIA 0x2E +#define B2056_TX_TSSIG 0x2F +#define B2056_TX_TSSI_MISC1 0x30 +#define B2056_TX_TSSI_MISC2 0x31 +#define B2056_TX_TSSI_MISC3 0x32 +#define B2056_TX_PA_SPARE1 0x33 +#define B2056_TX_PA_SPARE2 0x34 +#define B2056_TX_INTPAA_MASTER 0x35 +#define B2056_TX_INTPAA_GAIN 0x36 +#define B2056_TX_INTPAA_BOOST_TUNE 0x37 +#define B2056_TX_INTPAA_IAUX_STAT 0x38 +#define B2056_TX_INTPAA_IAUX_DYN 0x39 +#define B2056_TX_INTPAA_IMAIN_STAT 0x3A +#define B2056_TX_INTPAA_IMAIN_DYN 0x3B +#define B2056_TX_INTPAA_CASCBIAS 0x3C +#define B2056_TX_INTPAA_PASLOPE 0x3D +#define B2056_TX_INTPAA_PA_MISC 0x3E +#define B2056_TX_INTPAG_MASTER 0x3F +#define B2056_TX_INTPAG_GAIN 0x40 +#define B2056_TX_INTPAG_BOOST_TUNE 0x41 +#define B2056_TX_INTPAG_IAUX_STAT 0x42 +#define B2056_TX_INTPAG_IAUX_DYN 0x43 +#define B2056_TX_INTPAG_IMAIN_STAT 0x44 +#define B2056_TX_INTPAG_IMAIN_DYN 0x45 +#define B2056_TX_INTPAG_CASCBIAS 0x46 +#define B2056_TX_INTPAG_PASLOPE 0x47 +#define B2056_TX_INTPAG_PA_MISC 0x48 +#define B2056_TX_PADA_MASTER 0x49 +#define B2056_TX_PADA_IDAC 0x4A +#define B2056_TX_PADA_CASCBIAS 0x4B +#define B2056_TX_PADA_GAIN 0x4C +#define B2056_TX_PADA_BOOST_TUNE 0x4D +#define B2056_TX_PADA_SLOPE 0x4E +#define B2056_TX_PADG_MASTER 0x4F +#define B2056_TX_PADG_IDAC 0x50 +#define B2056_TX_PADG_CASCBIAS 0x51 +#define B2056_TX_PADG_GAIN 0x52 +#define B2056_TX_PADG_BOOST_TUNE 0x53 +#define B2056_TX_PADG_SLOPE 0x54 +#define B2056_TX_PGAA_MASTER 0x55 +#define B2056_TX_PGAA_IDAC 0x56 +#define B2056_TX_PGAA_GAIN 0x57 +#define B2056_TX_PGAA_BOOST_TUNE 0x58 +#define B2056_TX_PGAA_SLOPE 0x59 +#define B2056_TX_PGAA_MISC 0x5A +#define B2056_TX_PGAG_MASTER 0x5B +#define B2056_TX_PGAG_IDAC 0x5C +#define B2056_TX_PGAG_GAIN 0x5D +#define B2056_TX_PGAG_BOOST_TUNE 0x5E +#define B2056_TX_PGAG_SLOPE 0x5F +#define B2056_TX_PGAG_MISC 0x60 +#define B2056_TX_MIXA_MASTER 0x61 +#define B2056_TX_MIXA_BOOST_TUNE 0x62 +#define B2056_TX_MIXG 0x63 +#define B2056_TX_MIXG_BOOST_TUNE 0x64 +#define B2056_TX_BB_GM_MASTER 0x65 +#define B2056_TX_GMBB_GM 0x66 +#define B2056_TX_GMBB_IDAC 0x67 +#define B2056_TX_TXLPF_MASTER 0x68 +#define B2056_TX_TXLPF_RCCAL 0x69 +#define B2056_TX_TXLPF_RCCAL_OFF0 0x6A +#define B2056_TX_TXLPF_RCCAL_OFF1 0x6B +#define B2056_TX_TXLPF_RCCAL_OFF2 0x6C +#define B2056_TX_TXLPF_RCCAL_OFF3 0x6D +#define B2056_TX_TXLPF_RCCAL_OFF4 0x6E +#define B2056_TX_TXLPF_RCCAL_OFF5 0x6F +#define B2056_TX_TXLPF_RCCAL_OFF6 0x70 +#define B2056_TX_TXLPF_BW 0x71 +#define B2056_TX_TXLPF_GAIN 0x72 +#define B2056_TX_TXLPF_IDAC 0x73 +#define B2056_TX_TXLPF_IDAC_0 0x74 +#define B2056_TX_TXLPF_IDAC_1 0x75 +#define B2056_TX_TXLPF_IDAC_2 0x76 +#define B2056_TX_TXLPF_IDAC_3 0x77 +#define B2056_TX_TXLPF_IDAC_4 0x78 +#define B2056_TX_TXLPF_IDAC_5 0x79 +#define B2056_TX_TXLPF_IDAC_6 0x7A +#define B2056_TX_TXLPF_OPAMP_IDAC 0x7B +#define B2056_TX_TXLPF_MISC 0x7C +#define B2056_TX_TXSPARE1 0x7D +#define B2056_TX_TXSPARE2 0x7E +#define B2056_TX_TXSPARE3 0x7F +#define B2056_TX_TXSPARE4 0x80 +#define B2056_TX_TXSPARE5 0x81 +#define B2056_TX_TXSPARE6 0x82 +#define B2056_TX_TXSPARE7 0x83 +#define B2056_TX_TXSPARE8 0x84 +#define B2056_TX_TXSPARE9 0x85 +#define B2056_TX_TXSPARE10 0x86 +#define B2056_TX_TXSPARE11 0x87 +#define B2056_TX_TXSPARE12 0x88 +#define B2056_TX_TXSPARE13 0x89 +#define B2056_TX_TXSPARE14 0x8A +#define B2056_TX_TXSPARE15 0x8B +#define B2056_TX_TXSPARE16 0x8C +#define B2056_TX_STATUS_INTPA_GAIN 0x8D +#define B2056_TX_STATUS_PAD_GAIN 0x8E +#define B2056_TX_STATUS_PGA_GAIN 0x8F +#define B2056_TX_STATUS_GM_TXLPF_GAIN 0x90 +#define B2056_TX_STATUS_TXLPF_BW 0x91 +#define B2056_TX_STATUS_TXLPF_RC 0x92 +#define B2056_TX_GMBB_IDAC0 0x93 +#define B2056_TX_GMBB_IDAC1 0x94 +#define B2056_TX_GMBB_IDAC2 0x95 +#define B2056_TX_GMBB_IDAC3 0x96 +#define B2056_TX_GMBB_IDAC4 0x97 +#define B2056_TX_GMBB_IDAC5 0x98 +#define B2056_TX_GMBB_IDAC6 0x99 +#define B2056_TX_GMBB_IDAC7 0x9A + +#define B2056_RX_RESERVED_ADDR0 0x00 +#define B2056_RX_IDCODE 0x01 +#define B2056_RX_RESERVED_ADDR2 0x02 +#define B2056_RX_RESERVED_ADDR3 0x03 +#define B2056_RX_RESERVED_ADDR4 0x04 +#define B2056_RX_RESERVED_ADDR5 0x05 +#define B2056_RX_RESERVED_ADDR6 0x06 +#define B2056_RX_RESERVED_ADDR7 0x07 +#define B2056_RX_COM_CTRL 0x08 +#define B2056_RX_COM_PU 0x09 +#define B2056_RX_COM_OVR 0x0A +#define B2056_RX_COM_RESET 0x0B +#define B2056_RX_COM_RCAL 0x0C +#define B2056_RX_COM_RC_RXLPF 0x0D +#define B2056_RX_COM_RC_TXLPF 0x0E +#define B2056_RX_COM_RC_RXHPF 0x0F +#define B2056_RX_RESERVED_ADDR16 0x10 +#define B2056_RX_RESERVED_ADDR17 0x11 +#define B2056_RX_RESERVED_ADDR18 0x12 +#define B2056_RX_RESERVED_ADDR19 0x13 +#define B2056_RX_RESERVED_ADDR20 0x14 +#define B2056_RX_RESERVED_ADDR21 0x15 +#define B2056_RX_RESERVED_ADDR22 0x16 +#define B2056_RX_RESERVED_ADDR23 0x17 +#define B2056_RX_RESERVED_ADDR24 0x18 +#define B2056_RX_RESERVED_ADDR25 0x19 +#define B2056_RX_RESERVED_ADDR26 0x1A +#define B2056_RX_RESERVED_ADDR27 0x1B +#define B2056_RX_RESERVED_ADDR28 0x1C +#define B2056_RX_RESERVED_ADDR29 0x1D +#define B2056_RX_RESERVED_ADDR30 0x1E +#define B2056_RX_RESERVED_ADDR31 0x1F +#define B2056_RX_RXIQCAL_RXMUX 0x20 +#define B2056_RX_RSSI_PU 0x21 +#define B2056_RX_RSSI_SEL 0x22 +#define B2056_RX_RSSI_GAIN 0x23 +#define B2056_RX_RSSI_NB_IDAC 0x24 +#define B2056_RX_RSSI_WB2I_IDAC_1 0x25 +#define B2056_RX_RSSI_WB2I_IDAC_2 0x26 +#define B2056_RX_RSSI_WB2Q_IDAC_1 0x27 +#define B2056_RX_RSSI_WB2Q_IDAC_2 0x28 +#define B2056_RX_RSSI_POLE 0x29 +#define B2056_RX_RSSI_WB1_IDAC 0x2A +#define B2056_RX_RSSI_MISC 0x2B +#define B2056_RX_LNAA_MASTER 0x2C +#define B2056_RX_LNAA_TUNE 0x2D +#define B2056_RX_LNAA_GAIN 0x2E +#define B2056_RX_LNA_A_SLOPE 0x2F +#define B2056_RX_BIASPOLE_LNAA1_IDAC 0x30 +#define B2056_RX_LNAA2_IDAC 0x31 +#define B2056_RX_LNA1A_MISC 0x32 +#define B2056_RX_LNAG_MASTER 0x33 +#define B2056_RX_LNAG_TUNE 0x34 +#define B2056_RX_LNAG_GAIN 0x35 +#define B2056_RX_LNA_G_SLOPE 0x36 +#define B2056_RX_BIASPOLE_LNAG1_IDAC 0x37 +#define B2056_RX_LNAG2_IDAC 0x38 +#define B2056_RX_LNA1G_MISC 0x39 +#define B2056_RX_MIXA_MASTER 0x3A +#define B2056_RX_MIXA_VCM 0x3B +#define B2056_RX_MIXA_CTRLPTAT 0x3C +#define B2056_RX_MIXA_LOB_BIAS 0x3D +#define B2056_RX_MIXA_CORE_IDAC 0x3E +#define B2056_RX_MIXA_CMFB_IDAC 0x3F +#define B2056_RX_MIXA_BIAS_AUX 0x40 +#define B2056_RX_MIXA_BIAS_MAIN 0x41 +#define B2056_RX_MIXA_BIAS_MISC 0x42 +#define B2056_RX_MIXA_MAST_BIAS 0x43 +#define B2056_RX_MIXG_MASTER 0x44 +#define B2056_RX_MIXG_VCM 0x45 +#define B2056_RX_MIXG_CTRLPTAT 0x46 +#define B2056_RX_MIXG_LOB_BIAS 0x47 +#define B2056_RX_MIXG_CORE_IDAC 0x48 +#define B2056_RX_MIXG_CMFB_IDAC 0x49 +#define B2056_RX_MIXG_BIAS_AUX 0x4A +#define B2056_RX_MIXG_BIAS_MAIN 0x4B +#define B2056_RX_MIXG_BIAS_MISC 0x4C +#define B2056_RX_MIXG_MAST_BIAS 0x4D +#define B2056_RX_TIA_MASTER 0x4E +#define B2056_RX_TIA_IOPAMP 0x4F +#define B2056_RX_TIA_QOPAMP 0x50 +#define B2056_RX_TIA_IMISC 0x51 +#define B2056_RX_TIA_QMISC 0x52 +#define B2056_RX_TIA_GAIN 0x53 +#define B2056_RX_TIA_SPARE1 0x54 +#define B2056_RX_TIA_SPARE2 0x55 +#define B2056_RX_BB_LPF_MASTER 0x56 +#define B2056_RX_AACI_MASTER 0x57 +#define B2056_RX_RXLPF_IDAC 0x58 +#define B2056_RX_RXLPF_OPAMPBIAS_LOWQ 0x59 +#define B2056_RX_RXLPF_OPAMPBIAS_HIGHQ 0x5A +#define B2056_RX_RXLPF_BIAS_DCCANCEL 0x5B +#define B2056_RX_RXLPF_OUTVCM 0x5C +#define B2056_RX_RXLPF_INVCM_BODY 0x5D +#define B2056_RX_RXLPF_CC_OP 0x5E +#define B2056_RX_RXLPF_GAIN 0x5F +#define B2056_RX_RXLPF_Q_BW 0x60 +#define B2056_RX_RXLPF_HP_CORNER_BW 0x61 +#define B2056_RX_RXLPF_RCCAL_HPC 0x62 +#define B2056_RX_RXHPF_OFF0 0x63 +#define B2056_RX_RXHPF_OFF1 0x64 +#define B2056_RX_RXHPF_OFF2 0x65 +#define B2056_RX_RXHPF_OFF3 0x66 +#define B2056_RX_RXHPF_OFF4 0x67 +#define B2056_RX_RXHPF_OFF5 0x68 +#define B2056_RX_RXHPF_OFF6 0x69 +#define B2056_RX_RXHPF_OFF7 0x6A +#define B2056_RX_RXLPF_RCCAL_LPC 0x6B +#define B2056_RX_RXLPF_OFF_0 0x6C +#define B2056_RX_RXLPF_OFF_1 0x6D +#define B2056_RX_RXLPF_OFF_2 0x6E +#define B2056_RX_RXLPF_OFF_3 0x6F +#define B2056_RX_RXLPF_OFF_4 0x70 +#define B2056_RX_UNUSED 0x71 +#define B2056_RX_VGA_MASTER 0x72 +#define B2056_RX_VGA_BIAS 0x73 +#define B2056_RX_VGA_BIAS_DCCANCEL 0x74 +#define B2056_RX_VGA_GAIN 0x75 +#define B2056_RX_VGA_HP_CORNER_BW 0x76 +#define B2056_RX_VGABUF_BIAS 0x77 +#define B2056_RX_VGABUF_GAIN_BW 0x78 +#define B2056_RX_TXFBMIX_A 0x79 +#define B2056_RX_TXFBMIX_G 0x7A +#define B2056_RX_RXSPARE1 0x7B +#define B2056_RX_RXSPARE2 0x7C +#define B2056_RX_RXSPARE3 0x7D +#define B2056_RX_RXSPARE4 0x7E +#define B2056_RX_RXSPARE5 0x7F +#define B2056_RX_RXSPARE6 0x80 +#define B2056_RX_RXSPARE7 0x81 +#define B2056_RX_RXSPARE8 0x82 +#define B2056_RX_RXSPARE9 0x83 +#define B2056_RX_RXSPARE10 0x84 +#define B2056_RX_RXSPARE11 0x85 +#define B2056_RX_RXSPARE12 0x86 +#define B2056_RX_RXSPARE13 0x87 +#define B2056_RX_RXSPARE14 0x88 +#define B2056_RX_RXSPARE15 0x89 +#define B2056_RX_RXSPARE16 0x8A +#define B2056_RX_STATUS_LNAA_GAIN 0x8B +#define B2056_RX_STATUS_LNAG_GAIN 0x8C +#define B2056_RX_STATUS_MIXTIA_GAIN 0x8D +#define B2056_RX_STATUS_RXLPF_GAIN 0x8E +#define B2056_RX_STATUS_VGA_BUF_GAIN 0x8F +#define B2056_RX_STATUS_RXLPF_Q 0x90 +#define B2056_RX_STATUS_RXLPF_BUF_BW 0x91 +#define B2056_RX_STATUS_RXLPF_VGA_HPC 0x92 +#define B2056_RX_STATUS_RXLPF_RC 0x93 +#define B2056_RX_STATUS_HPC_RC 0x94 + +#define B2056_LNA1_A_PU 0x01 +#define B2056_LNA2_A_PU 0x02 +#define B2056_LNA1_G_PU 0x01 +#define B2056_LNA2_G_PU 0x02 +#define B2056_MIXA_PU_I 0x01 +#define B2056_MIXA_PU_Q 0x02 +#define B2056_MIXA_PU_GM 0x10 +#define B2056_MIXG_PU_I 0x01 +#define B2056_MIXG_PU_Q 0x02 +#define B2056_MIXG_PU_GM 0x10 +#define B2056_TIA_PU 0x01 +#define B2056_BB_LPF_PU 0x20 +#define B2056_W1_PU 0x02 +#define B2056_W2_PU 0x04 +#define B2056_NB_PU 0x08 +#define B2056_RSSI_W1_SEL 0x02 +#define B2056_RSSI_W2_SEL 0x04 +#define B2056_RSSI_NB_SEL 0x08 +#define B2056_VCM_MASK 0x1C +#define B2056_RSSI_VCM_SHIFT 0x02 + +#define B2056_SYN (0x0 << 12) +#define B2056_TX0 (0x2 << 12) +#define B2056_TX1 (0x3 << 12) +#define B2056_RX0 (0x6 << 12) +#define B2056_RX1 (0x7 << 12) +#define B2056_ALLTX (0xE << 12) +#define B2056_ALLRX (0xF << 12) + +#define B2056_SYN_RESERVED_ADDR0 0x00 +#define B2056_SYN_IDCODE 0x01 +#define B2056_SYN_RESERVED_ADDR2 0x02 +#define B2056_SYN_RESERVED_ADDR3 0x03 +#define B2056_SYN_RESERVED_ADDR4 0x04 +#define B2056_SYN_RESERVED_ADDR5 0x05 +#define B2056_SYN_RESERVED_ADDR6 0x06 +#define B2056_SYN_RESERVED_ADDR7 0x07 +#define B2056_SYN_COM_CTRL 0x08 +#define B2056_SYN_COM_PU 0x09 +#define B2056_SYN_COM_OVR 0x0A +#define B2056_SYN_COM_RESET 0x0B +#define B2056_SYN_COM_RCAL 0x0C +#define B2056_SYN_COM_RC_RXLPF 0x0D +#define B2056_SYN_COM_RC_TXLPF 0x0E +#define B2056_SYN_COM_RC_RXHPF 0x0F +#define B2056_SYN_RESERVED_ADDR16 0x10 +#define B2056_SYN_RESERVED_ADDR17 0x11 +#define B2056_SYN_RESERVED_ADDR18 0x12 +#define B2056_SYN_RESERVED_ADDR19 0x13 +#define B2056_SYN_RESERVED_ADDR20 0x14 +#define B2056_SYN_RESERVED_ADDR21 0x15 +#define B2056_SYN_RESERVED_ADDR22 0x16 +#define B2056_SYN_RESERVED_ADDR23 0x17 +#define B2056_SYN_RESERVED_ADDR24 0x18 +#define B2056_SYN_RESERVED_ADDR25 0x19 +#define B2056_SYN_RESERVED_ADDR26 0x1A +#define B2056_SYN_RESERVED_ADDR27 0x1B +#define B2056_SYN_RESERVED_ADDR28 0x1C +#define B2056_SYN_RESERVED_ADDR29 0x1D +#define B2056_SYN_RESERVED_ADDR30 0x1E +#define B2056_SYN_RESERVED_ADDR31 0x1F +#define B2056_SYN_GPIO_MASTER1 0x20 +#define B2056_SYN_GPIO_MASTER2 0x21 +#define B2056_SYN_TOPBIAS_MASTER 0x22 +#define B2056_SYN_TOPBIAS_RCAL 0x23 +#define B2056_SYN_AFEREG 0x24 +#define B2056_SYN_TEMPPROCSENSE 0x25 +#define B2056_SYN_TEMPPROCSENSEIDAC 0x26 +#define B2056_SYN_TEMPPROCSENSERCAL 0x27 +#define B2056_SYN_LPO 0x28 +#define B2056_SYN_VDDCAL_MASTER 0x29 +#define B2056_SYN_VDDCAL_IDAC 0x2A +#define B2056_SYN_VDDCAL_STATUS 0x2B +#define B2056_SYN_RCAL_MASTER 0x2C +#define B2056_SYN_RCAL_CODE_OUT 0x2D +#define B2056_SYN_RCCAL_CTRL0 0x2E +#define B2056_SYN_RCCAL_CTRL1 0x2F +#define B2056_SYN_RCCAL_CTRL2 0x30 +#define B2056_SYN_RCCAL_CTRL3 0x31 +#define B2056_SYN_RCCAL_CTRL4 0x32 +#define B2056_SYN_RCCAL_CTRL5 0x33 +#define B2056_SYN_RCCAL_CTRL6 0x34 +#define B2056_SYN_RCCAL_CTRL7 0x35 +#define B2056_SYN_RCCAL_CTRL8 0x36 +#define B2056_SYN_RCCAL_CTRL9 0x37 +#define B2056_SYN_RCCAL_CTRL10 0x38 +#define B2056_SYN_RCCAL_CTRL11 0x39 +#define B2056_SYN_ZCAL_SPARE1 0x3A +#define B2056_SYN_ZCAL_SPARE2 0x3B +#define B2056_SYN_PLL_MAST1 0x3C +#define B2056_SYN_PLL_MAST2 0x3D +#define B2056_SYN_PLL_MAST3 0x3E +#define B2056_SYN_PLL_BIAS_RESET 0x3F +#define B2056_SYN_PLL_XTAL0 0x40 +#define B2056_SYN_PLL_XTAL1 0x41 +#define B2056_SYN_PLL_XTAL3 0x42 +#define B2056_SYN_PLL_XTAL4 0x43 +#define B2056_SYN_PLL_XTAL5 0x44 +#define B2056_SYN_PLL_XTAL6 0x45 +#define B2056_SYN_PLL_REFDIV 0x46 +#define B2056_SYN_PLL_PFD 0x47 +#define B2056_SYN_PLL_CP1 0x48 +#define B2056_SYN_PLL_CP2 0x49 +#define B2056_SYN_PLL_CP3 0x4A +#define B2056_SYN_PLL_LOOPFILTER1 0x4B +#define B2056_SYN_PLL_LOOPFILTER2 0x4C +#define B2056_SYN_PLL_LOOPFILTER3 0x4D +#define B2056_SYN_PLL_LOOPFILTER4 0x4E +#define B2056_SYN_PLL_LOOPFILTER5 0x4F +#define B2056_SYN_PLL_MMD1 0x50 +#define B2056_SYN_PLL_MMD2 0x51 +#define B2056_SYN_PLL_VCO1 0x52 +#define B2056_SYN_PLL_VCO2 0x53 +#define B2056_SYN_PLL_MONITOR1 0x54 +#define B2056_SYN_PLL_MONITOR2 0x55 +#define B2056_SYN_PLL_VCOCAL1 0x56 +#define B2056_SYN_PLL_VCOCAL2 0x57 +#define B2056_SYN_PLL_VCOCAL4 0x58 +#define B2056_SYN_PLL_VCOCAL5 0x59 +#define B2056_SYN_PLL_VCOCAL6 0x5A +#define B2056_SYN_PLL_VCOCAL7 0x5B +#define B2056_SYN_PLL_VCOCAL8 0x5C +#define B2056_SYN_PLL_VCOCAL9 0x5D +#define B2056_SYN_PLL_VCOCAL10 0x5E +#define B2056_SYN_PLL_VCOCAL11 0x5F +#define B2056_SYN_PLL_VCOCAL12 0x60 +#define B2056_SYN_PLL_VCOCAL13 0x61 +#define B2056_SYN_PLL_VREG 0x62 +#define B2056_SYN_PLL_STATUS1 0x63 +#define B2056_SYN_PLL_STATUS2 0x64 +#define B2056_SYN_PLL_STATUS3 0x65 +#define B2056_SYN_LOGEN_PU0 0x66 +#define B2056_SYN_LOGEN_PU1 0x67 +#define B2056_SYN_LOGEN_PU2 0x68 +#define B2056_SYN_LOGEN_PU3 0x69 +#define B2056_SYN_LOGEN_PU5 0x6A +#define B2056_SYN_LOGEN_PU6 0x6B +#define B2056_SYN_LOGEN_PU7 0x6C +#define B2056_SYN_LOGEN_PU8 0x6D +#define B2056_SYN_LOGEN_BIAS_RESET 0x6E +#define B2056_SYN_LOGEN_RCCR1 0x6F +#define B2056_SYN_LOGEN_VCOBUF1 0x70 +#define B2056_SYN_LOGEN_MIXER1 0x71 +#define B2056_SYN_LOGEN_MIXER2 0x72 +#define B2056_SYN_LOGEN_BUF1 0x73 +#define B2056_SYN_LOGENBUF2 0x74 +#define B2056_SYN_LOGEN_BUF3 0x75 +#define B2056_SYN_LOGEN_BUF4 0x76 +#define B2056_SYN_LOGEN_DIV1 0x77 +#define B2056_SYN_LOGEN_DIV2 0x78 +#define B2056_SYN_LOGEN_DIV3 0x79 +#define B2056_SYN_LOGEN_ACL1 0x7A +#define B2056_SYN_LOGEN_ACL2 0x7B +#define B2056_SYN_LOGEN_ACL3 0x7C +#define B2056_SYN_LOGEN_ACL4 0x7D +#define B2056_SYN_LOGEN_ACL5 0x7E +#define B2056_SYN_LOGEN_ACL6 0x7F +#define B2056_SYN_LOGEN_ACLOUT 0x80 +#define B2056_SYN_LOGEN_ACLCAL1 0x81 +#define B2056_SYN_LOGEN_ACLCAL2 0x82 +#define B2056_SYN_LOGEN_ACLCAL3 0x83 +#define B2056_SYN_CALEN 0x84 +#define B2056_SYN_LOGEN_PEAKDET1 0x85 +#define B2056_SYN_LOGEN_CORE_ACL_OVR 0x86 +#define B2056_SYN_LOGEN_RX_DIFF_ACL_OVR 0x87 +#define B2056_SYN_LOGEN_TX_DIFF_ACL_OVR 0x88 +#define B2056_SYN_LOGEN_RX_CMOS_ACL_OVR 0x89 +#define B2056_SYN_LOGEN_TX_CMOS_ACL_OVR 0x8A +#define B2056_SYN_LOGEN_VCOBUF2 0x8B +#define B2056_SYN_LOGEN_MIXER3 0x8C +#define B2056_SYN_LOGEN_BUF5 0x8D +#define B2056_SYN_LOGEN_BUF6 0x8E +#define B2056_SYN_LOGEN_CBUFRX1 0x8F +#define B2056_SYN_LOGEN_CBUFRX2 0x90 +#define B2056_SYN_LOGEN_CBUFRX3 0x91 +#define B2056_SYN_LOGEN_CBUFRX4 0x92 +#define B2056_SYN_LOGEN_CBUFTX1 0x93 +#define B2056_SYN_LOGEN_CBUFTX2 0x94 +#define B2056_SYN_LOGEN_CBUFTX3 0x95 +#define B2056_SYN_LOGEN_CBUFTX4 0x96 +#define B2056_SYN_LOGEN_CMOSRX1 0x97 +#define B2056_SYN_LOGEN_CMOSRX2 0x98 +#define B2056_SYN_LOGEN_CMOSRX3 0x99 +#define B2056_SYN_LOGEN_CMOSRX4 0x9A +#define B2056_SYN_LOGEN_CMOSTX1 0x9B +#define B2056_SYN_LOGEN_CMOSTX2 0x9C +#define B2056_SYN_LOGEN_CMOSTX3 0x9D +#define B2056_SYN_LOGEN_CMOSTX4 0x9E +#define B2056_SYN_LOGEN_VCOBUF2_OVRVAL 0x9F +#define B2056_SYN_LOGEN_MIXER3_OVRVAL 0xA0 +#define B2056_SYN_LOGEN_BUF5_OVRVAL 0xA1 +#define B2056_SYN_LOGEN_BUF6_OVRVAL 0xA2 +#define B2056_SYN_LOGEN_CBUFRX1_OVRVAL 0xA3 +#define B2056_SYN_LOGEN_CBUFRX2_OVRVAL 0xA4 +#define B2056_SYN_LOGEN_CBUFRX3_OVRVAL 0xA5 +#define B2056_SYN_LOGEN_CBUFRX4_OVRVAL 0xA6 +#define B2056_SYN_LOGEN_CBUFTX1_OVRVAL 0xA7 +#define B2056_SYN_LOGEN_CBUFTX2_OVRVAL 0xA8 +#define B2056_SYN_LOGEN_CBUFTX3_OVRVAL 0xA9 +#define B2056_SYN_LOGEN_CBUFTX4_OVRVAL 0xAA +#define B2056_SYN_LOGEN_CMOSRX1_OVRVAL 0xAB +#define B2056_SYN_LOGEN_CMOSRX2_OVRVAL 0xAC +#define B2056_SYN_LOGEN_CMOSRX3_OVRVAL 0xAD +#define B2056_SYN_LOGEN_CMOSRX4_OVRVAL 0xAE +#define B2056_SYN_LOGEN_CMOSTX1_OVRVAL 0xAF +#define B2056_SYN_LOGEN_CMOSTX2_OVRVAL 0xB0 +#define B2056_SYN_LOGEN_CMOSTX3_OVRVAL 0xB1 +#define B2056_SYN_LOGEN_CMOSTX4_OVRVAL 0xB2 +#define B2056_SYN_LOGEN_ACL_WAITCNT 0xB3 +#define B2056_SYN_LOGEN_CORE_CALVALID 0xB4 +#define B2056_SYN_LOGEN_RX_CMOS_CALVALID 0xB5 +#define B2056_SYN_LOGEN_TX_CMOS_VALID 0xB6 + +#define B2056_TX_RESERVED_ADDR0 0x00 +#define B2056_TX_IDCODE 0x01 +#define B2056_TX_RESERVED_ADDR2 0x02 +#define B2056_TX_RESERVED_ADDR3 0x03 +#define B2056_TX_RESERVED_ADDR4 0x04 +#define B2056_TX_RESERVED_ADDR5 0x05 +#define B2056_TX_RESERVED_ADDR6 0x06 +#define B2056_TX_RESERVED_ADDR7 0x07 +#define B2056_TX_COM_CTRL 0x08 +#define B2056_TX_COM_PU 0x09 +#define B2056_TX_COM_OVR 0x0A +#define B2056_TX_COM_RESET 0x0B +#define B2056_TX_COM_RCAL 0x0C +#define B2056_TX_COM_RC_RXLPF 0x0D +#define B2056_TX_COM_RC_TXLPF 0x0E +#define B2056_TX_COM_RC_RXHPF 0x0F +#define B2056_TX_RESERVED_ADDR16 0x10 +#define B2056_TX_RESERVED_ADDR17 0x11 +#define B2056_TX_RESERVED_ADDR18 0x12 +#define B2056_TX_RESERVED_ADDR19 0x13 +#define B2056_TX_RESERVED_ADDR20 0x14 +#define B2056_TX_RESERVED_ADDR21 0x15 +#define B2056_TX_RESERVED_ADDR22 0x16 +#define B2056_TX_RESERVED_ADDR23 0x17 +#define B2056_TX_RESERVED_ADDR24 0x18 +#define B2056_TX_RESERVED_ADDR25 0x19 +#define B2056_TX_RESERVED_ADDR26 0x1A +#define B2056_TX_RESERVED_ADDR27 0x1B +#define B2056_TX_RESERVED_ADDR28 0x1C +#define B2056_TX_RESERVED_ADDR29 0x1D +#define B2056_TX_RESERVED_ADDR30 0x1E +#define B2056_TX_RESERVED_ADDR31 0x1F +#define B2056_TX_IQCAL_GAIN_BW 0x20 +#define B2056_TX_LOFT_FINE_I 0x21 +#define B2056_TX_LOFT_FINE_Q 0x22 +#define B2056_TX_LOFT_COARSE_I 0x23 +#define B2056_TX_LOFT_COARSE_Q 0x24 +#define B2056_TX_TX_COM_MASTER1 0x25 +#define B2056_TX_TX_COM_MASTER2 0x26 +#define B2056_TX_RXIQCAL_TXMUX 0x27 +#define B2056_TX_TX_SSI_MASTER 0x28 +#define B2056_TX_IQCAL_VCM_HG 0x29 +#define B2056_TX_IQCAL_IDAC 0x2A +#define B2056_TX_TSSI_VCM 0x2B +#define B2056_TX_TX_AMP_DET 0x2C +#define B2056_TX_TX_SSI_MUX 0x2D +#define B2056_TX_TSSIA 0x2E +#define B2056_TX_TSSIG 0x2F +#define B2056_TX_TSSI_MISC1 0x30 +#define B2056_TX_TSSI_MISC2 0x31 +#define B2056_TX_TSSI_MISC3 0x32 +#define B2056_TX_PA_SPARE1 0x33 +#define B2056_TX_PA_SPARE2 0x34 +#define B2056_TX_INTPAA_MASTER 0x35 +#define B2056_TX_INTPAA_GAIN 0x36 +#define B2056_TX_INTPAA_BOOST_TUNE 0x37 +#define B2056_TX_INTPAA_IAUX_STAT 0x38 +#define B2056_TX_INTPAA_IAUX_DYN 0x39 +#define B2056_TX_INTPAA_IMAIN_STAT 0x3A +#define B2056_TX_INTPAA_IMAIN_DYN 0x3B +#define B2056_TX_INTPAA_CASCBIAS 0x3C +#define B2056_TX_INTPAA_PASLOPE 0x3D +#define B2056_TX_INTPAA_PA_MISC 0x3E +#define B2056_TX_INTPAG_MASTER 0x3F +#define B2056_TX_INTPAG_GAIN 0x40 +#define B2056_TX_INTPAG_BOOST_TUNE 0x41 +#define B2056_TX_INTPAG_IAUX_STAT 0x42 +#define B2056_TX_INTPAG_IAUX_DYN 0x43 +#define B2056_TX_INTPAG_IMAIN_STAT 0x44 +#define B2056_TX_INTPAG_IMAIN_DYN 0x45 +#define B2056_TX_INTPAG_CASCBIAS 0x46 +#define B2056_TX_INTPAG_PASLOPE 0x47 +#define B2056_TX_INTPAG_PA_MISC 0x48 +#define B2056_TX_PADA_MASTER 0x49 +#define B2056_TX_PADA_IDAC 0x4A +#define B2056_TX_PADA_CASCBIAS 0x4B +#define B2056_TX_PADA_GAIN 0x4C +#define B2056_TX_PADA_BOOST_TUNE 0x4D +#define B2056_TX_PADA_SLOPE 0x4E +#define B2056_TX_PADG_MASTER 0x4F +#define B2056_TX_PADG_IDAC 0x50 +#define B2056_TX_PADG_CASCBIAS 0x51 +#define B2056_TX_PADG_GAIN 0x52 +#define B2056_TX_PADG_BOOST_TUNE 0x53 +#define B2056_TX_PADG_SLOPE 0x54 +#define B2056_TX_PGAA_MASTER 0x55 +#define B2056_TX_PGAA_IDAC 0x56 +#define B2056_TX_PGAA_GAIN 0x57 +#define B2056_TX_PGAA_BOOST_TUNE 0x58 +#define B2056_TX_PGAA_SLOPE 0x59 +#define B2056_TX_PGAA_MISC 0x5A +#define B2056_TX_PGAG_MASTER 0x5B +#define B2056_TX_PGAG_IDAC 0x5C +#define B2056_TX_PGAG_GAIN 0x5D +#define B2056_TX_PGAG_BOOST_TUNE 0x5E +#define B2056_TX_PGAG_SLOPE 0x5F +#define B2056_TX_PGAG_MISC 0x60 +#define B2056_TX_MIXA_MASTER 0x61 +#define B2056_TX_MIXA_BOOST_TUNE 0x62 +#define B2056_TX_MIXG 0x63 +#define B2056_TX_MIXG_BOOST_TUNE 0x64 +#define B2056_TX_BB_GM_MASTER 0x65 +#define B2056_TX_GMBB_GM 0x66 +#define B2056_TX_GMBB_IDAC 0x67 +#define B2056_TX_TXLPF_MASTER 0x68 +#define B2056_TX_TXLPF_RCCAL 0x69 +#define B2056_TX_TXLPF_RCCAL_OFF0 0x6A +#define B2056_TX_TXLPF_RCCAL_OFF1 0x6B +#define B2056_TX_TXLPF_RCCAL_OFF2 0x6C +#define B2056_TX_TXLPF_RCCAL_OFF3 0x6D +#define B2056_TX_TXLPF_RCCAL_OFF4 0x6E +#define B2056_TX_TXLPF_RCCAL_OFF5 0x6F +#define B2056_TX_TXLPF_RCCAL_OFF6 0x70 +#define B2056_TX_TXLPF_BW 0x71 +#define B2056_TX_TXLPF_GAIN 0x72 +#define B2056_TX_TXLPF_IDAC 0x73 +#define B2056_TX_TXLPF_IDAC_0 0x74 +#define B2056_TX_TXLPF_IDAC_1 0x75 +#define B2056_TX_TXLPF_IDAC_2 0x76 +#define B2056_TX_TXLPF_IDAC_3 0x77 +#define B2056_TX_TXLPF_IDAC_4 0x78 +#define B2056_TX_TXLPF_IDAC_5 0x79 +#define B2056_TX_TXLPF_IDAC_6 0x7A +#define B2056_TX_TXLPF_OPAMP_IDAC 0x7B +#define B2056_TX_TXLPF_MISC 0x7C +#define B2056_TX_TXSPARE1 0x7D +#define B2056_TX_TXSPARE2 0x7E +#define B2056_TX_TXSPARE3 0x7F +#define B2056_TX_TXSPARE4 0x80 +#define B2056_TX_TXSPARE5 0x81 +#define B2056_TX_TXSPARE6 0x82 +#define B2056_TX_TXSPARE7 0x83 +#define B2056_TX_TXSPARE8 0x84 +#define B2056_TX_TXSPARE9 0x85 +#define B2056_TX_TXSPARE10 0x86 +#define B2056_TX_TXSPARE11 0x87 +#define B2056_TX_TXSPARE12 0x88 +#define B2056_TX_TXSPARE13 0x89 +#define B2056_TX_TXSPARE14 0x8A +#define B2056_TX_TXSPARE15 0x8B +#define B2056_TX_TXSPARE16 0x8C +#define B2056_TX_STATUS_INTPA_GAIN 0x8D +#define B2056_TX_STATUS_PAD_GAIN 0x8E +#define B2056_TX_STATUS_PGA_GAIN 0x8F +#define B2056_TX_STATUS_GM_TXLPF_GAIN 0x90 +#define B2056_TX_STATUS_TXLPF_BW 0x91 +#define B2056_TX_STATUS_TXLPF_RC 0x92 +#define B2056_TX_GMBB_IDAC0 0x93 +#define B2056_TX_GMBB_IDAC1 0x94 +#define B2056_TX_GMBB_IDAC2 0x95 +#define B2056_TX_GMBB_IDAC3 0x96 +#define B2056_TX_GMBB_IDAC4 0x97 +#define B2056_TX_GMBB_IDAC5 0x98 +#define B2056_TX_GMBB_IDAC6 0x99 +#define B2056_TX_GMBB_IDAC7 0x9A + +#define B2056_RX_RESERVED_ADDR0 0x00 +#define B2056_RX_IDCODE 0x01 +#define B2056_RX_RESERVED_ADDR2 0x02 +#define B2056_RX_RESERVED_ADDR3 0x03 +#define B2056_RX_RESERVED_ADDR4 0x04 +#define B2056_RX_RESERVED_ADDR5 0x05 +#define B2056_RX_RESERVED_ADDR6 0x06 +#define B2056_RX_RESERVED_ADDR7 0x07 +#define B2056_RX_COM_CTRL 0x08 +#define B2056_RX_COM_PU 0x09 +#define B2056_RX_COM_OVR 0x0A +#define B2056_RX_COM_RESET 0x0B +#define B2056_RX_COM_RCAL 0x0C +#define B2056_RX_COM_RC_RXLPF 0x0D +#define B2056_RX_COM_RC_TXLPF 0x0E +#define B2056_RX_COM_RC_RXHPF 0x0F +#define B2056_RX_RESERVED_ADDR16 0x10 +#define B2056_RX_RESERVED_ADDR17 0x11 +#define B2056_RX_RESERVED_ADDR18 0x12 +#define B2056_RX_RESERVED_ADDR19 0x13 +#define B2056_RX_RESERVED_ADDR20 0x14 +#define B2056_RX_RESERVED_ADDR21 0x15 +#define B2056_RX_RESERVED_ADDR22 0x16 +#define B2056_RX_RESERVED_ADDR23 0x17 +#define B2056_RX_RESERVED_ADDR24 0x18 +#define B2056_RX_RESERVED_ADDR25 0x19 +#define B2056_RX_RESERVED_ADDR26 0x1A +#define B2056_RX_RESERVED_ADDR27 0x1B +#define B2056_RX_RESERVED_ADDR28 0x1C +#define B2056_RX_RESERVED_ADDR29 0x1D +#define B2056_RX_RESERVED_ADDR30 0x1E +#define B2056_RX_RESERVED_ADDR31 0x1F +#define B2056_RX_RXIQCAL_RXMUX 0x20 +#define B2056_RX_RSSI_PU 0x21 +#define B2056_RX_RSSI_SEL 0x22 +#define B2056_RX_RSSI_GAIN 0x23 +#define B2056_RX_RSSI_NB_IDAC 0x24 +#define B2056_RX_RSSI_WB2I_IDAC_1 0x25 +#define B2056_RX_RSSI_WB2I_IDAC_2 0x26 +#define B2056_RX_RSSI_WB2Q_IDAC_1 0x27 +#define B2056_RX_RSSI_WB2Q_IDAC_2 0x28 +#define B2056_RX_RSSI_POLE 0x29 +#define B2056_RX_RSSI_WB1_IDAC 0x2A +#define B2056_RX_RSSI_MISC 0x2B +#define B2056_RX_LNAA_MASTER 0x2C +#define B2056_RX_LNAA_TUNE 0x2D +#define B2056_RX_LNAA_GAIN 0x2E +#define B2056_RX_LNA_A_SLOPE 0x2F +#define B2056_RX_BIASPOLE_LNAA1_IDAC 0x30 +#define B2056_RX_LNAA2_IDAC 0x31 +#define B2056_RX_LNA1A_MISC 0x32 +#define B2056_RX_LNAG_MASTER 0x33 +#define B2056_RX_LNAG_TUNE 0x34 +#define B2056_RX_LNAG_GAIN 0x35 +#define B2056_RX_LNA_G_SLOPE 0x36 +#define B2056_RX_BIASPOLE_LNAG1_IDAC 0x37 +#define B2056_RX_LNAG2_IDAC 0x38 +#define B2056_RX_LNA1G_MISC 0x39 +#define B2056_RX_MIXA_MASTER 0x3A +#define B2056_RX_MIXA_VCM 0x3B +#define B2056_RX_MIXA_CTRLPTAT 0x3C +#define B2056_RX_MIXA_LOB_BIAS 0x3D +#define B2056_RX_MIXA_CORE_IDAC 0x3E +#define B2056_RX_MIXA_CMFB_IDAC 0x3F +#define B2056_RX_MIXA_BIAS_AUX 0x40 +#define B2056_RX_MIXA_BIAS_MAIN 0x41 +#define B2056_RX_MIXA_BIAS_MISC 0x42 +#define B2056_RX_MIXA_MAST_BIAS 0x43 +#define B2056_RX_MIXG_MASTER 0x44 +#define B2056_RX_MIXG_VCM 0x45 +#define B2056_RX_MIXG_CTRLPTAT 0x46 +#define B2056_RX_MIXG_LOB_BIAS 0x47 +#define B2056_RX_MIXG_CORE_IDAC 0x48 +#define B2056_RX_MIXG_CMFB_IDAC 0x49 +#define B2056_RX_MIXG_BIAS_AUX 0x4A +#define B2056_RX_MIXG_BIAS_MAIN 0x4B +#define B2056_RX_MIXG_BIAS_MISC 0x4C +#define B2056_RX_MIXG_MAST_BIAS 0x4D +#define B2056_RX_TIA_MASTER 0x4E +#define B2056_RX_TIA_IOPAMP 0x4F +#define B2056_RX_TIA_QOPAMP 0x50 +#define B2056_RX_TIA_IMISC 0x51 +#define B2056_RX_TIA_QMISC 0x52 +#define B2056_RX_TIA_GAIN 0x53 +#define B2056_RX_TIA_SPARE1 0x54 +#define B2056_RX_TIA_SPARE2 0x55 +#define B2056_RX_BB_LPF_MASTER 0x56 +#define B2056_RX_AACI_MASTER 0x57 +#define B2056_RX_RXLPF_IDAC 0x58 +#define B2056_RX_RXLPF_OPAMPBIAS_LOWQ 0x59 +#define B2056_RX_RXLPF_OPAMPBIAS_HIGHQ 0x5A +#define B2056_RX_RXLPF_BIAS_DCCANCEL 0x5B +#define B2056_RX_RXLPF_OUTVCM 0x5C +#define B2056_RX_RXLPF_INVCM_BODY 0x5D +#define B2056_RX_RXLPF_CC_OP 0x5E +#define B2056_RX_RXLPF_GAIN 0x5F +#define B2056_RX_RXLPF_Q_BW 0x60 +#define B2056_RX_RXLPF_HP_CORNER_BW 0x61 +#define B2056_RX_RXLPF_RCCAL_HPC 0x62 +#define B2056_RX_RXHPF_OFF0 0x63 +#define B2056_RX_RXHPF_OFF1 0x64 +#define B2056_RX_RXHPF_OFF2 0x65 +#define B2056_RX_RXHPF_OFF3 0x66 +#define B2056_RX_RXHPF_OFF4 0x67 +#define B2056_RX_RXHPF_OFF5 0x68 +#define B2056_RX_RXHPF_OFF6 0x69 +#define B2056_RX_RXHPF_OFF7 0x6A +#define B2056_RX_RXLPF_RCCAL_LPC 0x6B +#define B2056_RX_RXLPF_OFF_0 0x6C +#define B2056_RX_RXLPF_OFF_1 0x6D +#define B2056_RX_RXLPF_OFF_2 0x6E +#define B2056_RX_RXLPF_OFF_3 0x6F +#define B2056_RX_RXLPF_OFF_4 0x70 +#define B2056_RX_UNUSED 0x71 +#define B2056_RX_VGA_MASTER 0x72 +#define B2056_RX_VGA_BIAS 0x73 +#define B2056_RX_VGA_BIAS_DCCANCEL 0x74 +#define B2056_RX_VGA_GAIN 0x75 +#define B2056_RX_VGA_HP_CORNER_BW 0x76 +#define B2056_RX_VGABUF_BIAS 0x77 +#define B2056_RX_VGABUF_GAIN_BW 0x78 +#define B2056_RX_TXFBMIX_A 0x79 +#define B2056_RX_TXFBMIX_G 0x7A +#define B2056_RX_RXSPARE1 0x7B +#define B2056_RX_RXSPARE2 0x7C +#define B2056_RX_RXSPARE3 0x7D +#define B2056_RX_RXSPARE4 0x7E +#define B2056_RX_RXSPARE5 0x7F +#define B2056_RX_RXSPARE6 0x80 +#define B2056_RX_RXSPARE7 0x81 +#define B2056_RX_RXSPARE8 0x82 +#define B2056_RX_RXSPARE9 0x83 +#define B2056_RX_RXSPARE10 0x84 +#define B2056_RX_RXSPARE11 0x85 +#define B2056_RX_RXSPARE12 0x86 +#define B2056_RX_RXSPARE13 0x87 +#define B2056_RX_RXSPARE14 0x88 +#define B2056_RX_RXSPARE15 0x89 +#define B2056_RX_RXSPARE16 0x8A +#define B2056_RX_STATUS_LNAA_GAIN 0x8B +#define B2056_RX_STATUS_LNAG_GAIN 0x8C +#define B2056_RX_STATUS_MIXTIA_GAIN 0x8D +#define B2056_RX_STATUS_RXLPF_GAIN 0x8E +#define B2056_RX_STATUS_VGA_BUF_GAIN 0x8F +#define B2056_RX_STATUS_RXLPF_Q 0x90 +#define B2056_RX_STATUS_RXLPF_BUF_BW 0x91 +#define B2056_RX_STATUS_RXLPF_VGA_HPC 0x92 +#define B2056_RX_STATUS_RXLPF_RC 0x93 +#define B2056_RX_STATUS_HPC_RC 0x94 + +#define B2056_LNA1_A_PU 0x01 +#define B2056_LNA2_A_PU 0x02 +#define B2056_LNA1_G_PU 0x01 +#define B2056_LNA2_G_PU 0x02 +#define B2056_MIXA_PU_I 0x01 +#define B2056_MIXA_PU_Q 0x02 +#define B2056_MIXA_PU_GM 0x10 +#define B2056_MIXG_PU_I 0x01 +#define B2056_MIXG_PU_Q 0x02 +#define B2056_MIXG_PU_GM 0x10 +#define B2056_TIA_PU 0x01 +#define B2056_BB_LPF_PU 0x20 +#define B2056_W1_PU 0x02 +#define B2056_W2_PU 0x04 +#define B2056_NB_PU 0x08 +#define B2056_RSSI_W1_SEL 0x02 +#define B2056_RSSI_W2_SEL 0x04 +#define B2056_RSSI_NB_SEL 0x08 +#define B2056_VCM_MASK 0x1C +#define B2056_RSSI_VCM_SHIFT 0x02 + struct b43_nphy_channeltab_entry_rev3 { - /* The channel number */ - u8 channel; /* The channel frequency in MHz */ u16 freq; /* Radio register values on channelswitch */ - /* TODO */ + u8 radio_syn_pll_vcocal1; + u8 radio_syn_pll_vcocal2; + u8 radio_syn_pll_refdiv; + u8 radio_syn_pll_mmd2; + u8 radio_syn_pll_mmd1; + u8 radio_syn_pll_loopfilter1; + u8 radio_syn_pll_loopfilter2; + u8 radio_syn_pll_loopfilter3; + u8 radio_syn_pll_loopfilter4; + u8 radio_syn_pll_loopfilter5; + u8 radio_syn_reserved_addr27; + u8 radio_syn_reserved_addr28; + u8 radio_syn_reserved_addr29; + u8 radio_syn_logen_vcobuf1; + u8 radio_syn_logen_mixer2; + u8 radio_syn_logen_buf3; + u8 radio_syn_logen_buf4; + u8 radio_rx0_lnaa_tune; + u8 radio_rx0_lnag_tune; + u8 radio_tx0_intpaa_boost_tune; + u8 radio_tx0_intpag_boost_tune; + u8 radio_tx0_pada_boost_tune; + u8 radio_tx0_padg_boost_tune; + u8 radio_tx0_pgaa_boost_tune; + u8 radio_tx0_pgag_boost_tune; + u8 radio_tx0_mixa_boost_tune; + u8 radio_tx0_mixg_boost_tune; + u8 radio_rx1_lnaa_tune; + u8 radio_rx1_lnag_tune; + u8 radio_tx1_intpaa_boost_tune; + u8 radio_tx1_intpag_boost_tune; + u8 radio_tx1_pada_boost_tune; + u8 radio_tx1_padg_boost_tune; + u8 radio_tx1_pgaa_boost_tune; + u8 radio_tx1_pgag_boost_tune; + u8 radio_tx1_mixa_boost_tune; + u8 radio_tx1_mixg_boost_tune; /* PHY register values on channelswitch */ struct b43_phy_n_sfo_cfg phy_regs; }; +void b2056_upload_inittabs(struct b43_wldev *dev, + bool ghz5, bool ignore_uploadflag); + #endif /* B43_RADIO_2056_H_ */ diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 78016ae21c50..86bc0a0f735c 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -28,23 +28,8 @@ /* Returns TRUE, if the radio is enabled in hardware. */ bool b43_is_hw_radio_enabled(struct b43_wldev *dev) { - if (dev->phy.rev >= 3 || dev->phy.type == B43_PHYTYPE_LP) { - if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) - & B43_MMIO_RADIO_HWENABLED_HI_MASK)) - return 1; - } else { - /* To prevent CPU fault on PPC, do not read a register - * unless the interface is started; however, on resume - * for hibernation, this routine is entered early. When - * that happens, unconditionally return TRUE. - */ - if (b43_status(dev) < B43_STAT_STARTED) - return 1; - if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO) - & B43_MMIO_RADIO_HWENABLED_LO_MASK) - return 1; - } - return 0; + return !(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) + & B43_MMIO_RADIO_HWENABLED_HI_MASK); } /* The poll callback for the hardware button. */ diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index d60db078eae2..dc8ef09a8552 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -28,41 +28,41 @@ #include "phy_n.h" static const u8 b43_ntab_adjustpower0[] = { - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, - 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, - 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, - 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, - 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, - 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, - 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, - 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, - 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, - 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1B, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, 0x1D, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static const u8 b43_ntab_adjustpower1[] = { - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, - 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, - 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, - 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, - 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, - 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, - 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, - 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, - 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, - 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1B, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, 0x1D, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static const u16 b43_ntab_bdi[] = { @@ -130,8 +130,8 @@ static const u32 b43_ntab_framestruct[] = { 0x09804506, 0x00100030, 0x09804507, 0x00100030, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x08004A0C, 0x00100008, 0x01000A0D, 0x00100028, - 0x0980450E, 0x00100038, 0x0980450F, 0x00100038, + 0x08004A0C, 0x00100004, 0x01000A0D, 0x00100024, + 0x0980450E, 0x00100034, 0x0980450F, 0x00100034, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000A04, 0x00100000, 0x11008A05, 0x00100020, @@ -202,13 +202,13 @@ static const u32 b43_ntab_framestruct[] = { 0x53028A06, 0x01900060, 0x53028A07, 0x01900060, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4002140C, 0x000F4810, 0x6203140D, 0x00100050, - 0x53028A0E, 0x01900070, 0x53028A0F, 0x01900070, + 0x4002140C, 0x000F4808, 0x6203140D, 0x00100048, + 0x53028A0E, 0x01900068, 0x53028A0F, 0x01900068, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000A0C, 0x00100008, 0x11008A0D, 0x00100028, - 0x1980C50E, 0x00100038, 0x2181050E, 0x00100038, - 0x2181050E, 0x00100038, 0x0180050C, 0x00100038, + 0x00000A0C, 0x00100004, 0x11008A0D, 0x00100024, + 0x1980C50E, 0x00100034, 0x2181050E, 0x00100034, + 0x2181050E, 0x00100034, 0x0180050C, 0x00100038, 0x1180850D, 0x00100038, 0x1181850D, 0x00100038, 0x2981450F, 0x01100038, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -238,9 +238,9 @@ static const u32 b43_ntab_framestruct[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4002140C, 0x00100010, 0x0200140D, 0x00100050, - 0x0B004A0E, 0x01900070, 0x13008A0E, 0x01900070, - 0x13008A0E, 0x01900070, 0x43020A0C, 0x00100070, + 0x4002140C, 0x00100008, 0x0200140D, 0x00100048, + 0x0B004A0E, 0x01900068, 0x13008A0E, 0x01900068, + 0x13008A0E, 0x01900068, 0x43020A0C, 0x00100070, 0x1B00CA0D, 0x00100070, 0x1B014A0D, 0x00100070, 0x23010A0F, 0x01500070, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -337,73 +337,73 @@ static const u32 b43_ntab_framestruct[] = { }; static const u32 b43_ntab_gainctl0[] = { - 0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E, - 0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C, - 0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A, - 0x00730C39, 0x00720D39, 0x00710E38, 0x00700F38, - 0x006F0037, 0x006E0137, 0x006D0236, 0x006C0336, - 0x006B0435, 0x006A0535, 0x00690634, 0x00680734, - 0x00670833, 0x00660933, 0x00650A32, 0x00640B32, - 0x00630C31, 0x00620D31, 0x00610E30, 0x00600F30, - 0x005F002F, 0x005E012F, 0x005D022E, 0x005C032E, - 0x005B042D, 0x005A052D, 0x0059062C, 0x0058072C, - 0x0057082B, 0x0056092B, 0x00550A2A, 0x00540B2A, - 0x00530C29, 0x00520D29, 0x00510E28, 0x00500F28, - 0x004F0027, 0x004E0127, 0x004D0226, 0x004C0326, - 0x004B0425, 0x004A0525, 0x00490624, 0x00480724, - 0x00470823, 0x00460923, 0x00450A22, 0x00440B22, - 0x00430C21, 0x00420D21, 0x00410E20, 0x00400F20, - 0x003F001F, 0x003E011F, 0x003D021E, 0x003C031E, - 0x003B041D, 0x003A051D, 0x0039061C, 0x0038071C, - 0x0037081B, 0x0036091B, 0x00350A1A, 0x00340B1A, - 0x00330C19, 0x00320D19, 0x00310E18, 0x00300F18, - 0x002F0017, 0x002E0117, 0x002D0216, 0x002C0316, - 0x002B0415, 0x002A0515, 0x00290614, 0x00280714, - 0x00270813, 0x00260913, 0x00250A12, 0x00240B12, - 0x00230C11, 0x00220D11, 0x00210E10, 0x00200F10, - 0x001F000F, 0x001E010F, 0x001D020E, 0x001C030E, - 0x001B040D, 0x001A050D, 0x0019060C, 0x0018070C, - 0x0017080B, 0x0016090B, 0x00150A0A, 0x00140B0A, - 0x00130C09, 0x00120D09, 0x00110E08, 0x00100F08, - 0x000F0007, 0x000E0107, 0x000D0206, 0x000C0306, - 0x000B0405, 0x000A0505, 0x00090604, 0x00080704, - 0x00070803, 0x00060903, 0x00050A02, 0x00040B02, - 0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00, + 0x03CC2B44, 0x03CC2B42, 0x03CC2B40, 0x03CC2B3E, + 0x03CC2B3D, 0x03CC2B3B, 0x03C82B44, 0x03C82B42, + 0x03C82B40, 0x03C82B3E, 0x03C82B3D, 0x03C82B3B, + 0x03C82B39, 0x03C82B38, 0x03C82B36, 0x03C82B34, + 0x03C42B44, 0x03C42B42, 0x03C42B40, 0x03C42B3E, + 0x03C42B3D, 0x03C42B3B, 0x03C42B39, 0x03C42B38, + 0x03C42B36, 0x03C42B34, 0x03C42B33, 0x03C42B32, + 0x03C42B30, 0x03C42B2F, 0x03C42B2D, 0x03C02B44, + 0x03C02B42, 0x03C02B40, 0x03C02B3E, 0x03C02B3D, + 0x03C02B3B, 0x03C02B39, 0x03C02B38, 0x03C02B36, + 0x03C02B34, 0x03B02B44, 0x03B02B42, 0x03B02B40, + 0x03B02B3E, 0x03B02B3D, 0x03B02B3B, 0x03B02B39, + 0x03B02B38, 0x03B02B36, 0x03B02B34, 0x03B02B33, + 0x03B02B32, 0x03B02B30, 0x03B02B2F, 0x03B02B2D, + 0x03A02B44, 0x03A02B42, 0x03A02B40, 0x03A02B3E, + 0x03A02B3D, 0x03A02B3B, 0x03A02B39, 0x03A02B38, + 0x03A02B36, 0x03A02B34, 0x03902B44, 0x03902B42, + 0x03902B40, 0x03902B3E, 0x03902B3D, 0x03902B3B, + 0x03902B39, 0x03902B38, 0x03902B36, 0x03902B34, + 0x03902B33, 0x03902B32, 0x03902B30, 0x03802B44, + 0x03802B42, 0x03802B40, 0x03802B3E, 0x03802B3D, + 0x03802B3B, 0x03802B39, 0x03802B38, 0x03802B36, + 0x03802B34, 0x03802B33, 0x03802B32, 0x03802B30, + 0x03802B2F, 0x03802B2D, 0x03802B2C, 0x03802B2B, + 0x03802B2A, 0x03802B29, 0x03802B27, 0x03802B26, + 0x03802B25, 0x03802B24, 0x03802B23, 0x03802B22, + 0x03802B21, 0x03802B20, 0x03802B1F, 0x03802B1E, + 0x03802B1E, 0x03802B1D, 0x03802B1C, 0x03802B1B, + 0x03802B1A, 0x03802B1A, 0x03802B19, 0x03802B18, + 0x03802B18, 0x03802B18, 0x03802B18, 0x03802B18, + 0x03802B18, 0x03802B18, 0x03802B18, 0x03802B18, + 0x03802B18, 0x03802B18, 0x03802B18, 0x00002B00, }; static const u32 b43_ntab_gainctl1[] = { - 0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E, - 0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C, - 0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A, - 0x00730C39, 0x00720D39, 0x00710E38, 0x00700F38, - 0x006F0037, 0x006E0137, 0x006D0236, 0x006C0336, - 0x006B0435, 0x006A0535, 0x00690634, 0x00680734, - 0x00670833, 0x00660933, 0x00650A32, 0x00640B32, - 0x00630C31, 0x00620D31, 0x00610E30, 0x00600F30, - 0x005F002F, 0x005E012F, 0x005D022E, 0x005C032E, - 0x005B042D, 0x005A052D, 0x0059062C, 0x0058072C, - 0x0057082B, 0x0056092B, 0x00550A2A, 0x00540B2A, - 0x00530C29, 0x00520D29, 0x00510E28, 0x00500F28, - 0x004F0027, 0x004E0127, 0x004D0226, 0x004C0326, - 0x004B0425, 0x004A0525, 0x00490624, 0x00480724, - 0x00470823, 0x00460923, 0x00450A22, 0x00440B22, - 0x00430C21, 0x00420D21, 0x00410E20, 0x00400F20, - 0x003F001F, 0x003E011F, 0x003D021E, 0x003C031E, - 0x003B041D, 0x003A051D, 0x0039061C, 0x0038071C, - 0x0037081B, 0x0036091B, 0x00350A1A, 0x00340B1A, - 0x00330C19, 0x00320D19, 0x00310E18, 0x00300F18, - 0x002F0017, 0x002E0117, 0x002D0216, 0x002C0316, - 0x002B0415, 0x002A0515, 0x00290614, 0x00280714, - 0x00270813, 0x00260913, 0x00250A12, 0x00240B12, - 0x00230C11, 0x00220D11, 0x00210E10, 0x00200F10, - 0x001F000F, 0x001E010F, 0x001D020E, 0x001C030E, - 0x001B040D, 0x001A050D, 0x0019060C, 0x0018070C, - 0x0017080B, 0x0016090B, 0x00150A0A, 0x00140B0A, - 0x00130C09, 0x00120D09, 0x00110E08, 0x00100F08, - 0x000F0007, 0x000E0107, 0x000D0206, 0x000C0306, - 0x000B0405, 0x000A0505, 0x00090604, 0x00080704, - 0x00070803, 0x00060903, 0x00050A02, 0x00040B02, - 0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00, + 0x03CC2B44, 0x03CC2B42, 0x03CC2B40, 0x03CC2B3E, + 0x03CC2B3D, 0x03CC2B3B, 0x03C82B44, 0x03C82B42, + 0x03C82B40, 0x03C82B3E, 0x03C82B3D, 0x03C82B3B, + 0x03C82B39, 0x03C82B38, 0x03C82B36, 0x03C82B34, + 0x03C42B44, 0x03C42B42, 0x03C42B40, 0x03C42B3E, + 0x03C42B3D, 0x03C42B3B, 0x03C42B39, 0x03C42B38, + 0x03C42B36, 0x03C42B34, 0x03C42B33, 0x03C42B32, + 0x03C42B30, 0x03C42B2F, 0x03C42B2D, 0x03C02B44, + 0x03C02B42, 0x03C02B40, 0x03C02B3E, 0x03C02B3D, + 0x03C02B3B, 0x03C02B39, 0x03C02B38, 0x03C02B36, + 0x03C02B34, 0x03B02B44, 0x03B02B42, 0x03B02B40, + 0x03B02B3E, 0x03B02B3D, 0x03B02B3B, 0x03B02B39, + 0x03B02B38, 0x03B02B36, 0x03B02B34, 0x03B02B33, + 0x03B02B32, 0x03B02B30, 0x03B02B2F, 0x03B02B2D, + 0x03A02B44, 0x03A02B42, 0x03A02B40, 0x03A02B3E, + 0x03A02B3D, 0x03A02B3B, 0x03A02B39, 0x03A02B38, + 0x03A02B36, 0x03A02B34, 0x03902B44, 0x03902B42, + 0x03902B40, 0x03902B3E, 0x03902B3D, 0x03902B3B, + 0x03902B39, 0x03902B38, 0x03902B36, 0x03902B34, + 0x03902B33, 0x03902B32, 0x03902B30, 0x03802B44, + 0x03802B42, 0x03802B40, 0x03802B3E, 0x03802B3D, + 0x03802B3B, 0x03802B39, 0x03802B38, 0x03802B36, + 0x03802B34, 0x03802B33, 0x03802B32, 0x03802B30, + 0x03802B2F, 0x03802B2D, 0x03802B2C, 0x03802B2B, + 0x03802B2A, 0x03802B29, 0x03802B27, 0x03802B26, + 0x03802B25, 0x03802B24, 0x03802B23, 0x03802B22, + 0x03802B21, 0x03802B20, 0x03802B1F, 0x03802B1E, + 0x03802B1E, 0x03802B1D, 0x03802B1C, 0x03802B1B, + 0x03802B1A, 0x03802B1A, 0x03802B19, 0x03802B18, + 0x03802B18, 0x03802B18, 0x03802B18, 0x03802B18, + 0x03802B18, 0x03802B18, 0x03802B18, 0x03802B18, + 0x03802B18, 0x03802B18, 0x03802B18, 0x00002B00, }; static const u32 b43_ntab_intlevel[] = { @@ -1811,9 +1811,7 @@ void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset, } #define ntab_upload(dev, offset, data) do { \ - unsigned int i; \ - for (i = 0; i < (offset##_SIZE); i++) \ - b43_ntab_write(dev, (offset) + i, (data)[i]); \ + b43_ntab_write_bulk(dev, offset, offset##_SIZE, data); \ } while (0) void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev) @@ -1825,24 +1823,24 @@ void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev) ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn); ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel); ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot); - ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt); ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0); ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1); ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0); ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1); - ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi); ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest); ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs); - - /* Volatile tables */ ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10); ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11); + + /* Volatile tables */ + ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi); + ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt); + ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0); + ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1); ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0); ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1); ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0); ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1); - ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0); - ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1); ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0); ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1); ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0); diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 67f18ecdb3bf..1f11e1670bf0 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -181,52 +181,75 @@ static int b43legacy_ratelimit(struct b43legacy_wl *wl) void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (!b43legacy_ratelimit(wl)) return; + va_start(args, fmt); - printk(KERN_INFO "b43legacy-%s: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_INFO "b43legacy-%s: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (!b43legacy_ratelimit(wl)) return; + va_start(args, fmt); - printk(KERN_ERR "b43legacy-%s ERROR: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_ERR "b43legacy-%s ERROR: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (!b43legacy_ratelimit(wl)) return; + va_start(args, fmt); - printk(KERN_WARNING "b43legacy-%s warning: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_WARNING "b43legacy-%s warning: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } #if B43legacy_DEBUG void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; va_start(args, fmt); - printk(KERN_DEBUG "b43legacy-%s debug: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_DEBUG "b43legacy-%s debug: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } #endif /* DEBUG */ diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c index d579df72b783..b90f223fb31c 100644 --- a/drivers/net/wireless/b43legacy/rfkill.c +++ b/drivers/net/wireless/b43legacy/rfkill.c @@ -29,7 +29,7 @@ /* Returns TRUE, if the radio is enabled in hardware. */ bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) { - if (dev->phy.rev >= 3) { + if (dev->dev->id.revision >= 3) { if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI) & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK)) return 1; diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index dbb986946e1a..18d63f57777d 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -858,7 +858,10 @@ void hostap_free_data(struct ap_data *ap) return; } + flush_work_sync(&ap->add_sta_proc_queue); + #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT + flush_work_sync(&ap->wds_oper_queue); if (ap->crypt) ap->crypt->deinit(ap->crypt_priv); ap->crypt = ap->crypt_priv = NULL; diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index b7cb165d612b..a8bddd81b4d1 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -3317,7 +3317,13 @@ static void prism2_free_local_data(struct net_device *dev) unregister_netdev(local->dev); - flush_scheduled_work(); + flush_work_sync(&local->reset_queue); + flush_work_sync(&local->set_multicast_list_queue); + flush_work_sync(&local->set_tim_queue); +#ifndef PRISM2_NO_STATION_MODES + flush_work_sync(&local->info_queue); +#endif + flush_work_sync(&local->comms_qual_update); lib80211_crypt_info_free(&local->crypt_info); diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index b82364258dc5..ed424574160e 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -106,6 +106,9 @@ config IWL5000 Intel WiFi Link 1000BGN Intel Wireless WiFi 5150AGN Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN + Intel 6000 Gen 2 Series Wi-Fi Adapters (6000G2A and 6000G2B) + Intel WIreless WiFi Link 6050BGN Gen 2 Adapter + Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN) config IWL3945 tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)" diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 63edbe2e557f..93380f97835f 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -2,20 +2,27 @@ obj-$(CONFIG_IWLWIFI) += iwlcore.o iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwlcore-objs += iwl-scan.o iwl-led.o +iwlcore-$(CONFIG_IWL3945) += iwl-legacy.o +iwlcore-$(CONFIG_IWL4965) += iwl-legacy.o iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o +# If 3945 is selected only, iwl-legacy.o will be added +# to iwlcore-m above, but it needs to be built in. +iwlcore-objs += $(iwlcore-m) + CFLAGS_iwl-devtrace.o := -I$(src) # AGN obj-$(CONFIG_IWLAGN) += iwlagn.o -iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o -iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o +iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o +iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o +iwlagn-$(CONFIG_IWL5000) += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o iwlagn-$(CONFIG_IWL5000) += iwl-5000.o iwlagn-$(CONFIG_IWL5000) += iwl-6000.o iwlagn-$(CONFIG_IWL5000) += iwl-1000.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 0e027f787fbc..ba78bc8a259f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -147,7 +147,11 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); - priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); + if (priv->cfg->rx_with_siso_diversity) + priv->hw_params.rx_chains_num = 1; + else + priv->hw_params.rx_chains_num = + num_of_ant(priv->cfg->valid_rx_ant); priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; @@ -211,14 +215,16 @@ static struct iwl_lib_ops iwl1000_lib = { .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwlagn_temperature, }, - .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -226,7 +232,6 @@ static struct iwl_lib_ops iwl1000_lib = { .bt_stats_read = iwl_ucode_bt_stats_read, .reply_tx_error = iwl_reply_tx_error_read, }, - .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, .check_ack_health = iwl_good_ack_health, .txfifo_flush = iwlagn_txfifo_flush, @@ -243,6 +248,7 @@ static const struct iwl_ops iwl1000_ops = { .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl1000_base_params = { @@ -259,7 +265,7 @@ static struct iwl_base_params iwl1000_base_params = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 128, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -270,68 +276,49 @@ static struct iwl_ht_params iwl1000_ht_params = { .use_rts_for_aggregation = true, /* use rts/cts protection */ }; +#define IWL_DEVICE_1000 \ + .fw_name_pre = IWL1000_FW_PRE, \ + .ucode_api_max = IWL1000_UCODE_API_MAX, \ + .ucode_api_min = IWL1000_UCODE_API_MIN, \ + .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ + .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ + .ops = &iwl1000_ops, \ + .mod_params = &iwlagn_mod_params, \ + .base_params = &iwl1000_base_params, \ + .led_mode = IWL_LED_BLINK + struct iwl_cfg iwl1000_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN", - .fw_name_pre = IWL1000_FW_PRE, - .ucode_api_max = IWL1000_UCODE_API_MAX, - .ucode_api_min = IWL1000_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_1000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, - .ops = &iwl1000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl1000_base_params, + IWL_DEVICE_1000, .ht_params = &iwl1000_ht_params, }; struct iwl_cfg iwl1000_bg_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 1000 BG", - .fw_name_pre = IWL1000_FW_PRE, - .ucode_api_max = IWL1000_UCODE_API_MAX, - .ucode_api_min = IWL1000_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_1000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, - .ops = &iwl1000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl1000_base_params, + IWL_DEVICE_1000, }; +#define IWL_DEVICE_100 \ + .fw_name_pre = IWL100_FW_PRE, \ + .ucode_api_max = IWL100_UCODE_API_MAX, \ + .ucode_api_min = IWL100_UCODE_API_MIN, \ + .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ + .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ + .ops = &iwl1000_ops, \ + .mod_params = &iwlagn_mod_params, \ + .base_params = &iwl1000_base_params, \ + .led_mode = IWL_LED_RF_STATE, \ + .rx_with_siso_diversity = true + struct iwl_cfg iwl100_bgn_cfg = { - .name = "Intel(R) 100 Series 1x1 BGN", - .fw_name_pre = IWL100_FW_PRE, - .ucode_api_max = IWL100_UCODE_API_MAX, - .ucode_api_min = IWL100_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_A, - .eeprom_ver = EEPROM_1000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, - .ops = &iwl1000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl1000_base_params, + .name = "Intel(R) Centrino(R) Wireless-N 100 BGN", + IWL_DEVICE_100, .ht_params = &iwl1000_ht_params, - .use_new_eeprom_reading = true, }; struct iwl_cfg iwl100_bg_cfg = { - .name = "Intel(R) 100 Series 1x1 BG", - .fw_name_pre = IWL100_FW_PRE, - .ucode_api_max = IWL100_UCODE_API_MAX, - .ucode_api_min = IWL100_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_A, - .eeprom_ver = EEPROM_1000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, - .ops = &iwl1000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl1000_base_params, - .use_new_eeprom_reading = true, + .name = "Intel(R) Centrino(R) Wireless-N 100 BG", + IWL_DEVICE_100, }; MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 176e52577673..a9b852be4509 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -51,6 +51,7 @@ #include "iwl-led.h" #include "iwl-3945-led.h" #include "iwl-3945-debugfs.h" +#include "iwl-legacy.h" #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ @@ -115,7 +116,7 @@ void iwl3945_disable_events(struct iwl_priv *priv) u32 base; /* SRAM address of event log header */ u32 disable_ptr; /* SRAM address of event-disable bitmap array */ u32 array_size; /* # of u32 entries in array */ - u32 evt_disable[IWL_EVT_DISABLE_SIZE] = { + static const u32 evt_disable[IWL_EVT_DISABLE_SIZE] = { 0x00000000, /* 31 - 0 Event id numbers */ 0x00000000, /* 63 - 32 */ 0x00000000, /* 95 - 64 */ @@ -296,7 +297,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) && (txq_id != IWL39_CMD_QUEUE_NUM) && priv->mac80211_registered) - iwl_wake_queue(priv, txq_id); + iwl_wake_queue(priv, txq); } /** @@ -324,6 +325,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, return; } + txq->time_stamp = jiffies; info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); ieee80211_tx_info_clear_status(info); @@ -1451,6 +1453,10 @@ static int iwl3945_send_tx_power(struct iwl_priv *priv) }; u16 chan; + if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status), + "TX Power requested while scanning!\n")) + return -EAGAIN; + chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel); txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1; @@ -1779,6 +1785,9 @@ int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) int rc = 0; bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK); + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return -EINVAL; + if (!iwl_is_alive(priv)) return -1; @@ -2722,11 +2731,9 @@ static struct iwl_lib_ops iwl3945_lib = { }, .send_tx_power = iwl3945_send_tx_power, .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr, - .post_associate = iwl3945_post_associate, - .isr = iwl_isr_legacy, - .config_ap = iwl3945_config_ap, - .manage_ibss_station = iwl3945_manage_ibss_station, - .recover_from_tx_stall = iwl_bg_monitor_recover, + .isr_ops = { + .isr = iwl_isr_legacy, + }, .check_plcp_health = iwl3945_good_plcp_health, .debugfs_ops = { @@ -2736,10 +2743,16 @@ static struct iwl_lib_ops iwl3945_lib = { }, }; +static const struct iwl_legacy_ops iwl3945_legacy_ops = { + .post_associate = iwl3945_post_associate, + .config_ap = iwl3945_config_ap, + .manage_ibss_station = iwl3945_manage_ibss_station, +}; + static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { .get_hcmd_size = iwl3945_get_hcmd_size, .build_addsta_hcmd = iwl3945_build_addsta_hcmd, - .tx_cmd_protection = iwlcore_tx_cmd_protection, + .tx_cmd_protection = iwl_legacy_tx_cmd_protection, .request_scan = iwl3945_request_scan, .post_scan = iwl3945_post_scan, }; @@ -2749,6 +2762,8 @@ static const struct iwl_ops iwl3945_ops = { .hcmd = &iwl3945_hcmd, .utils = &iwl3945_hcmd_utils, .led = &iwl3945_led_ops, + .legacy = &iwl3945_legacy_ops, + .ieee80211_ops = &iwl3945_hw_ops, }; static struct iwl_base_params iwl3945_base_params = { @@ -2761,7 +2776,7 @@ static struct iwl_base_params iwl3945_base_params = { .led_compensation = 64, .broken_powersave = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 512, .tx_power_by_driver = true, }; @@ -2776,6 +2791,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .ops = &iwl3945_ops, .mod_params = &iwl3945_mod_params, .base_params = &iwl3945_base_params, + .led_mode = IWL_LED_BLINK, }; static struct iwl_cfg iwl3945_abg_cfg = { @@ -2788,6 +2804,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .ops = &iwl3945_ops, .mod_params = &iwl3945_mod_params, .base_params = &iwl3945_base_params, + .led_mode = IWL_LED_BLINK, }; DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 09391f0ee61f..3eef1eb74a78 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -264,10 +264,8 @@ void iwl3945_reply_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); extern void iwl3945_disable_events(struct iwl_priv *priv); extern int iwl4965_get_temperature(const struct iwl_priv *priv); -extern void iwl3945_post_associate(struct iwl_priv *priv, - struct ieee80211_vif *vif); -extern void iwl3945_config_ap(struct iwl_priv *priv, - struct ieee80211_vif *vif); +extern void iwl3945_post_associate(struct iwl_priv *priv); +extern void iwl3945_config_ap(struct iwl_priv *priv); extern int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); @@ -282,6 +280,8 @@ extern int iwl3945_commit_rxon(struct iwl_priv *priv, */ extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid); +extern struct ieee80211_ops iwl3945_hw_ops; + /* * Forward declare iwl-3945.c functions for iwl-base.c */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index b207e3e9299f..3f1e5f1bf847 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -48,6 +48,7 @@ #include "iwl-agn-led.h" #include "iwl-agn.h" #include "iwl-agn-debugfs.h" +#include "iwl-legacy.h" static int iwl4965_send_tx_power(struct iwl_priv *priv); static int iwl4965_hw_get_temperature(struct iwl_priv *priv); @@ -1377,13 +1378,9 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv) u8 ctrl_chan_high = 0; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - if (test_bit(STATUS_SCANNING, &priv->status)) { - /* If this gets hit a lot, switch it to a BUG() and catch - * the stack trace to find out who is calling this during - * a scan. */ - IWL_WARN(priv, "TX Power requested while scanning!\n"); + if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status), + "TX Power requested while scanning!\n")) return -EAGAIN; - } band = priv->band == IEEE80211_BAND_2GHZ; @@ -1447,6 +1444,142 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv, return ret; } +static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) +{ + /* cast away the const for active_rxon in this function */ + struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active; + int ret; + bool new_assoc = + !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); + + if (!iwl_is_alive(priv)) + return -EBUSY; + + if (!ctx->is_active) + return 0; + + /* always get timestamp with Rx frame */ + ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; + + ret = iwl_check_rxon_cmd(priv, ctx); + if (ret) { + IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); + return -EINVAL; + } + + /* + * receive commit_rxon request + * abort any previous channel switch if still in process + */ + if (priv->switch_rxon.switch_in_progress && + (priv->switch_rxon.channel != ctx->staging.channel)) { + IWL_DEBUG_11H(priv, "abort channel switch on %d\n", + le16_to_cpu(priv->switch_rxon.channel)); + iwl_chswitch_done(priv, false); + } + + /* If we don't need to send a full RXON, we can use + * iwl_rxon_assoc_cmd which is used to reconfigure filter + * and other flags for the current radio configuration. */ + if (!iwl_full_rxon_required(priv, ctx)) { + ret = iwl_send_rxon_assoc(priv, ctx); + if (ret) { + IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); + return ret; + } + + memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); + iwl_print_rx_config_cmd(priv, ctx); + return 0; + } + + /* If we are currently associated and the new config requires + * an RXON_ASSOC and the new config wants the associated mask enabled, + * we must clear the associated from the active configuration + * before we apply the new config */ + if (iwl_is_associated_ctx(ctx) && new_assoc) { + IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); + active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; + + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, + sizeof(struct iwl_rxon_cmd), + active_rxon); + + /* If the mask clearing failed then we set + * active_rxon back to what it was previously */ + if (ret) { + active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; + IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); + return ret; + } + iwl_clear_ucode_stations(priv, ctx); + iwl_restore_stations(priv, ctx); + ret = iwl_restore_default_wep_keys(priv, ctx); + if (ret) { + IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); + return ret; + } + } + + IWL_DEBUG_INFO(priv, "Sending RXON\n" + "* with%s RXON_FILTER_ASSOC_MSK\n" + "* channel = %d\n" + "* bssid = %pM\n", + (new_assoc ? "" : "out"), + le16_to_cpu(ctx->staging.channel), + ctx->staging.bssid_addr); + + iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); + + /* Apply the new configuration + * RXON unassoc clears the station table in uCode so restoration of + * stations is needed after it (the RXON command) completes + */ + if (!new_assoc) { + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, + sizeof(struct iwl_rxon_cmd), &ctx->staging); + if (ret) { + IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); + return ret; + } + IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); + memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); + iwl_clear_ucode_stations(priv, ctx); + iwl_restore_stations(priv, ctx); + ret = iwl_restore_default_wep_keys(priv, ctx); + if (ret) { + IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); + return ret; + } + } + if (new_assoc) { + priv->start_calib = 0; + /* Apply the new configuration + * RXON assoc doesn't clear the station table in uCode, + */ + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, + sizeof(struct iwl_rxon_cmd), &ctx->staging); + if (ret) { + IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); + return ret; + } + memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); + } + iwl_print_rx_config_cmd(priv, ctx); + + iwl_init_sensitivity(priv); + + /* If we issue a new RXON command which required a tune then we must + * send a new TXPOWER command or we won't be able to Tx any frames */ + ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); + if (ret) { + IWL_ERR(priv, "Error sending TX power (%d)\n", ret); + return ret; + } + + return 0; +} + static int iwl4965_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_channel_switch *ch_switch) { @@ -1554,22 +1687,6 @@ static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv, } /** - * sign_extend - Sign extend a value using specified bit as sign-bit - * - * Example: sign_extend(9, 3) would return -7 as bit3 of 1001b is 1 - * and bit0..2 is 001b which when sign extended to 1111111111111001b is -7. - * - * @param oper value to sign extend - * @param index 0 based bit index (0<=index<32) to sign bit - */ -static s32 sign_extend(u32 oper, int index) -{ - u8 shift = 31 - index; - - return (s32)(oper << shift) >> shift; -} - -/** * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin) * @statistics: Provides the temperature reading from the uCode * @@ -1606,9 +1723,9 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv) * "initialize" ALIVE response. */ if (!test_bit(STATUS_TEMPERATURE, &priv->status)) - vt = sign_extend(R4, 23); + vt = sign_extend32(R4, 23); else - vt = sign_extend(le32_to_cpu(priv->_agn.statistics. + vt = sign_extend32(le32_to_cpu(priv->_agn.statistics. general.common.temperature), 23); IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); @@ -2081,6 +2198,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, return; } + txq->time_stamp = jiffies; info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); memset(&info->status, 0, sizeof(info->status)); @@ -2121,12 +2239,8 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark) && - (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { - if (agg->state == IWL_AGG_OFF) - iwl_wake_queue(priv, txq_id); - else - iwl_wake_queue(priv, txq->swq_id); - } + (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) + iwl_wake_queue(priv, txq); } } else { info->status.rates[0].count = tx_resp->failure_frame + 1; @@ -2150,7 +2264,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark)) - iwl_wake_queue(priv, txq_id); + iwl_wake_queue(priv, txq); } if (qc && likely(sta_id != IWL_INVALID_STATION)) iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); @@ -2216,7 +2330,7 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) static struct iwl_hcmd_ops iwl4965_hcmd = { .rxon_assoc = iwl4965_send_rxon_assoc, - .commit_rxon = iwlagn_commit_rxon, + .commit_rxon = iwl4965_commit_rxon, .set_rxon_chain = iwlagn_set_rxon_chain, .send_bt_config = iwl_send_bt_config, }; @@ -2233,12 +2347,155 @@ static void iwl4965_post_scan(struct iwl_priv *priv) iwlcore_commit_rxon(priv, ctx); } +static void iwl4965_post_associate(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct ieee80211_vif *vif = ctx->vif; + struct ieee80211_conf *conf = NULL; + int ret = 0; + + if (!vif || !priv->is_open) + return; + + if (vif->type == NL80211_IFTYPE_AP) { + IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); + return; + } + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + iwl_scan_cancel_timeout(priv, 200); + + conf = ieee80211_get_hw_conf(priv->hw); + + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); + + ret = iwl_send_rxon_timing(priv, ctx); + if (ret) + IWL_WARN(priv, "RXON timing - " + "Attempting to continue.\n"); + + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + + iwl_set_rxon_ht(priv, &priv->current_ht_config); + + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + + ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); + + IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", + vif->bss_conf.aid, vif->bss_conf.beacon_int); + + if (vif->bss_conf.use_short_preamble) + ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + else + ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + + if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { + if (vif->bss_conf.use_short_slot) + ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; + else + ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + } + + iwlcore_commit_rxon(priv, ctx); + + IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", + vif->bss_conf.aid, ctx->active.bssid_addr); + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + break; + case NL80211_IFTYPE_ADHOC: + iwlagn_send_beacon_cmd(priv); + break; + default: + IWL_ERR(priv, "%s Should not be called in %d mode\n", + __func__, vif->type); + break; + } + + /* the chain noise calibration will enabled PM upon completion + * If chain noise has already been run, then we need to enable + * power management here */ + if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) + iwl_power_update_mode(priv, false); + + /* Enable Rx differential gain and sensitivity calibrations */ + iwl_chain_noise_reset(priv); + priv->start_calib = 1; +} + +static void iwl4965_config_ap(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct ieee80211_vif *vif = ctx->vif; + int ret = 0; + + lockdep_assert_held(&priv->mutex); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + /* The following should be done only at AP bring up */ + if (!iwl_is_associated_ctx(ctx)) { + + /* RXON - unassoc (to set timing command) */ + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); + + /* RXON Timing */ + ret = iwl_send_rxon_timing(priv, ctx); + if (ret) + IWL_WARN(priv, "RXON timing failed - " + "Attempting to continue.\n"); + + /* AP has all antennas */ + priv->chain_noise_data.active_chains = + priv->hw_params.valid_rx_ant; + iwl_set_rxon_ht(priv, &priv->current_ht_config); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + + ctx->staging.assoc_id = 0; + + if (vif->bss_conf.use_short_preamble) + ctx->staging.flags |= + RXON_FLG_SHORT_PREAMBLE_MSK; + else + ctx->staging.flags &= + ~RXON_FLG_SHORT_PREAMBLE_MSK; + + if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { + if (vif->bss_conf.use_short_slot) + ctx->staging.flags |= + RXON_FLG_SHORT_SLOT_MSK; + else + ctx->staging.flags &= + ~RXON_FLG_SHORT_SLOT_MSK; + } + /* need to send beacon cmd before committing assoc RXON! */ + iwlagn_send_beacon_cmd(priv); + /* restore RXON assoc */ + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); + } + iwlagn_send_beacon_cmd(priv); + + /* FIXME - we need to add code here to detect a totally new + * configuration, reset the AP, unassoc, rxon timing, assoc, + * clear sta table, add BCAST sta... */ +} + static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .get_hcmd_size = iwl4965_get_hcmd_size, .build_addsta_hcmd = iwl4965_build_addsta_hcmd, .chain_noise_reset = iwl4965_chain_noise_reset, .gain_computation = iwl4965_gain_computation, - .tx_cmd_protection = iwlcore_tx_cmd_protection, + .tx_cmd_protection = iwl_legacy_tx_cmd_protection, .calc_rssi = iwl4965_calc_rssi, .request_scan = iwlagn_request_scan, .post_scan = iwl4965_post_scan, @@ -2285,14 +2542,12 @@ static struct iwl_lib_ops iwl4965_lib = { }, .send_tx_power = iwl4965_send_tx_power, .update_chain_flags = iwl_update_chain_flags, - .post_associate = iwl_post_associate, - .config_ap = iwl_config_ap, - .isr = iwl_isr_legacy, + .isr_ops = { + .isr = iwl_isr_legacy, + }, .temp_ops = { .temperature = iwl4965_temperature_calib, }, - .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -2300,15 +2555,46 @@ static struct iwl_lib_ops iwl4965_lib = { .bt_stats_read = iwl_ucode_bt_stats_read, .reply_tx_error = iwl_reply_tx_error_read, }, - .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, }; +static const struct iwl_legacy_ops iwl4965_legacy_ops = { + .post_associate = iwl4965_post_associate, + .config_ap = iwl4965_config_ap, + .manage_ibss_station = iwlagn_manage_ibss_station, + .update_bcast_stations = iwl_update_bcast_stations, +}; + +struct ieee80211_ops iwl4965_hw_ops = { + .tx = iwlagn_mac_tx, + .start = iwlagn_mac_start, + .stop = iwlagn_mac_stop, + .add_interface = iwl_mac_add_interface, + .remove_interface = iwl_mac_remove_interface, + .change_interface = iwl_mac_change_interface, + .config = iwl_legacy_mac_config, + .configure_filter = iwlagn_configure_filter, + .set_key = iwlagn_mac_set_key, + .update_tkip_key = iwlagn_mac_update_tkip_key, + .conf_tx = iwl_mac_conf_tx, + .reset_tsf = iwl_legacy_mac_reset_tsf, + .bss_info_changed = iwl_legacy_mac_bss_info_changed, + .ampdu_action = iwlagn_mac_ampdu_action, + .hw_scan = iwl_mac_hw_scan, + .sta_add = iwlagn_mac_sta_add, + .sta_remove = iwl_mac_sta_remove, + .channel_switch = iwlagn_mac_channel_switch, + .flush = iwlagn_mac_flush, + .tx_last_beacon = iwl_mac_tx_last_beacon, +}; + static const struct iwl_ops iwl4965_ops = { .lib = &iwl4965_lib, .hcmd = &iwl4965_hcmd, .utils = &iwl4965_hcmd_utils, .led = &iwlagn_led_ops, + .legacy = &iwl4965_legacy_ops, + .ieee80211_ops = &iwl4965_hw_ops, }; static struct iwl_base_params iwl4965_base_params = { @@ -2323,13 +2609,14 @@ static struct iwl_base_params iwl4965_base_params = { .led_compensation = 61, .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .wd_timeout = IWL_DEF_WD_TIMEOUT, .temperature_kelvin = true, .max_event_log_size = 512, .tx_power_by_driver = true, .ucode_tracing = true, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, + .no_agg_framecnt_info = true, }; struct iwl_cfg iwl4965_agn_cfg = { @@ -2337,7 +2624,6 @@ struct iwl_cfg iwl4965_agn_cfg = { .fw_name_pre = IWL4965_FW_PRE, .ucode_api_max = IWL4965_UCODE_API_MAX, .ucode_api_min = IWL4965_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_ABC, .eeprom_ver = EEPROM_4965_EEPROM_VERSION, @@ -2345,6 +2631,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .ops = &iwl4965_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl4965_base_params, + .led_mode = IWL_LED_BLINK, /* * Force use of chains B and C for scan RX on 5 GHz band * because the device has off-channel reception on chain A. diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index fd9fbc93ea1b..79ab0a6b1386 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -385,14 +385,16 @@ static struct iwl_lib_ops iwl5000_lib = { .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwlagn_temperature, }, - .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -400,7 +402,6 @@ static struct iwl_lib_ops iwl5000_lib = { .bt_stats_read = iwl_ucode_bt_stats_read, .reply_tx_error = iwl_reply_tx_error_read, }, - .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, .check_ack_health = iwl_good_ack_health, .txfifo_flush = iwlagn_txfifo_flush, @@ -453,14 +454,16 @@ static struct iwl_lib_ops iwl5150_lib = { .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwl5150_temperature, }, - .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -468,7 +471,6 @@ static struct iwl_lib_ops iwl5150_lib = { .bt_stats_read = iwl_ucode_bt_stats_read, .reply_tx_error = iwl_reply_tx_error_read, }, - .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, .check_ack_health = iwl_good_ack_health, .txfifo_flush = iwlagn_txfifo_flush, @@ -485,6 +487,7 @@ static const struct iwl_ops iwl5000_ops = { .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl5150_ops = { @@ -492,6 +495,7 @@ static const struct iwl_ops iwl5150_ops = { .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl5000_base_params = { @@ -505,7 +509,7 @@ static struct iwl_base_params iwl5000_base_params = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, + .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -516,66 +520,43 @@ static struct iwl_ht_params iwl5000_ht_params = { .use_rts_for_aggregation = true, /* use rts/cts protection */ }; +#define IWL_DEVICE_5000 \ + .fw_name_pre = IWL5000_FW_PRE, \ + .ucode_api_max = IWL5000_UCODE_API_MAX, \ + .ucode_api_min = IWL5000_UCODE_API_MIN, \ + .eeprom_ver = EEPROM_5000_EEPROM_VERSION, \ + .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \ + .ops = &iwl5000_ops, \ + .mod_params = &iwlagn_mod_params, \ + .base_params = &iwl5000_base_params, \ + .led_mode = IWL_LED_BLINK + struct iwl_cfg iwl5300_agn_cfg = { .name = "Intel(R) Ultimate N WiFi Link 5300 AGN", - .fw_name_pre = IWL5000_FW_PRE, - .ucode_api_max = IWL5000_UCODE_API_MAX, - .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_ABC, - .valid_rx_ant = ANT_ABC, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .ops = &iwl5000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl5000_base_params, + IWL_DEVICE_5000, .ht_params = &iwl5000_ht_params, }; struct iwl_cfg iwl5100_bgn_cfg = { .name = "Intel(R) WiFi Link 5100 BGN", - .fw_name_pre = IWL5000_FW_PRE, - .ucode_api_max = IWL5000_UCODE_API_MAX, - .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_B, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .ops = &iwl5000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl5000_base_params, + IWL_DEVICE_5000, + .valid_tx_ant = ANT_B, /* .cfg overwrite */ + .valid_rx_ant = ANT_AB, /* .cfg overwrite */ .ht_params = &iwl5000_ht_params, }; struct iwl_cfg iwl5100_abg_cfg = { .name = "Intel(R) WiFi Link 5100 ABG", - .fw_name_pre = IWL5000_FW_PRE, - .ucode_api_max = IWL5000_UCODE_API_MAX, - .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .valid_tx_ant = ANT_B, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .ops = &iwl5000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl5000_base_params, + IWL_DEVICE_5000, + .valid_tx_ant = ANT_B, /* .cfg overwrite */ + .valid_rx_ant = ANT_AB, /* .cfg overwrite */ }; struct iwl_cfg iwl5100_agn_cfg = { .name = "Intel(R) WiFi Link 5100 AGN", - .fw_name_pre = IWL5000_FW_PRE, - .ucode_api_max = IWL5000_UCODE_API_MAX, - .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_B, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .ops = &iwl5000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl5000_base_params, + IWL_DEVICE_5000, + .valid_tx_ant = ANT_B, /* .cfg overwrite */ + .valid_rx_ant = ANT_AB, /* .cfg overwrite */ .ht_params = &iwl5000_ht_params, }; @@ -584,48 +565,39 @@ struct iwl_cfg iwl5350_agn_cfg = { .fw_name_pre = IWL5000_FW_PRE, .ucode_api_max = IWL5000_UCODE_API_MAX, .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_ABC, - .valid_rx_ant = ANT_ABC, .eeprom_ver = EEPROM_5050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, .ops = &iwl5000_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl5000_base_params, .ht_params = &iwl5000_ht_params, + .led_mode = IWL_LED_BLINK, + .internal_wimax_coex = true, }; +#define IWL_DEVICE_5150 \ + .fw_name_pre = IWL5150_FW_PRE, \ + .ucode_api_max = IWL5150_UCODE_API_MAX, \ + .ucode_api_min = IWL5150_UCODE_API_MIN, \ + .eeprom_ver = EEPROM_5050_EEPROM_VERSION, \ + .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ + .ops = &iwl5150_ops, \ + .mod_params = &iwlagn_mod_params, \ + .base_params = &iwl5000_base_params, \ + .need_dc_calib = true, \ + .led_mode = IWL_LED_BLINK, \ + .internal_wimax_coex = true + struct iwl_cfg iwl5150_agn_cfg = { .name = "Intel(R) WiMAX/WiFi Link 5150 AGN", - .fw_name_pre = IWL5150_FW_PRE, - .ucode_api_max = IWL5150_UCODE_API_MAX, - .ucode_api_min = IWL5150_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_5050_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, - .ops = &iwl5150_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl5000_base_params, + IWL_DEVICE_5150, .ht_params = &iwl5000_ht_params, - .need_dc_calib = true, + }; struct iwl_cfg iwl5150_abg_cfg = { .name = "Intel(R) WiMAX/WiFi Link 5150 ABG", - .fw_name_pre = IWL5150_FW_PRE, - .ucode_api_max = IWL5150_UCODE_API_MAX, - .ucode_api_min = IWL5150_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_5050_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, - .ops = &iwl5150_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl5000_base_params, - .need_dc_calib = true, + IWL_DEVICE_5150, }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 0ceeaac85eda..af505bcd7ae0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -53,13 +53,11 @@ #define IWL6000_UCODE_API_MAX 4 #define IWL6050_UCODE_API_MAX 5 #define IWL6000G2_UCODE_API_MAX 5 -#define IWL130_UCODE_API_MAX 5 /* Lowest firmware API version supported */ #define IWL6000_UCODE_API_MIN 4 #define IWL6050_UCODE_API_MIN 4 #define IWL6000G2_UCODE_API_MIN 4 -#define IWL130_UCODE_API_MIN 5 #define IWL6000_FW_PRE "iwlwifi-6000-" #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" @@ -77,10 +75,6 @@ #define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode" #define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api) -#define IWL130_FW_PRE "iwlwifi-130-" -#define _IWL130_MODULE_FIRMWARE(api) IWL130_FW_PRE #api ".ucode" -#define IWL130_MODULE_FIRMWARE(api) _IWL130_MODULE_FIRMWARE(api) - static void iwl6000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ @@ -188,7 +182,11 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); - priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); + if (priv->cfg->rx_with_siso_diversity) + priv->hw_params.rx_chains_num = 1; + else + priv->hw_params.rx_chains_num = + num_of_ant(priv->cfg->valid_rx_ant); priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; @@ -328,14 +326,16 @@ static struct iwl_lib_ops iwl6000_lib = { .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwlagn_temperature, }, - .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -343,7 +343,6 @@ static struct iwl_lib_ops iwl6000_lib = { .bt_stats_read = iwl_ucode_bt_stats_read, .reply_tx_error = iwl_reply_tx_error_read, }, - .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, .check_ack_health = iwl_good_ack_health, .txfifo_flush = iwlagn_txfifo_flush, @@ -399,14 +398,16 @@ static struct iwl_lib_ops iwl6000g2b_lib = { .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwlagn_temperature, }, - .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -414,7 +415,6 @@ static struct iwl_lib_ops iwl6000g2b_lib = { .bt_stats_read = iwl_ucode_bt_stats_read, .reply_tx_error = iwl_reply_tx_error_read, }, - .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, .check_ack_health = iwl_good_ack_health, .txfifo_flush = iwlagn_txfifo_flush, @@ -439,6 +439,7 @@ static const struct iwl_ops iwl6000_ops = { .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl6050_ops = { @@ -447,6 +448,7 @@ static const struct iwl_ops iwl6050_ops = { .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, .nic = &iwl6050_nic_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl6050g2_ops = { @@ -455,6 +457,7 @@ static const struct iwl_ops iwl6050g2_ops = { .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, .nic = &iwl6050g2_nic_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl6000g2b_ops = { @@ -462,6 +465,7 @@ static const struct iwl_ops iwl6000g2b_ops = { .hcmd = &iwlagn_bt_hcmd, .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl6000_base_params = { @@ -480,11 +484,12 @@ static struct iwl_base_params iwl6000_base_params = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, + .shadow_reg_enable = true, }; static struct iwl_base_params iwl6050_base_params = { @@ -503,13 +508,14 @@ static struct iwl_base_params iwl6050_base_params = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1500, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, + .shadow_reg_enable = true, }; -static struct iwl_base_params iwl6000_coex_base_params = { +static struct iwl_base_params iwl6000_g2_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, @@ -518,18 +524,19 @@ static struct iwl_base_params iwl6000_coex_base_params = { .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, - .led_compensation = 51, + .led_compensation = 57, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, + .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, + .shadow_reg_enable = true, }; static struct iwl_ht_params iwl6000_ht_params = { @@ -541,271 +548,164 @@ static struct iwl_bt_params iwl6000_bt_params = { .bt_statistics = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .advanced_bt_coexist = true, + .agg_time_limit = BT_AGG_THRESHOLD_DEF, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, + .bt_sco_disable = true, +}; + +#define IWL_DEVICE_6005 \ + .fw_name_pre = IWL6000G2A_FW_PRE, \ + .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ + .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ + .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, \ + .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, \ + .ops = &iwl6000_ops, \ + .mod_params = &iwlagn_mod_params, \ + .base_params = &iwl6000_g2_base_params, \ + .need_dc_calib = true, \ + .need_temp_offset_calib = true, \ + .led_mode = IWL_LED_RF_STATE + +struct iwl_cfg iwl6005_2agn_cfg = { + .name = "Intel(R) Centrino(R) Advanced-N 6205 AGN", + IWL_DEVICE_6005, + .ht_params = &iwl6000_ht_params, }; -struct iwl_cfg iwl6000g2a_2agn_cfg = { - .name = "6000 Series 2x2 AGN Gen2a", - .fw_name_pre = IWL6000G2A_FW_PRE, - .ucode_api_max = IWL6000G2_UCODE_API_MAX, - .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, - .ops = &iwl6000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, +struct iwl_cfg iwl6005_2abg_cfg = { + .name = "Intel(R) Centrino(R) Advanced-N 6205 ABG", + IWL_DEVICE_6005, +}; + +struct iwl_cfg iwl6005_2bg_cfg = { + .name = "Intel(R) Centrino(R) Advanced-N 6205 BG", + IWL_DEVICE_6005, +}; + +#define IWL_DEVICE_6030 \ + .fw_name_pre = IWL6000G2B_FW_PRE, \ + .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ + .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ + .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, \ + .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, \ + .ops = &iwl6000g2b_ops, \ + .mod_params = &iwlagn_mod_params, \ + .base_params = &iwl6000_g2_base_params, \ + .bt_params = &iwl6000_bt_params, \ + .need_dc_calib = true, \ + .need_temp_offset_calib = true, \ + .led_mode = IWL_LED_RF_STATE, \ + .adv_pm = true \ + +struct iwl_cfg iwl6030_2agn_cfg = { + .name = "Intel(R) Centrino(R) Advanced-N 6230 AGN", + IWL_DEVICE_6030, .ht_params = &iwl6000_ht_params, - .need_dc_calib = true, - .need_temp_offset_calib = true, - .use_new_eeprom_reading = true, -}; - -struct iwl_cfg iwl6000g2a_2abg_cfg = { - .name = "6000 Series 2x2 ABG Gen2a", - .fw_name_pre = IWL6000G2A_FW_PRE, - .ucode_api_max = IWL6000G2_UCODE_API_MAX, - .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, - .ops = &iwl6000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, - .need_dc_calib = true, - .need_temp_offset_calib = true, - .use_new_eeprom_reading = true, -}; - -struct iwl_cfg iwl6000g2a_2bg_cfg = { - .name = "6000 Series 2x2 BG Gen2a", - .fw_name_pre = IWL6000G2A_FW_PRE, - .ucode_api_max = IWL6000G2_UCODE_API_MAX, - .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, - .ops = &iwl6000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, - .need_dc_calib = true, - .need_temp_offset_calib = true, - .use_new_eeprom_reading = true, -}; - -struct iwl_cfg iwl6000g2b_2agn_cfg = { - .name = "6000 Series 2x2 AGN Gen2b", - .fw_name_pre = IWL6000G2B_FW_PRE, - .ucode_api_max = IWL6000G2_UCODE_API_MAX, - .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, - .ops = &iwl6000g2b_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_coex_base_params, - .bt_params = &iwl6000_bt_params, +}; + +struct iwl_cfg iwl6030_2abg_cfg = { + .name = "Intel(R) Centrino(R) Advanced-N 6230 ABG", + IWL_DEVICE_6030, +}; + +struct iwl_cfg iwl6030_2bgn_cfg = { + .name = "Intel(R) Centrino(R) Advanced-N 6230 BGN", + IWL_DEVICE_6030, .ht_params = &iwl6000_ht_params, - .need_dc_calib = true, - .need_temp_offset_calib = true, - /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ - .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, - .use_new_eeprom_reading = true, -}; - -struct iwl_cfg iwl6000g2b_2abg_cfg = { - .name = "6000 Series 2x2 ABG Gen2b", - .fw_name_pre = IWL6000G2B_FW_PRE, - .ucode_api_max = IWL6000G2_UCODE_API_MAX, - .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, - .ops = &iwl6000g2b_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_coex_base_params, - .bt_params = &iwl6000_bt_params, - .need_dc_calib = true, - .need_temp_offset_calib = true, - /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ - .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, - .use_new_eeprom_reading = true, -}; - -struct iwl_cfg iwl6000g2b_2bgn_cfg = { - .name = "6000 Series 2x2 BGN Gen2b", - .fw_name_pre = IWL6000G2B_FW_PRE, - .ucode_api_max = IWL6000G2_UCODE_API_MAX, - .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, - .ops = &iwl6000g2b_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_coex_base_params, - .bt_params = &iwl6000_bt_params, +}; + +struct iwl_cfg iwl6030_2bg_cfg = { + .name = "Intel(R) Centrino(R) Advanced-N 6230 BG", + IWL_DEVICE_6030, +}; + +struct iwl_cfg iwl1030_bgn_cfg = { + .name = "Intel(R) Centrino(R) Wireless-N 1030 BGN", + IWL_DEVICE_6030, .ht_params = &iwl6000_ht_params, - .need_dc_calib = true, - .need_temp_offset_calib = true, - /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ - .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, - .use_new_eeprom_reading = true, -}; - -struct iwl_cfg iwl6000g2b_2bg_cfg = { - .name = "6000 Series 2x2 BG Gen2b", - .fw_name_pre = IWL6000G2B_FW_PRE, - .ucode_api_max = IWL6000G2_UCODE_API_MAX, - .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, - .ops = &iwl6000g2b_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_coex_base_params, - .bt_params = &iwl6000_bt_params, - .need_dc_calib = true, - .need_temp_offset_calib = true, - /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ - .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, - .use_new_eeprom_reading = true, -}; - -struct iwl_cfg iwl6000g2b_bgn_cfg = { - .name = "6000 Series 1x2 BGN Gen2b", - .fw_name_pre = IWL6000G2B_FW_PRE, - .ucode_api_max = IWL6000G2_UCODE_API_MAX, - .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, - .ops = &iwl6000g2b_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_coex_base_params, - .bt_params = &iwl6000_bt_params, +}; + +struct iwl_cfg iwl1030_bg_cfg = { + .name = "Intel(R) Centrino(R) Wireless-N 1030 BG", + IWL_DEVICE_6030, +}; + +struct iwl_cfg iwl130_bgn_cfg = { + .name = "Intel(R) Centrino(R) Wireless-N 130 BGN", + IWL_DEVICE_6030, .ht_params = &iwl6000_ht_params, - .need_dc_calib = true, - .need_temp_offset_calib = true, - /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ - .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, - .use_new_eeprom_reading = true, -}; - -struct iwl_cfg iwl6000g2b_bg_cfg = { - .name = "6000 Series 1x2 BG Gen2b", - .fw_name_pre = IWL6000G2B_FW_PRE, - .ucode_api_max = IWL6000G2_UCODE_API_MAX, - .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, - .ops = &iwl6000g2b_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_coex_base_params, - .bt_params = &iwl6000_bt_params, - .need_dc_calib = true, - .need_temp_offset_calib = true, - /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ - .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, - .use_new_eeprom_reading = true, + .rx_with_siso_diversity = true, +}; + +struct iwl_cfg iwl130_bg_cfg = { + .name = "Intel(R) Centrino(R) Wireless-N 130 BG", + IWL_DEVICE_6030, + .rx_with_siso_diversity = true, }; /* * "i": Internal configuration, use internal Power Amplifier */ +#define IWL_DEVICE_6000i \ + .fw_name_pre = IWL6000_FW_PRE, \ + .ucode_api_max = IWL6000_UCODE_API_MAX, \ + .ucode_api_min = IWL6000_UCODE_API_MIN, \ + .valid_tx_ant = ANT_BC, /* .cfg overwrite */ \ + .valid_rx_ant = ANT_BC, /* .cfg overwrite */ \ + .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ + .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ + .ops = &iwl6000_ops, \ + .mod_params = &iwlagn_mod_params, \ + .base_params = &iwl6000_base_params, \ + .pa_type = IWL_PA_INTERNAL, \ + .led_mode = IWL_LED_BLINK + struct iwl_cfg iwl6000i_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN", - .fw_name_pre = IWL6000_FW_PRE, - .ucode_api_max = IWL6000_UCODE_API_MAX, - .ucode_api_min = IWL6000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_BC, - .valid_rx_ant = ANT_BC, - .eeprom_ver = EEPROM_6000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, - .ops = &iwl6000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, + IWL_DEVICE_6000i, .ht_params = &iwl6000_ht_params, - .pa_type = IWL_PA_INTERNAL, }; struct iwl_cfg iwl6000i_2abg_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6200 ABG", - .fw_name_pre = IWL6000_FW_PRE, - .ucode_api_max = IWL6000_UCODE_API_MAX, - .ucode_api_min = IWL6000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .valid_tx_ant = ANT_BC, - .valid_rx_ant = ANT_BC, - .eeprom_ver = EEPROM_6000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, - .ops = &iwl6000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, - .pa_type = IWL_PA_INTERNAL, + IWL_DEVICE_6000i, }; struct iwl_cfg iwl6000i_2bg_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6200 BG", - .fw_name_pre = IWL6000_FW_PRE, - .ucode_api_max = IWL6000_UCODE_API_MAX, - .ucode_api_min = IWL6000_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_BC, - .valid_rx_ant = ANT_BC, - .eeprom_ver = EEPROM_6000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, - .ops = &iwl6000_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, - .pa_type = IWL_PA_INTERNAL, -}; + IWL_DEVICE_6000i, +}; + +#define IWL_DEVICE_6050 \ + .fw_name_pre = IWL6050_FW_PRE, \ + .ucode_api_max = IWL6050_UCODE_API_MAX, \ + .ucode_api_min = IWL6050_UCODE_API_MIN, \ + .ops = &iwl6050_ops, \ + .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \ + .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ + .mod_params = &iwlagn_mod_params, \ + .base_params = &iwl6050_base_params, \ + .need_dc_calib = true, \ + .led_mode = IWL_LED_BLINK, \ + .internal_wimax_coex = true struct iwl_cfg iwl6050_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN", - .fw_name_pre = IWL6050_FW_PRE, - .ucode_api_max = IWL6050_UCODE_API_MAX, - .ucode_api_min = IWL6050_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, - .ops = &iwl6050_ops, - .eeprom_ver = EEPROM_6050_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6050_base_params, + IWL_DEVICE_6050, .ht_params = &iwl6000_ht_params, - .need_dc_calib = true, }; -struct iwl_cfg iwl6050g2_bgn_cfg = { - .name = "6050 Series 1x2 BGN Gen2", +struct iwl_cfg iwl6050_2abg_cfg = { + .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG", + IWL_DEVICE_6050, +}; + +struct iwl_cfg iwl6150_bgn_cfg = { + .name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN", .fw_name_pre = IWL6050_FW_PRE, .ucode_api_max = IWL6050_UCODE_API_MAX, .ucode_api_min = IWL6050_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_6050G2_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION, .ops = &iwl6050g2_ops, @@ -813,23 +713,8 @@ struct iwl_cfg iwl6050g2_bgn_cfg = { .base_params = &iwl6050_base_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, - .use_new_eeprom_reading = true, -}; - -struct iwl_cfg iwl6050_2abg_cfg = { - .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG", - .fw_name_pre = IWL6050_FW_PRE, - .ucode_api_max = IWL6050_UCODE_API_MAX, - .ucode_api_min = IWL6050_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, - .eeprom_ver = EEPROM_6050_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, - .ops = &iwl6050_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6050_base_params, - .need_dc_calib = true, + .led_mode = IWL_LED_RF_STATE, + .internal_wimax_coex = true, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -837,9 +722,6 @@ struct iwl_cfg iwl6000_3agn_cfg = { .fw_name_pre = IWL6000_FW_PRE, .ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_min = IWL6000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_ABC, - .valid_rx_ant = ANT_ABC, .eeprom_ver = EEPROM_6000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .ops = &iwl6000_ops, @@ -847,51 +729,10 @@ struct iwl_cfg iwl6000_3agn_cfg = { .base_params = &iwl6000_base_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, -}; - -struct iwl_cfg iwl130_bgn_cfg = { - .name = "Intel(R) 130 Series 1x1 BGN", - .fw_name_pre = IWL6000G2B_FW_PRE, - .ucode_api_max = IWL130_UCODE_API_MAX, - .ucode_api_min = IWL130_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_A, - .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, - .ops = &iwl6000g2b_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_coex_base_params, - .bt_params = &iwl6000_bt_params, - .ht_params = &iwl6000_ht_params, - .need_dc_calib = true, - /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ - .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, - .use_new_eeprom_reading = true, -}; - -struct iwl_cfg iwl130_bg_cfg = { - .name = "Intel(R) 130 Series 1x2 BG", - .fw_name_pre = IWL6000G2B_FW_PRE, - .ucode_api_max = IWL130_UCODE_API_MAX, - .ucode_api_min = IWL130_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_A, - .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, - .ops = &iwl6000g2b_ops, - .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_coex_base_params, - .bt_params = &iwl6000_bt_params, - .need_dc_calib = true, - /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ - .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, - .use_new_eeprom_reading = true, + .led_mode = IWL_LED_BLINK, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL130_MODULE_FIRMWARE(IWL130_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index e2019e756936..d16bb5ede014 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -732,8 +732,122 @@ static inline u8 find_first_chain(u8 mask) return CHAIN_C; } +/** + * Run disconnected antenna algorithm to find out which antennas are + * disconnected. + */ +static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, + struct iwl_chain_noise_data *data) +{ + u32 active_chains = 0; + u32 max_average_sig; + u16 max_average_sig_antenna_i; + u8 num_tx_chains; + u8 first_chain; + u16 i = 0; + + average_sig[0] = data->chain_signal_a / + priv->cfg->base_params->chain_noise_num_beacons; + average_sig[1] = data->chain_signal_b / + priv->cfg->base_params->chain_noise_num_beacons; + average_sig[2] = data->chain_signal_c / + priv->cfg->base_params->chain_noise_num_beacons; + + if (average_sig[0] >= average_sig[1]) { + max_average_sig = average_sig[0]; + max_average_sig_antenna_i = 0; + active_chains = (1 << max_average_sig_antenna_i); + } else { + max_average_sig = average_sig[1]; + max_average_sig_antenna_i = 1; + active_chains = (1 << max_average_sig_antenna_i); + } + + if (average_sig[2] >= max_average_sig) { + max_average_sig = average_sig[2]; + max_average_sig_antenna_i = 2; + active_chains = (1 << max_average_sig_antenna_i); + } + + IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n", + average_sig[0], average_sig[1], average_sig[2]); + IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n", + max_average_sig, max_average_sig_antenna_i); + + /* Compare signal strengths for all 3 receivers. */ + for (i = 0; i < NUM_RX_CHAINS; i++) { + if (i != max_average_sig_antenna_i) { + s32 rssi_delta = (max_average_sig - average_sig[i]); + + /* If signal is very weak, compared with + * strongest, mark it as disconnected. */ + if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS) + data->disconn_array[i] = 1; + else + active_chains |= (1 << i); + IWL_DEBUG_CALIB(priv, "i = %d rssiDelta = %d " + "disconn_array[i] = %d\n", + i, rssi_delta, data->disconn_array[i]); + } + } + + /* + * The above algorithm sometimes fails when the ucode + * reports 0 for all chains. It's not clear why that + * happens to start with, but it is then causing trouble + * because this can make us enable more chains than the + * hardware really has. + * + * To be safe, simply mask out any chains that we know + * are not on the device. + */ + active_chains &= priv->hw_params.valid_rx_ant; + + num_tx_chains = 0; + for (i = 0; i < NUM_RX_CHAINS; i++) { + /* loops on all the bits of + * priv->hw_setting.valid_tx_ant */ + u8 ant_msk = (1 << i); + if (!(priv->hw_params.valid_tx_ant & ant_msk)) + continue; + + num_tx_chains++; + if (data->disconn_array[i] == 0) + /* there is a Tx antenna connected */ + break; + if (num_tx_chains == priv->hw_params.tx_chains_num && + data->disconn_array[i]) { + /* + * If all chains are disconnected + * connect the first valid tx chain + */ + first_chain = + find_first_chain(priv->cfg->valid_tx_ant); + data->disconn_array[first_chain] = 0; + active_chains |= BIT(first_chain); + IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected \ + W/A - declare %d as connected\n", + first_chain); + break; + } + } + + if (active_chains != priv->hw_params.valid_rx_ant && + active_chains != priv->chain_noise_data.active_chains) + IWL_DEBUG_CALIB(priv, + "Detected that not all antennas are connected! " + "Connected: %#x, valid: %#x.\n", + active_chains, priv->hw_params.valid_rx_ant); + + /* Save for use within RXON, TX, SCAN commands, etc. */ + data->active_chains = active_chains; + IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", + active_chains); +} + + /* - * Accumulate 20 beacons of signal and noise statistics for each of + * Accumulate 16 beacons of signal and noise statistics for each of * 3 receivers/antennas/rx-chains, then figure out: * 1) Which antennas are connected. * 2) Differential rx gain settings to balance the 3 receivers. @@ -750,8 +864,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) u32 chain_sig_c; u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; - u32 max_average_sig; - u16 max_average_sig_antenna_i; u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE; u16 min_average_noise_antenna_i = INITIALIZATION_VALUE; u16 i = 0; @@ -759,11 +871,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) u16 stat_chnum = INITIALIZATION_VALUE; u8 rxon_band24; u8 stat_band24; - u32 active_chains = 0; - u8 num_tx_chains; unsigned long flags; struct statistics_rx_non_phy *rx_info; - u8 first_chain; + /* * MULTI-FIXME: * When we support multiple interfaces on different channels, @@ -869,108 +979,16 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) return; /* Analyze signal for disconnected antenna */ - average_sig[0] = data->chain_signal_a / - priv->cfg->base_params->chain_noise_num_beacons; - average_sig[1] = data->chain_signal_b / - priv->cfg->base_params->chain_noise_num_beacons; - average_sig[2] = data->chain_signal_c / - priv->cfg->base_params->chain_noise_num_beacons; - - if (average_sig[0] >= average_sig[1]) { - max_average_sig = average_sig[0]; - max_average_sig_antenna_i = 0; - active_chains = (1 << max_average_sig_antenna_i); - } else { - max_average_sig = average_sig[1]; - max_average_sig_antenna_i = 1; - active_chains = (1 << max_average_sig_antenna_i); - } - - if (average_sig[2] >= max_average_sig) { - max_average_sig = average_sig[2]; - max_average_sig_antenna_i = 2; - active_chains = (1 << max_average_sig_antenna_i); - } - - IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n", - average_sig[0], average_sig[1], average_sig[2]); - IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n", - max_average_sig, max_average_sig_antenna_i); - - /* Compare signal strengths for all 3 receivers. */ - for (i = 0; i < NUM_RX_CHAINS; i++) { - if (i != max_average_sig_antenna_i) { - s32 rssi_delta = (max_average_sig - average_sig[i]); - - /* If signal is very weak, compared with - * strongest, mark it as disconnected. */ - if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS) - data->disconn_array[i] = 1; - else - active_chains |= (1 << i); - IWL_DEBUG_CALIB(priv, "i = %d rssiDelta = %d " - "disconn_array[i] = %d\n", - i, rssi_delta, data->disconn_array[i]); - } - } - - /* - * The above algorithm sometimes fails when the ucode - * reports 0 for all chains. It's not clear why that - * happens to start with, but it is then causing trouble - * because this can make us enable more chains than the - * hardware really has. - * - * To be safe, simply mask out any chains that we know - * are not on the device. - */ if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && - priv->bt_full_concurrent) { - /* operated as 1x1 in full concurrency mode */ - active_chains &= first_antenna(priv->hw_params.valid_rx_ant); + priv->cfg->bt_params->advanced_bt_coexist) { + /* Disable disconnected antenna algorithm for advanced + bt coex, assuming valid antennas are connected */ + data->active_chains = priv->hw_params.valid_rx_ant; + for (i = 0; i < NUM_RX_CHAINS; i++) + if (!(data->active_chains & (1<<i))) + data->disconn_array[i] = 1; } else - active_chains &= priv->hw_params.valid_rx_ant; - - num_tx_chains = 0; - for (i = 0; i < NUM_RX_CHAINS; i++) { - /* loops on all the bits of - * priv->hw_setting.valid_tx_ant */ - u8 ant_msk = (1 << i); - if (!(priv->hw_params.valid_tx_ant & ant_msk)) - continue; - - num_tx_chains++; - if (data->disconn_array[i] == 0) - /* there is a Tx antenna connected */ - break; - if (num_tx_chains == priv->hw_params.tx_chains_num && - data->disconn_array[i]) { - /* - * If all chains are disconnected - * connect the first valid tx chain - */ - first_chain = - find_first_chain(priv->cfg->valid_tx_ant); - data->disconn_array[first_chain] = 0; - active_chains |= BIT(first_chain); - IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - declare %d as connected\n", - first_chain); - break; - } - } - - if (active_chains != priv->hw_params.valid_rx_ant && - active_chains != priv->chain_noise_data.active_chains) - IWL_DEBUG_CALIB(priv, - "Detected that not all antennas are connected! " - "Connected: %#x, valid: %#x.\n", - active_chains, priv->hw_params.valid_rx_ant); - - /* Save for use within RXON, TX, SCAN commands, etc. */ - priv->chain_noise_data.active_chains = active_chains; - IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", - active_chains); + iwl_find_disconn_antenna(priv, average_sig, data); /* Analyze noise for rx balance */ average_noise[0] = data->chain_noise_a / diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index a358d4334a1a..a6dbd8983dac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c @@ -856,6 +856,9 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file, if (!iwl_is_alive(priv)) return -EAGAIN; + if (!priv->bt_enable_flag) + return -EINVAL; + /* make request to uCode to retrieve statistics information */ mutex_lock(&priv->mutex); ret = iwl_send_statistics_request(priv, CMD_SYNC, false); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c index 9eeeda18748d..97906dd442e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -75,109 +75,6 @@ #include "iwl-agn.h" #include "iwl-io.h" -/************************** EEPROM BANDS **************************** - * - * The iwl_eeprom_band definitions below provide the mapping from the - * EEPROM contents to the specific channel number supported for each - * band. - * - * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3 - * definition below maps to physical channel 42 in the 5.2GHz spectrum. - * The specific geography and calibration information for that channel - * is contained in the eeprom map itself. - * - * During init, we copy the eeprom information and channel map - * information into priv->channel_info_24/52 and priv->channel_map_24/52 - * - * channel_map_24/52 provides the index in the channel_info array for a - * given channel. We have to have two separate maps as there is channel - * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and - * band_2 - * - * A value of 0xff stored in the channel_map indicates that the channel - * is not supported by the hardware at all. - * - * A value of 0xfe in the channel_map indicates that the channel is not - * valid for Tx with the current hardware. This means that - * while the system can tune and receive on a given channel, it may not - * be able to associate or transmit any frames on that - * channel. There is no corresponding channel information for that - * entry. - * - *********************************************************************/ - -/** - * struct iwl_txpwr_section: eeprom section information - * @offset: indirect address into eeprom image - * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section - * @band: band type for the section - * @is_common - true: common section, false: channel section - * @is_cck - true: cck section, false: not cck section - * @is_ht_40 - true: all channel in the section are HT40 channel, - * false: legacy or HT 20 MHz - * ignore if it is common section - * @iwl_eeprom_section_channel: channel array in the section, - * ignore if common section - */ -struct iwl_txpwr_section { - u32 offset; - u8 count; - enum ieee80211_band band; - bool is_common; - bool is_cck; - bool is_ht40; - u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS]; -}; - -/** - * section 1 - 3 are regulatory tx power apply to all channels based on - * modulation: CCK, OFDM - * Band: 2.4GHz, 5.2GHz - * section 4 - 10 are regulatory tx power apply to specified channels - * For example: - * 1L - Channel 1 Legacy - * 1HT - Channel 1 HT - * (1,+1) - Channel 1 HT40 "_above_" - * - * Section 1: all CCK channels - * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels - * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels - * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT - * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) - * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT - * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1) - * Section 8: 2.4 GHz channel: 13L, 13HT - * Section 9: 2.4 GHz channel: 140L, 140HT - * Section 10: 2.4 GHz 40MHz channels: (132,+1) (44,+1) - * - */ -static const struct iwl_txpwr_section enhinfo[] = { - { EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false }, - { EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false }, - { EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false }, - { EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ, - false, false, false, - {1, 1, 2, 2, 10, 10, 11, 11 } }, - { EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ, - false, false, true, - { 1, 2, 6, 7, 9 } }, - { EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ, - false, false, false, - { 36, 64, 100, 36, 64, 100 } }, - { EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ, - false, false, true, - { 36, 60, 100 } }, - { EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ, - false, false, false, - { 13, 13 } }, - { EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ, - false, false, false, - { 140, 140 } }, - { EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ, - false, false, true, - { 132, 44 } }, -}; - /****************************************************************************** * * EEPROM related functions @@ -248,6 +145,47 @@ err: } +int iwl_eeprom_check_sku(struct iwl_priv *priv) +{ + u16 eeprom_sku; + u16 radio_cfg; + + eeprom_sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP); + + priv->cfg->sku = ((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >> + EEPROM_SKU_CAP_BAND_POS); + if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE) + priv->cfg->sku |= IWL_SKU_N; + + if (!priv->cfg->sku) { + IWL_ERR(priv, "Invalid device sku\n"); + return -EINVAL; + } + + IWL_INFO(priv, "Device SKU: 0X%x\n", priv->cfg->sku); + + if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) { + /* not using .cfg overwrite */ + radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); + priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); + priv->cfg->valid_rx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); + if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) { + IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n", + priv->cfg->valid_tx_ant, + priv->cfg->valid_rx_ant); + return -EINVAL; + } + IWL_INFO(priv, "Valid Tx ant: 0X%x, Valid Rx ant: 0X%x\n", + priv->cfg->valid_tx_ant, priv->cfg->valid_rx_ant); + } + /* + * for some special cases, + * EEPROM did not reflect the correct antenna setting + * so overwrite the valid tx/rx antenna from .cfg + */ + return 0; +} + void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) { const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv, @@ -265,15 +203,6 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, { s8 max_txpower_avg = 0; /* (dBm) */ - IWL_DEBUG_INFO(priv, "%d - " - "chain_a: %d dB chain_b: %d dB " - "chain_c: %d dB mimo2: %d dB mimo3: %d dB\n", - element, - enhanced_txpower[element].chain_a_max >> 1, - enhanced_txpower[element].chain_b_max >> 1, - enhanced_txpower[element].chain_c_max >> 1, - enhanced_txpower[element].mimo2_max >> 1, - enhanced_txpower[element].mimo3_max >> 1); /* Take the highest tx power from any valid chains */ if ((priv->cfg->valid_tx_ant & ANT_A) && (enhanced_txpower[element].chain_a_max > max_txpower_avg)) @@ -303,157 +232,6 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1); } -/** - * iwl_update_common_txpower: update channel tx power - * update tx power per band based on EEPROM enhanced tx power info. - */ -static s8 iwl_update_common_txpower(struct iwl_priv *priv, - struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, - int section, int element, s8 *max_txpower_in_half_dbm) -{ - struct iwl_channel_info *ch_info; - int ch; - bool is_ht40 = false; - s8 max_txpower_avg; /* (dBm) */ - - /* it is common section, contain all type (Legacy, HT and HT40) - * based on the element in the section to determine - * is it HT 40 or not - */ - if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX) - is_ht40 = true; - max_txpower_avg = - iwl_get_max_txpower_avg(priv, enhanced_txpower, - element, max_txpower_in_half_dbm); - - ch_info = priv->channel_info; - - for (ch = 0; ch < priv->channel_count; ch++) { - /* find matching band and update tx power if needed */ - if ((ch_info->band == enhinfo[section].band) && - (ch_info->max_power_avg < max_txpower_avg) && - (!is_ht40)) { - /* Update regulatory-based run-time data */ - ch_info->max_power_avg = ch_info->curr_txpow = - max_txpower_avg; - ch_info->scan_power = max_txpower_avg; - } - if ((ch_info->band == enhinfo[section].band) && is_ht40 && - (ch_info->ht40_max_power_avg < max_txpower_avg)) { - /* Update regulatory-based run-time data */ - ch_info->ht40_max_power_avg = max_txpower_avg; - } - ch_info++; - } - return max_txpower_avg; -} - -/** - * iwl_update_channel_txpower: update channel tx power - * update channel tx power based on EEPROM enhanced tx power info. - */ -static s8 iwl_update_channel_txpower(struct iwl_priv *priv, - struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, - int section, int element, s8 *max_txpower_in_half_dbm) -{ - struct iwl_channel_info *ch_info; - int ch; - u8 channel; - s8 max_txpower_avg; /* (dBm) */ - - channel = enhinfo[section].iwl_eeprom_section_channel[element]; - max_txpower_avg = - iwl_get_max_txpower_avg(priv, enhanced_txpower, - element, max_txpower_in_half_dbm); - - ch_info = priv->channel_info; - for (ch = 0; ch < priv->channel_count; ch++) { - /* find matching channel and update tx power if needed */ - if (ch_info->channel == channel) { - if ((ch_info->max_power_avg < max_txpower_avg) && - (!enhinfo[section].is_ht40)) { - /* Update regulatory-based run-time data */ - ch_info->max_power_avg = max_txpower_avg; - ch_info->curr_txpow = max_txpower_avg; - ch_info->scan_power = max_txpower_avg; - } - if ((enhinfo[section].is_ht40) && - (ch_info->ht40_max_power_avg < max_txpower_avg)) { - /* Update regulatory-based run-time data */ - ch_info->ht40_max_power_avg = max_txpower_avg; - } - break; - } - ch_info++; - } - return max_txpower_avg; -} - -/** - * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info - */ -static void iwlcore_eeprom_enhanced_txpower_old(struct iwl_priv *priv) -{ - int eeprom_section_count = 0; - int section, element; - struct iwl_eeprom_enhanced_txpwr *enhanced_txpower; - u32 offset; - s8 max_txpower_avg; /* (dBm) */ - s8 max_txpower_in_half_dbm; /* (half-dBm) */ - - /* Loop through all the sections - * adjust bands and channel's max tx power - * Set the tx_power_user_lmt to the highest power - * supported by any channels and chains - */ - for (section = 0; section < ARRAY_SIZE(enhinfo); section++) { - eeprom_section_count = enhinfo[section].count; - offset = enhinfo[section].offset; - enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *) - iwl_eeprom_query_addr(priv, offset); - - /* - * check for valid entry - - * different version of EEPROM might contain different set - * of enhanced tx power table - * always check for valid entry before process - * the information - */ - if (!(enhanced_txpower->flags || enhanced_txpower->channel) || - enhanced_txpower->delta_20_in_40) - continue; - - for (element = 0; element < eeprom_section_count; element++) { - if (enhinfo[section].is_common) - max_txpower_avg = - iwl_update_common_txpower(priv, - enhanced_txpower, section, - element, - &max_txpower_in_half_dbm); - else - max_txpower_avg = - iwl_update_channel_txpower(priv, - enhanced_txpower, section, - element, - &max_txpower_in_half_dbm); - - /* Update the tx_power_user_lmt to the highest power - * supported by any channel */ - if (max_txpower_avg > priv->tx_power_user_lmt) - priv->tx_power_user_lmt = max_txpower_avg; - - /* - * Update the tx_power_lmt_in_half_dbm to - * the highest power supported by any channel - */ - if (max_txpower_in_half_dbm > - priv->tx_power_lmt_in_half_dbm) - priv->tx_power_lmt_in_half_dbm = - max_txpower_in_half_dbm; - } - } -} - static void iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv, struct iwl_eeprom_enhanced_txpwr *txp, @@ -492,7 +270,10 @@ iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv, #define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr) #define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE) -static void iwlcore_eeprom_enhanced_txpower_new(struct iwl_priv *priv) +#define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \ + ? # x " " : "") + +void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) { struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; int idx, entries; @@ -506,13 +287,39 @@ static void iwlcore_eeprom_enhanced_txpower_new(struct iwl_priv *priv) entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; txp_array = (void *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_OFFS); + for (idx = 0; idx < entries; idx++) { txp = &txp_array[idx]; - /* skip invalid entries */ if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID)) continue; + IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n", + (txp->channel && (txp->flags & + IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ? + "Common " : (txp->channel) ? + "Channel" : "Common", + (txp->channel), + TXP_CHECK_AND_PRINT(VALID), + TXP_CHECK_AND_PRINT(BAND_52G), + TXP_CHECK_AND_PRINT(OFDM), + TXP_CHECK_AND_PRINT(40MHZ), + TXP_CHECK_AND_PRINT(HT_AP), + TXP_CHECK_AND_PRINT(RES1), + TXP_CHECK_AND_PRINT(RES2), + TXP_CHECK_AND_PRINT(COMMON_TYPE), + txp->flags); + IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x " + "chain_B: 0X%02x chain_C: 0X%02x\n", + txp->chain_a_max, txp->chain_b_max, + txp->chain_c_max); + IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x " + "MIMO3: 0x%02x High 20_on_40: 0x%02x " + "Low 20_on_40: 0x%02x\n", + txp->mimo2_max, txp->mimo3_max, + ((txp->delta_20_in_40 & 0xf0) >> 4), + (txp->delta_20_in_40 & 0x0f)); + max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx, &max_txp_avg_halfdbm); @@ -528,11 +335,3 @@ static void iwlcore_eeprom_enhanced_txpower_new(struct iwl_priv *priv) iwlcore_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); } } - -void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) -{ - if (priv->cfg->use_new_eeprom_reading) - iwlcore_eeprom_enhanced_txpower_new(priv); - else - iwlcore_eeprom_enhanced_txpower_old(priv); -} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index ffb2f4111ad0..366340f3fb0f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -307,6 +307,7 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) if (ctx_bss->vif && ctx_pan->vif) { int bcnint = ctx_pan->vif->bss_conf.beacon_int; + int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; /* should be set, but seems unused?? */ cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE); @@ -329,10 +330,10 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) if (test_bit(STATUS_SCAN_HW, &priv->status) || (!ctx_bss->vif->bss_conf.idle && !ctx_bss->vif->bss_conf.assoc)) { - slot0 = bcnint * 3 - 20; + slot0 = dtim * bcnint * 3 - 20; slot1 = 20; } else if (!ctx_pan->vif->bss_conf.idle && - !ctx_pan->vif->bss_conf.assoc) { + !ctx_pan->vif->bss_conf.assoc) { slot1 = bcnint * 3 - 20; slot0 = 20; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 554afb7d9670..3dee87e8f55d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -405,6 +405,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, return; } + txq->time_stamp = jiffies; info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); memset(&info->status, 0, sizeof(info->status)); @@ -445,22 +446,17 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark) && - (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { - if (agg->state == IWL_AGG_OFF) - iwl_wake_queue(priv, txq_id); - else - iwl_wake_queue(priv, txq->swq_id); - } + (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) + iwl_wake_queue(priv, txq); } } else { - BUG_ON(txq_id != txq->swq_id); iwlagn_set_tx_status(priv, info, tx_resp, txq_id, false); freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); iwl_free_tfds_in_queue(priv, sta_id, tid, freed); if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark)) - iwl_wake_queue(priv, txq_id); + iwl_wake_queue(priv, txq); } iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); @@ -496,6 +492,10 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) struct iwlagn_tx_power_dbm_cmd tx_power_cmd; u8 tx_ant_cfg_cmd; + if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status), + "TX Power requested while scanning!\n")) + return -EAGAIN; + /* half dBm need to multiply */ tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); @@ -522,9 +522,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) else tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; - return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd, - sizeof(tx_power_cmd), &tx_power_cmd, - NULL); + return iwl_send_cmd_pdu(priv, tx_ant_cfg_cmd, sizeof(tx_power_cmd), + &tx_power_cmd); } void iwlagn_temperature(struct iwl_priv *priv) @@ -756,6 +755,12 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv) } else iwlagn_txq_ctx_reset(priv); + if (priv->cfg->base_params->shadow_reg_enable) { + /* enable shadow regs in HW */ + iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL, + 0x800FFFFF); + } + set_bit(STATUS_INIT, &priv->status); return 0; @@ -1487,15 +1492,11 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) if (priv->cfg->scan_rx_antennas[band]) rx_ant = priv->cfg->scan_rx_antennas[band]; - if (priv->cfg->scan_tx_antennas[band]) - scan_tx_antennas = priv->cfg->scan_tx_antennas[band]; - - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && - priv->bt_full_concurrent) { - /* operated as 1x1 in full concurrency mode */ - scan_tx_antennas = first_antenna( - priv->cfg->scan_tx_antennas[band]); + if (band == IEEE80211_BAND_2GHZ && + priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist) { + /* transmit 2.4 GHz probes only on first antenna */ + scan_tx_antennas = first_antenna(scan_tx_antennas); } priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band], @@ -1590,22 +1591,6 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) return ret; } -void iwlagn_post_scan(struct iwl_priv *priv) -{ - struct iwl_rxon_context *ctx; - - /* - * Since setting the RXON may have been deferred while - * performing the scan, fire one off if needed - */ - for_each_context(priv, ctx) - if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) - iwlagn_commit_rxon(priv, ctx); - - if (priv->cfg->ops->hcmd->set_pan_params) - priv->cfg->ops->hcmd->set_pan_params(priv); -} - int iwlagn_manage_ibss_station(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add) { @@ -1796,7 +1781,7 @@ static const __le32 iwlagn_def_3w_lookup[12] = { cpu_to_le32(0xc0004000), cpu_to_le32(0x00004000), cpu_to_le32(0xf0005000), - cpu_to_le32(0xf0004000), + cpu_to_le32(0xf0005000), }; static const __le32 iwlagn_concurrent_lookup[12] = { @@ -1832,6 +1817,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) bt_cmd.prio_boost = 0; bt_cmd.kill_ack_mask = priv->kill_ack_mask; bt_cmd.kill_cts_mask = priv->kill_cts_mask; + bt_cmd.valid = priv->bt_valid; bt_cmd.tx_prio_boost = 0; bt_cmd.rx_prio_boost = 0; @@ -1847,10 +1833,15 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) } else { bt_cmd.flags = IWLAGN_BT_FLAG_COEX_MODE_3W << IWLAGN_BT_FLAG_COEX_MODE_SHIFT; + if (priv->cfg->bt_params && + priv->cfg->bt_params->bt_sco_disable) + bt_cmd.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE; + if (priv->bt_ch_announce) bt_cmd.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION; IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", bt_cmd.flags); } + priv->bt_enable_flag = bt_cmd.flags; if (priv->bt_full_concurrent) memcpy(bt_cmd.bt3_lookup_table, iwlagn_concurrent_lookup, sizeof(iwlagn_concurrent_lookup)); @@ -1890,12 +1881,20 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) struct iwl_rxon_context *ctx; int smps_request = -1; + /* + * Note: bt_traffic_load can be overridden by scan complete and + * coex profile notifications. Ignore that since only bad consequence + * can be not matching debug print with actual state. + */ IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n", priv->bt_traffic_load); switch (priv->bt_traffic_load) { case IWL_BT_COEX_TRAFFIC_LOAD_NONE: - smps_request = IEEE80211_SMPS_AUTOMATIC; + if (priv->bt_status) + smps_request = IEEE80211_SMPS_DYNAMIC; + else + smps_request = IEEE80211_SMPS_AUTOMATIC; break; case IWL_BT_COEX_TRAFFIC_LOAD_LOW: smps_request = IEEE80211_SMPS_DYNAMIC; @@ -1912,6 +1911,16 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) mutex_lock(&priv->mutex); + /* + * We can not send command to firmware while scanning. When the scan + * complete we will schedule this work again. We do check with mutex + * locked to prevent new scan request to arrive. We do not check + * STATUS_SCANNING to avoid race when queue_work two times from + * different notifications, but quit and not perform any work at all. + */ + if (test_bit(STATUS_SCAN_HW, &priv->status)) + goto out; + if (priv->cfg->ops->lib->update_chain_flags) priv->cfg->ops->lib->update_chain_flags(priv); @@ -1921,7 +1930,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) ieee80211_request_smps(ctx->vif, smps_request); } } - +out: mutex_unlock(&priv->mutex); } @@ -1992,24 +2001,29 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv, BT_UART_MSG_FRAME7CONNECTABLE_POS); } -static void iwlagn_set_kill_ack_msk(struct iwl_priv *priv, - struct iwl_bt_uart_msg *uart_msg) +static void iwlagn_set_kill_msk(struct iwl_priv *priv, + struct iwl_bt_uart_msg *uart_msg) { - u8 kill_ack_msk; - __le32 bt_kill_ack_msg[2] = { - cpu_to_le32(0xFFFFFFF), cpu_to_le32(0xFFFFFC00) }; - - kill_ack_msk = (((BT_UART_MSG_FRAME3A2DP_MSK | - BT_UART_MSG_FRAME3SNIFF_MSK | - BT_UART_MSG_FRAME3SCOESCO_MSK) & - uart_msg->frame3) == 0) ? 1 : 0; - if (priv->kill_ack_mask != bt_kill_ack_msg[kill_ack_msk]) { + u8 kill_msk; + static const __le32 bt_kill_ack_msg[2] = { + IWLAGN_BT_KILL_ACK_MASK_DEFAULT, + IWLAGN_BT_KILL_ACK_CTS_MASK_SCO }; + static const __le32 bt_kill_cts_msg[2] = { + IWLAGN_BT_KILL_CTS_MASK_DEFAULT, + IWLAGN_BT_KILL_ACK_CTS_MASK_SCO }; + + kill_msk = (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) + ? 1 : 0; + if (priv->kill_ack_mask != bt_kill_ack_msg[kill_msk] || + priv->kill_cts_mask != bt_kill_cts_msg[kill_msk]) { priv->bt_valid |= IWLAGN_BT_VALID_KILL_ACK_MASK; - priv->kill_ack_mask = bt_kill_ack_msg[kill_ack_msk]; + priv->kill_ack_mask = bt_kill_ack_msg[kill_msk]; + priv->bt_valid |= IWLAGN_BT_VALID_KILL_CTS_MASK; + priv->kill_cts_mask = bt_kill_cts_msg[kill_msk]; + /* schedule to send runtime bt_config */ queue_work(priv->workqueue, &priv->bt_runtime_config); } - } void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, @@ -2020,7 +2034,6 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif; struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 }; struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg; - u8 last_traffic_load; IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n"); IWL_DEBUG_NOTIF(priv, " status: %d\n", coex->bt_status); @@ -2029,11 +2042,10 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, coex->bt_ci_compliance); iwlagn_print_uartmsg(priv, uart_msg); - last_traffic_load = priv->notif_bt_traffic_load; - priv->notif_bt_traffic_load = coex->bt_traffic_load; + priv->last_bt_traffic_load = priv->bt_traffic_load; if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { if (priv->bt_status != coex->bt_status || - last_traffic_load != coex->bt_traffic_load) { + priv->last_bt_traffic_load != coex->bt_traffic_load) { if (coex->bt_status) { /* BT on */ if (!priv->bt_ch_announce) @@ -2062,7 +2074,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, } } - iwlagn_set_kill_ack_msk(priv, uart_msg); + iwlagn_set_kill_msk(priv, uart_msg); /* FIXME: based on notification, adjust the prio_boost */ @@ -2282,7 +2294,7 @@ static const char *get_csr_string(int cmd) void iwl_dump_csr(struct iwl_priv *priv) { int i; - u32 csr_tbl[] = { + static const u32 csr_tbl[] = { CSR_HW_IF_CONFIG_REG, CSR_INT_COALESCING, CSR_INT, @@ -2341,7 +2353,7 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) int pos = 0; size_t bufsz = 0; #endif - u32 fh_tbl[] = { + static const u32 fh_tbl[] = { FH_RSCSR_CHNL0_STTS_WPTR_REG, FH_RSCSR_CHNL0_RBDCB_BASE_REG, FH_RSCSR_CHNL0_WPTR, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 065553629de5..75fcd30a7c13 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -387,7 +387,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, if (load > IWL_AGG_LOAD_THRESHOLD) { IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", sta->addr, tid); - ret = ieee80211_start_tx_ba_session(sta, tid); + ret = ieee80211_start_tx_ba_session(sta, tid, 5000); if (ret == -EAGAIN) { /* * driver and mac80211 is out of sync @@ -833,17 +833,23 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_lq_sta *lq_sta) { struct iwl_scale_tbl_info *tbl; - bool full_concurrent; + bool full_concurrent = priv->bt_full_concurrent; unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); - if (priv->bt_ci_compliance && priv->bt_ant_couple_ok) - full_concurrent = true; - else - full_concurrent = false; - spin_unlock_irqrestore(&priv->lock, flags); - - if (priv->bt_full_concurrent != full_concurrent) { + if (priv->bt_ant_couple_ok) { + /* + * Is there a need to switch between + * full concurrency and 3-wire? + */ + spin_lock_irqsave(&priv->lock, flags); + if (priv->bt_ci_compliance && priv->bt_ant_couple_ok) + full_concurrent = true; + else + full_concurrent = false; + spin_unlock_irqrestore(&priv->lock, flags); + } + if ((priv->bt_traffic_load != priv->last_bt_traffic_load) || + (priv->bt_full_concurrent != full_concurrent)) { priv->bt_full_concurrent = full_concurrent; /* Update uCode's rate table. */ @@ -1040,8 +1046,7 @@ done: if (sta && sta->supp_rates[sband->band]) rs_rate_scale_perform(priv, skb, sta, lq_sta); - /* Is there a need to switch between full concurrency and 3-wire? */ - if (priv->bt_ant_couple_ok) + if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) rs_bt_update_lq(priv, ctx, lq_sta); } @@ -2868,6 +2873,10 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_agg = 0; +#ifdef CONFIG_MAC80211_DEBUGFS + lq_sta->dbg_fixed_rate = 0; +#endif + rs_initialize_lq(priv, conf, sta, lq_sta); } @@ -3010,10 +3019,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, */ if (priv && priv->cfg->bt_params && priv->cfg->bt_params->agg_time_limit && - priv->cfg->bt_params->agg_time_limit >= - LINK_QUAL_AGG_TIME_LIMIT_MIN && - priv->cfg->bt_params->agg_time_limit <= - LINK_QUAL_AGG_TIME_LIMIT_MAX) + priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) lq_cmd->agg_params.agg_time_limit = cpu_to_le16(priv->cfg->bt_params->agg_time_limit); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c new file mode 100644 index 000000000000..6d140bd53291 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -0,0 +1,642 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless <ilw@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#include "iwl-dev.h" +#include "iwl-agn.h" +#include "iwl-sta.h" +#include "iwl-core.h" +#include "iwl-agn-calib.h" + +static int iwlagn_disable_bss(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct iwl_rxon_cmd *send) +{ + __le32 old_filter = send->filter_flags; + int ret; + + send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send); + + send->filter_flags = old_filter; + + if (ret) + IWL_ERR(priv, "Error clearing ASSOC_MSK on BSS (%d)\n", ret); + + return ret; +} + +static int iwlagn_disable_pan(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct iwl_rxon_cmd *send) +{ + __le32 old_filter = send->filter_flags; + u8 old_dev_type = send->dev_type; + int ret; + + send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; + send->dev_type = RXON_DEV_TYPE_P2P; + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send); + + send->filter_flags = old_filter; + send->dev_type = old_dev_type; + + if (ret) + IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); + + /* FIXME: WAIT FOR PAN DISABLE */ + msleep(300); + + return ret; +} + +static void iwlagn_update_qos(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) +{ + int ret; + + if (!ctx->is_active) + return; + + ctx->qos_data.def_qos_parm.qos_flags = 0; + + if (ctx->qos_data.qos_active) + ctx->qos_data.def_qos_parm.qos_flags |= + QOS_PARAM_FLG_UPDATE_EDCA_MSK; + + if (ctx->ht.enabled) + ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; + + IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", + ctx->qos_data.qos_active, + ctx->qos_data.def_qos_parm.qos_flags); + + ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd, + sizeof(struct iwl_qosparam_cmd), + &ctx->qos_data.def_qos_parm); + if (ret) + IWL_ERR(priv, "Failed to update QoS\n"); +} + +static int iwlagn_update_beacon(struct iwl_priv *priv, + struct ieee80211_vif *vif) +{ + lockdep_assert_held(&priv->mutex); + + dev_kfree_skb(priv->beacon_skb); + priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif); + if (!priv->beacon_skb) + return -ENOMEM; + return iwlagn_send_beacon_cmd(priv); +} + +/** + * iwlagn_commit_rxon - commit staging_rxon to hardware + * + * The RXON command in staging_rxon is committed to the hardware and + * the active_rxon structure is updated with the new data. This + * function correctly transitions out of the RXON_ASSOC_MSK state if + * a HW tune is required based on the RXON structure changes. + */ +int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) +{ + /* cast away the const for active_rxon in this function */ + struct iwl_rxon_cmd *active = (void *)&ctx->active; + bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); + bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK); + int ret; + + lockdep_assert_held(&priv->mutex); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return -EINVAL; + + if (!iwl_is_alive(priv)) + return -EBUSY; + + /* This function hardcodes a bunch of dual-mode assumptions */ + BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); + + if (!ctx->is_active) + return 0; + + /* always get timestamp with Rx frame */ + ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; + + if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || + !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK)) + ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; + else + ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + + ret = iwl_check_rxon_cmd(priv, ctx); + if (ret) { + IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); + return -EINVAL; + } + + /* + * receive commit_rxon request + * abort any previous channel switch if still in process + */ + if (priv->switch_rxon.switch_in_progress && + (priv->switch_rxon.channel != ctx->staging.channel)) { + IWL_DEBUG_11H(priv, "abort channel switch on %d\n", + le16_to_cpu(priv->switch_rxon.channel)); + iwl_chswitch_done(priv, false); + } + + /* + * If we don't need to send a full RXON, we can use + * iwl_rxon_assoc_cmd which is used to reconfigure filter + * and other flags for the current radio configuration. + */ + if (!iwl_full_rxon_required(priv, ctx)) { + ret = iwl_send_rxon_assoc(priv, ctx); + if (ret) { + IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); + return ret; + } + + memcpy(active, &ctx->staging, sizeof(*active)); + iwl_print_rx_config_cmd(priv, ctx); + return 0; + } + + if (priv->cfg->ops->hcmd->set_pan_params) { + ret = priv->cfg->ops->hcmd->set_pan_params(priv); + if (ret) + return ret; + } + + iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); + + IWL_DEBUG_INFO(priv, + "Going to commit RXON\n" + " * with%s RXON_FILTER_ASSOC_MSK\n" + " * channel = %d\n" + " * bssid = %pM\n", + (new_assoc ? "" : "out"), + le16_to_cpu(ctx->staging.channel), + ctx->staging.bssid_addr); + + /* + * Always clear associated first, but with the correct config. + * This is required as for example station addition for the + * AP station must be done after the BSSID is set to correctly + * set up filters in the device. + */ + if ((old_assoc && new_assoc) || !new_assoc) { + if (ctx->ctxid == IWL_RXON_CTX_BSS) + ret = iwlagn_disable_bss(priv, ctx, &ctx->staging); + else + ret = iwlagn_disable_pan(priv, ctx, &ctx->staging); + if (ret) + return ret; + + memcpy(active, &ctx->staging, sizeof(*active)); + + /* + * Un-assoc RXON clears the station table and WEP + * keys, so we have to restore those afterwards. + */ + iwl_clear_ucode_stations(priv, ctx); + iwl_restore_stations(priv, ctx); + ret = iwl_restore_default_wep_keys(priv, ctx); + if (ret) { + IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); + return ret; + } + } + + /* RXON timing must be before associated RXON */ + ret = iwl_send_rxon_timing(priv, ctx); + if (ret) { + IWL_ERR(priv, "Failed to send timing (%d)!\n", ret); + return ret; + } + + if (new_assoc) { + /* QoS info may be cleared by previous un-assoc RXON */ + iwlagn_update_qos(priv, ctx); + + /* + * We'll run into this code path when beaconing is + * enabled, but then we also need to send the beacon + * to the device. + */ + if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) { + ret = iwlagn_update_beacon(priv, ctx->vif); + if (ret) { + IWL_ERR(priv, + "Error sending required beacon (%d)!\n", + ret); + return ret; + } + } + + priv->start_calib = 0; + /* + * Apply the new configuration. + * + * Associated RXON doesn't clear the station table in uCode, + * so we don't need to restore stations etc. after this. + */ + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, + sizeof(struct iwl_rxon_cmd), &ctx->staging); + if (ret) { + IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); + return ret; + } + memcpy(active, &ctx->staging, sizeof(*active)); + + iwl_reprogram_ap_sta(priv, ctx); + + /* IBSS beacon needs to be sent after setting assoc */ + if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC)) + if (iwlagn_update_beacon(priv, ctx->vif)) + IWL_ERR(priv, "Error sending IBSS beacon\n"); + } + + iwl_print_rx_config_cmd(priv, ctx); + + iwl_init_sensitivity(priv); + + /* + * If we issue a new RXON command which required a tune then we must + * send a new TXPOWER command or we won't be able to Tx any frames. + * + * FIXME: which RXON requires a tune? Can we optimise this out in + * some cases? + */ + ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); + if (ret) { + IWL_ERR(priv, "Error sending TX power (%d)\n", ret); + return ret; + } + + return 0; +} + +int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_rxon_context *ctx; + struct ieee80211_conf *conf = &hw->conf; + struct ieee80211_channel *channel = conf->channel; + const struct iwl_channel_info *ch_info; + int ret = 0; + bool ht_changed[NUM_IWL_RXON_CTX] = {}; + + IWL_DEBUG_MAC80211(priv, "changed %#x", changed); + + mutex_lock(&priv->mutex); + + if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { + IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); + goto out; + } + + if (!iwl_is_ready(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); + goto out; + } + + if (changed & (IEEE80211_CONF_CHANGE_SMPS | + IEEE80211_CONF_CHANGE_CHANNEL)) { + /* mac80211 uses static for non-HT which is what we want */ + priv->current_ht_config.smps = conf->smps_mode; + + /* + * Recalculate chain counts. + * + * If monitor mode is enabled then mac80211 will + * set up the SM PS mode to OFF if an HT channel is + * configured. + */ + if (priv->cfg->ops->hcmd->set_rxon_chain) + for_each_context(priv, ctx) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + } + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + unsigned long flags; + + ch_info = iwl_get_channel_info(priv, channel->band, + channel->hw_value); + if (!is_channel_valid(ch_info)) { + IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); + ret = -EINVAL; + goto out; + } + + spin_lock_irqsave(&priv->lock, flags); + + for_each_context(priv, ctx) { + /* Configure HT40 channels */ + if (ctx->ht.enabled != conf_is_ht(conf)) { + ctx->ht.enabled = conf_is_ht(conf); + ht_changed[ctx->ctxid] = true; + } + + if (ctx->ht.enabled) { + if (conf_is_ht40_minus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_BELOW; + ctx->ht.is_40mhz = true; + } else if (conf_is_ht40_plus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + ctx->ht.is_40mhz = true; + } else { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_NONE; + ctx->ht.is_40mhz = false; + } + } else + ctx->ht.is_40mhz = false; + + /* + * Default to no protection. Protection mode will + * later be set from BSS config in iwl_ht_conf + */ + ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; + + /* if we are switching from ht to 2.4 clear flags + * from any ht related info since 2.4 does not + * support ht */ + if (le16_to_cpu(ctx->staging.channel) != + channel->hw_value) + ctx->staging.flags = 0; + + iwl_set_rxon_channel(priv, channel, ctx); + iwl_set_rxon_ht(priv, &priv->current_ht_config); + + iwl_set_flags_for_band(priv, ctx, channel->band, + ctx->vif); + } + + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_update_bcast_stations(priv); + + /* + * The list of supported rates and rate mask can be different + * for each band; since the band may have changed, reset + * the rate mask to what mac80211 lists. + */ + iwl_set_rate(priv); + } + + if (changed & (IEEE80211_CONF_CHANGE_PS | + IEEE80211_CONF_CHANGE_IDLE)) { + ret = iwl_power_update_mode(priv, false); + if (ret) + IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n"); + } + + if (changed & IEEE80211_CONF_CHANGE_POWER) { + IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", + priv->tx_power_user_lmt, conf->power_level); + + iwl_set_tx_power(priv, conf->power_level, false); + } + + for_each_context(priv, ctx) { + if (!memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) + continue; + iwlagn_commit_rxon(priv, ctx); + if (ht_changed[ctx->ctxid]) + iwlagn_update_qos(priv, ctx); + } + out: + mutex_unlock(&priv->mutex); + return ret; +} + +static void iwlagn_check_needed_chains(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_bss_conf *bss_conf) +{ + struct ieee80211_vif *vif = ctx->vif; + struct iwl_rxon_context *tmp; + struct ieee80211_sta *sta; + struct iwl_ht_config *ht_conf = &priv->current_ht_config; + bool need_multiple; + + lockdep_assert_held(&priv->mutex); + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + rcu_read_lock(); + sta = ieee80211_find_sta(vif, bss_conf->bssid); + if (sta) { + struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; + int maxstreams; + + maxstreams = (ht_cap->mcs.tx_params & + IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) + >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; + maxstreams += 1; + + need_multiple = true; + + if ((ht_cap->mcs.rx_mask[1] == 0) && + (ht_cap->mcs.rx_mask[2] == 0)) + need_multiple = false; + if (maxstreams <= 1) + need_multiple = false; + } else { + /* + * If at all, this can only happen through a race + * when the AP disconnects us while we're still + * setting up the connection, in that case mac80211 + * will soon tell us about that. + */ + need_multiple = false; + } + rcu_read_unlock(); + break; + case NL80211_IFTYPE_ADHOC: + /* currently */ + need_multiple = false; + break; + default: + /* only AP really */ + need_multiple = true; + break; + } + + ctx->ht_need_multiple_chains = need_multiple; + + if (!need_multiple) { + /* check all contexts */ + for_each_context(priv, tmp) { + if (!tmp->vif) + continue; + if (tmp->ht_need_multiple_chains) { + need_multiple = true; + break; + } + } + } + + ht_conf->single_chain_sufficient = !need_multiple; +} + +void iwlagn_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + int ret; + bool force = false; + + mutex_lock(&priv->mutex); + + if (unlikely(!iwl_is_ready(priv))) { + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); + mutex_unlock(&priv->mutex); + return; + } + + if (unlikely(!ctx->vif)) { + IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n"); + mutex_unlock(&priv->mutex); + return; + } + + if (changes & BSS_CHANGED_BEACON_INT) + force = true; + + if (changes & BSS_CHANGED_QOS) { + ctx->qos_data.qos_active = bss_conf->qos; + iwlagn_update_qos(priv, ctx); + } + + ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); + if (vif->bss_conf.use_short_preamble) + ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + else + ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + + if (changes & BSS_CHANGED_ASSOC) { + if (bss_conf->assoc) { + iwl_led_associate(priv); + priv->timestamp = bss_conf->timestamp; + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + } else { + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_led_disassociate(priv); + } + } + + if (ctx->ht.enabled) { + ctx->ht.protection = bss_conf->ht_operation_mode & + IEEE80211_HT_OP_MODE_PROTECTION; + ctx->ht.non_gf_sta_present = !!(bss_conf->ht_operation_mode & + IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); + iwlagn_check_needed_chains(priv, ctx, bss_conf); + iwl_set_rxon_ht(priv, &priv->current_ht_config); + } + + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + + if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) + ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; + else + ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + + if (bss_conf->use_cts_prot) + ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; + else + ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; + + memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN); + + if (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_ADHOC) { + if (vif->bss_conf.enable_beacon) { + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + priv->beacon_ctx = ctx; + } else { + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + priv->beacon_ctx = NULL; + } + } + + if (force || memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) + iwlagn_commit_rxon(priv, ctx); + + if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) { + /* + * The chain noise calibration will enable PM upon + * completion. If calibration has already been run + * then we need to enable power management here. + */ + if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) + iwl_power_update_mode(priv, false); + + /* Enable RX differential gain and sensitivity calibrations */ + iwl_chain_noise_reset(priv); + priv->start_calib = 1; + } + + if (changes & BSS_CHANGED_IBSS) { + ret = iwlagn_manage_ibss_station(priv, vif, + bss_conf->ibss_joined); + if (ret) + IWL_ERR(priv, "failed to %s IBSS station %pM\n", + bss_conf->ibss_joined ? "add" : "remove", + bss_conf->bssid); + } + + if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_ADHOC && + priv->beacon_ctx) { + if (iwlagn_update_beacon(priv, vif)) + IWL_ERR(priv, "Error sending IBSS beacon\n"); + } + + mutex_unlock(&priv->mutex); +} + +void iwlagn_post_scan(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx; + + /* + * Since setting the RXON may have been deferred while + * performing the scan, fire one off if needed + */ + for_each_context(priv, ctx) + if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) + iwlagn_commit_rxon(priv, ctx); + + if (priv->cfg->ops->hcmd->set_pan_params) + priv->cfg->ops->hcmd->set_pan_params(priv); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 35a30d2e0734..35f085ac336b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -684,7 +684,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } -void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) +static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) { unsigned long flags; @@ -714,3 +714,33 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) spin_unlock_irqrestore(&priv->sta_lock, flags); } + +void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; + int sta_id; + + switch (cmd) { + case STA_NOTIFY_SLEEP: + WARN_ON(!sta_priv->client); + sta_priv->asleep = true; + if (atomic_read(&sta_priv->pending_frames) > 0) + ieee80211_sta_block_awake(hw, sta, true); + break; + case STA_NOTIFY_AWAKE: + WARN_ON(!sta_priv->client); + if (!sta_priv->asleep) + break; + sta_priv->asleep = false; + sta_id = iwl_sta_id(sta); + if (sta_id != IWL_INVALID_STATION) + iwl_sta_modify_ps_wake(priv, sta_id); + break; + default: + break; + } +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 2b078a995729..24a11b8f73bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -67,8 +67,14 @@ */ static const u8 tid_to_ac[] = { - /* this matches the mac80211 numbers */ - 2, 3, 3, 2, 1, 1, 0, 0 + IEEE80211_AC_BE, + IEEE80211_AC_BK, + IEEE80211_AC_BK, + IEEE80211_AC_BE, + IEEE80211_AC_VI, + IEEE80211_AC_VI, + IEEE80211_AC_VO, + IEEE80211_AC_VO }; static inline int get_ac_from_tid(u16 tid) @@ -518,11 +524,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct iwl_cmd_meta *out_meta; struct iwl_tx_cmd *tx_cmd; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - int swq_id, txq_id; + int txq_id; dma_addr_t phys_addr; dma_addr_t txcmd_phys; dma_addr_t scratch_phys; - u16 len, len_org, firstlen, secondlen; + u16 len, firstlen, secondlen; u16 seq_number = 0; __le16 fc; u8 hdr_len; @@ -531,6 +537,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) u8 tid = 0; u8 *qc = NULL; unsigned long flags; + bool is_agg = false; if (info->control.vif) ctx = iwl_rxon_ctx_from_vif(info->control.vif); @@ -567,8 +574,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (sta) sta_priv = (void *)sta->drv_priv; - if (sta_priv && sta_priv->asleep) { - WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); + if (sta_priv && sta_priv->asleep && + (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) { /* * This sends an asynchronous command to the device, * but we can rely on it being processed before the @@ -616,11 +623,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (info->flags & IEEE80211_TX_CTL_AMPDU && priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; + is_agg = true; } } txq = &priv->txq[txq_id]; - swq_id = txq->swq_id; q = &txq->q; if (unlikely(iwl_queue_space(q) < q->high_mark)) { @@ -687,30 +694,23 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) */ len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) + hdr_len; - - len_org = len; - firstlen = len = (len + 3) & ~3; - - if (len_org != len) - len_org = 1; - else - len_org = 0; + firstlen = (len + 3) & ~3; /* Tell NIC about any 2-byte padding after MAC header */ - if (len_org) + if (firstlen != len) tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ txcmd_phys = pci_map_single(priv->pci_dev, - &out_cmd->hdr, len, + &out_cmd->hdr, firstlen, PCI_DMA_BIDIRECTIONAL); dma_unmap_addr_set(out_meta, mapping, txcmd_phys); - dma_unmap_len_set(out_meta, len, len); + dma_unmap_len_set(out_meta, len, firstlen); /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - txcmd_phys, len, 1, 0); + txcmd_phys, firstlen, 1, 0); if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; @@ -721,23 +721,21 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Set up TFD's 2nd entry to point directly to remainder of skb, * if any (802.11 null frames have no payload). */ - secondlen = len = skb->len - hdr_len; - if (len) { + secondlen = skb->len - hdr_len; + if (secondlen > 0) { phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, - len, PCI_DMA_TODEVICE); + secondlen, PCI_DMA_TODEVICE); priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - phys_addr, len, + phys_addr, secondlen, 0, 0); } scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + offsetof(struct iwl_tx_cmd, scratch); - len = sizeof(struct iwl_tx_cmd) + - sizeof(struct iwl_cmd_header) + hdr_len; /* take back ownership of DMA buffer to enable update */ pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys, - len, PCI_DMA_BIDIRECTIONAL); + firstlen, PCI_DMA_BIDIRECTIONAL); tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); @@ -753,7 +751,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) le16_to_cpu(tx_cmd->len)); pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, - len, PCI_DMA_BIDIRECTIONAL); + firstlen, PCI_DMA_BIDIRECTIONAL); trace_iwlwifi_dev_tx(priv, &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], @@ -773,8 +771,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) * whether or not we should update the write pointer. */ - /* avoid atomic ops if it isn't an associated client */ - if (sta_priv && sta_priv->client) + /* + * Avoid atomic ops if it isn't an associated client. + * Also, if this is a packet for aggregation, don't + * increase the counter because the ucode will stop + * aggregation queues when their respective station + * goes to sleep. + */ + if (sta_priv && sta_priv->client && !is_agg) atomic_inc(&sta_priv->pending_frames); if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { @@ -784,7 +788,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_txq_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); } else { - iwl_stop_queue(priv, txq->swq_id); + iwl_stop_queue(priv, txq); } } @@ -1013,7 +1017,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, tid_data = &priv->stations[sta_id].tid[tid]; *ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->agg.txq_id = txq_id; - priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(get_ac_from_tid(tid), txq_id); + iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id); spin_unlock_irqrestore(&priv->sta_lock, flags); ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, @@ -1153,14 +1157,15 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, return 0; } -static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info) +static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + const u8 *addr1) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data; struct ieee80211_sta *sta; struct iwl_station_priv *sta_priv; rcu_read_lock(); - sta = ieee80211_find_sta(tx_info->ctx->vif, hdr->addr1); + sta = ieee80211_find_sta(ctx->vif, addr1); if (sta) { sta_priv = (void *)sta->drv_priv; /* avoid atomic ops if this isn't a client */ @@ -1169,6 +1174,15 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info) ieee80211_sta_block_awake(priv->hw, sta, false); } rcu_read_unlock(); +} + +static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info, + bool is_agg) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data; + + if (!is_agg) + iwlagn_non_agg_tx_status(priv, tx_info->ctx, hdr->addr1); ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb); } @@ -1193,7 +1207,8 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { tx_info = &txq->txb[txq->q.read_ptr]; - iwlagn_tx_status(priv, tx_info); + iwlagn_tx_status(priv, tx_info, + txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); hdr = (struct ieee80211_hdr *)tx_info->skb->data; if (hdr && ieee80211_is_data_qos(hdr->frame_control)) @@ -1222,7 +1237,6 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, int i, sh, ack; u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); - u64 bitmap, sent_bitmap; int successes = 0; struct ieee80211_tx_info *info; @@ -1241,40 +1255,68 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, if (sh < 0) /* tbw something is wrong with indices */ sh += 0x100; - /* don't use 64-bit values for now */ - bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; - if (agg->frame_count > (64 - sh)) { IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); return -1; } + if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) { + /* + * sent and ack information provided by uCode + * use it instead of figure out ourself + */ + if (ba_resp->txed_2_done > ba_resp->txed) { + IWL_DEBUG_TX_REPLY(priv, + "bogus sent(%d) and ack(%d) count\n", + ba_resp->txed, ba_resp->txed_2_done); + /* + * set txed_2_done = txed, + * so it won't impact rate scale + */ + ba_resp->txed = ba_resp->txed_2_done; + } + IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", + ba_resp->txed, ba_resp->txed_2_done); + } else { + u64 bitmap, sent_bitmap; + + /* don't use 64-bit values for now */ + bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; + + /* check for success or failure according to the + * transmitted bitmap and block-ack bitmap */ + sent_bitmap = bitmap & agg->bitmap; + + /* For each frame attempted in aggregation, + * update driver's record of tx frame's status. */ + i = 0; + while (sent_bitmap) { + ack = sent_bitmap & 1ULL; + successes += ack; + IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", + ack ? "ACK" : "NACK", i, + (agg->start_idx + i) & 0xff, + agg->start_idx + i); + sent_bitmap >>= 1; + ++i; + } - /* check for success or failure according to the - * transmitted bitmap and block-ack bitmap */ - sent_bitmap = bitmap & agg->bitmap; - - /* For each frame attempted in aggregation, - * update driver's record of tx frame's status. */ - i = 0; - while (sent_bitmap) { - ack = sent_bitmap & 1ULL; - successes += ack; - IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", - ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, - agg->start_idx + i); - sent_bitmap >>= 1; - ++i; + IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", + (unsigned long long)bitmap); } info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb); memset(&info->status, 0, sizeof(info->status)); info->flags |= IEEE80211_TX_STAT_ACK; info->flags |= IEEE80211_TX_STAT_AMPDU; - info->status.ampdu_ack_len = successes; - info->status.ampdu_len = agg->frame_count; - iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); + if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) { + info->status.ampdu_ack_len = ba_resp->txed_2_done; + info->status.ampdu_len = ba_resp->txed; - IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); + } else { + info->status.ampdu_ack_len = successes; + info->status.ampdu_len = agg->frame_count; + } + iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); return 0; } @@ -1385,7 +1427,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && priv->mac80211_registered && (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) - iwl_wake_queue(priv, txq->swq_id); + iwl_wake_queue(priv, txq); iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 703621107dac..24dabcd2a36c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -40,30 +40,36 @@ #include "iwl-agn.h" #include "iwl-agn-calib.h" -static const s8 iwlagn_default_queue_to_tx_fifo[] = { - IWL_TX_FIFO_VO, - IWL_TX_FIFO_VI, - IWL_TX_FIFO_BE, - IWL_TX_FIFO_BK, - IWLAGN_CMD_FIFO_NUM, - IWL_TX_FIFO_UNUSED, - IWL_TX_FIFO_UNUSED, - IWL_TX_FIFO_UNUSED, - IWL_TX_FIFO_UNUSED, - IWL_TX_FIFO_UNUSED, +#define IWL_AC_UNSET -1 + +struct queue_to_fifo_ac { + s8 fifo, ac; +}; + +static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, }; -static const s8 iwlagn_ipan_queue_to_tx_fifo[] = { - IWL_TX_FIFO_VO, - IWL_TX_FIFO_VI, - IWL_TX_FIFO_BE, - IWL_TX_FIFO_BK, - IWL_TX_FIFO_BK_IPAN, - IWL_TX_FIFO_BE_IPAN, - IWL_TX_FIFO_VI_IPAN, - IWL_TX_FIFO_VO_IPAN, - IWL_TX_FIFO_BE_IPAN, - IWLAGN_CMD_FIFO_NUM, +static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_BE_IPAN, 2, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, }; static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { @@ -429,7 +435,7 @@ void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) int iwlagn_alive_notify(struct iwl_priv *priv) { - const s8 *queues; + const struct queue_to_fifo_ac *queue_to_fifo; u32 a; unsigned long flags; int i, chan; @@ -492,9 +498,9 @@ int iwlagn_alive_notify(struct iwl_priv *priv) /* map queues to FIFOs */ if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) - queues = iwlagn_ipan_queue_to_tx_fifo; + queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; else - queues = iwlagn_default_queue_to_tx_fifo; + queue_to_fifo = iwlagn_default_queue_to_tx_fifo; iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0); @@ -510,18 +516,25 @@ int iwlagn_alive_notify(struct iwl_priv *priv) BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10); for (i = 0; i < 10; i++) { - int ac = queues[i]; + int fifo = queue_to_fifo[i].fifo; + int ac = queue_to_fifo[i].ac; iwl_txq_ctx_activate(priv, i); - if (ac == IWL_TX_FIFO_UNUSED) + if (fifo == IWL_TX_FIFO_UNUSED) continue; - iwlagn_tx_queue_set_status(priv, &priv->txq[i], ac, 0); + if (ac != IWL_AC_UNSET) + iwl_set_swq_id(&priv->txq[i], ac, i); + iwlagn_tx_queue_set_status(priv, &priv->txq[i], fifo, 0); } spin_unlock_irqrestore(&priv->lock, flags); + /* Enable L1-Active */ + iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG, + APMG_PCIDEV_STT_VAL_L1_ACT_DIS); + iwlagn_send_wimax_coex(priv); iwlagn_set_Xtal_calib(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c2636a7ab9ee..f13a83a7e62b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -90,170 +90,6 @@ MODULE_ALIAS("iwl4965"); static int iwlagn_ant_coupling; static bool iwlagn_bt_ch_announce = 1; -/** - * iwlagn_commit_rxon - commit staging_rxon to hardware - * - * The RXON command in staging_rxon is committed to the hardware and - * the active_rxon structure is updated with the new data. This - * function correctly transitions out of the RXON_ASSOC_MSK state if - * a HW tune is required based on the RXON structure changes. - */ -int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) -{ - /* cast away the const for active_rxon in this function */ - struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active; - int ret; - bool new_assoc = - !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); - bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK); - - if (!iwl_is_alive(priv)) - return -EBUSY; - - if (!ctx->is_active) - return 0; - - /* always get timestamp with Rx frame */ - ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; - - ret = iwl_check_rxon_cmd(priv, ctx); - if (ret) { - IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); - return -EINVAL; - } - - /* - * receive commit_rxon request - * abort any previous channel switch if still in process - */ - if (priv->switch_rxon.switch_in_progress && - (priv->switch_rxon.channel != ctx->staging.channel)) { - IWL_DEBUG_11H(priv, "abort channel switch on %d\n", - le16_to_cpu(priv->switch_rxon.channel)); - iwl_chswitch_done(priv, false); - } - - /* If we don't need to send a full RXON, we can use - * iwl_rxon_assoc_cmd which is used to reconfigure filter - * and other flags for the current radio configuration. */ - if (!iwl_full_rxon_required(priv, ctx)) { - ret = iwl_send_rxon_assoc(priv, ctx); - if (ret) { - IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); - return ret; - } - - memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); - iwl_print_rx_config_cmd(priv, ctx); - return 0; - } - - /* If we are currently associated and the new config requires - * an RXON_ASSOC and the new config wants the associated mask enabled, - * we must clear the associated from the active configuration - * before we apply the new config */ - if (iwl_is_associated_ctx(ctx) && new_assoc) { - IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); - active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - - ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, - sizeof(struct iwl_rxon_cmd), - active_rxon); - - /* If the mask clearing failed then we set - * active_rxon back to what it was previously */ - if (ret) { - active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; - IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); - return ret; - } - iwl_clear_ucode_stations(priv, ctx); - iwl_restore_stations(priv, ctx); - ret = iwl_restore_default_wep_keys(priv, ctx); - if (ret) { - IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); - return ret; - } - } - - IWL_DEBUG_INFO(priv, "Sending RXON\n" - "* with%s RXON_FILTER_ASSOC_MSK\n" - "* channel = %d\n" - "* bssid = %pM\n", - (new_assoc ? "" : "out"), - le16_to_cpu(ctx->staging.channel), - ctx->staging.bssid_addr); - - iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); - - if (!old_assoc) { - /* - * First of all, before setting associated, we need to - * send RXON timing so the device knows about the DTIM - * period and other timing values - */ - ret = iwl_send_rxon_timing(priv, ctx); - if (ret) { - IWL_ERR(priv, "Error setting RXON timing!\n"); - return ret; - } - } - - if (priv->cfg->ops->hcmd->set_pan_params) { - ret = priv->cfg->ops->hcmd->set_pan_params(priv); - if (ret) - return ret; - } - - /* Apply the new configuration - * RXON unassoc clears the station table in uCode so restoration of - * stations is needed after it (the RXON command) completes - */ - if (!new_assoc) { - ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, - sizeof(struct iwl_rxon_cmd), &ctx->staging); - if (ret) { - IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); - return ret; - } - IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); - memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); - iwl_clear_ucode_stations(priv, ctx); - iwl_restore_stations(priv, ctx); - ret = iwl_restore_default_wep_keys(priv, ctx); - if (ret) { - IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); - return ret; - } - } - if (new_assoc) { - priv->start_calib = 0; - /* Apply the new configuration - * RXON assoc doesn't clear the station table in uCode, - */ - ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, - sizeof(struct iwl_rxon_cmd), &ctx->staging); - if (ret) { - IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); - return ret; - } - memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); - } - iwl_print_rx_config_cmd(priv, ctx); - - iwl_init_sensitivity(priv); - - /* If we issue a new RXON command which required a tune then we must - * send a new TXPOWER command or we won't be able to Tx any frames */ - ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); - if (ret) { - IWL_ERR(priv, "Error sending TX power (%d)\n", ret); - return ret; - } - - return 0; -} - void iwl_update_chain_flags(struct iwl_priv *priv) { struct iwl_rxon_context *ctx; @@ -261,7 +97,8 @@ void iwl_update_chain_flags(struct iwl_priv *priv) if (priv->cfg->ops->hcmd->set_rxon_chain) { for_each_context(priv, ctx) { priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - iwlcore_commit_rxon(priv, ctx); + if (ctx->active.rx_chain != ctx->staging.rx_chain) + iwlcore_commit_rxon(priv, ctx); } } } @@ -411,7 +248,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, return sizeof(*tx_beacon_cmd) + frame_size; } -static int iwl_send_beacon_cmd(struct iwl_priv *priv) + +int iwlagn_send_beacon_cmd(struct iwl_priv *priv) { struct iwl_frame *frame; unsigned int frame_size; @@ -661,7 +499,7 @@ static void iwl_bg_beacon_update(struct work_struct *work) priv->beacon_skb = beacon; - iwl_send_beacon_cmd(priv); + iwlagn_send_beacon_cmd(priv); out: mutex_unlock(&priv->mutex); } @@ -2664,7 +2502,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, return pos; } - /* enable/disable bt channel announcement */ + /* enable/disable bt channel inhibition */ priv->bt_ch_announce = iwlagn_bt_ch_announce; #ifdef CONFIG_IWLWIFI_DEBUG @@ -2816,13 +2654,8 @@ static void iwl_alive_start(struct iwl_priv *priv) /* After the ALIVE response, we can send host commands to the uCode */ set_bit(STATUS_ALIVE, &priv->status); - if (priv->cfg->ops->lib->recover_from_tx_stall) { - /* Enable timer to monitor the driver queues */ - mod_timer(&priv->monitor_recover, - jiffies + - msecs_to_jiffies( - priv->cfg->base_params->monitor_recover_period)); - } + /* Enable watchdog to monitor the driver tx queues */ + iwl_setup_watchdog(priv); if (iwl_is_rfkill(priv)) return; @@ -2879,6 +2712,8 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl_reset_run_time_calib(priv); + set_bit(STATUS_READY, &priv->status); + /* Configure the adapter for unassociated operation */ iwlcore_commit_rxon(priv, ctx); @@ -2888,7 +2723,6 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl_leds_init(priv); IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); - set_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); iwl_power_update_mode(priv, true); @@ -2916,8 +2750,7 @@ static void __iwl_down(struct iwl_priv *priv) /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set * to prevent rearm timer */ - if (priv->cfg->ops->lib->recover_from_tx_stall) - del_timer_sync(&priv->monitor_recover); + del_timer_sync(&priv->watchdog); iwl_clear_ucode_stations(priv, NULL); iwl_dealloc_bcast_stations(priv); @@ -2978,7 +2811,8 @@ static void __iwl_down(struct iwl_priv *priv) STATUS_EXIT_PENDING; /* device going down, Stop using ICT table */ - iwl_disable_ict(priv); + if (priv->cfg->ops->lib->isr_ops.disable) + priv->cfg->ops->lib->isr_ops.disable(priv); iwlagn_txq_ctx_stop(priv); iwlagn_rxq_stop(priv); @@ -3201,7 +3035,8 @@ static void iwl_bg_alive_start(struct work_struct *data) return; /* enable dram interrupt */ - iwl_reset_ict(priv); + if (priv->cfg->ops->lib->isr_ops.reset) + priv->cfg->ops->lib->isr_ops.reset(priv); mutex_lock(&priv->mutex); iwl_alive_start(priv); @@ -3309,92 +3144,6 @@ static void iwl_bg_rx_replenish(struct work_struct *data) mutex_unlock(&priv->mutex); } -#define IWL_DELAY_NEXT_SCAN (HZ*2) - -void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) -{ - struct iwl_rxon_context *ctx; - struct ieee80211_conf *conf = NULL; - int ret = 0; - - if (!vif || !priv->is_open) - return; - - ctx = iwl_rxon_ctx_from_vif(vif); - - if (vif->type == NL80211_IFTYPE_AP) { - IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); - return; - } - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - iwl_scan_cancel_timeout(priv, 200); - - conf = ieee80211_get_hw_conf(priv->hw); - - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv, ctx); - - ret = iwl_send_rxon_timing(priv, ctx); - if (ret) - IWL_WARN(priv, "RXON timing - " - "Attempting to continue.\n"); - - ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; - - iwl_set_rxon_ht(priv, &priv->current_ht_config); - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - - ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); - - IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", - vif->bss_conf.aid, vif->bss_conf.beacon_int); - - if (vif->bss_conf.use_short_preamble) - ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; - else - ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - - if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { - if (vif->bss_conf.use_short_slot) - ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; - else - ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - } - - iwlcore_commit_rxon(priv, ctx); - - IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", - vif->bss_conf.aid, ctx->active.bssid_addr); - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - break; - case NL80211_IFTYPE_ADHOC: - iwl_send_beacon_cmd(priv); - break; - default: - IWL_ERR(priv, "%s Should not be called in %d mode\n", - __func__, vif->type); - break; - } - - /* the chain noise calibration will enabled PM upon completion - * If chain noise has already been run, then we need to enable - * power management here */ - if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) - iwl_power_update_mode(priv, false); - - /* Enable Rx differential gain and sensitivity calibrations */ - iwl_chain_noise_reset(priv); - priv->start_calib = 1; - -} - /***************************************************************************** * * mac80211 entry point functions @@ -3420,7 +3169,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_NEED_DTIM_PERIOD | - IEEE80211_HW_SPECTRUM_MGMT; + IEEE80211_HW_SPECTRUM_MGMT | + IEEE80211_HW_REPORTS_TX_ACK_STATUS; if (!priv->cfg->base_params->broken_powersave) hw->flags |= IEEE80211_HW_SUPPORTS_PS | @@ -3474,7 +3224,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, } -static int iwl_mac_start(struct ieee80211_hw *hw) +int iwlagn_mac_start(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; int ret; @@ -3515,7 +3265,7 @@ out: return 0; } -static void iwl_mac_stop(struct ieee80211_hw *hw) +void iwlagn_mac_stop(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; @@ -3530,14 +3280,15 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) flush_workqueue(priv->workqueue); - /* enable interrupts again in order to receive rfkill changes */ + /* User space software may expect getting rfkill changes + * even if interface is down */ iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(priv); + iwl_enable_rfkill_int(priv); IWL_DEBUG_MAC80211(priv, "leave\n"); } -static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct iwl_priv *priv = hw->priv; @@ -3553,73 +3304,12 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) -{ - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - int ret = 0; - - lockdep_assert_held(&priv->mutex); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - /* The following should be done only at AP bring up */ - if (!iwl_is_associated_ctx(ctx)) { - - /* RXON - unassoc (to set timing command) */ - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv, ctx); - - /* RXON Timing */ - ret = iwl_send_rxon_timing(priv, ctx); - if (ret) - IWL_WARN(priv, "RXON timing failed - " - "Attempting to continue.\n"); - - /* AP has all antennas */ - priv->chain_noise_data.active_chains = - priv->hw_params.valid_rx_ant; - iwl_set_rxon_ht(priv, &priv->current_ht_config); - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - - ctx->staging.assoc_id = 0; - - if (vif->bss_conf.use_short_preamble) - ctx->staging.flags |= - RXON_FLG_SHORT_PREAMBLE_MSK; - else - ctx->staging.flags &= - ~RXON_FLG_SHORT_PREAMBLE_MSK; - - if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { - if (vif->bss_conf.use_short_slot) - ctx->staging.flags |= - RXON_FLG_SHORT_SLOT_MSK; - else - ctx->staging.flags &= - ~RXON_FLG_SHORT_SLOT_MSK; - } - /* need to send beacon cmd before committing assoc RXON! */ - iwl_send_beacon_cmd(priv); - /* restore RXON assoc */ - ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv, ctx); - } - iwl_send_beacon_cmd(priv); - - /* FIXME - we need to add code here to detect a totally new - * configuration, reset the AP, unassoc, rxon timing, assoc, - * clear sta table, add BCAST sta... */ -} - -static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_key_conf *keyconf, - struct ieee80211_sta *sta, - u32 iv32, u16 *phase1key) +void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, + u32 iv32, u16 *phase1key) { - struct iwl_priv *priv = hw->priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; @@ -3631,10 +3321,9 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "leave\n"); } -static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) +int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; @@ -3701,10 +3390,10 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } -static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn) +int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn) { struct iwl_priv *priv = hw->priv; int ret = -EINVAL; @@ -3785,39 +3474,9 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return ret; } -static void iwl_mac_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) -{ - struct iwl_priv *priv = hw->priv; - struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; - int sta_id; - - switch (cmd) { - case STA_NOTIFY_SLEEP: - WARN_ON(!sta_priv->client); - sta_priv->asleep = true; - if (atomic_read(&sta_priv->pending_frames) > 0) - ieee80211_sta_block_awake(hw, sta, true); - break; - case STA_NOTIFY_AWAKE: - WARN_ON(!sta_priv->client); - if (!sta_priv->asleep) - break; - sta_priv->asleep = false; - sta_id = iwl_sta_id(sta); - if (sta_id != IWL_INVALID_STATION) - iwl_sta_modify_ps_wake(priv, sta_id); - break; - default: - break; - } -} - -static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int iwlagn_mac_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct iwl_priv *priv = hw->priv; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; @@ -3858,8 +3517,8 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, return 0; } -static void iwl_mac_channel_switch(struct ieee80211_hw *hw, - struct ieee80211_channel_switch *ch_switch) +void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_channel_switch *ch_switch) { struct iwl_priv *priv = hw->priv; const struct iwl_channel_info *ch_info; @@ -3956,10 +3615,10 @@ out_exit: IWL_DEBUG_MAC80211(priv, "leave\n"); } -static void iwlagn_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) +void iwlagn_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) { struct iwl_priv *priv = hw->priv; __le32 filter_or = 0, filter_nand = 0; @@ -3976,7 +3635,8 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, changed_flags, *total_flags); CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); - CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); + /* Setting _just_ RXON_FILTER_CTL2HOST_MSK causes FH errors */ + CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK); CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); #undef CHK @@ -3986,7 +3646,11 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, for_each_context(priv, ctx) { ctx->staging.filter_flags &= ~filter_nand; ctx->staging.filter_flags |= filter_or; - iwlcore_commit_rxon(priv, ctx); + + /* + * Not committing directly because hardware can perform a scan, + * but we'll eventually commit the filter flags change anyway. + */ } mutex_unlock(&priv->mutex); @@ -4001,7 +3665,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; } -static void iwl_mac_flush(struct ieee80211_hw *hw, bool drop) +void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) { struct iwl_priv *priv = hw->priv; @@ -4074,12 +3738,9 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) priv->ucode_trace.data = (unsigned long)priv; priv->ucode_trace.function = iwl_bg_ucode_trace; - if (priv->cfg->ops->lib->recover_from_tx_stall) { - init_timer(&priv->monitor_recover); - priv->monitor_recover.data = (unsigned long)priv; - priv->monitor_recover.function = - priv->cfg->ops->lib->recover_from_tx_stall; - } + init_timer(&priv->watchdog); + priv->watchdog.data = (unsigned long)priv; + priv->watchdog.function = iwl_bg_watchdog; if (!priv->cfg->base_params->use_isr_legacy) tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) @@ -4172,13 +3833,13 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->bt_on_thresh = BT_ON_THRESHOLD_DEF; priv->bt_duration = BT_DURATION_LIMIT_DEF; priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; - priv->dynamic_agg_thresh = BT_AGG_THRESHOLD_DEF; } /* Set the tx_power_user_lmt to the lowest power level * this value will get overwritten by channel max power avg * from eeprom */ priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN; + priv->tx_power_next = IWLAGN_TX_POWER_TARGET_POWER_MIN; ret = iwl_init_channel_map(priv); if (ret) { @@ -4209,28 +3870,30 @@ static void iwl_uninit_drv(struct iwl_priv *priv) kfree(priv->scan_cmd); } -static struct ieee80211_ops iwl_hw_ops = { - .tx = iwl_mac_tx, - .start = iwl_mac_start, - .stop = iwl_mac_stop, +#ifdef CONFIG_IWL5000 +struct ieee80211_ops iwlagn_hw_ops = { + .tx = iwlagn_mac_tx, + .start = iwlagn_mac_start, + .stop = iwlagn_mac_stop, .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, - .config = iwl_mac_config, + .change_interface = iwl_mac_change_interface, + .config = iwlagn_mac_config, .configure_filter = iwlagn_configure_filter, - .set_key = iwl_mac_set_key, - .update_tkip_key = iwl_mac_update_tkip_key, + .set_key = iwlagn_mac_set_key, + .update_tkip_key = iwlagn_mac_update_tkip_key, .conf_tx = iwl_mac_conf_tx, - .reset_tsf = iwl_mac_reset_tsf, - .bss_info_changed = iwl_bss_info_changed, - .ampdu_action = iwl_mac_ampdu_action, + .bss_info_changed = iwlagn_bss_info_changed, + .ampdu_action = iwlagn_mac_ampdu_action, .hw_scan = iwl_mac_hw_scan, - .sta_notify = iwl_mac_sta_notify, + .sta_notify = iwlagn_mac_sta_notify, .sta_add = iwlagn_mac_sta_add, .sta_remove = iwl_mac_sta_remove, - .channel_switch = iwl_mac_channel_switch, - .flush = iwl_mac_flush, + .channel_switch = iwlagn_mac_channel_switch, + .flush = iwlagn_mac_flush, .tx_last_beacon = iwl_mac_tx_last_beacon, }; +#endif static void iwl_hw_detect(struct iwl_priv *priv) { @@ -4298,10 +3961,15 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (cfg->mod_params->disable_hw_scan) { dev_printk(KERN_DEBUG, &(pdev->dev), "sw scan support is deprecated\n"); - iwl_hw_ops.hw_scan = NULL; +#ifdef CONFIG_IWL5000 + iwlagn_hw_ops.hw_scan = NULL; +#endif +#ifdef CONFIG_IWL4965 + iwl4965_hw_ops.hw_scan = NULL; +#endif } - hw = iwl_alloc_all(cfg, &iwl_hw_ops); + hw = iwl_alloc_all(cfg); if (!hw) { err = -ENOMEM; goto out; @@ -4333,6 +4001,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) BIT(NL80211_IFTYPE_ADHOC); priv->contexts[IWL_RXON_CTX_BSS].interface_modes = BIT(NL80211_IFTYPE_STATION); + priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP; priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS; priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS; priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS; @@ -4368,8 +4037,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? true : false; - /* enable/disable bt channel announcement */ + /* enable/disable bt channel inhibition */ priv->bt_ch_announce = iwlagn_bt_ch_announce; + IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n", + (priv->bt_ch_announce) ? "On" : "Off"); if (iwl_alloc_traffic_mem(priv)) IWL_ERR(priv, "Not enough memory to generate traffic log\n"); @@ -4461,6 +4132,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto out_free_eeprom; + err = iwl_eeprom_check_sku(priv); + if (err) + goto out_free_eeprom; + /* extract MAC Address */ iwl_eeprom_get_mac(priv, priv->addresses[0].addr); IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); @@ -4500,8 +4175,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_enable_msi(priv->pci_dev); - iwl_alloc_isr_ict(priv); - err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr, + if (priv->cfg->ops->lib->isr_ops.alloc) + priv->cfg->ops->lib->isr_ops.alloc(priv); + + err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr, IRQF_SHARED, DRV_NAME, priv); if (err) { IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); @@ -4515,14 +4192,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * 8. Enable interrupts and read RFKILL state *********************************************/ - /* enable interrupts if needed: hw bug w/a */ + /* enable rfkill interrupt: hw bug w/a */ pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd); } - iwl_enable_interrupts(priv); + iwl_enable_rfkill_int(priv); /* If platform's RF_KILL switch is NOT set to KILL */ if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) @@ -4548,7 +4225,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) destroy_workqueue(priv->workqueue); priv->workqueue = NULL; free_irq(priv->pci_dev->irq, priv); - iwl_free_isr_ict(priv); + if (priv->cfg->ops->lib->isr_ops.free) + priv->cfg->ops->lib->isr_ops.free(priv); out_disable_msi: pci_disable_msi(priv->pci_dev); iwl_uninit_drv(priv); @@ -4643,7 +4321,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) iwl_uninit_drv(priv); - iwl_free_isr_ict(priv); + if (priv->cfg->ops->lib->isr_ops.free) + priv->cfg->ops->lib->isr_ops.free(priv); dev_kfree_skb(priv->beacon_skb); @@ -4734,51 +4413,32 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, -/* 6x00 Series Gen2a */ - {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1206, iwl6000g2a_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0085, 0x1216, iwl6000g2a_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1226, iwl6000g2a_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1207, iwl6000g2a_2bg_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2a_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6000g2a_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6000g2a_2bg_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2a_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6000g2a_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2a_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6000g2a_2abg_cfg)}, - -/* 6x00 Series Gen2b */ - {IWL_PCI_DEVICE(0x008F, 0x5105, iwl6000g2b_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0090, 0x5115, iwl6000g2b_bgn_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5125, iwl6000g2b_bgn_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5107, iwl6000g2b_bg_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5201, iwl6000g2b_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5221, iwl6000g2b_2agn_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5206, iwl6000g2b_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5226, iwl6000g2b_2abg_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5207, iwl6000g2b_2bg_cfg)}, - {IWL_PCI_DEVICE(0x008A, 0x5301, iwl6000g2b_bgn_cfg)}, - {IWL_PCI_DEVICE(0x008A, 0x5305, iwl6000g2b_bgn_cfg)}, - {IWL_PCI_DEVICE(0x008A, 0x5307, iwl6000g2b_bg_cfg)}, - {IWL_PCI_DEVICE(0x008A, 0x5321, iwl6000g2b_bgn_cfg)}, - {IWL_PCI_DEVICE(0x008A, 0x5325, iwl6000g2b_bgn_cfg)}, - {IWL_PCI_DEVICE(0x008B, 0x5311, iwl6000g2b_bgn_cfg)}, - {IWL_PCI_DEVICE(0x008B, 0x5315, iwl6000g2b_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6000g2b_2bgn_cfg)}, - {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6000g2b_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6000g2b_2bgn_cfg)}, - {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6000g2b_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6000g2b_2bg_cfg)}, - {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6000g2b_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6000g2b_2bgn_cfg)}, - {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6000g2b_2abg_cfg)}, +/* 6x05 Series */ + {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)}, + {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)}, + +/* 6x30 Series */ + {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)}, + {IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)}, + {IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)}, + {IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)}, + {IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)}, + {IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)}, + {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)}, + {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)}, + {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)}, + {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)}, + {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)}, + {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)}, + {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)}, /* 6x50 WiFi/WiMax Series */ {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, @@ -4788,13 +4448,13 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)}, {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)}, -/* 6x50 WiFi/WiMax Series Gen2 */ - {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6050g2_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0885, 0x1306, iwl6050g2_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6050g2_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0885, 0x1326, iwl6050g2_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6050g2_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0886, 0x1316, iwl6050g2_bgn_cfg)}, +/* 6150 WiFi/WiMax Series */ + {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)}, + {IWL_PCI_DEVICE(0x0885, 0x1306, iwl6150_bgn_cfg)}, + {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)}, + {IWL_PCI_DEVICE(0x0885, 0x1326, iwl6150_bgn_cfg)}, + {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)}, + {IWL_PCI_DEVICE(0x0886, 0x1316, iwl6150_bgn_cfg)}, /* 1000 Series WiFi */ {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)}, @@ -4812,10 +4472,11 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { /* 100 Series WiFi */ {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)}, + {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)}, {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)}, + {IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)}, {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)}, - {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)}, - {IWL_PCI_DEVICE(0x08AE, 0x1017, iwl100_bg_cfg)}, + {IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)}, /* 130 Series WiFi */ {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)}, @@ -4836,10 +4497,7 @@ static struct pci_driver iwl_driver = { .id_table = iwl_hw_card_ids, .probe = iwl_pci_probe, .remove = __devexit_p(iwl_pci_remove), -#ifdef CONFIG_PM - .suspend = iwl_pci_suspend, - .resume = iwl_pci_resume, -#endif + .driver.pm = IWL_PM_OPS, }; static int __init iwl_init(void) @@ -4925,6 +4583,6 @@ module_param_named(antenna_coupling, iwlagn_ant_coupling, int, S_IRUGO); MODULE_PARM_DESC(antenna_coupling, "specify antenna coupling in dB (defualt: 0 dB)"); -module_param_named(bt_ch_announce, iwlagn_bt_ch_announce, bool, S_IRUGO); -MODULE_PARM_DESC(bt_ch_announce, - "Enable BT channel announcement mode (default: enable)"); +module_param_named(bt_ch_inhibition, iwlagn_bt_ch_announce, bool, S_IRUGO); +MODULE_PARM_DESC(bt_ch_inhibition, + "Disable BT channel inhibition (default: enable)"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index f525d55f2c0f..da303585f801 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -74,22 +74,22 @@ extern struct iwl_cfg iwl5100_bgn_cfg; extern struct iwl_cfg iwl5100_abg_cfg; extern struct iwl_cfg iwl5150_agn_cfg; extern struct iwl_cfg iwl5150_abg_cfg; -extern struct iwl_cfg iwl6000g2a_2agn_cfg; -extern struct iwl_cfg iwl6000g2a_2abg_cfg; -extern struct iwl_cfg iwl6000g2a_2bg_cfg; -extern struct iwl_cfg iwl6000g2b_bgn_cfg; -extern struct iwl_cfg iwl6000g2b_bg_cfg; -extern struct iwl_cfg iwl6000g2b_2agn_cfg; -extern struct iwl_cfg iwl6000g2b_2abg_cfg; -extern struct iwl_cfg iwl6000g2b_2bgn_cfg; -extern struct iwl_cfg iwl6000g2b_2bg_cfg; +extern struct iwl_cfg iwl6005_2agn_cfg; +extern struct iwl_cfg iwl6005_2abg_cfg; +extern struct iwl_cfg iwl6005_2bg_cfg; +extern struct iwl_cfg iwl1030_bgn_cfg; +extern struct iwl_cfg iwl1030_bg_cfg; +extern struct iwl_cfg iwl6030_2agn_cfg; +extern struct iwl_cfg iwl6030_2abg_cfg; +extern struct iwl_cfg iwl6030_2bgn_cfg; +extern struct iwl_cfg iwl6030_2bg_cfg; extern struct iwl_cfg iwl6000i_2agn_cfg; extern struct iwl_cfg iwl6000i_2abg_cfg; extern struct iwl_cfg iwl6000i_2bg_cfg; extern struct iwl_cfg iwl6000_3agn_cfg; extern struct iwl_cfg iwl6050_2agn_cfg; extern struct iwl_cfg iwl6050_2abg_cfg; -extern struct iwl_cfg iwl6050g2_bgn_cfg; +extern struct iwl_cfg iwl6150_bgn_cfg; extern struct iwl_cfg iwl1000_bgn_cfg; extern struct iwl_cfg iwl1000_bg_cfg; extern struct iwl_cfg iwl100_bgn_cfg; @@ -102,6 +102,9 @@ extern struct iwl_hcmd_ops iwlagn_hcmd; extern struct iwl_hcmd_ops iwlagn_bt_hcmd; extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; +extern struct ieee80211_ops iwlagn_hw_ops; +extern struct ieee80211_ops iwl4965_hw_ops; + int iwl_reset_ict(struct iwl_priv *priv); void iwl_disable_ict(struct iwl_priv *priv); int iwl_alloc_isr_ict(struct iwl_priv *priv); @@ -132,6 +135,11 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv, /* RXON */ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx); +int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed); +void iwlagn_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes); /* uCode */ int iwlagn_load_ucode(struct iwl_priv *priv); @@ -249,6 +257,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, int iwlagn_send_rxon_assoc(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); +int iwlagn_send_beacon_cmd(struct iwl_priv *priv); /* bt coex */ void iwlagn_send_advance_bt_config(struct iwl_priv *priv); @@ -292,9 +301,12 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, int tid, u16 ssn); int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, int tid); -void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id); void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); int iwl_update_bcast_stations(struct iwl_priv *priv); +void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta); /* rate */ static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) @@ -318,4 +330,31 @@ void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); +/* mac80211 handlers (for 4965) */ +int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +int iwlagn_mac_start(struct ieee80211_hw *hw); +void iwlagn_mac_stop(struct ieee80211_hw *hw); +void iwlagn_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast); +int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key); +void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, + u32 iv32, u16 *phase1key); +int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn); +int iwlagn_mac_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_channel_switch *ch_switch); +void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop); + #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 424801abc80e..f893d4a6aa87 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2022,6 +2022,9 @@ struct iwl_compressed_ba_resp { __le64 bitmap; __le16 scd_flow; __le16 scd_ssn; + /* following only for 5000 series and up */ + u8 txed; /* number of frames sent */ + u8 txed_2_done; /* number of frames acked */ } __packed; /* @@ -2407,9 +2410,9 @@ struct iwl_link_quality_cmd { #define BT_FRAG_THRESHOLD_MAX 0 #define BT_FRAG_THRESHOLD_MIN 0 -#define BT_AGG_THRESHOLD_DEF 0 -#define BT_AGG_THRESHOLD_MAX 0 -#define BT_AGG_THRESHOLD_MIN 0 +#define BT_AGG_THRESHOLD_DEF 1200 +#define BT_AGG_THRESHOLD_MAX 8000 +#define BT_AGG_THRESHOLD_MIN 400 /* * REPLY_BT_CONFIG = 0x9b (command, has simple generic response) @@ -2436,8 +2439,9 @@ struct iwl_bt_cmd { #define IWLAGN_BT_FLAG_COEX_MODE_3W 2 #define IWLAGN_BT_FLAG_COEX_MODE_4W 3 -#define IWLAGN_BT_FLAG_UCODE_DEFAULT BIT(6) -#define IWLAGN_BT_FLAG_NOCOEX_NOTIF BIT(7) +#define IWLAGN_BT_FLAG_UCODE_DEFAULT BIT(6) +/* Disable Sync PSPoll on SCO/eSCO */ +#define IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE BIT(7) #define IWLAGN_BT_PRIO_BOOST_MAX 0xFF #define IWLAGN_BT_PRIO_BOOST_MIN 0x00 @@ -2447,8 +2451,9 @@ struct iwl_bt_cmd { #define IWLAGN_BT3_T7_DEFAULT 1 -#define IWLAGN_BT_KILL_ACK_MASK_DEFAULT cpu_to_le32(0xffffffff) -#define IWLAGN_BT_KILL_CTS_MASK_DEFAULT cpu_to_le32(0xffffffff) +#define IWLAGN_BT_KILL_ACK_MASK_DEFAULT cpu_to_le32(0xffff0000) +#define IWLAGN_BT_KILL_CTS_MASK_DEFAULT cpu_to_le32(0xffff0000) +#define IWLAGN_BT_KILL_ACK_CTS_MASK_SCO cpu_to_le32(0xffffffff) #define IWLAGN_BT3_PRIO_SAMPLE_DEFAULT 2 @@ -2664,9 +2669,16 @@ struct iwl_spectrum_notification { #define IWL_POWER_VEC_SIZE 5 #define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le16(BIT(0)) +#define IWL_POWER_POWER_SAVE_ENA_MSK cpu_to_le16(BIT(0)) +#define IWL_POWER_POWER_MANAGEMENT_ENA_MSK cpu_to_le16(BIT(1)) #define IWL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le16(BIT(2)) #define IWL_POWER_PCI_PM_MSK cpu_to_le16(BIT(3)) #define IWL_POWER_FAST_PD cpu_to_le16(BIT(4)) +#define IWL_POWER_BEACON_FILTERING cpu_to_le16(BIT(5)) +#define IWL_POWER_SHADOW_REG_ENA cpu_to_le16(BIT(6)) +#define IWL_POWER_CT_KILL_SET cpu_to_le16(BIT(7)) +#define IWL_POWER_BT_SCO_ENA cpu_to_le16(BIT(8)) +#define IWL_POWER_ADVANCE_PM_ENA_MSK cpu_to_le16(BIT(9)) struct iwl3945_powertable_cmd { __le16 flags; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 25fb3912342c..efbde1f1a8bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -77,15 +77,15 @@ EXPORT_SYMBOL(iwl_bcast_addr); /* This function both allocates and initializes hw and priv. */ -struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, - struct ieee80211_ops *hw_ops) +struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg) { struct iwl_priv *priv; - /* mac80211 allocates memory for this device instance, including * space for this driver's private structure */ - struct ieee80211_hw *hw = - ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops); + struct ieee80211_hw *hw; + + hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), + cfg->ops->ieee80211_ops); if (hw == NULL) { pr_err("%s: Can not allocate network device\n", cfg->name); @@ -100,35 +100,6 @@ out: } EXPORT_SYMBOL(iwl_alloc_all); -/* - * QoS support -*/ -static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) -{ - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (!ctx->is_active) - return; - - ctx->qos_data.def_qos_parm.qos_flags = 0; - - if (ctx->qos_data.qos_active) - ctx->qos_data.def_qos_parm.qos_flags |= - QOS_PARAM_FLG_UPDATE_EDCA_MSK; - - if (ctx->ht.enabled) - ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; - - IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", - ctx->qos_data.qos_active, - ctx->qos_data.def_qos_parm.qos_flags); - - iwl_send_cmd_pdu_async(priv, ctx->qos_cmd, - sizeof(struct iwl_qosparam_cmd), - &ctx->qos_data.def_qos_parm, NULL); -} - #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, @@ -317,40 +288,6 @@ void iwlcore_free_geos(struct iwl_priv *priv) } EXPORT_SYMBOL(iwlcore_free_geos); -/* - * iwlcore_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this - * function. - */ -void iwlcore_tx_cmd_protection(struct iwl_priv *priv, - struct ieee80211_tx_info *info, - __le16 fc, __le32 *tx_flags) -{ - if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { - *tx_flags |= TX_CMD_FLG_RTS_MSK; - *tx_flags &= ~TX_CMD_FLG_CTS_MSK; - *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; - - if (!ieee80211_is_mgmt(fc)) - return; - - switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { - case cpu_to_le16(IEEE80211_STYPE_AUTH): - case cpu_to_le16(IEEE80211_STYPE_DEAUTH): - case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): - case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): - *tx_flags &= ~TX_CMD_FLG_RTS_MSK; - *tx_flags |= TX_CMD_FLG_CTS_MSK; - break; - } - } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - *tx_flags &= ~TX_CMD_FLG_RTS_MSK; - *tx_flags |= TX_CMD_FLG_CTS_MSK; - *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; - } -} -EXPORT_SYMBOL(iwlcore_tx_cmd_protection); - - static bool iwl_is_channel_extension(struct iwl_priv *priv, enum ieee80211_band band, u16 channel, u8 extension_chan_offset) @@ -1020,6 +957,22 @@ void iwl_irq_handle_error(struct iwl_priv *priv) /* Cancel currently queued command. */ clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ + if (priv->cfg->internal_wimax_coex && + (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) & + APMS_CLK_VAL_MRB_FUNC_MODE) || + (iwl_read_prph(priv, APMG_PS_CTRL_REG) & + APMG_PS_CTRL_VAL_RESET_REQ))) { + wake_up_interruptible(&priv->wait_command_queue); + /* + *Keep the restart process from trying to send host + * commands by clearing the INIT status bit + */ + clear_bit(STATUS_READY, &priv->status); + IWL_ERR(priv, "RF is used by WiMAX\n"); + return; + } + IWL_ERR(priv, "Loaded firmware version: %s\n", priv->hw->wiphy->fw_version); @@ -1206,8 +1159,16 @@ EXPORT_SYMBOL(iwl_apm_init); int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) { - int ret = 0; - s8 prev_tx_power = priv->tx_power_user_lmt; + int ret; + s8 prev_tx_power; + + lockdep_assert_held(&priv->mutex); + + if (priv->tx_power_user_lmt == tx_power && !force) + return 0; + + if (!priv->cfg->ops->lib->send_tx_power) + return -EOPNOTSUPP; if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) { IWL_WARN(priv, @@ -1224,93 +1185,29 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) return -EINVAL; } - if (priv->tx_power_user_lmt != tx_power) - force = true; + if (!iwl_is_ready_rf(priv)) + return -EIO; - /* if nic is not up don't send command */ - if (iwl_is_ready_rf(priv)) { - priv->tx_power_user_lmt = tx_power; - if (force && priv->cfg->ops->lib->send_tx_power) - ret = priv->cfg->ops->lib->send_tx_power(priv); - else if (!priv->cfg->ops->lib->send_tx_power) - ret = -EOPNOTSUPP; - /* - * if fail to set tx_power, restore the orig. tx power - */ - if (ret) - priv->tx_power_user_lmt = prev_tx_power; + /* scan complete use tx_power_next, need to be updated */ + priv->tx_power_next = tx_power; + if (test_bit(STATUS_SCANNING, &priv->status) && !force) { + IWL_DEBUG_INFO(priv, "Deferring tx power set while scanning\n"); + return 0; } - /* - * Even this is an async host command, the command - * will always report success from uCode - * So once driver can placing the command into the queue - * successfully, driver can use priv->tx_power_user_lmt - * to reflect the current tx power - */ - return ret; -} -EXPORT_SYMBOL(iwl_set_tx_power); + prev_tx_power = priv->tx_power_user_lmt; + priv->tx_power_user_lmt = tx_power; -irqreturn_t iwl_isr_legacy(int irq, void *data) -{ - struct iwl_priv *priv = data; - u32 inta, inta_mask; - u32 inta_fh; - unsigned long flags; - if (!priv) - return IRQ_NONE; - - spin_lock_irqsave(&priv->lock, flags); + ret = priv->cfg->ops->lib->send_tx_power(priv); - /* Disable (but don't clear!) interrupts here to avoid - * back-to-back ISRs and sporadic interrupts from our NIC. - * If we have something to service, the tasklet will re-enable ints. - * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); - - /* Discover which interrupts are active/pending */ - inta = iwl_read32(priv, CSR_INT); - inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - - /* Ignore interrupt if there's nothing in NIC to service. - * This may be due to IRQ shared with another device, - * or due to sporadic interrupts thrown from our NIC. */ - if (!inta && !inta_fh) { - IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0, inta_fh == 0\n"); - goto none; + /* if fail to set tx_power, restore the orig. tx power */ + if (ret) { + priv->tx_power_user_lmt = prev_tx_power; + priv->tx_power_next = prev_tx_power; } - - if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { - /* Hardware disappeared. It might have already raised - * an interrupt */ - IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); - goto unplugged; - } - - IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", - inta, inta_mask, inta_fh); - - inta &= ~CSR_INT_BIT_SCD; - - /* iwl_irq_tasklet() will service interrupts and re-enable them */ - if (likely(inta || inta_fh)) - tasklet_schedule(&priv->irq_tasklet); - - unplugged: - spin_unlock_irqrestore(&priv->lock, flags); - return IRQ_HANDLED; - - none: - /* re-enable interrupts here since we don't have anything to service. */ - /* only Re-enable if diabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &priv->status)) - iwl_enable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - return IRQ_NONE; + return ret; } -EXPORT_SYMBOL(iwl_isr_legacy); +EXPORT_SYMBOL(iwl_set_tx_power); void iwl_send_bt_config(struct iwl_priv *priv) { @@ -1326,6 +1223,7 @@ void iwl_send_bt_config(struct iwl_priv *priv) else bt_cmd.flags = BT_COEX_ENABLE; + priv->bt_enable_flag = bt_cmd.flags; IWL_DEBUG_INFO(priv, "BT coex %s\n", (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); @@ -1452,318 +1350,51 @@ int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw) } EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon); -static void iwl_ht_conf(struct iwl_priv *priv, - struct ieee80211_vif *vif) +static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { - struct iwl_ht_config *ht_conf = &priv->current_ht_config; - struct ieee80211_sta *sta; - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - - IWL_DEBUG_MAC80211(priv, "enter:\n"); - - if (!ctx->ht.enabled) - return; - - ctx->ht.protection = - bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; - ctx->ht.non_gf_sta_present = - !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); - - ht_conf->single_chain_sufficient = false; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - rcu_read_lock(); - sta = ieee80211_find_sta(vif, bss_conf->bssid); - if (sta) { - struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; - int maxstreams; - - maxstreams = (ht_cap->mcs.tx_params & - IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) - >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; - maxstreams += 1; - - if ((ht_cap->mcs.rx_mask[1] == 0) && - (ht_cap->mcs.rx_mask[2] == 0)) - ht_conf->single_chain_sufficient = true; - if (maxstreams <= 1) - ht_conf->single_chain_sufficient = true; - } else { - /* - * If at all, this can only happen through a race - * when the AP disconnects us while we're still - * setting up the connection, in that case mac80211 - * will soon tell us about that. - */ - ht_conf->single_chain_sufficient = true; - } - rcu_read_unlock(); - break; - case NL80211_IFTYPE_ADHOC: - ht_conf->single_chain_sufficient = true; - break; - default: - break; - } - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} + iwl_connection_init_rx_config(priv, ctx); -static inline void iwl_set_no_assoc(struct iwl_priv *priv, - struct ieee80211_vif *vif) -{ - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - iwl_led_disassociate(priv); - /* - * inform the ucode that there is no longer an - * association and that no more packets should be - * sent - */ - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ctx->staging.assoc_id = 0; - iwlcore_commit_rxon(priv, ctx); + return iwlcore_commit_rxon(priv, ctx); } -static void iwlcore_beacon_update(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static int iwl_setup_interface(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { - struct iwl_priv *priv = hw->priv; - unsigned long flags; - __le64 timestamp; - struct sk_buff *skb = ieee80211_beacon_get(hw, vif); - - if (!skb) - return; - - IWL_DEBUG_ASSOC(priv, "enter\n"); + struct ieee80211_vif *vif = ctx->vif; + int err; lockdep_assert_held(&priv->mutex); - if (!priv->beacon_ctx) { - IWL_ERR(priv, "update beacon but no beacon context!\n"); - dev_kfree_skb(skb); - return; - } - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->beacon_skb) - dev_kfree_skb(priv->beacon_skb); - - priv->beacon_skb = skb; - - timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - priv->timestamp = le64_to_cpu(timestamp); - - IWL_DEBUG_ASSOC(priv, "leave\n"); - - spin_unlock_irqrestore(&priv->lock, flags); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return; - } - - priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif); -} - -void iwl_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) -{ - struct iwl_priv *priv = hw->priv; - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - int ret; - - IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); - - if (!iwl_is_alive(priv)) - return; - - mutex_lock(&priv->mutex); - - if (changes & BSS_CHANGED_QOS) { - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - ctx->qos_data.qos_active = bss_conf->qos; - iwl_update_qos(priv, ctx); - spin_unlock_irqrestore(&priv->lock, flags); - } - - if (changes & BSS_CHANGED_BEACON_ENABLED) { - /* - * the add_interface code must make sure we only ever - * have a single interface that could be beaconing at - * any time. - */ - if (vif->bss_conf.enable_beacon) - priv->beacon_ctx = ctx; - else - priv->beacon_ctx = NULL; - } - - if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) { - dev_kfree_skb(priv->beacon_skb); - priv->beacon_skb = ieee80211_beacon_get(hw, vif); - } - - if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP) - iwl_send_rxon_timing(priv, ctx); - - if (changes & BSS_CHANGED_BSSID) { - IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid); - - /* - * If there is currently a HW scan going on in the - * background then we need to cancel it else the RXON - * below/in post_associate will fail. - */ - if (iwl_scan_cancel_timeout(priv, 100)) { - IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); - IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); - mutex_unlock(&priv->mutex); - return; - } - - /* mac80211 only sets assoc when in STATION mode */ - if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { - memcpy(ctx->staging.bssid_addr, - bss_conf->bssid, ETH_ALEN); - - /* currently needed in a few places */ - memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); - } else { - ctx->staging.filter_flags &= - ~RXON_FILTER_ASSOC_MSK; - } - - } - /* - * This needs to be after setting the BSSID in case - * mac80211 decides to do both changes at once because - * it will invoke post_associate. + * This variable will be correct only when there's just + * a single context, but all code using it is for hardware + * that supports only one context. */ - if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON) - iwlcore_beacon_update(hw, vif); - - if (changes & BSS_CHANGED_ERP_PREAMBLE) { - IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", - bss_conf->use_short_preamble); - if (bss_conf->use_short_preamble) - ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; - else - ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - } - - if (changes & BSS_CHANGED_ERP_CTS_PROT) { - IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); - if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) - ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; - else - ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; - if (bss_conf->use_cts_prot) - ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; - else - ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; - } - - if (changes & BSS_CHANGED_BASIC_RATES) { - /* XXX use this information - * - * To do that, remove code from iwl_set_rate() and put something - * like this here: - * - if (A-band) - ctx->staging.ofdm_basic_rates = - bss_conf->basic_rates; - else - ctx->staging.ofdm_basic_rates = - bss_conf->basic_rates >> 4; - ctx->staging.cck_basic_rates = - bss_conf->basic_rates & 0xF; - */ - } - - if (changes & BSS_CHANGED_HT) { - iwl_ht_conf(priv, vif); - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - } - - if (changes & BSS_CHANGED_ASSOC) { - IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); - if (bss_conf->assoc) { - priv->timestamp = bss_conf->timestamp; - - iwl_led_associate(priv); - - if (!iwl_is_rfkill(priv)) - priv->cfg->ops->lib->post_associate(priv, vif); - } else - iwl_set_no_assoc(priv, vif); - } - - if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) { - IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n", - changes); - ret = iwl_send_rxon_assoc(priv, ctx); - if (!ret) { - /* Sync active_rxon with latest change. */ - memcpy((void *)&ctx->active, - &ctx->staging, - sizeof(struct iwl_rxon_cmd)); - } - } + priv->iw_mode = vif->type; - if (changes & BSS_CHANGED_BEACON_ENABLED) { - if (vif->bss_conf.enable_beacon) { - memcpy(ctx->staging.bssid_addr, - bss_conf->bssid, ETH_ALEN); - memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); - iwl_led_associate(priv); - iwlcore_config_ap(priv, vif); - } else - iwl_set_no_assoc(priv, vif); - } + ctx->is_active = true; - if (changes & BSS_CHANGED_IBSS) { - ret = priv->cfg->ops->lib->manage_ibss_station(priv, vif, - bss_conf->ibss_joined); - if (ret) - IWL_ERR(priv, "failed to %s IBSS station %pM\n", - bss_conf->ibss_joined ? "add" : "remove", - bss_conf->bssid); + err = iwl_set_mode(priv, ctx); + if (err) { + if (!ctx->always_active) + ctx->is_active = false; + return err; } - if (changes & BSS_CHANGED_IDLE && - priv->cfg->ops->hcmd->set_pan_params) { - if (priv->cfg->ops->hcmd->set_pan_params(priv)) - IWL_ERR(priv, "failed to update PAN params\n"); + if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist && + vif->type == NL80211_IFTYPE_ADHOC) { + /* + * pretend to have high BT traffic as long as we + * are operating in IBSS mode, as this will cause + * the rate scaling etc. to behave as intended. + */ + priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH; } - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} -EXPORT_SYMBOL(iwl_bss_info_changed); - -static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) -{ - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - - iwl_connection_init_rx_config(priv, ctx); - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - - return iwlcore_commit_rxon(priv, ctx); + return 0; } int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) @@ -1771,7 +1402,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct iwl_priv *priv = hw->priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; struct iwl_rxon_context *tmp, *ctx = NULL; - int err = 0; + int err; IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", vif->type, vif->addr); @@ -1813,36 +1444,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) vif_priv->ctx = ctx; ctx->vif = vif; - /* - * This variable will be correct only when there's just - * a single context, but all code using it is for hardware - * that supports only one context. - */ - priv->iw_mode = vif->type; - - ctx->is_active = true; - err = iwl_set_mode(priv, vif); - if (err) { - if (!ctx->always_active) - ctx->is_active = false; - goto out_err; - } - - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && - vif->type == NL80211_IFTYPE_ADHOC) { - /* - * pretend to have high BT traffic as long as we - * are operating in IBSS mode, as this will cause - * the rate scaling etc. to behave as intended. - */ - priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH; - } - - goto out; + err = iwl_setup_interface(priv, ctx); + if (!err) + goto out; - out_err: ctx->vif = NULL; priv->iw_mode = NL80211_IFTYPE_STATION; out: @@ -1853,27 +1459,24 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) } EXPORT_SYMBOL(iwl_mac_add_interface); -void iwl_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static void iwl_teardown_interface(struct iwl_priv *priv, + struct ieee80211_vif *vif, + bool mode_change) { - struct iwl_priv *priv = hw->priv; struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - IWL_DEBUG_MAC80211(priv, "enter\n"); - - mutex_lock(&priv->mutex); - - WARN_ON(ctx->vif != vif); - ctx->vif = NULL; + lockdep_assert_held(&priv->mutex); if (priv->scan_vif == vif) { iwl_scan_cancel_timeout(priv, 200); iwl_force_scan_end(priv); } - iwl_set_mode(priv, vif); - if (!ctx->always_active) - ctx->is_active = false; + if (!mode_change) { + iwl_set_mode(priv, ctx); + if (!ctx->always_active) + ctx->is_active = false; + } /* * When removing the IBSS interface, overwrite the @@ -1883,211 +1486,31 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, * both values are the same and zero. */ if (vif->type == NL80211_IFTYPE_ADHOC) - priv->bt_traffic_load = priv->notif_bt_traffic_load; - - memset(priv->bssid, 0, ETH_ALEN); - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - -} -EXPORT_SYMBOL(iwl_mac_remove_interface); - -/** - * iwl_mac_config - mac80211 config callback - */ -int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) -{ - struct iwl_priv *priv = hw->priv; - const struct iwl_channel_info *ch_info; - struct ieee80211_conf *conf = &hw->conf; - struct ieee80211_channel *channel = conf->channel; - struct iwl_ht_config *ht_conf = &priv->current_ht_config; - struct iwl_rxon_context *ctx; - unsigned long flags = 0; - int ret = 0; - u16 ch; - int scan_active = 0; - - mutex_lock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", - channel->hw_value, changed); - - if (unlikely(!priv->cfg->mod_params->disable_hw_scan && - test_bit(STATUS_SCANNING, &priv->status))) { - scan_active = 1; - IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); - } - - if (changed & (IEEE80211_CONF_CHANGE_SMPS | - IEEE80211_CONF_CHANGE_CHANNEL)) { - /* mac80211 uses static for non-HT which is what we want */ - priv->current_ht_config.smps = conf->smps_mode; - - /* - * Recalculate chain counts. - * - * If monitor mode is enabled then mac80211 will - * set up the SM PS mode to OFF if an HT channel is - * configured. - */ - if (priv->cfg->ops->hcmd->set_rxon_chain) - for_each_context(priv, ctx) - priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - } - - /* during scanning mac80211 will delay channel setting until - * scan finish with changed = 0 - */ - if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { - if (scan_active) - goto set_ch_out; - - ch = channel->hw_value; - ch_info = iwl_get_channel_info(priv, channel->band, ch); - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); - ret = -EINVAL; - goto set_ch_out; - } - - spin_lock_irqsave(&priv->lock, flags); - - for_each_context(priv, ctx) { - /* Configure HT40 channels */ - ctx->ht.enabled = conf_is_ht(conf); - if (ctx->ht.enabled) { - if (conf_is_ht40_minus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_BELOW; - ctx->ht.is_40mhz = true; - } else if (conf_is_ht40_plus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - ctx->ht.is_40mhz = true; - } else { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_NONE; - ctx->ht.is_40mhz = false; - } - } else - ctx->ht.is_40mhz = false; - - /* - * Default to no protection. Protection mode will - * later be set from BSS config in iwl_ht_conf - */ - ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; - - /* if we are switching from ht to 2.4 clear flags - * from any ht related info since 2.4 does not - * support ht */ - if ((le16_to_cpu(ctx->staging.channel) != ch)) - ctx->staging.flags = 0; - - iwl_set_rxon_channel(priv, channel, ctx); - iwl_set_rxon_ht(priv, ht_conf); - - iwl_set_flags_for_band(priv, ctx, channel->band, - ctx->vif); - } - - spin_unlock_irqrestore(&priv->lock, flags); - - if (priv->cfg->ops->lib->update_bcast_stations) - ret = priv->cfg->ops->lib->update_bcast_stations(priv); - - set_ch_out: - /* The list of supported rates and rate mask can be different - * for each band; since the band may have changed, reset - * the rate mask to what mac80211 lists */ - iwl_set_rate(priv); - } - - if (changed & (IEEE80211_CONF_CHANGE_PS | - IEEE80211_CONF_CHANGE_IDLE)) { - ret = iwl_power_update_mode(priv, false); - if (ret) - IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n"); - } - - if (changed & IEEE80211_CONF_CHANGE_POWER) { - IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", - priv->tx_power_user_lmt, conf->power_level); - - iwl_set_tx_power(priv, conf->power_level, false); - } - - if (!iwl_is_ready(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - goto out; - } - - if (scan_active) - goto out; - - for_each_context(priv, ctx) { - if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging))) - iwlcore_commit_rxon(priv, ctx); - else - IWL_DEBUG_INFO(priv, - "Not re-sending same RXON configuration.\n"); - } - -out: - IWL_DEBUG_MAC80211(priv, "leave\n"); - mutex_unlock(&priv->mutex); - return ret; + priv->bt_traffic_load = priv->last_bt_traffic_load; } -EXPORT_SYMBOL(iwl_mac_config); -void iwl_mac_reset_tsf(struct ieee80211_hw *hw) +void iwl_mac_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; - unsigned long flags; - /* IBSS can only be the IWL_RXON_CTX_BSS context */ - struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "enter\n"); - spin_lock_irqsave(&priv->lock, flags); - memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); - spin_unlock_irqrestore(&priv->lock, flags); - - spin_lock_irqsave(&priv->lock, flags); - - /* new association get rid of ibss beacon skb */ - if (priv->beacon_skb) - dev_kfree_skb(priv->beacon_skb); - - priv->beacon_skb = NULL; - - priv->timestamp = 0; - - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_scan_cancel_timeout(priv, 100); - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - mutex_unlock(&priv->mutex); - return; - } + mutex_lock(&priv->mutex); - /* we are restarting association process - * clear RXON_FILTER_ASSOC_MSK bit - */ - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv, ctx); + WARN_ON(ctx->vif != vif); + ctx->vif = NULL; - iwl_set_rate(priv); + iwl_teardown_interface(priv, vif, false); + memset(priv->bssid, 0, ETH_ALEN); mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); + } -EXPORT_SYMBOL(iwl_mac_reset_tsf); +EXPORT_SYMBOL(iwl_mac_remove_interface); int iwl_alloc_txq_mem(struct iwl_priv *priv) { @@ -2431,77 +1854,115 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) return 0; } -/** - * iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover - * - * During normal condition (no queue is stuck), the timer is continually set to - * execute every monitor_recover_period milliseconds after the last timer - * expired. When the queue read_ptr is at the same place, the timer is - * shorten to 100mSecs. This is - * 1) to reduce the chance that the read_ptr may wrap around (not stuck) - * 2) to detect the stuck queues quicker before the station and AP can - * disassociate each other. - * - * This function monitors all the tx queues and recover from it if any - * of the queues are stuck. - * 1. It first check the cmd queue for stuck conditions. If it is stuck, - * it will recover by resetting the firmware and return. - * 2. Then, it checks for station association. If it associates it will check - * other queues. If any queue is stuck, it will recover by resetting - * the firmware. - * Note: It the number of times the queue read_ptr to be at the same place to - * be MAX_REPEAT+1 in order to consider to be stuck. - */ +int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + enum nl80211_iftype newtype, bool newp2p) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + struct iwl_rxon_context *tmp; + u32 interface_modes; + int err; + + newtype = ieee80211_iftype_p2p(newtype, newp2p); + + mutex_lock(&priv->mutex); + + interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes; + + if (!(interface_modes & BIT(newtype))) { + err = -EBUSY; + goto out; + } + + if (ctx->exclusive_interface_modes & BIT(newtype)) { + for_each_context(priv, tmp) { + if (ctx == tmp) + continue; + + if (!tmp->vif) + continue; + + /* + * The current mode switch would be exclusive, but + * another context is active ... refuse the switch. + */ + err = -EBUSY; + goto out; + } + } + + /* success */ + iwl_teardown_interface(priv, vif, true); + vif->type = newtype; + err = iwl_setup_interface(priv, ctx); + WARN_ON(err); + /* + * We've switched internally, but submitting to the + * device may have failed for some reason. Mask this + * error, because otherwise mac80211 will not switch + * (and set the interface type back) and we'll be + * out of sync with it. + */ + err = 0; + + out: + mutex_unlock(&priv->mutex); + return err; +} +EXPORT_SYMBOL(iwl_mac_change_interface); + /* - * The maximum number of times the read pointer of the tx queue at the - * same place without considering to be stuck. + * On every watchdog tick we check (latest) time stamp. If it does not + * change during timeout period and queue is not empty we reset firmware. */ -#define MAX_REPEAT (2) static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt) { - struct iwl_tx_queue *txq; - struct iwl_queue *q; + struct iwl_tx_queue *txq = &priv->txq[cnt]; + struct iwl_queue *q = &txq->q; + unsigned long timeout; + int ret; - txq = &priv->txq[cnt]; - q = &txq->q; - /* queue is empty, skip */ - if (q->read_ptr == q->write_ptr) + if (q->read_ptr == q->write_ptr) { + txq->time_stamp = jiffies; return 0; + } - if (q->read_ptr == q->last_read_ptr) { - /* a queue has not been read from last time */ - if (q->repeat_same_read_ptr > MAX_REPEAT) { - IWL_ERR(priv, - "queue %d stuck %d time. Fw reload.\n", - q->id, q->repeat_same_read_ptr); - q->repeat_same_read_ptr = 0; - iwl_force_reset(priv, IWL_FW_RESET, false); - } else { - q->repeat_same_read_ptr++; - IWL_DEBUG_RADIO(priv, - "queue %d, not read %d time\n", - q->id, - q->repeat_same_read_ptr); - mod_timer(&priv->monitor_recover, - jiffies + msecs_to_jiffies( - IWL_ONE_HUNDRED_MSECS)); - return 1; - } - } else { - q->last_read_ptr = q->read_ptr; - q->repeat_same_read_ptr = 0; + timeout = txq->time_stamp + + msecs_to_jiffies(priv->cfg->base_params->wd_timeout); + + if (time_after(jiffies, timeout)) { + IWL_ERR(priv, "Queue %d stuck for %u ms.\n", + q->id, priv->cfg->base_params->wd_timeout); + ret = iwl_force_reset(priv, IWL_FW_RESET, false); + return (ret == -EAGAIN) ? 0 : 1; } + return 0; } -void iwl_bg_monitor_recover(unsigned long data) +/* + * Making watchdog tick be a quarter of timeout assure we will + * discover the queue hung between timeout and 1.25*timeout + */ +#define IWL_WD_TICK(timeout) ((timeout) / 4) + +/* + * Watchdog timer callback, we check each tx queue for stuck, if if hung + * we reset the firmware. If everything is fine just rearm the timer. + */ +void iwl_bg_watchdog(unsigned long data) { struct iwl_priv *priv = (struct iwl_priv *)data; int cnt; + unsigned long timeout; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; + timeout = priv->cfg->base_params->wd_timeout; + if (timeout == 0) + return; + /* monitor and check for stuck cmd queue */ if (iwl_check_stuck_queue(priv, priv->cmd_queue)) return; @@ -2516,17 +1977,23 @@ void iwl_bg_monitor_recover(unsigned long data) return; } } - if (priv->cfg->base_params->monitor_recover_period) { - /* - * Reschedule the timer to occur in - * priv->cfg->base_params->monitor_recover_period - */ - mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies( - priv->cfg->base_params->monitor_recover_period)); - } + + mod_timer(&priv->watchdog, jiffies + + msecs_to_jiffies(IWL_WD_TICK(timeout))); } -EXPORT_SYMBOL(iwl_bg_monitor_recover); +EXPORT_SYMBOL(iwl_bg_watchdog); + +void iwl_setup_watchdog(struct iwl_priv *priv) +{ + unsigned int timeout = priv->cfg->base_params->wd_timeout; + if (timeout) + mod_timer(&priv->watchdog, + jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout))); + else + del_timer(&priv->watchdog); +} +EXPORT_SYMBOL(iwl_setup_watchdog); /* * extended beacon time format @@ -2584,8 +2051,9 @@ EXPORT_SYMBOL(iwl_add_beacon_time); #ifdef CONFIG_PM -int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) +int iwl_pci_suspend(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct iwl_priv *priv = pci_get_drvdata(pdev); /* @@ -2597,18 +2065,14 @@ int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) */ iwl_apm_stop(priv); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - return 0; } EXPORT_SYMBOL(iwl_pci_suspend); -int iwl_pci_resume(struct pci_dev *pdev) +int iwl_pci_resume(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct iwl_priv *priv = pci_get_drvdata(pdev); - int ret; bool hw_rfkill = false; /* @@ -2617,11 +2081,6 @@ int iwl_pci_resume(struct pci_dev *pdev) */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - pci_set_power_state(pdev, PCI_D0); - ret = pci_enable_device(pdev); - if (ret) - return ret; - pci_restore_state(pdev); iwl_enable_interrupts(priv); if (!(iwl_read32(priv, CSR_GP_CNTRL) & @@ -2639,4 +2098,14 @@ int iwl_pci_resume(struct pci_dev *pdev) } EXPORT_SYMBOL(iwl_pci_resume); +const struct dev_pm_ops iwl_pm_ops = { + .suspend = iwl_pci_suspend, + .resume = iwl_pci_resume, + .freeze = iwl_pci_suspend, + .thaw = iwl_pci_resume, + .poweroff = iwl_pci_suspend, + .restore = iwl_pci_resume, +}; +EXPORT_SYMBOL(iwl_pm_ops); + #endif /* CONFIG_PM */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 954ecc2c34c4..a3474376fdbc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -120,6 +120,14 @@ struct iwl_apm_ops { void (*config)(struct iwl_priv *priv); }; +struct iwl_isr_ops { + irqreturn_t (*isr) (int irq, void *data); + void (*free)(struct iwl_priv *priv); + int (*alloc)(struct iwl_priv *priv); + int (*reset)(struct iwl_priv *priv); + void (*disable)(struct iwl_priv *priv); +}; + struct iwl_debugfs_ops { ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); @@ -193,22 +201,15 @@ struct iwl_lib_ops { /* power */ int (*send_tx_power) (struct iwl_priv *priv); void (*update_chain_flags)(struct iwl_priv *priv); - void (*post_associate)(struct iwl_priv *priv, - struct ieee80211_vif *vif); - void (*config_ap)(struct iwl_priv *priv, struct ieee80211_vif *vif); - irqreturn_t (*isr) (int irq, void *data); + + /* isr */ + struct iwl_isr_ops isr_ops; /* eeprom operations (as defined in iwl-eeprom.h) */ struct iwl_eeprom_ops eeprom_ops; /* temperature */ struct iwl_temp_ops temp_ops; - /* station management */ - int (*manage_ibss_station)(struct iwl_priv *priv, - struct ieee80211_vif *vif, bool add); - int (*update_bcast_stations)(struct iwl_priv *priv); - /* recover from tx queue stall */ - void (*recover_from_tx_stall)(unsigned long data); /* check for plcp health */ bool (*check_plcp_health)(struct iwl_priv *priv, struct iwl_rx_packet *pkt); @@ -235,12 +236,23 @@ struct iwl_nic_ops { void (*additional_nic_config)(struct iwl_priv *priv); }; +struct iwl_legacy_ops { + void (*post_associate)(struct iwl_priv *priv); + void (*config_ap)(struct iwl_priv *priv); + /* station management */ + int (*update_bcast_stations)(struct iwl_priv *priv); + int (*manage_ibss_station)(struct iwl_priv *priv, + struct ieee80211_vif *vif, bool add); +}; + struct iwl_ops { const struct iwl_lib_ops *lib; const struct iwl_hcmd_ops *hcmd; const struct iwl_hcmd_utils_ops *utils; const struct iwl_led_ops *led; const struct iwl_nic_ops *nic; + const struct iwl_legacy_ops *legacy; + const struct ieee80211_ops *ieee80211_ops; }; struct iwl_mod_params { @@ -266,7 +278,7 @@ struct iwl_mod_params { * @plcp_delta_threshold: plcp error rate threshold used to trigger * radio tuning when there is a high receiving plcp error rate * @chain_noise_scale: default chain noise scale used for gain computation - * @monitor_recover_period: default timer used to check stuck queues + * @wd_timeout: TX queues watchdog timeout * @temperature_kelvin: temperature report by uCode in kelvin * @max_event_log_size: size of event log buffer size for ucode event logging * @tx_power_by_driver: tx power calibration performed by driver @@ -276,7 +288,10 @@ struct iwl_mod_params { * sensitivity calibration operation * @chain_noise_calib_by_driver: driver has the capability to perform * chain noise calibration operation -*/ + * @shadow_reg_enable: HW shadhow register bit + * @no_agg_framecnt_info: uCode do not provide aggregation frame count + * information + */ struct iwl_base_params { int eeprom_size; int num_of_queues; /* def: HW dependent */ @@ -298,14 +313,15 @@ struct iwl_base_params { const bool support_wimax_coexist; u8 plcp_delta_threshold; s32 chain_noise_scale; - /* timer period for monitor the driver queues */ - u32 monitor_recover_period; + unsigned int wd_timeout; bool temperature_kelvin; u32 max_event_log_size; const bool tx_power_by_driver; const bool ucode_tracing; const bool sensitivity_calib_by_driver; const bool chain_noise_calib_by_driver; + const bool shadow_reg_enable; + const bool no_agg_framecnt_info; }; /* * @advanced_bt_coexist: support advanced bt coexist @@ -315,6 +331,7 @@ struct iwl_base_params { * @agg_time_limit: maximum number of uSec in aggregation * @ampdu_factor: Maximum A-MPDU length factor * @ampdu_density: Minimum A-MPDU spacing + * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode */ struct iwl_bt_params { bool advanced_bt_coexist; @@ -324,6 +341,7 @@ struct iwl_bt_params { u16 agg_time_limit; u8 ampdu_factor; u8 ampdu_density; + bool bt_sco_disable; }; /* * @use_rts_for_aggregation: use rts/cts protection for HT traffic @@ -344,6 +362,10 @@ struct iwl_ht_params { * @need_dc_calib: need to perform init dc calibration * @need_temp_offset_calib: need to perform temperature offset calibration * @scan_antennas: available antenna for scan operation + * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) + * @adv_pm: advance power management + * @rx_with_siso_diversity: 1x1 device with rx antenna diversity + * @internal_wimax_coex: internal wifi/wimax combo device * * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the @@ -389,16 +411,17 @@ struct iwl_cfg { const bool need_dc_calib; /* if used set to true */ const bool need_temp_offset_calib; /* if used set to true */ u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; - u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; - const bool use_new_eeprom_reading; /* temporary, remove later */ + enum iwl_led_mode led_mode; + const bool adv_pm; + const bool rx_with_siso_diversity; + const bool internal_wimax_coex; }; /*************************** * L i b * ***************************/ -struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, - struct ieee80211_ops *hw_ops); +struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg); int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); @@ -426,23 +449,16 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, u32 decrypt_res, struct ieee80211_rx_status *stats); void iwl_irq_handle_error(struct iwl_priv *priv); -void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); -void iwl_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes); int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void iwl_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); -void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif); -void iwl_mac_reset_tsf(struct ieee80211_hw *hw); +int iwl_mac_change_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum nl80211_iftype newtype, bool newp2p); int iwl_alloc_txq_mem(struct iwl_priv *priv); void iwl_free_txq_mem(struct iwl_priv *priv); -void iwlcore_tx_cmd_protection(struct iwl_priv *priv, - struct ieee80211_tx_info *info, - __le16 fc, __le32 *tx_flags); + #ifdef CONFIG_IWLWIFI_DEBUGFS int iwl_alloc_traffic_mem(struct iwl_priv *priv); void iwl_free_traffic_mem(struct iwl_priv *priv); @@ -530,6 +546,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, int slots_num, u32 txq_id); void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); +void iwl_setup_watchdog(struct iwl_priv *priv); /***************************************************** * TX power ****************************************************/ @@ -599,7 +616,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); /***************************************************** * PCI * *****************************************************/ -irqreturn_t iwl_isr_legacy(int irq, void *data); static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) { @@ -610,15 +626,23 @@ static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) return pci_lnk_ctl; } -void iwl_bg_monitor_recover(unsigned long data); +void iwl_bg_watchdog(unsigned long data); u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval); __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, u32 addon, u32 beacon_interval); #ifdef CONFIG_PM -int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); -int iwl_pci_resume(struct pci_dev *pdev); -#endif /* CONFIG_PM */ +int iwl_pci_suspend(struct device *device); +int iwl_pci_resume(struct device *device); +extern const struct dev_pm_ops iwl_pm_ops; + +#define IWL_PM_OPS (&iwl_pm_ops) + +#else /* !CONFIG_PM */ + +#define IWL_PM_OPS NULL + +#endif /* !CONFIG_PM */ /***************************************************** * Error Handling Debugging @@ -725,11 +749,6 @@ static inline int iwlcore_commit_rxon(struct iwl_priv *priv, { return priv->cfg->ops->hcmd->commit_rxon(priv, ctx); } -static inline void iwlcore_config_ap(struct iwl_priv *priv, - struct ieee80211_vif *vif) -{ - priv->cfg->ops->lib->config_ap(priv, vif); -} static inline const struct ieee80211_supported_band *iwl_get_hw_mode( struct iwl_priv *priv, enum ieee80211_band band) { diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 2aa15ab13892..b80bf7dff55b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -132,6 +132,8 @@ #define CSR_LED_REG (CSR_BASE+0x094) #define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0) +#define CSR_MAC_SHADOW_REG_CTRL (CSR_BASE+0x0A8) /* 6000 and up */ + /* GIO Chicken Bits (PCI Express bus link power management) */ #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 0b961a353ff6..ebdea3be3ef9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -120,6 +120,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) /* 0x000000F0 - 0x00000010 */ #define IWL_DL_MACDUMP (1 << 4) #define IWL_DL_HCMD_DUMP (1 << 5) +#define IWL_DL_EEPROM (1 << 6) #define IWL_DL_RADIO (1 << 7) /* 0x00000F00 - 0x00000100 */ #define IWL_DL_POWER (1 << 8) @@ -164,6 +165,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a) #define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) #define IWL_DEBUG_HC_DUMP(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD_DUMP, f, ## a) +#define IWL_DEBUG_EEPROM(p, f, a...) IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a) #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 8fdd4efdb1d3..6fe80b5e7a15 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -992,11 +992,8 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, " swq_id=%#.2x (ac %d/hwq %d)\n", cnt, q->read_ptr, q->write_ptr, !!test_bit(cnt, priv->queue_stopped), - txq->swq_id, - txq->swq_id & 0x80 ? txq->swq_id & 3 : - txq->swq_id, - txq->swq_id & 0x80 ? (txq->swq_id >> 2) & - 0x1f : txq->swq_id); + txq->swq_id, txq->swq_id & 3, + (txq->swq_id >> 2) & 0x1f); if (cnt >= 4) continue; /* for the ACs, display the stop count too */ @@ -1537,32 +1534,26 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, user_buf, count, ppos); } -static ssize_t iwl_dbgfs_monitor_period_write(struct file *file, +static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; char buf[8]; int buf_size; - int period; + int timeout; memset(buf, 0, sizeof(buf)); buf_size = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; - if (sscanf(buf, "%d", &period) != 1) + if (sscanf(buf, "%d", &timeout) != 1) return -EINVAL; - if (period < 0 || period > IWL_MAX_MONITORING_PERIOD) - priv->cfg->base_params->monitor_recover_period = - IWL_DEF_MONITORING_PERIOD; - else - priv->cfg->base_params->monitor_recover_period = period; + if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT) + timeout = IWL_DEF_WD_TIMEOUT; - if (priv->cfg->base_params->monitor_recover_period) - mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies( - priv->cfg->base_params->monitor_recover_period)); - else - del_timer_sync(&priv->monitor_recover); + priv->cfg->base_params->wd_timeout = timeout; + iwl_setup_watchdog(priv); return count; } @@ -1576,11 +1567,18 @@ static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, const size_t bufsz = sizeof(buf); ssize_t ret; + if (!priv->bt_enable_flag) { + pos += scnprintf(buf + pos, bufsz - pos, "BT coex disabled\n"); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + return ret; + } + pos += scnprintf(buf + pos, bufsz - pos, "BT enable flag: 0x%x\n", + priv->bt_enable_flag); pos += scnprintf(buf + pos, bufsz - pos, "BT in %s mode\n", priv->bt_full_concurrent ? "full concurrency" : "3-wire"); pos += scnprintf(buf + pos, bufsz - pos, "BT status: %s, " "last traffic notif: %d\n", - priv->bt_status ? "On" : "Off", priv->notif_bt_traffic_load); + priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load); pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, " "sco_active: %d, kill_ack_mask: %x, " "kill_cts_mask: %x\n", @@ -1689,7 +1687,7 @@ DEBUGFS_READ_FILE_OPS(rxon_flags); DEBUGFS_READ_FILE_OPS(rxon_filter_flags); DEBUGFS_WRITE_FILE_OPS(txfifo_flush); DEBUGFS_READ_FILE_OPS(ucode_bt_stats); -DEBUGFS_WRITE_FILE_OPS(monitor_period); +DEBUGFS_WRITE_FILE_OPS(wd_timeout); DEBUGFS_READ_FILE_OPS(bt_traffic); DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); DEBUGFS_READ_FILE_OPS(reply_tx_error); @@ -1766,7 +1764,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); - DEBUGFS_ADD_FILE(monitor_period, dir_debug, S_IWUSR); + DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); if (priv->cfg->base_params->sensitivity_calib_by_driver) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 70e07fa48405..8dda67850af4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -129,9 +129,6 @@ struct iwl_queue { int write_ptr; /* 1-st empty entry (index) host_w*/ int read_ptr; /* last used entry (index) host_r*/ /* use for monitoring and recovering the stuck queue */ - int last_read_ptr; /* storing the last read_ptr */ - /* number of time read_ptr and last_read_ptr are the same */ - u8 repeat_same_read_ptr; dma_addr_t dma_addr; /* physical addr for BD's */ int n_window; /* safe queue window */ u32 id; @@ -155,6 +152,7 @@ struct iwl_tx_info { * @meta: array of meta data for each command/tx buffer * @dma_addr_cmd: physical address of cmd/tx buffer array * @txb: array of per-TFD driver data + * @time_stamp: time (in jiffies) of last read_ptr change * @need_update: indicates need to update read/write index * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled * @@ -170,6 +168,7 @@ struct iwl_tx_queue { struct iwl_device_cmd **cmd; struct iwl_cmd_meta *meta; struct iwl_tx_info *txb; + unsigned long time_stamp; u8 need_update; u8 sched_retry; u8 active; @@ -1104,11 +1103,10 @@ struct iwl_event_log { #define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) -/* timer constants use to monitor and recover stuck tx queues in mSecs */ -#define IWL_DEF_MONITORING_PERIOD (1000) -#define IWL_LONG_MONITORING_PERIOD (5000) -#define IWL_ONE_HUNDRED_MSECS (100) -#define IWL_MAX_MONITORING_PERIOD (60000) +/* TX queue watchdog timeouts in mSecs */ +#define IWL_DEF_WD_TIMEOUT (2000) +#define IWL_LONG_WD_TIMEOUT (10000) +#define IWL_MAX_WD_TIMEOUT (120000) /* BT Antenna Coupling Threshold (dB) */ #define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35) @@ -1162,6 +1160,8 @@ struct iwl_rxon_context { */ bool always_active, is_active; + bool ht_need_multiple_chains; + enum iwl_rxon_context_id ctxid; u32 interface_modes, exclusive_interface_modes; @@ -1468,8 +1468,9 @@ struct iwl_priv { }; /* bt coex */ + u8 bt_enable_flag; u8 bt_status; - u8 bt_traffic_load, notif_bt_traffic_load; + u8 bt_traffic_load, last_bt_traffic_load; bool bt_ch_announce; bool bt_sco_active; bool bt_full_concurrent; @@ -1480,7 +1481,6 @@ struct iwl_priv { u16 bt_on_thresh; u16 bt_duration; u16 dynamic_frag_thresh; - u16 dynamic_agg_thresh; u8 bt_ci_compliance; struct work_struct bt_traffic_change_work; @@ -1517,6 +1517,7 @@ struct iwl_priv { s8 tx_power_user_lmt; s8 tx_power_device_lmt; s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */ + s8 tx_power_next; #ifdef CONFIG_IWLWIFI_DEBUG @@ -1542,7 +1543,7 @@ struct iwl_priv { struct work_struct run_time_calib_work; struct timer_list statistics_periodic; struct timer_list ucode_trace; - struct timer_list monitor_recover; + struct timer_list watchdog; bool hw_ready; struct iwl_event_log event_log; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 87cd10ff285d..358cfd7e5af1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -147,7 +147,7 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv) u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; int ret = 0; - IWL_DEBUG_INFO(priv, "EEPROM signature=0x%08x\n", gp); + IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp); switch (gp) { case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP: if (priv->nvm_device_type != NVM_DEVICE_TYPE_OTP) { @@ -354,7 +354,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv, */ valid_addr = next_link_addr; next_link_addr = le16_to_cpu(link_value) * sizeof(u16); - IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n", + IWL_DEBUG_EEPROM(priv, "OTP blocks %d addr 0x%x\n", usedblocks, next_link_addr); if (iwl_read_otp_word(priv, next_link_addr, &link_value)) return -EINVAL; @@ -374,7 +374,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv, } while (usedblocks <= priv->cfg->base_params->max_ll_items); /* OTP has no valid blocks */ - IWL_DEBUG_INFO(priv, "OTP has no valid blocks\n"); + IWL_DEBUG_EEPROM(priv, "OTP has no valid blocks\n"); return -EINVAL; } @@ -414,7 +414,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) return -ENOENT; /* allocate eeprom */ sz = priv->cfg->base_params->eeprom_size; - IWL_DEBUG_INFO(priv, "NVM size = %d\n", sz); + IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz); priv->eeprom = kzalloc(sz, GFP_KERNEL); if (!priv->eeprom) { ret = -ENOMEM; @@ -492,7 +492,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) } } - IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n", + IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n", (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) ? "OTP" : "EEPROM", iwl_eeprom_query16(priv, EEPROM_VERSION)); @@ -594,7 +594,7 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, if (!is_channel_valid(ch_info)) return -1; - IWL_DEBUG_INFO(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):" + IWL_DEBUG_EEPROM(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):" " Ad-Hoc %ssupported\n", ch_info->channel, is_channel_a_band(ch_info) ? @@ -634,11 +634,11 @@ int iwl_init_channel_map(struct iwl_priv *priv) struct iwl_channel_info *ch_info; if (priv->channel_count) { - IWL_DEBUG_INFO(priv, "Channel map already initialized.\n"); + IWL_DEBUG_EEPROM(priv, "Channel map already initialized.\n"); return 0; } - IWL_DEBUG_INFO(priv, "Initializing regulatory info from EEPROM\n"); + IWL_DEBUG_EEPROM(priv, "Initializing regulatory info from EEPROM\n"); priv->channel_count = ARRAY_SIZE(iwl_eeprom_band_1) + @@ -647,7 +647,8 @@ int iwl_init_channel_map(struct iwl_priv *priv) ARRAY_SIZE(iwl_eeprom_band_4) + ARRAY_SIZE(iwl_eeprom_band_5); - IWL_DEBUG_INFO(priv, "Parsing data for %d channels.\n", priv->channel_count); + IWL_DEBUG_EEPROM(priv, "Parsing data for %d channels.\n", + priv->channel_count); priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) * priv->channel_count, GFP_KERNEL); @@ -686,7 +687,8 @@ int iwl_init_channel_map(struct iwl_priv *priv) IEEE80211_CHAN_NO_HT40; if (!(is_channel_valid(ch_info))) { - IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - " + IWL_DEBUG_EEPROM(priv, + "Ch. %d Flags %x [%sGHz] - " "No traffic\n", ch_info->channel, ch_info->flags, @@ -702,7 +704,8 @@ int iwl_init_channel_map(struct iwl_priv *priv) ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; ch_info->min_power = 0; - IWL_DEBUG_INFO(priv, "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm):" + IWL_DEBUG_EEPROM(priv, "Ch. %d [%sGHz] " + "%s%s%s%s%s%s(0x%02x %ddBm):" " Ad-Hoc %ssupported\n", ch_info->channel, is_channel_a_band(ch_info) ? diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index e3a279d2d0b6..9e6f31355eee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -110,9 +110,18 @@ enum { }; /* SKU Capabilities */ +/* 3945 only */ #define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0) #define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) +/* 5000 and up */ +#define EEPROM_SKU_CAP_BAND_POS (4) +#define EEPROM_SKU_CAP_BAND_SELECTION \ + (3 << EEPROM_SKU_CAP_BAND_POS) +#define EEPROM_SKU_CAP_11N_ENABLE (1 << 6) +#define EEPROM_SKU_CAP_AMT_ENABLE (1 << 7) +#define EEPROM_SKU_CAP_IPAN_ENABLE (1 << 8) + /* *regulatory* channel data format in eeprom, one for each channel. * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */ struct iwl_eeprom_channel { @@ -222,59 +231,6 @@ struct iwl_eeprom_enhanced_txpwr { #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS ((0x80)\ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ -/* 6000 and up regulatory tx power - indirect access */ -/* max. elements per section */ -#define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS (8) -#define EEPROM_TXPOWER_COMMON_HT40_INDEX (2) - -/** - * Partition the enhanced tx power portion of eeprom image into - * 10 sections based on band, modulation, frequency and channel - * - * Section 1: all CCK channels - * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40 ) channels - * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels - * Section 4: 2.4 GHz 20MHz channels: 1, 2, 10, 11. Both Legacy and HT - * Section 5: 2.4 GHz 40MHz channels: 1, 2, 6, 7, 9, (_above_) - * Section 6: 5.2 GHz 20MHz channels: 36, 64, 100, both Legacy and HT - * Section 7: 5.2 GHz 40MHz channels: 36, 60, 100 (_above_) - * Section 8: 2.4 GHz channel 13, Both Legacy and HT - * Section 9: 2.4 GHz channel 140, Both Legacy and HT - * Section 10: 2.4 GHz 40MHz channels: 132, 44 (_above_) - */ -/* 2.4 GHz band: CCK */ -#define EEPROM_LB_CCK_20_COMMON ((0xA8)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 8 bytes */ -/* 2.4 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */ -#define EEPROM_LB_OFDM_COMMON ((0xB0)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ -/* 5.2 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */ -#define EEPROM_HB_OFDM_COMMON ((0xC8)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ -/* 2.4GHz band channels: - * 1Legacy, 1HT, 2Legacy, 2HT, 10Legacy, 10HT, 11Legacy, 11HT */ -#define EEPROM_LB_OFDM_20_BAND ((0xE0)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 64 bytes */ -/* 2.4 GHz band HT40 channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) */ -#define EEPROM_LB_OFDM_HT40_BAND ((0x120)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 40 bytes */ -/* 5.2GHz band channels: 36Legacy, 36HT, 64Legacy, 64HT, 100Legacy, 100HT */ -#define EEPROM_HB_OFDM_20_BAND ((0x148)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 48 bytes */ -/* 5.2 GHz band HT40 channels: (36,+1) (60,+1) (100,+1) */ -#define EEPROM_HB_OFDM_HT40_BAND ((0x178)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ -/* 2.4 GHz band, channnel 13: Legacy, HT */ -#define EEPROM_LB_OFDM_20_CHANNEL_13 ((0x190)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */ -/* 5.2 GHz band, channnel 140: Legacy, HT */ -#define EEPROM_HB_OFDM_20_CHANNEL_140 ((0x1A0)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */ -/* 5.2 GHz band, HT40 channnels (132,+1) (44,+1) */ -#define EEPROM_HB_OFDM_HT40_BAND_1 ((0x1B0)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */ - - /* 5050 Specific */ #define EEPROM_5050_TX_POWER_VERSION (4) #define EEPROM_5050_EEPROM_VERSION (0x21E) @@ -414,11 +370,10 @@ struct iwl_eeprom_calib_info { #define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ #define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ #define EEPROM_VERSION (2*0x44) /* 2 bytes */ -#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */ +#define EEPROM_SKU_CAP (2*0x45) /* 2 bytes */ #define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ #define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ -#define EEPROM_3945_M_VERSION (2*0x4A) /* 1 bytes */ #define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */ /* The following masks are to be applied on EEPROM_RADIO_CONFIG */ @@ -521,6 +476,7 @@ struct iwl_eeprom_ops { int iwl_eeprom_init(struct iwl_priv *priv); void iwl_eeprom_free(struct iwl_priv *priv); int iwl_eeprom_check_version(struct iwl_priv *priv); +int iwl_eeprom_check_sku(struct iwl_priv *priv); const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); int iwlcore_eeprom_verify_signature(struct iwl_priv *priv); u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 1aaef70deaec..8821f088ba7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -44,15 +44,6 @@ static inline struct ieee80211_conf *ieee80211_get_hw_conf( return &hw->conf; } -static inline unsigned long elapsed_jiffies(unsigned long start, - unsigned long end) -{ - if (end >= start) - return end - start; - - return end + (MAX_JIFFY_OFFSET - start) + 1; -} - /** * iwl_queue_inc_wrap - increment queue index, wrap back to beginning * @index -- current index @@ -104,42 +95,36 @@ static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, * | | | | | | | | * | | | | | | +-+-------- AC queue (0-3) * | | | | | | - * | +-+-+-+-+------------ HW A-MPDU queue + * | +-+-+-+-+------------ HW queue ID * | - * +---------------------- indicates agg queue + * +---------------------- unused */ -static inline u8 iwl_virtual_agg_queue_num(u8 ac, u8 hwq) +static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq) { BUG_ON(ac > 3); /* only have 2 bits */ - BUG_ON(hwq > 31); /* only have 5 bits */ + BUG_ON(hwq > 31); /* only use 5 bits */ - return 0x80 | (hwq << 2) | ac; + txq->swq_id = (hwq << 2) | ac; } -static inline void iwl_wake_queue(struct iwl_priv *priv, u8 queue) +static inline void iwl_wake_queue(struct iwl_priv *priv, + struct iwl_tx_queue *txq) { - u8 ac = queue; - u8 hwq = queue; - - if (queue & 0x80) { - ac = queue & 3; - hwq = (queue >> 2) & 0x1f; - } + u8 queue = txq->swq_id; + u8 ac = queue & 3; + u8 hwq = (queue >> 2) & 0x1f; if (test_and_clear_bit(hwq, priv->queue_stopped)) if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0) ieee80211_wake_queue(priv->hw, ac); } -static inline void iwl_stop_queue(struct iwl_priv *priv, u8 queue) +static inline void iwl_stop_queue(struct iwl_priv *priv, + struct iwl_tx_queue *txq) { - u8 ac = queue; - u8 hwq = queue; - - if (queue & 0x80) { - ac = queue & 3; - hwq = (queue >> 2) & 0x1f; - } + u8 queue = txq->swq_id; + u8 ac = queue & 3; + u8 hwq = (queue >> 2) & 0x1f; if (!test_and_set_bit(hwq, priv->queue_stopped)) if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0) @@ -163,6 +148,12 @@ static inline void iwl_disable_interrupts(struct iwl_priv *priv) IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); } +static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) +{ + IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); + iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); +} + static inline void iwl_enable_interrupts(struct iwl_priv *priv) { IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 86c2b6fed0c6..46ccdf406e8e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -45,9 +45,8 @@ /* default: IWL_LED_BLINK(0) using blinking index table */ static int led_mode; module_param(led_mode, int, S_IRUGO); -MODULE_PARM_DESC(led_mode, "led mode: 0=blinking, 1=On(RF On)/Off(RF Off), " - "(default 0)"); - +MODULE_PARM_DESC(led_mode, "0=system default, " + "1=On(RF On)/Off(RF Off), 2=blinking"); static const struct { u16 tpt; /* Mb/s */ @@ -128,12 +127,13 @@ EXPORT_SYMBOL(iwl_led_start); int iwl_led_associate(struct iwl_priv *priv) { IWL_DEBUG_LED(priv, "Associated\n"); - if (led_mode == IWL_LED_BLINK) + if (priv->cfg->led_mode == IWL_LED_BLINK) priv->allow_blinking = 1; priv->last_blink_time = jiffies; return 0; } +EXPORT_SYMBOL(iwl_led_associate); int iwl_led_disassociate(struct iwl_priv *priv) { @@ -141,6 +141,7 @@ int iwl_led_disassociate(struct iwl_priv *priv) return 0; } +EXPORT_SYMBOL(iwl_led_disassociate); /* * calculate blink rate according to last second Tx/Rx activities @@ -221,5 +222,8 @@ void iwl_leds_init(struct iwl_priv *priv) priv->last_blink_rate = 0; priv->last_blink_time = 0; priv->allow_blinking = 0; + if (led_mode != IWL_LED_DEFAULT && + led_mode != priv->cfg->led_mode) + priv->cfg->led_mode = led_mode; } EXPORT_SYMBOL(iwl_leds_init); diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 49a70baa3fb6..9079b33486ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -47,14 +47,16 @@ enum led_type { /* * LED mode - * IWL_LED_BLINK: adjust led blink rate based on blink table + * IWL_LED_DEFAULT: use system default * IWL_LED_RF_STATE: turn LED on/off based on RF state * LED ON = RF ON * LED OFF = RF OFF + * IWL_LED_BLINK: adjust led blink rate based on blink table */ enum iwl_led_mode { - IWL_LED_BLINK, + IWL_LED_DEFAULT, IWL_LED_RF_STATE, + IWL_LED_BLINK, }; void iwl_leds_init(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.c b/drivers/net/wireless/iwlwifi/iwl-legacy.c new file mode 100644 index 000000000000..a08b4e56e6b1 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-legacy.c @@ -0,0 +1,662 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless <ilw@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + +#include <linux/kernel.h> +#include <net/mac80211.h> + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-helpers.h" +#include "iwl-legacy.h" + +static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) +{ + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + if (!ctx->is_active) + return; + + ctx->qos_data.def_qos_parm.qos_flags = 0; + + if (ctx->qos_data.qos_active) + ctx->qos_data.def_qos_parm.qos_flags |= + QOS_PARAM_FLG_UPDATE_EDCA_MSK; + + if (ctx->ht.enabled) + ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; + + IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", + ctx->qos_data.qos_active, + ctx->qos_data.def_qos_parm.qos_flags); + + iwl_send_cmd_pdu_async(priv, ctx->qos_cmd, + sizeof(struct iwl_qosparam_cmd), + &ctx->qos_data.def_qos_parm, NULL); +} + +/** + * iwl_legacy_mac_config - mac80211 config callback + */ +int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed) +{ + struct iwl_priv *priv = hw->priv; + const struct iwl_channel_info *ch_info; + struct ieee80211_conf *conf = &hw->conf; + struct ieee80211_channel *channel = conf->channel; + struct iwl_ht_config *ht_conf = &priv->current_ht_config; + struct iwl_rxon_context *ctx; + unsigned long flags = 0; + int ret = 0; + u16 ch; + int scan_active = 0; + bool ht_changed[NUM_IWL_RXON_CTX] = {}; + + if (WARN_ON(!priv->cfg->ops->legacy)) + return -EOPNOTSUPP; + + mutex_lock(&priv->mutex); + + IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", + channel->hw_value, changed); + + if (unlikely(!priv->cfg->mod_params->disable_hw_scan && + test_bit(STATUS_SCANNING, &priv->status))) { + scan_active = 1; + IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); + } + + if (changed & (IEEE80211_CONF_CHANGE_SMPS | + IEEE80211_CONF_CHANGE_CHANNEL)) { + /* mac80211 uses static for non-HT which is what we want */ + priv->current_ht_config.smps = conf->smps_mode; + + /* + * Recalculate chain counts. + * + * If monitor mode is enabled then mac80211 will + * set up the SM PS mode to OFF if an HT channel is + * configured. + */ + if (priv->cfg->ops->hcmd->set_rxon_chain) + for_each_context(priv, ctx) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + } + + /* during scanning mac80211 will delay channel setting until + * scan finish with changed = 0 + */ + if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { + if (scan_active) + goto set_ch_out; + + ch = channel->hw_value; + ch_info = iwl_get_channel_info(priv, channel->band, ch); + if (!is_channel_valid(ch_info)) { + IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); + ret = -EINVAL; + goto set_ch_out; + } + + spin_lock_irqsave(&priv->lock, flags); + + for_each_context(priv, ctx) { + /* Configure HT40 channels */ + if (ctx->ht.enabled != conf_is_ht(conf)) { + ctx->ht.enabled = conf_is_ht(conf); + ht_changed[ctx->ctxid] = true; + } + if (ctx->ht.enabled) { + if (conf_is_ht40_minus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_BELOW; + ctx->ht.is_40mhz = true; + } else if (conf_is_ht40_plus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + ctx->ht.is_40mhz = true; + } else { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_NONE; + ctx->ht.is_40mhz = false; + } + } else + ctx->ht.is_40mhz = false; + + /* + * Default to no protection. Protection mode will + * later be set from BSS config in iwl_ht_conf + */ + ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; + + /* if we are switching from ht to 2.4 clear flags + * from any ht related info since 2.4 does not + * support ht */ + if ((le16_to_cpu(ctx->staging.channel) != ch)) + ctx->staging.flags = 0; + + iwl_set_rxon_channel(priv, channel, ctx); + iwl_set_rxon_ht(priv, ht_conf); + + iwl_set_flags_for_band(priv, ctx, channel->band, + ctx->vif); + } + + spin_unlock_irqrestore(&priv->lock, flags); + + if (priv->cfg->ops->legacy->update_bcast_stations) + ret = priv->cfg->ops->legacy->update_bcast_stations(priv); + + set_ch_out: + /* The list of supported rates and rate mask can be different + * for each band; since the band may have changed, reset + * the rate mask to what mac80211 lists */ + iwl_set_rate(priv); + } + + if (changed & (IEEE80211_CONF_CHANGE_PS | + IEEE80211_CONF_CHANGE_IDLE)) { + ret = iwl_power_update_mode(priv, false); + if (ret) + IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n"); + } + + if (changed & IEEE80211_CONF_CHANGE_POWER) { + IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", + priv->tx_power_user_lmt, conf->power_level); + + iwl_set_tx_power(priv, conf->power_level, false); + } + + if (!iwl_is_ready(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); + goto out; + } + + if (scan_active) + goto out; + + for_each_context(priv, ctx) { + if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging))) + iwlcore_commit_rxon(priv, ctx); + else + IWL_DEBUG_INFO(priv, + "Not re-sending same RXON configuration.\n"); + if (ht_changed[ctx->ctxid]) + iwl_update_qos(priv, ctx); + } + +out: + IWL_DEBUG_MAC80211(priv, "leave\n"); + mutex_unlock(&priv->mutex); + return ret; +} +EXPORT_SYMBOL(iwl_legacy_mac_config); + +void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + /* IBSS can only be the IWL_RXON_CTX_BSS context */ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + + if (WARN_ON(!priv->cfg->ops->legacy)) + return; + + mutex_lock(&priv->mutex); + IWL_DEBUG_MAC80211(priv, "enter\n"); + + spin_lock_irqsave(&priv->lock, flags); + memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); + spin_unlock_irqrestore(&priv->lock, flags); + + spin_lock_irqsave(&priv->lock, flags); + + /* new association get rid of ibss beacon skb */ + if (priv->beacon_skb) + dev_kfree_skb(priv->beacon_skb); + + priv->beacon_skb = NULL; + + priv->timestamp = 0; + + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_scan_cancel_timeout(priv, 100); + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); + mutex_unlock(&priv->mutex); + return; + } + + /* we are restarting association process + * clear RXON_FILTER_ASSOC_MSK bit + */ + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); + + iwl_set_rate(priv); + + mutex_unlock(&priv->mutex); + + IWL_DEBUG_MAC80211(priv, "leave\n"); +} +EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf); + +static void iwl_ht_conf(struct iwl_priv *priv, + struct ieee80211_vif *vif) +{ + struct iwl_ht_config *ht_conf = &priv->current_ht_config; + struct ieee80211_sta *sta; + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + + IWL_DEBUG_ASSOC(priv, "enter:\n"); + + if (!ctx->ht.enabled) + return; + + ctx->ht.protection = + bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; + ctx->ht.non_gf_sta_present = + !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); + + ht_conf->single_chain_sufficient = false; + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + rcu_read_lock(); + sta = ieee80211_find_sta(vif, bss_conf->bssid); + if (sta) { + struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; + int maxstreams; + + maxstreams = (ht_cap->mcs.tx_params & + IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) + >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; + maxstreams += 1; + + if ((ht_cap->mcs.rx_mask[1] == 0) && + (ht_cap->mcs.rx_mask[2] == 0)) + ht_conf->single_chain_sufficient = true; + if (maxstreams <= 1) + ht_conf->single_chain_sufficient = true; + } else { + /* + * If at all, this can only happen through a race + * when the AP disconnects us while we're still + * setting up the connection, in that case mac80211 + * will soon tell us about that. + */ + ht_conf->single_chain_sufficient = true; + } + rcu_read_unlock(); + break; + case NL80211_IFTYPE_ADHOC: + ht_conf->single_chain_sufficient = true; + break; + default: + break; + } + + IWL_DEBUG_ASSOC(priv, "leave\n"); +} + +static inline void iwl_set_no_assoc(struct iwl_priv *priv, + struct ieee80211_vif *vif) +{ + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + + iwl_led_disassociate(priv); + /* + * inform the ucode that there is no longer an + * association and that no more packets should be + * sent + */ + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + ctx->staging.assoc_id = 0; + iwlcore_commit_rxon(priv, ctx); +} + +static void iwlcore_beacon_update(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + __le64 timestamp; + struct sk_buff *skb = ieee80211_beacon_get(hw, vif); + + if (!skb) + return; + + IWL_DEBUG_MAC80211(priv, "enter\n"); + + lockdep_assert_held(&priv->mutex); + + if (!priv->beacon_ctx) { + IWL_ERR(priv, "update beacon but no beacon context!\n"); + dev_kfree_skb(skb); + return; + } + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->beacon_skb) + dev_kfree_skb(priv->beacon_skb); + + priv->beacon_skb = skb; + + timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; + priv->timestamp = le64_to_cpu(timestamp); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + spin_unlock_irqrestore(&priv->lock, flags); + + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); + return; + } + + priv->cfg->ops->legacy->post_associate(priv); +} + +void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + int ret; + + if (WARN_ON(!priv->cfg->ops->legacy)) + return; + + IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); + + if (!iwl_is_alive(priv)) + return; + + mutex_lock(&priv->mutex); + + if (changes & BSS_CHANGED_QOS) { + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + ctx->qos_data.qos_active = bss_conf->qos; + iwl_update_qos(priv, ctx); + spin_unlock_irqrestore(&priv->lock, flags); + } + + if (changes & BSS_CHANGED_BEACON_ENABLED) { + /* + * the add_interface code must make sure we only ever + * have a single interface that could be beaconing at + * any time. + */ + if (vif->bss_conf.enable_beacon) + priv->beacon_ctx = ctx; + else + priv->beacon_ctx = NULL; + } + + if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) { + dev_kfree_skb(priv->beacon_skb); + priv->beacon_skb = ieee80211_beacon_get(hw, vif); + } + + if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP) + iwl_send_rxon_timing(priv, ctx); + + if (changes & BSS_CHANGED_BSSID) { + IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid); + + /* + * If there is currently a HW scan going on in the + * background then we need to cancel it else the RXON + * below/in post_associate will fail. + */ + if (iwl_scan_cancel_timeout(priv, 100)) { + IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); + IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); + mutex_unlock(&priv->mutex); + return; + } + + /* mac80211 only sets assoc when in STATION mode */ + if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { + memcpy(ctx->staging.bssid_addr, + bss_conf->bssid, ETH_ALEN); + + /* currently needed in a few places */ + memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); + } else { + ctx->staging.filter_flags &= + ~RXON_FILTER_ASSOC_MSK; + } + + } + + /* + * This needs to be after setting the BSSID in case + * mac80211 decides to do both changes at once because + * it will invoke post_associate. + */ + if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON) + iwlcore_beacon_update(hw, vif); + + if (changes & BSS_CHANGED_ERP_PREAMBLE) { + IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", + bss_conf->use_short_preamble); + if (bss_conf->use_short_preamble) + ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + else + ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + } + + if (changes & BSS_CHANGED_ERP_CTS_PROT) { + IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); + if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) + ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; + else + ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + if (bss_conf->use_cts_prot) + ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; + else + ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; + } + + if (changes & BSS_CHANGED_BASIC_RATES) { + /* XXX use this information + * + * To do that, remove code from iwl_set_rate() and put something + * like this here: + * + if (A-band) + ctx->staging.ofdm_basic_rates = + bss_conf->basic_rates; + else + ctx->staging.ofdm_basic_rates = + bss_conf->basic_rates >> 4; + ctx->staging.cck_basic_rates = + bss_conf->basic_rates & 0xF; + */ + } + + if (changes & BSS_CHANGED_HT) { + iwl_ht_conf(priv, vif); + + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + } + + if (changes & BSS_CHANGED_ASSOC) { + IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); + if (bss_conf->assoc) { + priv->timestamp = bss_conf->timestamp; + + iwl_led_associate(priv); + + if (!iwl_is_rfkill(priv)) + priv->cfg->ops->legacy->post_associate(priv); + } else + iwl_set_no_assoc(priv, vif); + } + + if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) { + IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n", + changes); + ret = iwl_send_rxon_assoc(priv, ctx); + if (!ret) { + /* Sync active_rxon with latest change. */ + memcpy((void *)&ctx->active, + &ctx->staging, + sizeof(struct iwl_rxon_cmd)); + } + } + + if (changes & BSS_CHANGED_BEACON_ENABLED) { + if (vif->bss_conf.enable_beacon) { + memcpy(ctx->staging.bssid_addr, + bss_conf->bssid, ETH_ALEN); + memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); + iwl_led_associate(priv); + priv->cfg->ops->legacy->config_ap(priv); + } else + iwl_set_no_assoc(priv, vif); + } + + if (changes & BSS_CHANGED_IBSS) { + ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif, + bss_conf->ibss_joined); + if (ret) + IWL_ERR(priv, "failed to %s IBSS station %pM\n", + bss_conf->ibss_joined ? "add" : "remove", + bss_conf->bssid); + } + + mutex_unlock(&priv->mutex); + + IWL_DEBUG_MAC80211(priv, "leave\n"); +} +EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed); + +irqreturn_t iwl_isr_legacy(int irq, void *data) +{ + struct iwl_priv *priv = data; + u32 inta, inta_mask; + u32 inta_fh; + unsigned long flags; + if (!priv) + return IRQ_NONE; + + spin_lock_irqsave(&priv->lock, flags); + + /* Disable (but don't clear!) interrupts here to avoid + * back-to-back ISRs and sporadic interrupts from our NIC. + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. */ + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); + + /* Discover which interrupts are active/pending */ + inta = iwl_read32(priv, CSR_INT); + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); + + /* Ignore interrupt if there's nothing in NIC to service. + * This may be due to IRQ shared with another device, + * or due to sporadic interrupts thrown from our NIC. */ + if (!inta && !inta_fh) { + IWL_DEBUG_ISR(priv, + "Ignore interrupt, inta == 0, inta_fh == 0\n"); + goto none; + } + + if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { + /* Hardware disappeared. It might have already raised + * an interrupt */ + IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); + goto unplugged; + } + + IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", + inta, inta_mask, inta_fh); + + inta &= ~CSR_INT_BIT_SCD; + + /* iwl_irq_tasklet() will service interrupts and re-enable them */ + if (likely(inta || inta_fh)) + tasklet_schedule(&priv->irq_tasklet); + +unplugged: + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_HANDLED; + +none: + /* re-enable interrupts here since we don't have anything to service. */ + /* only Re-enable if diabled by irq */ + if (test_bit(STATUS_INT_ENABLED, &priv->status)) + iwl_enable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_NONE; +} +EXPORT_SYMBOL(iwl_isr_legacy); + +/* + * iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this + * function. + */ +void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv, + struct ieee80211_tx_info *info, + __le16 fc, __le32 *tx_flags) +{ + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { + *tx_flags |= TX_CMD_FLG_RTS_MSK; + *tx_flags &= ~TX_CMD_FLG_CTS_MSK; + *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; + + if (!ieee80211_is_mgmt(fc)) + return; + + switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { + case cpu_to_le16(IEEE80211_STYPE_AUTH): + case cpu_to_le16(IEEE80211_STYPE_DEAUTH): + case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): + case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): + *tx_flags &= ~TX_CMD_FLG_RTS_MSK; + *tx_flags |= TX_CMD_FLG_CTS_MSK; + break; + } + } else if (info->control.rates[0].flags & + IEEE80211_TX_RC_USE_CTS_PROTECT) { + *tx_flags &= ~TX_CMD_FLG_RTS_MSK; + *tx_flags |= TX_CMD_FLG_CTS_MSK; + *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; + } +} +EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection); diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.h b/drivers/net/wireless/iwlwifi/iwl-legacy.h new file mode 100644 index 000000000000..9f7b2f935964 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-legacy.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless <ilw@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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. + *****************************************************************************/ + +#ifndef __iwl_legacy_h__ +#define __iwl_legacy_h__ + +/* mac80211 handlers */ +int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed); +void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw); +void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes); +void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv, + struct ieee80211_tx_info *info, + __le16 fc, __le32 *tx_flags); + +irqreturn_t iwl_isr_legacy(int irq, void *data); + +#endif /* __iwl_legacy_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 49d7788937a9..1eec18d909d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -75,6 +75,10 @@ struct iwl_power_vec_entry { #define NOSLP cpu_to_le16(0), 0, 0 #define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 +#define ASLP (IWL_POWER_POWER_SAVE_ENA_MSK | \ + IWL_POWER_POWER_MANAGEMENT_ENA_MSK | \ + IWL_POWER_ADVANCE_PM_ENA_MSK) +#define ASLP_TOUT(T) cpu_to_le32(T) #define TU_TO_USEC 1024 #define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC) #define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \ @@ -114,6 +118,52 @@ static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = { {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} }; +/* advance power management */ +/* DTIM 0 - 2 */ +static const struct iwl_power_vec_entry apm_range_0[IWL_POWER_NUM] = { + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 6, 8, 0xFF), ASLP_TOUT(2)}, 2} +}; + + +/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */ +/* DTIM 3 - 10 */ +static const struct iwl_power_vec_entry apm_range_1[IWL_POWER_NUM] = { + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 6, 8, 0xFF), 0}, 2} +}; + +/* for DTIM period > IWL_DTIM_RANGE_1_MAX */ +/* DTIM 11 - */ +static const struct iwl_power_vec_entry apm_range_2[IWL_POWER_NUM] = { + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 6, 8, 0xFF), ASLP_TOUT(2)}, 2} +}; + static void iwl_static_sleep_cmd(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, enum iwl_power_level lvl, int period) @@ -124,11 +174,19 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, u8 skip; u32 slp_itrvl; - table = range_2; - if (period <= IWL_DTIM_RANGE_1_MAX) - table = range_1; - if (period <= IWL_DTIM_RANGE_0_MAX) - table = range_0; + if (priv->cfg->adv_pm) { + table = apm_range_2; + if (period <= IWL_DTIM_RANGE_1_MAX) + table = apm_range_1; + if (period <= IWL_DTIM_RANGE_0_MAX) + table = apm_range_0; + } else { + table = range_2; + if (period <= IWL_DTIM_RANGE_1_MAX) + table = range_1; + if (period <= IWL_DTIM_RANGE_0_MAX) + table = range_0; + } BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM); @@ -163,6 +221,20 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, else cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; + if (priv->cfg->base_params->shadow_reg_enable) + cmd->flags |= IWL_POWER_SHADOW_REG_ENA; + else + cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; + + if (priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist) { + if (!priv->cfg->bt_params->bt_sco_disable) + cmd->flags |= IWL_POWER_BT_SCO_ENA; + else + cmd->flags &= ~IWL_POWER_BT_SCO_ENA; + } + + slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]); if (slp_itrvl > IWL_CONN_MAX_LISTEN_INTERVAL) cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] = @@ -236,6 +308,19 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv, if (priv->power_data.pci_pm) cmd->flags |= IWL_POWER_PCI_PM_MSK; + if (priv->cfg->base_params->shadow_reg_enable) + cmd->flags |= IWL_POWER_SHADOW_REG_ENA; + else + cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; + + if (priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist) { + if (!priv->cfg->bt_params->bt_sco_disable) + cmd->flags |= IWL_POWER_BT_SCO_ENA; + else + cmd->flags &= ~IWL_POWER_BT_SCO_ENA; + } + cmd->rx_data_timeout = cpu_to_le32(1000 * dynps_ms); cmd->tx_data_timeout = cpu_to_le32(1000 * dynps_ms); @@ -263,70 +348,95 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) sizeof(struct iwl_powertable_cmd), cmd); } -/* priv->mutex must be held */ -int iwl_power_update_mode(struct iwl_priv *priv, bool force) +static void iwl_power_build_cmd(struct iwl_priv *priv, + struct iwl_powertable_cmd *cmd) { - int ret = 0; bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS; - bool update_chains; - struct iwl_powertable_cmd cmd; int dtimper; - /* Don't update the RX chain when chain noise calibration is running */ - update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || - priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; - dtimper = priv->hw->conf.ps_dtim_period ?: 1; if (priv->cfg->base_params->broken_powersave) - iwl_power_sleep_cam_cmd(priv, &cmd); + iwl_power_sleep_cam_cmd(priv, cmd); else if (priv->cfg->base_params->supports_idle && priv->hw->conf.flags & IEEE80211_CONF_IDLE) - iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); + iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && priv->cfg->ops->lib->tt_ops.tt_power_mode && priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) { /* in thermal throttling low power state */ - iwl_static_sleep_cmd(priv, &cmd, + iwl_static_sleep_cmd(priv, cmd, priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper); } else if (!enabled) - iwl_power_sleep_cam_cmd(priv, &cmd); + iwl_power_sleep_cam_cmd(priv, cmd); else if (priv->power_data.debug_sleep_level_override >= 0) - iwl_static_sleep_cmd(priv, &cmd, + iwl_static_sleep_cmd(priv, cmd, priv->power_data.debug_sleep_level_override, dtimper); else if (no_sleep_autoadjust) - iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_1, dtimper); + iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_1, dtimper); else - iwl_power_fill_sleep_cmd(priv, &cmd, + iwl_power_fill_sleep_cmd(priv, cmd, priv->hw->conf.dynamic_ps_timeout, priv->hw->conf.max_sleep_period); +} + +int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, + bool force) +{ + int ret; + bool update_chains; + + lockdep_assert_held(&priv->mutex); + + /* Don't update the RX chain when chain noise calibration is running */ + update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || + priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; + + if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force) + return 0; + + if (!iwl_is_ready_rf(priv)) + return -EIO; - if (iwl_is_ready_rf(priv) && - (memcmp(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)) || force)) { - if (cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) - set_bit(STATUS_POWER_PMI, &priv->status); - - ret = iwl_set_power(priv, &cmd); - if (!ret) { - if (!(cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) - clear_bit(STATUS_POWER_PMI, &priv->status); - - if (priv->cfg->ops->lib->update_chain_flags && - update_chains) - priv->cfg->ops->lib->update_chain_flags(priv); - else if (priv->cfg->ops->lib->update_chain_flags) - IWL_DEBUG_POWER(priv, + /* scan complete use sleep_power_next, need to be updated */ + memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd)); + if (test_bit(STATUS_SCANNING, &priv->status) && !force) { + IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n"); + return 0; + } + + if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) + set_bit(STATUS_POWER_PMI, &priv->status); + + ret = iwl_set_power(priv, cmd); + if (!ret) { + if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) + clear_bit(STATUS_POWER_PMI, &priv->status); + + if (priv->cfg->ops->lib->update_chain_flags && update_chains) + priv->cfg->ops->lib->update_chain_flags(priv); + else if (priv->cfg->ops->lib->update_chain_flags) + IWL_DEBUG_POWER(priv, "Cannot update the power, chain noise " "calibration running: %d\n", priv->chain_noise_data.state); - memcpy(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)); - } else - IWL_ERR(priv, "set power fail, ret = %d", ret); - } + + memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)); + } else + IWL_ERR(priv, "set power fail, ret = %d", ret); return ret; } +EXPORT_SYMBOL(iwl_power_set_mode); + +int iwl_power_update_mode(struct iwl_priv *priv, bool force) +{ + struct iwl_powertable_cmd cmd; + + iwl_power_build_cmd(priv, &cmd); + return iwl_power_set_mode(priv, &cmd, force); +} EXPORT_SYMBOL(iwl_power_update_mode); /* initialize to default */ diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index df81565a7cc4..fe012032c28c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -41,10 +41,13 @@ enum iwl_power_level { struct iwl_power_mgr { struct iwl_powertable_cmd sleep_cmd; + struct iwl_powertable_cmd sleep_cmd_next; int debug_sleep_level_override; bool pci_pm; }; +int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, + bool force); int iwl_power_update_mode(struct iwl_priv *priv, bool force); void iwl_power_initialize(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 5469655646ae..86f5123bccda 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -83,10 +83,10 @@ #define APMG_DIGITAL_SVR_REG (APMG_BASE + 0x0058) #define APMG_ANALOG_SVR_REG (APMG_BASE + 0x006C) +#define APMS_CLK_VAL_MRB_FUNC_MODE (0x00000001) #define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200) #define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800) - #define APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS (0x00400000) #define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000) #define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000) diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index f436270ca39a..87a6fd84d4d2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -134,28 +134,37 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q if (q->need_update == 0) goto exit_unlock; - /* If power-saving is in use, make sure device is awake */ - if (test_bit(STATUS_POWER_PMI, &priv->status)) { - reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); + if (priv->cfg->base_params->shadow_reg_enable) { + /* shadow register enabled */ + /* Device expects a multiple of 8 */ + q->write_actual = (q->write & ~0x7); + iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual); + } else { + /* If power-saving is in use, make sure device is awake */ + if (test_bit(STATUS_POWER_PMI, &priv->status)) { + reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); - if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO(priv, "Rx queue requesting wakeup, GP1 = 0x%x\n", - reg); - iwl_set_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - goto exit_unlock; - } + if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { + IWL_DEBUG_INFO(priv, + "Rx queue requesting wakeup," + " GP1 = 0x%x\n", reg); + iwl_set_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + goto exit_unlock; + } - q->write_actual = (q->write & ~0x7); - iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual); + q->write_actual = (q->write & ~0x7); + iwl_write_direct32(priv, rx_wrt_ptr_reg, + q->write_actual); - /* Else device is assumed to be awake */ - } else { - /* Device expects a multiple of 8 */ - q->write_actual = (q->write & ~0x7); - iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual); + /* Else device is assumed to be awake */ + } else { + /* Device expects a multiple of 8 */ + q->write_actual = (q->write & ~0x7); + iwl_write_direct32(priv, rx_wrt_ptr_reg, + q->write_actual); + } } - q->need_update = 0; exit_unlock: diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 67da31295781..12d9363d0afe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -252,8 +252,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n", (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", - jiffies_to_msecs(elapsed_jiffies - (priv->scan_start, jiffies))); + jiffies_to_msecs(jiffies - priv->scan_start)); queue_work(priv->workqueue, &priv->scan_completed); @@ -603,13 +602,16 @@ out_settings: if (!iwl_is_ready_rf(priv)) goto out; - /* Since setting the TXPOWER may have been deferred while - * performing the scan, fire one off */ - iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); + /* + * We do not commit power settings while scan is pending, + * do it now if the settings changed. + */ + iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false); + iwl_set_tx_power(priv, priv->tx_power_next, false); priv->cfg->ops->utils->post_scan(priv); - out: +out: mutex_unlock(&priv->mutex); } diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 7c7f7dcb1b1e..4776323b1eba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -400,7 +400,8 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) } static int iwl_send_remove_station(struct iwl_priv *priv, - const u8 *addr, int sta_id) + const u8 *addr, int sta_id, + bool temporary) { struct iwl_rx_packet *pkt; int ret; @@ -436,9 +437,11 @@ static int iwl_send_remove_station(struct iwl_priv *priv, if (!ret) { switch (pkt->u.rem_sta.status) { case REM_STA_SUCCESS_MSK: - spin_lock_irqsave(&priv->sta_lock, flags_spin); - iwl_sta_ucode_deactivate(priv, sta_id); - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + if (!temporary) { + spin_lock_irqsave(&priv->sta_lock, flags_spin); + iwl_sta_ucode_deactivate(priv, sta_id); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + } IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); break; default: @@ -505,7 +508,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, spin_unlock_irqrestore(&priv->sta_lock, flags); - return iwl_send_remove_station(priv, addr, sta_id); + return iwl_send_remove_station(priv, addr, sta_id, false); out_err: spin_unlock_irqrestore(&priv->sta_lock, flags); return -EINVAL; @@ -624,6 +627,49 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } EXPORT_SYMBOL(iwl_restore_stations); +void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) +{ + unsigned long flags; + int sta_id = ctx->ap_sta_id; + int ret; + struct iwl_addsta_cmd sta_cmd; + struct iwl_link_quality_cmd lq; + bool active; + + spin_lock_irqsave(&priv->sta_lock, flags); + if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { + spin_unlock_irqrestore(&priv->sta_lock, flags); + return; + } + + memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); + sta_cmd.mode = 0; + memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq)); + + active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE; + priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + if (active) { + ret = iwl_send_remove_station( + priv, priv->stations[sta_id].sta.sta.addr, + sta_id, true); + if (ret) + IWL_ERR(priv, "failed to remove STA %pM (%d)\n", + priv->stations[sta_id].sta.sta.addr, ret); + } + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); + if (ret) + IWL_ERR(priv, "failed to re-add STA %pM (%d)\n", + priv->stations[sta_id].sta.sta.addr, ret); + iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); +} +EXPORT_SYMBOL(iwl_reprogram_ap_sta); + int iwl_get_free_ucode_key_index(struct iwl_priv *priv) { int i; @@ -736,6 +782,14 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, if (WARN_ON(lq->sta_id == IWL_INVALID_STATION)) return -EINVAL; + + spin_lock_irqsave(&priv->sta_lock, flags_spin); + if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) { + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + return -EINVAL; + } + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + iwl_dump_lq_cmd(priv, lq); BUG_ON(init && (cmd.flags & CMD_ASYNC)); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 06475872eee4..206f1e1a0caf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -63,6 +63,7 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_link_quality_cmd *lq, u8 flags, bool init); +void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx); /** * iwl_clear_driver_stations - clear knowledge of all stations from driver diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7261ee49f282..073b6ce6141c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -49,30 +49,39 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) if (txq->need_update == 0) return; - /* if we're trying to save power */ - if (test_bit(STATUS_POWER_PMI, &priv->status)) { - /* wake up nic if it's powered down ... - * uCode will wake up, and interrupt us again, so next - * time we'll skip this part. */ - reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); - - if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup, GP1 = 0x%x\n", - txq_id, reg); - iwl_set_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - return; - } - - iwl_write_direct32(priv, HBUS_TARG_WRPTR, - txq->q.write_ptr | (txq_id << 8)); - - /* else not in power-save mode, uCode will never sleep when we're - * trying to tx (during RFKILL, we're not trying to tx). */ - } else + if (priv->cfg->base_params->shadow_reg_enable) { + /* shadow register enabled */ iwl_write32(priv, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); + } else { + /* if we're trying to save power */ + if (test_bit(STATUS_POWER_PMI, &priv->status)) { + /* wake up nic if it's powered down ... + * uCode will wake up, and interrupt us again, so next + * time we'll skip this part. */ + reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); + + if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { + IWL_DEBUG_INFO(priv, + "Tx queue %d requesting wakeup," + " GP1 = 0x%x\n", txq_id, reg); + iwl_set_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + return; + } + + iwl_write_direct32(priv, HBUS_TARG_WRPTR, + txq->q.write_ptr | (txq_id << 8)); + /* + * else not in power-save mode, + * uCode will never sleep when we're + * trying to tx (during RFKILL, we're not trying to tx). + */ + } else + iwl_write32(priv, HBUS_TARG_WRPTR, + txq->q.write_ptr | (txq_id << 8)); + } txq->need_update = 0; } EXPORT_SYMBOL(iwl_txq_update_write_ptr); @@ -254,8 +263,6 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, q->high_mark = 2; q->write_ptr = q->read_ptr = 0; - q->last_read_ptr = 0; - q->repeat_same_read_ptr = 0; return 0; } @@ -350,13 +357,12 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, txq->need_update = 0; /* - * Aggregation TX queues will get their ID when aggregation begins; - * they overwrite the setting done here. The command FIFO doesn't - * need an swq_id so don't set one to catch errors, all others can - * be set up to the identity mapping. + * For the default queues 0-3, set up the swq_id + * already -- all others need to get one later + * (if they need one at all). */ - if (txq_id != priv->cmd_queue) - txq->swq_id = txq_id; + if (txq_id < 4) + iwl_set_swq_id(txq, txq_id, txq_id); /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 7edf8c2fb8c7..371abbf60eac 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -61,6 +61,7 @@ #include "iwl-helpers.h" #include "iwl-dev.h" #include "iwl-spectrum.h" +#include "iwl-legacy.h" /* * module name, copyright, version, etc. @@ -474,7 +475,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) dma_addr_t phys_addr; dma_addr_t txcmd_phys; int txq_id = skb_get_queue_mapping(skb); - u16 len, idx, len_org, hdr_len; /* TODO: len_org is not used */ + u16 len, idx, hdr_len; u8 id; u8 unicast; u8 sta_id; @@ -611,15 +612,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) */ len = sizeof(struct iwl3945_tx_cmd) + sizeof(struct iwl_cmd_header) + hdr_len; - - len_org = len; len = (len + 3) & ~3; - if (len_org != len) - len_org = 1; - else - len_org = 0; - /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr, @@ -661,7 +655,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_unlock_irqrestore(&priv->lock, flags); } - iwl_stop_queue(priv, skb_get_queue_mapping(skb)); + iwl_stop_queue(priv, txq); } return 0; @@ -2515,13 +2509,8 @@ static void iwl3945_alive_start(struct iwl_priv *priv) /* After the ALIVE response, we can send commands to 3945 uCode */ set_bit(STATUS_ALIVE, &priv->status); - if (priv->cfg->ops->lib->recover_from_tx_stall) { - /* Enable timer to monitor the driver queues */ - mod_timer(&priv->monitor_recover, - jiffies + - msecs_to_jiffies( - priv->cfg->base_params->monitor_recover_period)); - } + /* Enable watchdog to monitor the driver tx queues */ + iwl_setup_watchdog(priv); if (iwl_is_rfkill(priv)) return; @@ -2578,8 +2567,7 @@ static void __iwl3945_down(struct iwl_priv *priv) /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set * to prevent rearm timer */ - if (priv->cfg->ops->lib->recover_from_tx_stall) - del_timer_sync(&priv->monitor_recover); + del_timer_sync(&priv->watchdog); /* Station information will now be cleared in device */ iwl_clear_ucode_stations(priv, NULL); @@ -3057,22 +3045,22 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data) mutex_unlock(&priv->mutex); } -void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) +void iwl3945_post_associate(struct iwl_priv *priv) { int rc = 0; struct ieee80211_conf *conf = NULL; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - if (!vif || !priv->is_open) + if (!ctx->vif || !priv->is_open) return; - if (vif->type == NL80211_IFTYPE_AP) { + if (ctx->vif->type == NL80211_IFTYPE_AP) { IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); return; } IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", - vif->bss_conf.aid, ctx->active.bssid_addr); + ctx->vif->bss_conf.aid, ctx->active.bssid_addr); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -3091,18 +3079,18 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; - ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); + ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid); IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", - vif->bss_conf.aid, vif->bss_conf.beacon_int); + ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int); - if (vif->bss_conf.use_short_preamble) + if (ctx->vif->bss_conf.use_short_preamble) ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { - if (vif->bss_conf.use_short_slot) + if (ctx->vif->bss_conf.use_short_slot) ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; else ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; @@ -3110,7 +3098,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) iwl3945_commit_rxon(priv, ctx); - switch (vif->type) { + switch (ctx->vif->type) { case NL80211_IFTYPE_STATION: iwl3945_rate_scale_init(priv->hw, IWL_AP_ID); break; @@ -3119,7 +3107,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) break; default: IWL_ERR(priv, "%s Should not be called in %d mode\n", - __func__, vif->type); + __func__, ctx->vif->type); break; } } @@ -3234,9 +3222,10 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) +void iwl3945_config_ap(struct iwl_priv *priv) { struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct ieee80211_vif *vif = ctx->vif; int rc = 0; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) @@ -3407,9 +3396,9 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw, ctx->staging.filter_flags |= filter_or; /* - * Committing directly here breaks for some reason, - * but we'll eventually commit the filter flags - * change anyway. + * Not committing directly because hardware can perform a scan, + * but even if hw is ready, committing here breaks for some reason, + * we'll eventually commit the filter flags change anyway. */ mutex_unlock(&priv->mutex); @@ -3780,12 +3769,9 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) iwl3945_hw_setup_deferred_work(priv); - if (priv->cfg->ops->lib->recover_from_tx_stall) { - init_timer(&priv->monitor_recover); - priv->monitor_recover.data = (unsigned long)priv; - priv->monitor_recover.function = - priv->cfg->ops->lib->recover_from_tx_stall; - } + init_timer(&priv->watchdog); + priv->watchdog.data = (unsigned long)priv; + priv->watchdog.function = iwl_bg_watchdog; tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) iwl3945_irq_tasklet, (unsigned long)priv); @@ -3824,18 +3810,19 @@ static struct attribute_group iwl3945_attribute_group = { .attrs = iwl3945_sysfs_entries, }; -static struct ieee80211_ops iwl3945_hw_ops = { +struct ieee80211_ops iwl3945_hw_ops = { .tx = iwl3945_mac_tx, .start = iwl3945_mac_start, .stop = iwl3945_mac_stop, .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, - .config = iwl_mac_config, + .change_interface = iwl_mac_change_interface, + .config = iwl_legacy_mac_config, .configure_filter = iwl3945_configure_filter, .set_key = iwl3945_mac_set_key, .conf_tx = iwl_mac_conf_tx, - .reset_tsf = iwl_mac_reset_tsf, - .bss_info_changed = iwl_bss_info_changed, + .reset_tsf = iwl_legacy_mac_reset_tsf, + .bss_info_changed = iwl_legacy_mac_bss_info_changed, .hw_scan = iwl_mac_hw_scan, .sta_add = iwl3945_mac_sta_add, .sta_remove = iwl_mac_sta_remove, @@ -3865,7 +3852,15 @@ static int iwl3945_init_drv(struct iwl_priv *priv) priv->iw_mode = NL80211_IFTYPE_STATION; priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; + /* initialize force reset */ + priv->force_reset[IWL_RF_RESET].reset_duration = + IWL_DELAY_NEXT_FORCE_RF_RESET; + priv->force_reset[IWL_FW_RESET].reset_duration = + IWL_DELAY_NEXT_FORCE_FW_RELOAD; + + priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; + priv->tx_power_next = IWL_DEFAULT_TX_POWER; if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n", @@ -3965,7 +3960,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* mac80211 allocates memory for this device instance, including * space for this driver's private structure */ - hw = iwl_alloc_all(cfg, &iwl3945_hw_ops); + hw = iwl_alloc_all(cfg); if (hw == NULL) { pr_err("Can not allocate network device\n"); err = -ENOMEM; @@ -4117,7 +4112,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e pci_enable_msi(priv->pci_dev); - err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr, + err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr, IRQF_SHARED, DRV_NAME, priv); if (err) { IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); @@ -4275,10 +4270,7 @@ static struct pci_driver iwl3945_driver = { .id_table = iwl3945_hw_card_ids, .probe = iwl3945_pci_probe, .remove = __devexit_p(iwl3945_pci_remove), -#ifdef CONFIG_PM - .suspend = iwl_pci_suspend, - .resume = iwl_pci_resume, -#endif + .driver.pm = IWL_PM_OPS, }; static int __init iwl3945_init(void) diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index c6c0eff9b5ed..5a4982271e96 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -225,7 +225,8 @@ static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev, - u8 key_index) + u8 key_index, bool unicast, + bool multicast) { struct iwm_priv *iwm = ndev_to_iwm(ndev); diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 330c7d9cf101..50dee6a0a5ca 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -908,7 +908,7 @@ int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, return ret; } - iwm->scan_id = iwm->scan_id++ % IWM_SCAN_ID_MAX; + iwm->scan_id = (iwm->scan_id + 1) % IWM_SCAN_ID_MAX; return 0; } diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 113f4f204657..698a1f7694ed 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -9,8 +9,6 @@ #include <linux/sched.h> #include <linux/wait.h> #include <linux/slab.h> -#include <linux/sched.h> -#include <linux/wait.h> #include <linux/ieee80211.h> #include <net/cfg80211.h> #include <asm/unaligned.h> @@ -1424,7 +1422,8 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev, static int lbs_cfg_set_default_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index) + u8 key_index, bool unicast, + bool multicast) { struct lbs_private *priv = wiphy_priv(wiphy); @@ -2062,7 +2061,7 @@ static void lbs_cfg_set_regulatory_hint(struct lbs_private *priv) }; /* Section 5.17.2 */ - static struct region_code_mapping regmap[] = { + static const struct region_code_mapping regmap[] = { {"US ", 0x10}, /* US FCC */ {"CA ", 0x20}, /* Canada */ {"EU ", 0x30}, /* ETSI */ diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 70745928f3f8..78c4da150a74 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -177,6 +177,14 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, struct cmd_ds_host_sleep cmd_config; int ret; + /* + * Certain firmware versions do not support EHS_REMOVE_WAKEUP command + * and the card will return a failure. Since we need to be + * able to reset the mask, in those cases we set a 0 mask instead. + */ + if (criteria == EHS_REMOVE_WAKEUP && !priv->ehs_remove_supported) + criteria = 0; + cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config)); cmd_config.criteria = cpu_to_le32(criteria); cmd_config.gpio = priv->wol_gpio; diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index cb14c38caf3a..18dd9a02c459 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -138,6 +138,7 @@ struct lbs_private { uint32_t wol_criteria; uint8_t wol_gpio; uint8_t wol_gap; + bool ehs_remove_supported; /* Transmitting */ int tx_pending_len; /* -1 while building packet */ diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index ecd4d04b2c3c..00600239a053 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -784,7 +784,7 @@ static int lbs_spi_thread(void *data) up(&card->spi_thread_terminated); do_exit(0); } - } while (err == EINTR); + } while (err == -EINTR); /* Read the host interrupt status register to see what we * can do. */ diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index efaf85032208..6524c70363d9 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -345,6 +345,13 @@ static int if_usb_probe(struct usb_interface *intf, if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2)) lbs_pr_err("cannot register lbs_flash_boot2 attribute\n"); + /* + * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. + */ + priv->wol_criteria = EHS_REMOVE_WAKEUP; + if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL)) + priv->ehs_remove_supported = false; + return 0; err_start_card: @@ -1090,12 +1097,6 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) if (priv->psstate != PS_STATE_FULL_POWER) return -1; - if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { - lbs_pr_info("Suspend attempt without " - "configuring wake params!\n"); - return -ENOSYS; - } - ret = lbs_suspend(priv); if (ret) goto out; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index fcd1bbfc632d..6836a6dd9853 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -851,9 +851,10 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) priv->work_thread = create_singlethread_workqueue("lbs_worker"); INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); - priv->wol_criteria = 0xffffffff; + priv->wol_criteria = EHS_REMOVE_WAKEUP; priv->wol_gpio = 0xff; priv->wol_gap = 20; + priv->ehs_remove_supported = true; goto done; diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index a4d0bca9ef2c..a2b1df21d286 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -55,7 +55,9 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) struct rxpd *p_rx_pd; int hdrchop; struct ethhdr *p_ethhdr; - const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; + static const u8 rfc1042_eth_hdr[] = { + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 + }; lbs_deb_enter(LBS_DEB_RX); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 7eaaa3bab547..454f045ddff3 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -309,6 +309,8 @@ struct mac80211_hwsim_data { */ u64 group; struct dentry *debugfs_group; + + int power_level; }; @@ -497,7 +499,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, rx_status.band = data->channel->band; rx_status.rate_idx = info->control.rates[0].idx; /* TODO: simulate real signal strength (and optional packet loss) */ - rx_status.signal = -50; + rx_status.signal = data->power_level - 50; if (data->ps != PS_DISABLED) hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); @@ -698,6 +700,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); data->channel = conf->channel; + data->power_level = conf->power_level; if (!data->started || !data->beacon_int) del_timer(&data->beacon_timer); else diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index f152a25be59f..9ecf8407cb1b 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -29,6 +29,12 @@ #define MWL8K_NAME KBUILD_MODNAME #define MWL8K_VERSION "0.12" +/* Module parameters */ +static unsigned ap_mode_default; +module_param(ap_mode_default, bool, 0); +MODULE_PARM_DESC(ap_mode_default, + "Set to 1 to make ap mode the default instead of sta mode"); + /* Register definitions */ #define MWL8K_HIU_GEN_PTR 0x00000c10 #define MWL8K_MODE_STA 0x0000005a @@ -92,8 +98,10 @@ struct rxd_ops { struct mwl8k_device_info { char *part_name; char *helper_image; - char *fw_image; + char *fw_image_sta; + char *fw_image_ap; struct rxd_ops *ap_rxd_ops; + u32 fw_api_ap; }; struct mwl8k_rx_queue { @@ -136,8 +144,8 @@ struct mwl8k_priv { void __iomem *regs; /* firmware */ - struct firmware *fw_helper; - struct firmware *fw_ucode; + const struct firmware *fw_helper; + const struct firmware *fw_ucode; /* hardware/firmware parameters */ bool ap_fw; @@ -210,6 +218,18 @@ struct mwl8k_priv { /* Most recently reported noise in dBm */ s8 noise; + + /* + * preserve the queue configurations so they can be restored if/when + * the firmware image is swapped. + */ + struct ieee80211_tx_queue_params wmm_params[MWL8K_TX_QUEUES]; + + /* async firmware loading state */ + unsigned fw_state; + char *fw_pref; + char *fw_alt; + struct completion firmware_loading_complete; }; /* Per interface specific private data */ @@ -285,8 +305,9 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { }; /* Set or get info from Firmware */ -#define MWL8K_CMD_SET 0x0001 #define MWL8K_CMD_GET 0x0000 +#define MWL8K_CMD_SET 0x0001 +#define MWL8K_CMD_SET_LIST 0x0002 /* Firmware command codes */ #define MWL8K_CMD_CODE_DNLD 0x0001 @@ -296,6 +317,7 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { #define MWL8K_CMD_GET_STAT 0x0014 #define MWL8K_CMD_RADIO_CONTROL 0x001c #define MWL8K_CMD_RF_TX_POWER 0x001e +#define MWL8K_CMD_TX_POWER 0x001f #define MWL8K_CMD_RF_ANTENNA 0x0020 #define MWL8K_CMD_SET_BEACON 0x0100 /* per-vif */ #define MWL8K_CMD_SET_PRE_SCAN 0x0107 @@ -333,6 +355,7 @@ static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) MWL8K_CMDNAME(GET_STAT); MWL8K_CMDNAME(RADIO_CONTROL); MWL8K_CMDNAME(RF_TX_POWER); + MWL8K_CMDNAME(TX_POWER); MWL8K_CMDNAME(RF_ANTENNA); MWL8K_CMDNAME(SET_BEACON); MWL8K_CMDNAME(SET_PRE_SCAN); @@ -372,7 +395,7 @@ static void mwl8k_hw_reset(struct mwl8k_priv *priv) } /* Release fw image */ -static void mwl8k_release_fw(struct firmware **fw) +static void mwl8k_release_fw(const struct firmware **fw) { if (*fw == NULL) return; @@ -386,37 +409,68 @@ static void mwl8k_release_firmware(struct mwl8k_priv *priv) mwl8k_release_fw(&priv->fw_helper); } +/* states for asynchronous f/w loading */ +static void mwl8k_fw_state_machine(const struct firmware *fw, void *context); +enum { + FW_STATE_INIT = 0, + FW_STATE_LOADING_PREF, + FW_STATE_LOADING_ALT, + FW_STATE_ERROR, +}; + /* Request fw image */ static int mwl8k_request_fw(struct mwl8k_priv *priv, - const char *fname, struct firmware **fw) + const char *fname, const struct firmware **fw, + bool nowait) { /* release current image */ if (*fw != NULL) mwl8k_release_fw(fw); - return request_firmware((const struct firmware **)fw, - fname, &priv->pdev->dev); + if (nowait) + return request_firmware_nowait(THIS_MODULE, 1, fname, + &priv->pdev->dev, GFP_KERNEL, + priv, mwl8k_fw_state_machine); + else + return request_firmware(fw, fname, &priv->pdev->dev); } -static int mwl8k_request_firmware(struct mwl8k_priv *priv) +static int mwl8k_request_firmware(struct mwl8k_priv *priv, char *fw_image, + bool nowait) { struct mwl8k_device_info *di = priv->device_info; int rc; if (di->helper_image != NULL) { - rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw_helper); - if (rc) { - printk(KERN_ERR "%s: Error requesting helper " - "firmware file %s\n", pci_name(priv->pdev), - di->helper_image); + if (nowait) + rc = mwl8k_request_fw(priv, di->helper_image, + &priv->fw_helper, true); + else + rc = mwl8k_request_fw(priv, di->helper_image, + &priv->fw_helper, false); + if (rc) + printk(KERN_ERR "%s: Error requesting helper fw %s\n", + pci_name(priv->pdev), di->helper_image); + + if (rc || nowait) return rc; - } } - rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw_ucode); + if (nowait) { + /* + * if we get here, no helper image is needed. Skip the + * FW_STATE_INIT state. + */ + priv->fw_state = FW_STATE_LOADING_PREF; + rc = mwl8k_request_fw(priv, fw_image, + &priv->fw_ucode, + true); + } else + rc = mwl8k_request_fw(priv, fw_image, + &priv->fw_ucode, false); if (rc) { printk(KERN_ERR "%s: Error requesting firmware file %s\n", - pci_name(priv->pdev), di->fw_image); + pci_name(priv->pdev), fw_image); mwl8k_release_fw(&priv->fw_helper); return rc; } @@ -577,12 +631,12 @@ static int mwl8k_feed_fw_image(struct mwl8k_priv *priv, static int mwl8k_load_firmware(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; - struct firmware *fw = priv->fw_ucode; + const struct firmware *fw = priv->fw_ucode; int rc; int loops; if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { - struct firmware *helper = priv->fw_helper; + const struct firmware *helper = priv->fw_helper; if (helper == NULL) { printk(KERN_ERR "%s: helper image needed but none " @@ -1811,6 +1865,7 @@ struct mwl8k_cmd_get_hw_spec_ap { __le32 wcbbase1; __le32 wcbbase2; __le32 wcbbase3; + __le32 fw_api_version; } __packed; static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) @@ -1818,6 +1873,7 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) struct mwl8k_priv *priv = hw->priv; struct mwl8k_cmd_get_hw_spec_ap *cmd; int rc; + u32 api_version; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) @@ -1834,6 +1890,16 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) if (!rc) { int off; + api_version = le32_to_cpu(cmd->fw_api_version); + if (priv->device_info->fw_api_ap != api_version) { + printk(KERN_ERR "%s: Unsupported fw API version for %s." + " Expected %d got %d.\n", MWL8K_NAME, + priv->device_info->part_name, + priv->device_info->fw_api_ap, + api_version); + rc = -EINVAL; + goto done; + } SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr); priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); priv->fw_rev = le32_to_cpu(cmd->fw_rev); @@ -1861,6 +1927,7 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) iowrite32(priv->txq[3].txd_dma, priv->sram + off); } +done: kfree(cmd); return rc; } @@ -2084,7 +2151,7 @@ mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) /* * CMD_RF_TX_POWER. */ -#define MWL8K_TX_POWER_LEVEL_TOTAL 8 +#define MWL8K_RF_TX_POWER_LEVEL_TOTAL 8 struct mwl8k_cmd_rf_tx_power { struct mwl8k_cmd_pkt header; @@ -2092,7 +2159,7 @@ struct mwl8k_cmd_rf_tx_power { __le16 support_level; __le16 current_level; __le16 reserved; - __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; + __le16 power_level_list[MWL8K_RF_TX_POWER_LEVEL_TOTAL]; } __packed; static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm) @@ -2116,6 +2183,65 @@ static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm) } /* + * CMD_TX_POWER. + */ +#define MWL8K_TX_POWER_LEVEL_TOTAL 12 + +struct mwl8k_cmd_tx_power { + struct mwl8k_cmd_pkt header; + __le16 action; + __le16 band; + __le16 channel; + __le16 bw; + __le16 sub_ch; + __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; +} __attribute__((packed)); + +static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw, + struct ieee80211_conf *conf, + unsigned short pwr) +{ + struct ieee80211_channel *channel = conf->channel; + struct mwl8k_cmd_tx_power *cmd; + int rc; + int i; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_TX_POWER); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le16(MWL8K_CMD_SET_LIST); + + if (channel->band == IEEE80211_BAND_2GHZ) + cmd->band = cpu_to_le16(0x1); + else if (channel->band == IEEE80211_BAND_5GHZ) + cmd->band = cpu_to_le16(0x4); + + cmd->channel = channel->hw_value; + + if (conf->channel_type == NL80211_CHAN_NO_HT || + conf->channel_type == NL80211_CHAN_HT20) { + cmd->bw = cpu_to_le16(0x2); + } else { + cmd->bw = cpu_to_le16(0x4); + if (conf->channel_type == NL80211_CHAN_HT40MINUS) + cmd->sub_ch = cpu_to_le16(0x3); + else if (conf->channel_type == NL80211_CHAN_HT40PLUS) + cmd->sub_ch = cpu_to_le16(0x1); + } + + for (i = 0; i < MWL8K_TX_POWER_LEVEL_TOTAL; i++) + cmd->power_level_list[i] = cpu_to_le16(pwr); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* * CMD_RF_ANTENNA. */ struct mwl8k_cmd_rf_antenna { @@ -3283,13 +3409,16 @@ static void mwl8k_stop(struct ieee80211_hw *hw) mwl8k_txq_reclaim(hw, i, INT_MAX, 1); } +static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image); + static int mwl8k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_vif *mwl8k_vif; u32 macids_supported; - int macid; + int macid, rc; + struct mwl8k_device_info *di; /* * Reject interface creation if sniffer mode is active, as @@ -3302,12 +3431,28 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, return -EINVAL; } - + di = priv->device_info; switch (vif->type) { case NL80211_IFTYPE_AP: + if (!priv->ap_fw && di->fw_image_ap) { + /* we must load the ap fw to meet this request */ + if (!list_empty(&priv->vif_list)) + return -EBUSY; + rc = mwl8k_reload_firmware(hw, di->fw_image_ap); + if (rc) + return rc; + } macids_supported = priv->ap_macids_supported; break; case NL80211_IFTYPE_STATION: + if (priv->ap_fw && di->fw_image_sta) { + /* we must load the sta fw to meet this request */ + if (!list_empty(&priv->vif_list)) + return -EBUSY; + rc = mwl8k_reload_firmware(hw, di->fw_image_sta); + if (rc) + return rc; + } macids_supported = priv->sta_macids_supported; break; default: @@ -3377,15 +3522,19 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) if (conf->power_level > 18) conf->power_level = 18; - rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level); - if (rc) - goto out; if (priv->ap_fw) { + rc = mwl8k_cmd_tx_power(hw, conf, conf->power_level); + if (rc) + goto out; + rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x7); if (!rc) rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_TX, 0x7); } else { + rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level); + if (rc) + goto out; rc = mwl8k_cmd_mimo_config(hw, 0x7, 0x7); } @@ -3739,6 +3888,9 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, rc = mwl8k_fw_lock(hw); if (!rc) { + BUG_ON(queue > MWL8K_TX_QUEUES - 1); + memcpy(&priv->wmm_params[queue], params, sizeof(*params)); + if (!priv->wmm_enabled) rc = mwl8k_cmd_set_wmm_mode(hw, 1); @@ -3838,21 +3990,27 @@ enum { MWL8366, }; +#define MWL8K_8366_AP_FW_API 1 +#define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" +#define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) + static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { [MWL8363] = { .part_name = "88w8363", .helper_image = "mwl8k/helper_8363.fw", - .fw_image = "mwl8k/fmimage_8363.fw", + .fw_image_sta = "mwl8k/fmimage_8363.fw", }, [MWL8687] = { .part_name = "88w8687", .helper_image = "mwl8k/helper_8687.fw", - .fw_image = "mwl8k/fmimage_8687.fw", + .fw_image_sta = "mwl8k/fmimage_8687.fw", }, [MWL8366] = { .part_name = "88w8366", .helper_image = "mwl8k/helper_8366.fw", - .fw_image = "mwl8k/fmimage_8366.fw", + .fw_image_sta = "mwl8k/fmimage_8366.fw", + .fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API), + .fw_api_ap = MWL8K_8366_AP_FW_API, .ap_rxd_ops = &rxd_8366_ap_ops, }, }; @@ -3863,6 +4021,7 @@ MODULE_FIRMWARE("mwl8k/helper_8687.fw"); MODULE_FIRMWARE("mwl8k/fmimage_8687.fw"); MODULE_FIRMWARE("mwl8k/helper_8366.fw"); MODULE_FIRMWARE("mwl8k/fmimage_8366.fw"); +MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API)); static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, }, @@ -3876,94 +4035,133 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { }; MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); -static int __devinit mwl8k_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int mwl8k_request_alt_fw(struct mwl8k_priv *priv) { - static int printed_version = 0; - struct ieee80211_hw *hw; - struct mwl8k_priv *priv; int rc; - int i; - - if (!printed_version) { - printk(KERN_INFO "%s version %s\n", MWL8K_DESC, MWL8K_VERSION); - printed_version = 1; - } - - - rc = pci_enable_device(pdev); + printk(KERN_ERR "%s: Error requesting preferred fw %s.\n" + "Trying alternative firmware %s\n", pci_name(priv->pdev), + priv->fw_pref, priv->fw_alt); + rc = mwl8k_request_fw(priv, priv->fw_alt, &priv->fw_ucode, true); if (rc) { - printk(KERN_ERR "%s: Cannot enable new PCI device\n", - MWL8K_NAME); + printk(KERN_ERR "%s: Error requesting alt fw %s\n", + pci_name(priv->pdev), priv->fw_alt); return rc; } + return 0; +} - rc = pci_request_regions(pdev, MWL8K_NAME); - if (rc) { - printk(KERN_ERR "%s: Cannot obtain PCI resources\n", - MWL8K_NAME); - goto err_disable_device; - } - - pci_set_master(pdev); - - - hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); - if (hw == NULL) { - printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); - rc = -ENOMEM; - goto err_free_reg; - } +static int mwl8k_firmware_load_success(struct mwl8k_priv *priv); +static void mwl8k_fw_state_machine(const struct firmware *fw, void *context) +{ + struct mwl8k_priv *priv = context; + struct mwl8k_device_info *di = priv->device_info; + int rc; - SET_IEEE80211_DEV(hw, &pdev->dev); - pci_set_drvdata(pdev, hw); + switch (priv->fw_state) { + case FW_STATE_INIT: + if (!fw) { + printk(KERN_ERR "%s: Error requesting helper fw %s\n", + pci_name(priv->pdev), di->helper_image); + goto fail; + } + priv->fw_helper = fw; + rc = mwl8k_request_fw(priv, priv->fw_pref, &priv->fw_ucode, + true); + if (rc && priv->fw_alt) { + rc = mwl8k_request_alt_fw(priv); + if (rc) + goto fail; + priv->fw_state = FW_STATE_LOADING_ALT; + } else if (rc) + goto fail; + else + priv->fw_state = FW_STATE_LOADING_PREF; + break; - priv = hw->priv; - priv->hw = hw; - priv->pdev = pdev; - priv->device_info = &mwl8k_info_tbl[id->driver_data]; + case FW_STATE_LOADING_PREF: + if (!fw) { + if (priv->fw_alt) { + rc = mwl8k_request_alt_fw(priv); + if (rc) + goto fail; + priv->fw_state = FW_STATE_LOADING_ALT; + } else + goto fail; + } else { + priv->fw_ucode = fw; + rc = mwl8k_firmware_load_success(priv); + if (rc) + goto fail; + else + complete(&priv->firmware_loading_complete); + } + break; + case FW_STATE_LOADING_ALT: + if (!fw) { + printk(KERN_ERR "%s: Error requesting alt fw %s\n", + pci_name(priv->pdev), di->helper_image); + goto fail; + } + priv->fw_ucode = fw; + rc = mwl8k_firmware_load_success(priv); + if (rc) + goto fail; + else + complete(&priv->firmware_loading_complete); + break; - priv->sram = pci_iomap(pdev, 0, 0x10000); - if (priv->sram == NULL) { - wiphy_err(hw->wiphy, "Cannot map device SRAM\n"); - goto err_iounmap; + default: + printk(KERN_ERR "%s: Unexpected firmware loading state: %d\n", + MWL8K_NAME, priv->fw_state); + BUG_ON(1); } - /* - * If BAR0 is a 32 bit BAR, the register BAR will be BAR1. - * If BAR0 is a 64 bit BAR, the register BAR will be BAR2. - */ - priv->regs = pci_iomap(pdev, 1, 0x10000); - if (priv->regs == NULL) { - priv->regs = pci_iomap(pdev, 2, 0x10000); - if (priv->regs == NULL) { - wiphy_err(hw->wiphy, "Cannot map device registers\n"); - goto err_iounmap; - } - } + return; +fail: + priv->fw_state = FW_STATE_ERROR; + complete(&priv->firmware_loading_complete); + device_release_driver(&priv->pdev->dev); + mwl8k_release_firmware(priv); +} + +static int mwl8k_init_firmware(struct ieee80211_hw *hw, char *fw_image, + bool nowait) +{ + struct mwl8k_priv *priv = hw->priv; + int rc; /* Reset firmware and hardware */ mwl8k_hw_reset(priv); /* Ask userland hotplug daemon for the device firmware */ - rc = mwl8k_request_firmware(priv); + rc = mwl8k_request_firmware(priv, fw_image, nowait); if (rc) { wiphy_err(hw->wiphy, "Firmware files not found\n"); - goto err_stop_firmware; + return rc; } + if (nowait) + return rc; + /* Load firmware into hardware */ rc = mwl8k_load_firmware(hw); - if (rc) { + if (rc) wiphy_err(hw->wiphy, "Cannot start firmware\n"); - goto err_stop_firmware; - } /* Reclaim memory once firmware is successfully loaded */ mwl8k_release_firmware(priv); + return rc; +} + +/* initialize hw after successfully loading a firmware image */ +static int mwl8k_probe_hw(struct ieee80211_hw *hw) +{ + struct mwl8k_priv *priv = hw->priv; + int rc = 0; + int i; if (priv->ap_fw) { priv->rxd_ops = priv->device_info->ap_rxd_ops; @@ -3980,58 +4178,11 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv->wmm_enabled = false; priv->pending_tx_pkts = 0; - - /* - * Extra headroom is the size of the required DMA header - * minus the size of the smallest 802.11 frame (CTS frame). - */ - hw->extra_tx_headroom = - sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts); - - hw->channel_change_time = 10; - - hw->queues = MWL8K_TX_QUEUES; - - /* Set rssi values to dBm */ - hw->flags |= IEEE80211_HW_SIGNAL_DBM; - hw->vif_data_size = sizeof(struct mwl8k_vif); - hw->sta_data_size = sizeof(struct mwl8k_sta); - - priv->macids_used = 0; - INIT_LIST_HEAD(&priv->vif_list); - - /* Set default radio state and preamble */ - priv->radio_on = 0; - priv->radio_short_preamble = 0; - - /* Finalize join worker */ - INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); - - /* TX reclaim and RX tasklets. */ - tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); - tasklet_disable(&priv->poll_tx_task); - tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw); - tasklet_disable(&priv->poll_rx_task); - - /* Power management cookie */ - priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); - if (priv->cookie == NULL) - goto err_stop_firmware; - rc = mwl8k_rxq_init(hw, 0); if (rc) - goto err_free_cookie; + goto err_stop_firmware; rxq_refill(hw, 0, INT_MAX); - mutex_init(&priv->fw_mutex); - priv->fw_mutex_owner = NULL; - priv->fw_mutex_depth = 0; - priv->hostcmd_wait = NULL; - - spin_lock_init(&priv->tx_lock); - - priv->tx_wait = NULL; - for (i = 0; i < MWL8K_TX_QUEUES; i++) { rc = mwl8k_txq_init(hw, i); if (rc) @@ -4071,13 +4222,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, goto err_free_irq; } - hw->wiphy->interface_modes = 0; - if (priv->ap_macids_supported) - hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); - if (priv->sta_macids_supported) - hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION); - - /* Turn radio off */ rc = mwl8k_cmd_radio_disable(hw); if (rc) { @@ -4096,12 +4240,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); free_irq(priv->pdev->irq, hw); - rc = ieee80211_register_hw(hw); - if (rc) { - wiphy_err(hw->wiphy, "Cannot register device\n"); - goto err_free_queues; - } - wiphy_info(hw->wiphy, "%s v%d, %pm, %s firmware %u.%u.%u.%u\n", priv->device_info->part_name, priv->hw_rev, hw->wiphy->perm_addr, @@ -4120,14 +4258,238 @@ err_free_queues: mwl8k_txq_deinit(hw, i); mwl8k_rxq_deinit(hw, 0); +err_stop_firmware: + mwl8k_hw_reset(priv); + + return rc; +} + +/* + * invoke mwl8k_reload_firmware to change the firmware image after the device + * has already been registered + */ +static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image) +{ + int i, rc = 0; + struct mwl8k_priv *priv = hw->priv; + + mwl8k_stop(hw); + mwl8k_rxq_deinit(hw, 0); + + for (i = 0; i < MWL8K_TX_QUEUES; i++) + mwl8k_txq_deinit(hw, i); + + rc = mwl8k_init_firmware(hw, fw_image, false); + if (rc) + goto fail; + + rc = mwl8k_probe_hw(hw); + if (rc) + goto fail; + + rc = mwl8k_start(hw); + if (rc) + goto fail; + + rc = mwl8k_config(hw, ~0); + if (rc) + goto fail; + + for (i = 0; i < MWL8K_TX_QUEUES; i++) { + rc = mwl8k_conf_tx(hw, i, &priv->wmm_params[i]); + if (rc) + goto fail; + } + + return rc; + +fail: + printk(KERN_WARNING "mwl8k: Failed to reload firmware image.\n"); + return rc; +} + +static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) +{ + struct ieee80211_hw *hw = priv->hw; + int i, rc; + + rc = mwl8k_load_firmware(hw); + mwl8k_release_firmware(priv); + if (rc) { + wiphy_err(hw->wiphy, "Cannot start firmware\n"); + return rc; + } + + /* + * Extra headroom is the size of the required DMA header + * minus the size of the smallest 802.11 frame (CTS frame). + */ + hw->extra_tx_headroom = + sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts); + + hw->channel_change_time = 10; + + hw->queues = MWL8K_TX_QUEUES; + + /* Set rssi values to dBm */ + hw->flags |= IEEE80211_HW_SIGNAL_DBM; + hw->vif_data_size = sizeof(struct mwl8k_vif); + hw->sta_data_size = sizeof(struct mwl8k_sta); + + priv->macids_used = 0; + INIT_LIST_HEAD(&priv->vif_list); + + /* Set default radio state and preamble */ + priv->radio_on = 0; + priv->radio_short_preamble = 0; + + /* Finalize join worker */ + INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); + + /* TX reclaim and RX tasklets. */ + tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); + tasklet_disable(&priv->poll_tx_task); + tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw); + tasklet_disable(&priv->poll_rx_task); + + /* Power management cookie */ + priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); + if (priv->cookie == NULL) + return -ENOMEM; + + mutex_init(&priv->fw_mutex); + priv->fw_mutex_owner = NULL; + priv->fw_mutex_depth = 0; + priv->hostcmd_wait = NULL; + + spin_lock_init(&priv->tx_lock); + + priv->tx_wait = NULL; + + rc = mwl8k_probe_hw(hw); + if (rc) + goto err_free_cookie; + + hw->wiphy->interface_modes = 0; + if (priv->ap_macids_supported || priv->device_info->fw_image_ap) + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); + if (priv->sta_macids_supported || priv->device_info->fw_image_sta) + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION); + + rc = ieee80211_register_hw(hw); + if (rc) { + wiphy_err(hw->wiphy, "Cannot register device\n"); + goto err_unprobe_hw; + } + + return 0; + +err_unprobe_hw: + for (i = 0; i < MWL8K_TX_QUEUES; i++) + mwl8k_txq_deinit(hw, i); + mwl8k_rxq_deinit(hw, 0); + err_free_cookie: if (priv->cookie != NULL) pci_free_consistent(priv->pdev, 4, priv->cookie, priv->cookie_dma); + return rc; +} +static int __devinit mwl8k_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + static int printed_version; + struct ieee80211_hw *hw; + struct mwl8k_priv *priv; + struct mwl8k_device_info *di; + int rc; + + if (!printed_version) { + printk(KERN_INFO "%s version %s\n", MWL8K_DESC, MWL8K_VERSION); + printed_version = 1; + } + + + rc = pci_enable_device(pdev); + if (rc) { + printk(KERN_ERR "%s: Cannot enable new PCI device\n", + MWL8K_NAME); + return rc; + } + + rc = pci_request_regions(pdev, MWL8K_NAME); + if (rc) { + printk(KERN_ERR "%s: Cannot obtain PCI resources\n", + MWL8K_NAME); + goto err_disable_device; + } + + pci_set_master(pdev); + + + hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); + if (hw == NULL) { + printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); + rc = -ENOMEM; + goto err_free_reg; + } + + SET_IEEE80211_DEV(hw, &pdev->dev); + pci_set_drvdata(pdev, hw); + + priv = hw->priv; + priv->hw = hw; + priv->pdev = pdev; + priv->device_info = &mwl8k_info_tbl[id->driver_data]; + + + priv->sram = pci_iomap(pdev, 0, 0x10000); + if (priv->sram == NULL) { + wiphy_err(hw->wiphy, "Cannot map device SRAM\n"); + goto err_iounmap; + } + + /* + * If BAR0 is a 32 bit BAR, the register BAR will be BAR1. + * If BAR0 is a 64 bit BAR, the register BAR will be BAR2. + */ + priv->regs = pci_iomap(pdev, 1, 0x10000); + if (priv->regs == NULL) { + priv->regs = pci_iomap(pdev, 2, 0x10000); + if (priv->regs == NULL) { + wiphy_err(hw->wiphy, "Cannot map device registers\n"); + goto err_iounmap; + } + } + + /* + * Choose the initial fw image depending on user input. If a second + * image is available, make it the alternative image that will be + * loaded if the first one fails. + */ + init_completion(&priv->firmware_loading_complete); + di = priv->device_info; + if (ap_mode_default && di->fw_image_ap) { + priv->fw_pref = di->fw_image_ap; + priv->fw_alt = di->fw_image_sta; + } else if (!ap_mode_default && di->fw_image_sta) { + priv->fw_pref = di->fw_image_sta; + priv->fw_alt = di->fw_image_ap; + } else if (ap_mode_default && !di->fw_image_ap && di->fw_image_sta) { + printk(KERN_WARNING "AP fw is unavailable. Using STA fw."); + priv->fw_pref = di->fw_image_sta; + } else if (!ap_mode_default && !di->fw_image_sta && di->fw_image_ap) { + printk(KERN_WARNING "STA fw is unavailable. Using AP fw."); + priv->fw_pref = di->fw_image_ap; + } + rc = mwl8k_init_firmware(hw, priv->fw_pref, true); + if (rc) + goto err_stop_firmware; + return rc; + err_stop_firmware: mwl8k_hw_reset(priv); - mwl8k_release_firmware(priv); err_iounmap: if (priv->regs != NULL) @@ -4163,6 +4525,13 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) return; priv = hw->priv; + wait_for_completion(&priv->firmware_loading_complete); + + if (priv->fw_state == FW_STATE_ERROR) { + mwl8k_hw_reset(priv); + goto unmap; + } + ieee80211_stop_queues(hw); ieee80211_unregister_hw(hw); @@ -4185,6 +4554,7 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) pci_free_consistent(priv->pdev, 4, priv->cookie, priv->cookie_dma); +unmap: pci_iounmap(pdev, priv->regs); pci_iounmap(pdev, priv->sram); pci_set_drvdata(pdev, NULL); diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index e5afabee60d1..e793679e2e19 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@ -893,6 +893,14 @@ static int orinoco_ioctl_set_auth(struct net_device *dev, */ break; + case IW_AUTH_MFP: + /* Management Frame Protection not supported. + * Only fail if set to required. + */ + if (param->value == IW_AUTH_MFP_REQUIRED) + ret = -EINVAL; + break; + case IW_AUTH_KEY_MGMT: /* wl_lkm implies value 2 == PSK for Hermes I * which ties in with WEXT diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 2325e56a9b0b..21713a7638c4 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -189,7 +189,7 @@ static void p54u_rx_cb(struct urb *urb) static void p54u_tx_cb(struct urb *urb) { struct sk_buff *skb = urb->context; - struct ieee80211_hw *dev = (struct ieee80211_hw *) + struct ieee80211_hw *dev = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); p54_free_skb(dev, skb); diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 97007d9e2c1f..0764d1a30d13 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -1776,11 +1776,8 @@ static void ray_update_multi_list(struct net_device *dev, int all) /* Copy the kernel's list of MC addresses to card */ netdev_for_each_mc_addr(ha, dev) { memcpy_toio(p, ha->addr, ETH_ALEN); - dev_dbg(&link->dev, - "ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n", - ha->addr[0], ha->addr[1], - ha->addr[2], ha->addr[3], - ha->addr[4], ha->addr[5]); + dev_dbg(&link->dev, "ray_update_multi add addr %pm\n", + ha->addr); p += ETH_ALEN; i++; } @@ -2015,11 +2012,8 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id) memcpy_fromio(&local->bss_id, prcs->var.rejoin_net_complete. bssid, ADDRLEN); - dev_dbg(&link->dev, - "ray_cs new BSSID = %02x%02x%02x%02x%02x%02x\n", - local->bss_id[0], local->bss_id[1], - local->bss_id[2], local->bss_id[3], - local->bss_id[4], local->bss_id[5]); + dev_dbg(&link->dev, "ray_cs new BSSID = %pm\n", + local->bss_id); if (!sniffer) authenticate(local); } @@ -2286,8 +2280,8 @@ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len) struct ethhdr *peth; UCHAR srcaddr[ADDRLEN]; UCHAR destaddr[ADDRLEN]; - static UCHAR org_bridge[3] = { 0, 0, 0xf8 }; - static UCHAR org_1042[3] = { 0, 0, 0 }; + static const UCHAR org_bridge[3] = { 0, 0, 0xf8 }; + static const UCHAR org_1042[3] = { 0, 0, 0 }; memcpy(destaddr, ieee80211_get_DA(pmac), ADDRLEN); memcpy(srcaddr, ieee80211_get_SA(pmac), ADDRLEN); diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 71b5971da597..848cc2cce247 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -129,6 +129,7 @@ MODULE_PARM_DESC(workaround_interval, #define OID_802_11_RTS_THRESHOLD cpu_to_le32(0x0d01020a) #define OID_802_11_SUPPORTED_RATES cpu_to_le32(0x0d01020e) #define OID_802_11_CONFIGURATION cpu_to_le32(0x0d010211) +#define OID_802_11_POWER_MODE cpu_to_le32(0x0d010216) #define OID_802_11_BSSID_LIST cpu_to_le32(0x0d010217) @@ -156,6 +157,12 @@ MODULE_PARM_DESC(workaround_interval, #define RNDIS_STATUS_ADAPTER_NOT_OPEN cpu_to_le32(0xc0010012) +/* Known device types */ +#define RNDIS_UNKNOWN 0 +#define RNDIS_BCM4320A 1 +#define RNDIS_BCM4320B 2 + + /* NDIS data structures. Taken from wpa_supplicant driver_ndis.c * slightly modified for datatype endianess, etc */ @@ -233,6 +240,12 @@ enum ndis_80211_addwep_bits { NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31) }; +enum ndis_80211_power_mode { + NDIS_80211_POWER_MODE_CAM, + NDIS_80211_POWER_MODE_MAX_PSP, + NDIS_80211_POWER_MODE_FAST_PSP, +}; + struct ndis_80211_auth_request { __le32 length; u8 bssid[6]; @@ -472,12 +485,16 @@ struct rndis_wlan_private { struct mutex command_lock; unsigned long work_pending; int last_qual; + s32 cqm_rssi_thold; + u32 cqm_rssi_hyst; + int last_cqm_event_rssi; struct ieee80211_supported_band band; struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)]; struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)]; u32 cipher_suites[ARRAY_SIZE(rndis_cipher_suites)]; + int device_type; int caps; int multicast_size; @@ -493,10 +510,10 @@ struct rndis_wlan_private { /* hardware state */ bool radio_on; + int power_mode; int infra_mode; bool connected; u8 bssid[ETH_ALEN]; - struct ndis_80211_ssid essid; __le32 current_command_oid; /* encryption stuff */ @@ -547,7 +564,7 @@ static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool pairwise, const u8 *mac_addr); static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index); + u8 key_index, bool unicast, bool multicast); static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, u8 *mac, struct station_info *sinfo); @@ -563,7 +580,14 @@ static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev); -static struct cfg80211_ops rndis_config_ops = { +static int rndis_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, + bool enabled, int timeout); + +static int rndis_set_cqm_rssi_config(struct wiphy *wiphy, + struct net_device *dev, + s32 rssi_thold, u32 rssi_hyst); + +static const struct cfg80211_ops rndis_config_ops = { .change_virtual_intf = rndis_change_virtual_intf, .scan = rndis_scan, .set_wiphy_params = rndis_set_wiphy_params, @@ -582,6 +606,8 @@ static struct cfg80211_ops rndis_config_ops = { .set_pmksa = rndis_set_pmksa, .del_pmksa = rndis_del_pmksa, .flush_pmksa = rndis_flush_pmksa, + .set_power_mgmt = rndis_set_power_mgmt, + .set_cqm_rssi_config = rndis_set_cqm_rssi_config, }; static void *rndis_wiphy_privid = &rndis_wiphy_privid; @@ -680,6 +706,7 @@ static const char *oid_to_string(__le32 oid) OID_STR(OID_802_11_ADD_KEY); OID_STR(OID_802_11_REMOVE_KEY); OID_STR(OID_802_11_ASSOCIATION_INFORMATION); + OID_STR(OID_802_11_CAPABILITY); OID_STR(OID_802_11_PMKID); OID_STR(OID_802_11_NETWORK_TYPES_SUPPORTED); OID_STR(OID_802_11_NETWORK_TYPE_IN_USE); @@ -690,6 +717,7 @@ static const char *oid_to_string(__le32 oid) OID_STR(OID_802_11_RTS_THRESHOLD); OID_STR(OID_802_11_SUPPORTED_RATES); OID_STR(OID_802_11_CONFIGURATION); + OID_STR(OID_802_11_POWER_MODE); OID_STR(OID_802_11_BSSID_LIST); #undef OID_STR } @@ -810,7 +838,8 @@ exit_unlock: return ret; } -static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len) +static int rndis_set_oid(struct usbnet *dev, __le32 oid, const void *data, + int len) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev); union { @@ -994,7 +1023,18 @@ static int level_to_qual(int level) */ static int set_infra_mode(struct usbnet *usbdev, int mode); static void restore_keys(struct usbnet *usbdev); -static int rndis_check_bssid_list(struct usbnet *usbdev); +static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid, + bool *matched); + +static int rndis_start_bssid_list_scan(struct usbnet *usbdev) +{ + __le32 tmp; + + /* Note: OID_802_11_BSSID_LIST_SCAN clears internal BSS list. */ + tmp = cpu_to_le32(1); + return rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, + sizeof(tmp)); +} static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) { @@ -1007,7 +1047,6 @@ static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) return ret; } if (ret == 0) { - memcpy(&priv->essid, ssid, sizeof(priv->essid)); priv->radio_on = true; netdev_dbg(usbdev->net, "%s(): radio_on = true\n", __func__); } @@ -1015,7 +1054,7 @@ static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) return ret; } -static int set_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN]) +static int set_bssid(struct usbnet *usbdev, const u8 *bssid) { int ret; @@ -1031,7 +1070,9 @@ static int set_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN]) static int clear_bssid(struct usbnet *usbdev) { - u8 broadcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + static const u8 broadcast_mac[ETH_ALEN] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; return set_bssid(usbdev, broadcast_mac); } @@ -1904,14 +1945,14 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, struct usbnet *usbdev = netdev_priv(dev); struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); int ret; - __le32 tmp; + int delay = SCAN_DELAY_JIFFIES; netdev_dbg(usbdev->net, "cfg80211.scan\n"); /* Get current bssid list from device before new scan, as new scan * clears internal bssid list. */ - rndis_check_bssid_list(usbdev); + rndis_check_bssid_list(usbdev, NULL, NULL); if (!request) return -EINVAL; @@ -1921,13 +1962,13 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, priv->scan_request = request; - tmp = cpu_to_le32(1); - ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, - sizeof(tmp)); + ret = rndis_start_bssid_list_scan(usbdev); if (ret == 0) { + if (priv->device_type == RNDIS_BCM4320A) + delay = HZ; + /* Wait before retrieving scan results from device */ - queue_delayed_work(priv->workqueue, &priv->scan_work, - SCAN_DELAY_JIFFIES); + queue_delayed_work(priv->workqueue, &priv->scan_work, delay); } return ret; @@ -1946,8 +1987,8 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev, int ie_len, bssid_len; u8 *ie; - netdev_dbg(usbdev->net, " found bssid: '%.32s' [%pM]\n", - bssid->ssid.essid, bssid->mac); + netdev_dbg(usbdev->net, " found bssid: '%.32s' [%pM], len: %d\n", + bssid->ssid.essid, bssid->mac, le32_to_cpu(bssid->length)); /* parse bssid structure */ bssid_len = le32_to_cpu(bssid->length); @@ -1981,49 +2022,98 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev, GFP_KERNEL); } -static int rndis_check_bssid_list(struct usbnet *usbdev) +static struct ndis_80211_bssid_ex *next_bssid_list_item( + struct ndis_80211_bssid_ex *bssid, + int *bssid_len, void *buf, int len) +{ + void *buf_end, *bssid_end; + + buf_end = (char *)buf + len; + bssid_end = (char *)bssid + *bssid_len; + + if ((int)(buf_end - bssid_end) < sizeof(bssid->length)) { + *bssid_len = 0; + return NULL; + } else { + bssid = (void *)((char *)bssid + *bssid_len); + *bssid_len = le32_to_cpu(bssid->length); + return bssid; + } +} + +static bool check_bssid_list_item(struct ndis_80211_bssid_ex *bssid, + int bssid_len, void *buf, int len) +{ + void *buf_end, *bssid_end; + + if (!bssid || bssid_len <= 0 || bssid_len > len) + return false; + + buf_end = (char *)buf + len; + bssid_end = (char *)bssid + bssid_len; + + return (int)(buf_end - bssid_end) >= 0 && (int)(bssid_end - buf) >= 0; +} + +static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid, + bool *matched) { void *buf = NULL; struct ndis_80211_bssid_list_ex *bssid_list; struct ndis_80211_bssid_ex *bssid; - int ret = -EINVAL, len, count, bssid_len; - bool resized = false; + int ret = -EINVAL, len, count, bssid_len, real_count, new_len; - netdev_dbg(usbdev->net, "check_bssid_list\n"); + netdev_dbg(usbdev->net, "%s()\n", __func__); len = CONTROL_BUFFER_SIZE; resize_buf: - buf = kmalloc(len, GFP_KERNEL); + buf = kzalloc(len, GFP_KERNEL); if (!buf) { ret = -ENOMEM; goto out; } - ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len); - if (ret != 0) + /* BSSID-list might have got bigger last time we checked, keep + * resizing until it won't get any bigger. + */ + new_len = len; + ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &new_len); + if (ret != 0 || new_len < sizeof(struct ndis_80211_bssid_list_ex)) goto out; - if (!resized && len > CONTROL_BUFFER_SIZE) { - resized = true; + if (new_len > len) { + len = new_len; kfree(buf); goto resize_buf; } + len = new_len; + bssid_list = buf; - bssid = bssid_list->bssid; - bssid_len = le32_to_cpu(bssid->length); count = le32_to_cpu(bssid_list->num_items); - netdev_dbg(usbdev->net, "check_bssid_list: %d BSSIDs found (buflen: %d)\n", - count, len); + real_count = 0; + netdev_dbg(usbdev->net, "%s(): buflen: %d\n", __func__, len); + + bssid_len = 0; + bssid = next_bssid_list_item(bssid_list->bssid, &bssid_len, buf, len); - while (count && ((void *)bssid + bssid_len) <= (buf + len)) { - rndis_bss_info_update(usbdev, bssid); + /* Device returns incorrect 'num_items'. Workaround by ignoring the + * received 'num_items' and walking through full bssid buffer instead. + */ + while (check_bssid_list_item(bssid, bssid_len, buf, len)) { + if (rndis_bss_info_update(usbdev, bssid) && match_bssid && + matched) { + if (compare_ether_addr(bssid->mac, match_bssid)) + *matched = true; + } - bssid = (void *)bssid + bssid_len; - bssid_len = le32_to_cpu(bssid->length); - count--; + real_count++; + bssid = next_bssid_list_item(bssid, &bssid_len, buf, len); } + netdev_dbg(usbdev->net, "%s(): num_items from device: %d, really found:" + " %d\n", __func__, count, real_count); + out: kfree(buf); return ret; @@ -2041,7 +2131,7 @@ static void rndis_get_scan_results(struct work_struct *work) if (!priv->scan_request) return; - ret = rndis_check_bssid_list(usbdev); + ret = rndis_check_bssid_list(usbdev, NULL, NULL); cfg80211_scan_done(priv->scan_request, ret < 0); @@ -2355,7 +2445,7 @@ static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, } static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index) + u8 key_index, bool unicast, bool multicast) { struct rndis_wlan_private *priv = wiphy_priv(wiphy); struct usbnet *usbdev = priv->usbdev; @@ -2365,6 +2455,9 @@ static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, priv->encr_tx_key_index = key_index; + if (is_wpa_key(priv, key_index)) + return 0; + key = priv->encr_keys[key_index]; return add_wep_key(usbdev, key.material, key.len, key_index); @@ -2495,6 +2588,136 @@ static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid)); } +static int rndis_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, + bool enabled, int timeout) +{ + struct rndis_wlan_private *priv = wiphy_priv(wiphy); + struct usbnet *usbdev = priv->usbdev; + int power_mode; + __le32 mode; + int ret; + + netdev_dbg(usbdev->net, "%s(): %s, %d\n", __func__, + enabled ? "enabled" : "disabled", + timeout); + + if (enabled) + power_mode = NDIS_80211_POWER_MODE_FAST_PSP; + else + power_mode = NDIS_80211_POWER_MODE_CAM; + + if (power_mode == priv->power_mode) + return 0; + + priv->power_mode = power_mode; + + mode = cpu_to_le32(power_mode); + ret = rndis_set_oid(usbdev, OID_802_11_POWER_MODE, &mode, sizeof(mode)); + + netdev_dbg(usbdev->net, "%s(): OID_802_11_POWER_MODE -> %d\n", + __func__, ret); + + return ret; +} + +static int rndis_set_cqm_rssi_config(struct wiphy *wiphy, + struct net_device *dev, + s32 rssi_thold, u32 rssi_hyst) +{ + struct rndis_wlan_private *priv = wiphy_priv(wiphy); + + priv->cqm_rssi_thold = rssi_thold; + priv->cqm_rssi_hyst = rssi_hyst; + priv->last_cqm_event_rssi = 0; + + return 0; +} + +static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, + struct ndis_80211_assoc_info *info) +{ + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); + struct ieee80211_channel *channel; + struct ndis_80211_conf config; + struct ndis_80211_ssid ssid; + s32 signal; + u64 timestamp; + u16 capability; + u16 beacon_interval; + __le32 rssi; + u8 ie_buf[34]; + int len, ret, ie_len; + + /* Get signal quality, in case of error use rssi=0 and ignore error. */ + len = sizeof(rssi); + rssi = 0; + ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len); + signal = level_to_qual(le32_to_cpu(rssi)); + + netdev_dbg(usbdev->net, "%s(): OID_802_11_RSSI -> %d, " + "rssi:%d, qual: %d\n", __func__, ret, le32_to_cpu(rssi), + level_to_qual(le32_to_cpu(rssi))); + + /* Get AP capabilities */ + if (info) { + capability = le16_to_cpu(info->resp_ie.capa); + } else { + /* Set atleast ESS/IBSS capability */ + capability = (priv->infra_mode == NDIS_80211_INFRA_INFRA) ? + WLAN_CAPABILITY_ESS : WLAN_CAPABILITY_IBSS; + } + + /* Get channel and beacon interval */ + len = sizeof(config); + ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len); + netdev_dbg(usbdev->net, "%s(): OID_802_11_CONFIGURATION -> %d\n", + __func__, ret); + if (ret >= 0) { + beacon_interval = le16_to_cpu(config.beacon_period); + channel = ieee80211_get_channel(priv->wdev.wiphy, + KHZ_TO_MHZ(le32_to_cpu(config.ds_config))); + if (!channel) { + netdev_warn(usbdev->net, "%s(): could not get channel." + "\n", __func__); + return; + } + } else { + netdev_warn(usbdev->net, "%s(): could not get configuration.\n", + __func__); + return; + } + + /* Get SSID, in case of error, use zero length SSID and ignore error. */ + len = sizeof(ssid); + memset(&ssid, 0, sizeof(ssid)); + ret = rndis_query_oid(usbdev, OID_802_11_SSID, &ssid, &len); + netdev_dbg(usbdev->net, "%s(): OID_802_11_SSID -> %d, len: %d, ssid: " + "'%.32s'\n", __func__, ret, + le32_to_cpu(ssid.length), ssid.essid); + + if (le32_to_cpu(ssid.length) > 32) + ssid.length = cpu_to_le32(32); + + ie_buf[0] = WLAN_EID_SSID; + ie_buf[1] = le32_to_cpu(ssid.length); + memcpy(&ie_buf[2], ssid.essid, le32_to_cpu(ssid.length)); + + ie_len = le32_to_cpu(ssid.length) + 2; + + /* no tsf */ + timestamp = 0; + + netdev_dbg(usbdev->net, "%s(): channel:%d(freq), bssid:[%pM], tsf:%d, " + "capa:%x, beacon int:%d, resp_ie(len:%d, essid:'%.32s'), " + "signal:%d\n", __func__, (channel ? channel->center_freq : -1), + bssid, (u32)timestamp, capability, beacon_interval, ie_len, + ssid.essid, signal); + + cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid, + timestamp, capability, beacon_interval, ie_buf, ie_len, + signal, GFP_KERNEL); +} + /* * workers, indication handlers, device poller */ @@ -2507,6 +2730,7 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) u8 *req_ie, *resp_ie; int ret, offset; bool roamed = false; + bool match_bss; if (priv->infra_mode == NDIS_80211_INFRA_INFRA && priv->connected) { /* received media connect indication while connected, either @@ -2558,6 +2782,13 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) resp_ie_len = CONTROL_BUFFER_SIZE - offset; } + } else { + /* Since rndis_wlan_craft_connected_bss() might use info + * later and expects info to contain valid data if + * non-null, free info and set NULL here. + */ + kfree(info); + info = NULL; } } else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC)) return; @@ -2569,13 +2800,26 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) netdev_dbg(usbdev->net, "link up work: [%pM]%s\n", bssid, roamed ? " roamed" : ""); - /* Internal bss list in device always contains at least the currently + /* Internal bss list in device should contain at least the currently * connected bss and we can get it to cfg80211 with * rndis_check_bssid_list(). - * NOTE: This is true for Broadcom chip, but not mentioned in RNDIS - * spec. + * + * NDIS spec says: "If the device is associated, but the associated + * BSSID is not in its BSSID scan list, then the driver must add an + * entry for the BSSID at the end of the data that it returns in + * response to query of OID_802_11_BSSID_LIST." + * + * NOTE: Seems to be true for BCM4320b variant, but not BCM4320a. */ - rndis_check_bssid_list(usbdev); + match_bss = false; + rndis_check_bssid_list(usbdev, bssid, &match_bss); + + if (!is_zero_ether_addr(bssid) && !match_bss) { + /* Couldn't get bss from device, we need to manually craft bss + * for cfg80211. + */ + rndis_wlan_craft_connected_bss(usbdev, bssid, info); + } if (priv->infra_mode == NDIS_80211_INFRA_INFRA) { if (!roamed) @@ -2918,6 +3162,32 @@ static int rndis_wlan_get_caps(struct usbnet *usbdev, struct wiphy *wiphy) return retval; } +static void rndis_do_cqm(struct usbnet *usbdev, s32 rssi) +{ + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); + enum nl80211_cqm_rssi_threshold_event event; + int thold, hyst, last_event; + + if (priv->cqm_rssi_thold >= 0 || rssi >= 0) + return; + if (priv->infra_mode != NDIS_80211_INFRA_INFRA) + return; + + last_event = priv->last_cqm_event_rssi; + thold = priv->cqm_rssi_thold; + hyst = priv->cqm_rssi_hyst; + + if (rssi < thold && (last_event == 0 || rssi < last_event - hyst)) + event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; + else if (rssi > thold && (last_event == 0 || rssi > last_event + hyst)) + event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; + else + return; + + priv->last_cqm_event_rssi = rssi; + cfg80211_cqm_rssi_notify(usbdev->net, event, GFP_KERNEL); +} + #define DEVICE_POLLER_JIFFIES (HZ) static void rndis_device_poller(struct work_struct *work) { @@ -2934,13 +3204,28 @@ static void rndis_device_poller(struct work_struct *work) * also polls device with rndis_command() and catches for media link * indications. */ - if (!is_associated(usbdev)) + if (!is_associated(usbdev)) { + /* Workaround bad scanning in BCM4320a devices with active + * background scanning when not associated. + */ + if (priv->device_type == RNDIS_BCM4320A && priv->radio_on && + !priv->scan_request) { + /* Get previous scan results */ + rndis_check_bssid_list(usbdev, NULL, NULL); + + /* Initiate new scan */ + rndis_start_bssid_list_scan(usbdev); + } + goto end; + } len = sizeof(rssi); ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len); - if (ret == 0) + if (ret == 0) { priv->last_qual = level_to_qual(le32_to_cpu(rssi)); + rndis_do_cqm(usbdev, le32_to_cpu(rssi)); + } netdev_dbg(usbdev->net, "dev-poller: OID_802_11_RSSI -> %d, rssi:%d, qual: %d\n", ret, le32_to_cpu(rssi), level_to_qual(le32_to_cpu(rssi))); @@ -2992,10 +3277,12 @@ end: /* * driver/device initialization */ -static void rndis_copy_module_params(struct usbnet *usbdev) +static void rndis_copy_module_params(struct usbnet *usbdev, int device_type) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); + priv->device_type = device_type; + priv->param_country[0] = modparam_country[0]; priv->param_country[1] = modparam_country[1]; priv->param_country[2] = 0; @@ -3038,12 +3325,25 @@ static void rndis_copy_module_params(struct usbnet *usbdev) priv->param_workaround_interval = modparam_workaround_interval; } +static int unknown_early_init(struct usbnet *usbdev) +{ + /* copy module parameters for unknown so that iwconfig reports txpower + * and workaround parameter is copied to private structure correctly. + */ + rndis_copy_module_params(usbdev, RNDIS_UNKNOWN); + + /* This is unknown device, so do not try set configuration parameters. + */ + + return 0; +} + static int bcm4320a_early_init(struct usbnet *usbdev) { /* copy module parameters for bcm4320a so that iwconfig reports txpower * and workaround parameter is copied to private structure correctly. */ - rndis_copy_module_params(usbdev); + rndis_copy_module_params(usbdev, RNDIS_BCM4320A); /* bcm4320a doesn't handle configuration parameters well. Try * set any and you get partially zeroed mac and broken device. @@ -3057,7 +3357,7 @@ static int bcm4320b_early_init(struct usbnet *usbdev) struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); char buf[8]; - rndis_copy_module_params(usbdev); + rndis_copy_module_params(usbdev, RNDIS_BCM4320B); /* Early initialization settings, setting these won't have effect * if called after generic_rndis_bind(). @@ -3187,13 +3487,15 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf) set_default_iw_params(usbdev); + priv->power_mode = -1; + /* set default rts/frag */ rndis_set_wiphy_params(wiphy, WIPHY_PARAM_FRAG_THRESHOLD | WIPHY_PARAM_RTS_THRESHOLD); - /* turn radio on */ - priv->radio_on = true; - disassociate(usbdev, true); + /* turn radio off on init */ + priv->radio_on = false; + disassociate(usbdev, false); netif_carrier_off(usbdev->net); return 0; @@ -3320,7 +3622,7 @@ static const struct driver_info rndis_wlan_info = { .tx_fixup = rndis_tx_fixup, .reset = rndis_wlan_reset, .stop = rndis_wlan_stop, - .early_init = bcm4320a_early_init, + .early_init = unknown_early_init, .indication = rndis_wlan_indication, }; diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 4396d4b9bfb9..6f383cd684b0 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -53,51 +53,41 @@ config RT61PCI When compiled as a module, this driver will be called rt61pci. -config RT2800PCI_PCI - boolean - depends on PCI - default y - -config RT2800PCI_SOC - boolean - depends on RALINK_RT288X || RALINK_RT305X - default y - config RT2800PCI - tristate "Ralink rt28xx/rt30xx/rt35xx (PCI/PCIe/PCMCIA) support (EXPERIMENTAL)" - depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL + tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" + depends on PCI || RALINK_RT288X || RALINK_RT305X select RT2800_LIB - select RT2X00_LIB_PCI if RT2800PCI_PCI - select RT2X00_LIB_SOC if RT2800PCI_SOC + select RT2X00_LIB_PCI if PCI + select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X select RT2X00_LIB_HT select RT2X00_LIB_FIRMWARE select RT2X00_LIB_CRYPTO select CRC_CCITT select EEPROM_93CX6 ---help--- - This adds support for rt2800/rt3000/rt3500 wireless chipset family. - Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052 - - This driver is non-functional at the moment and is intended for - developers. + This adds support for rt27xx/rt28xx/rt30xx wireless chipset family. + Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890, RT3052, + RT3090, RT3091 & RT3092 When compiled as a module, this driver will be called "rt2800pci.ko". if RT2800PCI -config RT2800PCI_RT30XX - bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices" - default y +config RT2800PCI_RT33XX + bool "rt2800pci - Include support for rt33xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL + default n ---help--- - This adds support for rt30xx wireless chipset family to the + This adds support for rt33xx wireless chipset family to the rt2800pci driver. - Supported chips: RT3090, RT3091 & RT3092 + Supported chips: RT3390 Support for these devices is non-functional at the moment and is intended for testers and developers. config RT2800PCI_RT35XX - bool "rt2800pci - Include support for rt35xx (PCI/PCIe/PCMCIA) devices" + bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL default n ---help--- This adds support for rt35xx wireless chipset family to the @@ -134,8 +124,8 @@ config RT73USB When compiled as a module, this driver will be called rt73usb. config RT2800USB - tristate "Ralink rt2800 (USB) support (EXPERIMENTAL)" - depends on USB && EXPERIMENTAL + tristate "Ralink rt27xx/rt28xx/rt30xx (USB) support" + depends on USB select RT2800_LIB select RT2X00_LIB_USB select RT2X00_LIB_HT @@ -143,30 +133,28 @@ config RT2800USB select RT2X00_LIB_CRYPTO select CRC_CCITT ---help--- - This adds experimental support for rt2800 wireless chipset family. - Supported chips: RT2770, RT2870 & RT3070. - - Known issues: - - support for RT2870 chips doesn't work with 802.11n APs yet - - support for RT3070 chips is non-functional at the moment + This adds support for rt27xx/rt28xx/rt30xx wireless chipset family. + Supported chips: RT2770, RT2870 & RT3070, RT3071 & RT3072 When compiled as a module, this driver will be called "rt2800usb.ko". if RT2800USB -config RT2800USB_RT30XX - bool "rt2800usb - Include support for rt30xx (USB) devices" - default y +config RT2800USB_RT33XX + bool "rt2800usb - Include support for rt33xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL + default n ---help--- - This adds support for rt30xx wireless chipset family to the + This adds support for rt33xx wireless chipset family to the rt2800usb driver. - Supported chips: RT3070, RT3071 & RT3072 + Supported chips: RT3370 Support for these devices is non-functional at the moment and is intended for testers and developers. config RT2800USB_RT35XX - bool "rt2800usb - Include support for rt35xx (USB) devices" + bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL default n ---help--- This adds support for rt35xx wireless chipset family to the @@ -180,9 +168,9 @@ config RT2800USB_UNKNOWN bool "rt2800usb - Include support for unknown (USB) devices" default n ---help--- - This adds support for rt2800 family devices that are known to - have a rt2800 family chipset, but for which the exact chipset - is unknown. + This adds support for rt2800usb devices that are known to + have a rt28xx family compatible chipset, but for which the exact + chipset is unknown. Support status for these devices is unknown, and enabling these devices may or may not work. diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 4f420a9ec5dc..54ca49ad3472 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -633,6 +633,88 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev, } /* + * Queue handlers. + */ +static void rt2400pci_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); + break; + case QID_BEACON: + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, 1); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + break; + default: + break; + } +} + +static void rt2400pci_kick_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_AC_VO: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + case QID_AC_VI: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + case QID_ATIM: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + default: + break; + } +} + +static void rt2400pci_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_ATIM: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_ABORT, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + case QID_RX: + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); + break; + case QID_BEACON: + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); + rt2x00_set_field32(®, CSR14_TBCN, 0); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + break; + default: + break; + } +} + +/* * Initialization functions. */ static bool rt2400pci_get_entry_state(struct queue_entry *entry) @@ -878,18 +960,6 @@ static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev) /* * Device state switch handlers. */ -static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} - static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, enum dev_state state) { @@ -988,12 +1058,6 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, case STATE_RADIO_OFF: rt2400pci_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2400pci_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -1125,32 +1189,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry, rt2x00pci_register_write(rt2x00dev, CSR14, reg); } -static void rt2400pci_kick_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE)); - rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK)); - rt2x00_set_field32(®, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM)); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); -} - -static void rt2400pci_kill_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - if (queue->qid == QID_BEACON) { - rt2x00pci_register_write(rt2x00dev, CSR14, 0); - } else { - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_ABORT, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); - } -} - /* * RX control handlers */ @@ -1284,13 +1322,13 @@ static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance) * 4 - Priority ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) - rt2400pci_txdone(rt2x00dev, QID_AC_BE); + rt2400pci_txdone(rt2x00dev, QID_AC_VO); /* * 5 - Tx ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) - rt2400pci_txdone(rt2x00dev, QID_AC_BK); + rt2400pci_txdone(rt2x00dev, QID_AC_VI); /* Enable interrupts again. */ rt2x00dev->ops->lib->set_device_state(rt2x00dev, @@ -1612,6 +1650,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .get_tsf = rt2400pci_get_tsf, .tx_last_beacon = rt2400pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { @@ -1627,10 +1666,11 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .link_stats = rt2400pci_link_stats, .reset_tuner = rt2400pci_reset_tuner, .link_tuner = rt2400pci_link_tuner, + .start_queue = rt2400pci_start_queue, + .kick_queue = rt2400pci_kick_queue, + .stop_queue = rt2400pci_stop_queue, .write_tx_desc = rt2400pci_write_tx_desc, .write_beacon = rt2400pci_write_beacon, - .kick_tx_queue = rt2400pci_kick_tx_queue, - .kill_tx_queue = rt2400pci_kill_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, .config_filter = rt2400pci_config_filter, .config_intf = rt2400pci_config_intf, @@ -1640,28 +1680,28 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { }; static const struct data_queue_desc rt2400pci_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 24, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2400pci_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 24, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2400pci_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 1, .data_size = MGMT_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2400pci_queue_atim = { - .entry_num = ATIM_ENTRIES, + .entry_num = 8, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index c048b18f4133..d3a4a68cc439 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -809,8 +809,8 @@ /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 8 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 8 * sizeof(__le32) ) +#define TXD_DESC_SIZE (8 * sizeof(__le32)) +#define RXD_DESC_SIZE (8 * sizeof(__le32)) /* * TX descriptor format for TX, PRIO, ATIM and Beacon Ring. @@ -948,6 +948,6 @@ ((__CLAMP_TX(__txpower) - MAX_TXPOWER) + MIN_TXPOWER) #define TXPOWER_TO_DEV(__txpower) \ - MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER) + (MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER)) #endif /* RT2400PCI_H */ diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 97feb7aef809..a9ff26a27724 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -723,6 +723,88 @@ dynamic_cca_tune: } /* + * Queue handlers. + */ +static void rt2500pci_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); + break; + case QID_BEACON: + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, 1); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + break; + default: + break; + } +} + +static void rt2500pci_kick_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_AC_VO: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + case QID_AC_VI: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + case QID_ATIM: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + default: + break; + } +} + +static void rt2500pci_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_ATIM: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_ABORT, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + case QID_RX: + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); + break; + case QID_BEACON: + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); + rt2x00_set_field32(®, CSR14_TBCN, 0); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + break; + default: + break; + } +} + +/* * Initialization functions. */ static bool rt2500pci_get_entry_state(struct queue_entry *entry) @@ -1033,18 +1115,6 @@ static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev) /* * Device state switch handlers. */ -static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} - static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, enum dev_state state) { @@ -1143,12 +1213,6 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, case STATE_RADIO_OFF: rt2500pci_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2500pci_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -1193,9 +1257,9 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry, rt2x00_desc_read(txd, 2, &word); rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max); + rt2x00_set_field32(&word, TXD_W2_AIFS, entry->queue->aifs); + rt2x00_set_field32(&word, TXD_W2_CWMIN, entry->queue->cw_min); + rt2x00_set_field32(&word, TXD_W2_CWMAX, entry->queue->cw_max); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 3, &word); @@ -1279,32 +1343,6 @@ static void rt2500pci_write_beacon(struct queue_entry *entry, rt2x00pci_register_write(rt2x00dev, CSR14, reg); } -static void rt2500pci_kick_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE)); - rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK)); - rt2x00_set_field32(®, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM)); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); -} - -static void rt2500pci_kill_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - if (queue->qid == QID_BEACON) { - rt2x00pci_register_write(rt2x00dev, CSR14, 0); - } else { - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_ABORT, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); - } -} - /* * RX control handlers */ @@ -1417,13 +1455,13 @@ static irqreturn_t rt2500pci_interrupt_thread(int irq, void *dev_instance) * 4 - Priority ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) - rt2500pci_txdone(rt2x00dev, QID_AC_BE); + rt2500pci_txdone(rt2x00dev, QID_AC_VO); /* * 5 - Tx ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) - rt2500pci_txdone(rt2x00dev, QID_AC_BK); + rt2500pci_txdone(rt2x00dev, QID_AC_VI); /* Enable interrupts again. */ rt2x00dev->ops->lib->set_device_state(rt2x00dev, @@ -1909,6 +1947,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .get_tsf = rt2500pci_get_tsf, .tx_last_beacon = rt2500pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { @@ -1924,10 +1963,11 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .link_stats = rt2500pci_link_stats, .reset_tuner = rt2500pci_reset_tuner, .link_tuner = rt2500pci_link_tuner, + .start_queue = rt2500pci_start_queue, + .kick_queue = rt2500pci_kick_queue, + .stop_queue = rt2500pci_stop_queue, .write_tx_desc = rt2500pci_write_tx_desc, .write_beacon = rt2500pci_write_beacon, - .kick_tx_queue = rt2500pci_kick_tx_queue, - .kill_tx_queue = rt2500pci_kill_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, .config_filter = rt2500pci_config_filter, .config_intf = rt2500pci_config_intf, @@ -1937,28 +1977,28 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { }; static const struct data_queue_desc rt2500pci_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2500pci_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2500pci_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 1, .data_size = MGMT_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2500pci_queue_atim = { - .entry_num = ATIM_ENTRIES, + .entry_num = 8, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index d708031361ac..2aad7ba8a100 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -1088,8 +1088,8 @@ /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 11 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 11 * sizeof(__le32) ) +#define TXD_DESC_SIZE (11 * sizeof(__le32)) +#define RXD_DESC_SIZE (11 * sizeof(__le32)) /* * TX descriptor format for TX, PRIO, ATIM and Beacon Ring. diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 93e44c7f3a74..6b3b1de46792 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -39,7 +39,7 @@ /* * Allow hardware encryption to be disabled. */ -static int modparam_nohwcrypt = 0; +static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -739,6 +739,55 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev, } /* + * Queue handlers. + */ +static void rt2500usb_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u16 reg; + + switch (queue->qid) { + case QID_RX: + rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); + rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); + break; + case QID_BEACON: + rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); + rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 1); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + break; + default: + break; + } +} + +static void rt2500usb_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u16 reg; + + switch (queue->qid) { + case QID_RX: + rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); + rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, 1); + rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); + break; + case QID_BEACON: + rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); + rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + break; + default: + break; + } +} + +/* * Initialization functions. */ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) @@ -931,18 +980,6 @@ static int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev) /* * Device state switch handlers. */ -static void rt2500usb_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u16 reg; - - rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); - rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); -} - static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev) { /* @@ -1018,12 +1055,6 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, case STATE_RADIO_OFF: rt2500usb_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2500usb_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -1081,9 +1112,9 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry, rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); - rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); + rt2x00_set_field32(&word, TXD_W1_AIFS, entry->queue->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max); rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); @@ -1206,14 +1237,6 @@ static int rt2500usb_get_tx_data_len(struct queue_entry *entry) return length; } -static void rt2500usb_kill_tx_queue(struct data_queue *queue) -{ - if (queue->qid == QID_BEACON) - rt2500usb_register_write(queue->rt2x00dev, TXRX_CSR19, 0); - - rt2x00usb_kill_tx_queue(queue); -} - /* * RX control handlers */ @@ -1801,6 +1824,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { @@ -1813,11 +1837,13 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .link_stats = rt2500usb_link_stats, .reset_tuner = rt2500usb_reset_tuner, .watchdog = rt2x00usb_watchdog, + .start_queue = rt2500usb_start_queue, + .kick_queue = rt2x00usb_kick_queue, + .stop_queue = rt2500usb_stop_queue, + .flush_queue = rt2x00usb_flush_queue, .write_tx_desc = rt2500usb_write_tx_desc, .write_beacon = rt2500usb_write_beacon, .get_tx_data_len = rt2500usb_get_tx_data_len, - .kick_tx_queue = rt2x00usb_kick_tx_queue, - .kill_tx_queue = rt2500usb_kill_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, .config_shared_key = rt2500usb_config_key, .config_pairwise_key = rt2500usb_config_key, @@ -1829,28 +1855,28 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { }; static const struct data_queue_desc rt2500usb_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt2500usb_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt2500usb_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 1, .data_size = MGMT_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb_bcn), }; static const struct data_queue_desc rt2500usb_queue_atim = { - .entry_num = ATIM_ENTRIES, + .entry_num = 8, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index eb8b6cab9925..4c55e8525cad 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -46,7 +46,11 @@ * RF2020 2.4G B/G * RF3021 2.4G 1T2R * RF3022 2.4G 2T2R - * RF3052 2.4G 2T2R + * RF3052 2.4G/5G 2T2R + * RF2853 2.4G/5G 3T3R + * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) + * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) + * RF3853 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) */ #define RF2820 0x0001 #define RF2850 0x0002 @@ -57,7 +61,10 @@ #define RF3021 0x0007 #define RF3022 0x0008 #define RF3052 0x0009 +#define RF2853 0x000a #define RF3320 0x000b +#define RF3322 0x000c +#define RF3853 0x000d /* * Chipset revisions. @@ -206,10 +213,10 @@ /* * WMM_AIFSN_CFG: Aifsn for each EDCA AC - * AIFSN0: AC_BE - * AIFSN1: AC_BK - * AIFSN2: AC_VI - * AIFSN3: AC_VO + * AIFSN0: AC_VO + * AIFSN1: AC_VI + * AIFSN2: AC_BE + * AIFSN3: AC_BK */ #define WMM_AIFSN_CFG 0x0214 #define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f) @@ -219,10 +226,10 @@ /* * WMM_CWMIN_CSR: CWmin for each EDCA AC - * CWMIN0: AC_BE - * CWMIN1: AC_BK - * CWMIN2: AC_VI - * CWMIN3: AC_VO + * CWMIN0: AC_VO + * CWMIN1: AC_VI + * CWMIN2: AC_BE + * CWMIN3: AC_BK */ #define WMM_CWMIN_CFG 0x0218 #define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f) @@ -232,10 +239,10 @@ /* * WMM_CWMAX_CSR: CWmax for each EDCA AC - * CWMAX0: AC_BE - * CWMAX1: AC_BK - * CWMAX2: AC_VI - * CWMAX3: AC_VO + * CWMAX0: AC_VO + * CWMAX1: AC_VI + * CWMAX2: AC_BE + * CWMAX3: AC_BK */ #define WMM_CWMAX_CFG 0x021c #define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f) @@ -244,18 +251,18 @@ #define WMM_CWMAX_CFG_CWMAX3 FIELD32(0x0000f000) /* - * AC_TXOP0: AC_BK/AC_BE TXOP register - * AC0TXOP: AC_BK in unit of 32us - * AC1TXOP: AC_BE in unit of 32us + * AC_TXOP0: AC_VO/AC_VI TXOP register + * AC0TXOP: AC_VO in unit of 32us + * AC1TXOP: AC_VI in unit of 32us */ #define WMM_TXOP0_CFG 0x0220 #define WMM_TXOP0_CFG_AC0TXOP FIELD32(0x0000ffff) #define WMM_TXOP0_CFG_AC1TXOP FIELD32(0xffff0000) /* - * AC_TXOP1: AC_VO/AC_VI TXOP register - * AC2TXOP: AC_VI in unit of 32us - * AC3TXOP: AC_VO in unit of 32us + * AC_TXOP1: AC_BE/AC_BK TXOP register + * AC2TXOP: AC_BE in unit of 32us + * AC3TXOP: AC_BK in unit of 32us */ #define WMM_TXOP1_CFG 0x0224 #define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff) @@ -281,7 +288,7 @@ #define MCU_CMD_CFG 0x022c /* - * AC_BK register offsets + * AC_VO register offsets */ #define TX_BASE_PTR0 0x0230 #define TX_MAX_CNT0 0x0234 @@ -289,7 +296,7 @@ #define TX_DTX_IDX0 0x023c /* - * AC_BE register offsets + * AC_VI register offsets */ #define TX_BASE_PTR1 0x0240 #define TX_MAX_CNT1 0x0244 @@ -297,7 +304,7 @@ #define TX_DTX_IDX1 0x024c /* - * AC_VI register offsets + * AC_BE register offsets */ #define TX_BASE_PTR2 0x0250 #define TX_MAX_CNT2 0x0254 @@ -305,7 +312,7 @@ #define TX_DTX_IDX2 0x025c /* - * AC_VO register offsets + * AC_BK register offsets */ #define TX_BASE_PTR3 0x0260 #define TX_MAX_CNT3 0x0264 @@ -412,10 +419,22 @@ #define BCN_OFFSET1_BCN7 FIELD32(0xff000000) /* - * PBF registers - * Most are for debug. Driver doesn't touch PBF register. + * TXRXQ_PCNT: PBF register + * PCNT_TX0Q: Page count for TX hardware queue 0 + * PCNT_TX1Q: Page count for TX hardware queue 1 + * PCNT_TX2Q: Page count for TX hardware queue 2 + * PCNT_RX0Q: Page count for RX hardware queue */ #define TXRXQ_PCNT 0x0438 +#define TXRXQ_PCNT_TX0Q FIELD32(0x000000ff) +#define TXRXQ_PCNT_TX1Q FIELD32(0x0000ff00) +#define TXRXQ_PCNT_TX2Q FIELD32(0x00ff0000) +#define TXRXQ_PCNT_RX0Q FIELD32(0xff000000) + +/* + * PBF register + * Debug. Driver doesn't touch PBF register. + */ #define PBF_DBG 0x043c /* @@ -686,8 +705,18 @@ /* * CH_TIME_CFG: count as channel busy + * EIFS_BUSY: Count EIFS as channel busy + * NAV_BUSY: Count NAS as channel busy + * RX_BUSY: Count RX as channel busy + * TX_BUSY: Count TX as channel busy + * TMR_EN: Enable channel statistics timer */ #define CH_TIME_CFG 0x110c +#define CH_TIME_CFG_EIFS_BUSY FIELD32(0x00000010) +#define CH_TIME_CFG_NAV_BUSY FIELD32(0x00000008) +#define CH_TIME_CFG_RX_BUSY FIELD32(0x00000004) +#define CH_TIME_CFG_TX_BUSY FIELD32(0x00000002) +#define CH_TIME_CFG_TMR_EN FIELD32(0x00000001) /* * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us @@ -960,8 +989,31 @@ /* * TXOP_CTRL_CFG: + * TIMEOUT_TRUN_EN: Enable/Disable TXOP timeout truncation + * AC_TRUN_EN: Enable/Disable truncation for AC change + * TXRATEGRP_TRUN_EN: Enable/Disable truncation for TX rate group change + * USER_MODE_TRUN_EN: Enable/Disable truncation for user TXOP mode + * MIMO_PS_TRUN_EN: Enable/Disable truncation for MIMO PS RTS/CTS + * RESERVED_TRUN_EN: Reserved + * LSIG_TXOP_EN: Enable/Disable L-SIG TXOP protection + * EXT_CCA_EN: Enable/Disable extension channel CCA reference (Defer 40Mhz + * transmissions if extension CCA is clear). + * EXT_CCA_DLY: Extension CCA signal delay time (unit: us) + * EXT_CWMIN: CwMin for extension channel backoff + * 0: Disabled + * */ #define TXOP_CTRL_CFG 0x1340 +#define TXOP_CTRL_CFG_TIMEOUT_TRUN_EN FIELD32(0x00000001) +#define TXOP_CTRL_CFG_AC_TRUN_EN FIELD32(0x00000002) +#define TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN FIELD32(0x00000004) +#define TXOP_CTRL_CFG_USER_MODE_TRUN_EN FIELD32(0x00000008) +#define TXOP_CTRL_CFG_MIMO_PS_TRUN_EN FIELD32(0x00000010) +#define TXOP_CTRL_CFG_RESERVED_TRUN_EN FIELD32(0x00000020) +#define TXOP_CTRL_CFG_LSIG_TXOP_EN FIELD32(0x00000040) +#define TXOP_CTRL_CFG_EXT_CCA_EN FIELD32(0x00000080) +#define TXOP_CTRL_CFG_EXT_CCA_DLY FIELD32(0x0000ff00) +#define TXOP_CTRL_CFG_EXT_CWMIN FIELD32(0x000f0000) /* * TX_RTS_CFG: @@ -1485,17 +1537,17 @@ #define SHARED_KEY_MODE_BASE 0x7000 #define MAC_WCID_ENTRY(__idx) \ - ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) ) + (MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry))) #define PAIRWISE_KEY_ENTRY(__idx) \ - ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) + (PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry))) #define MAC_IVEIV_ENTRY(__idx) \ - ( MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry)) ) + (MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry))) #define MAC_WCID_ATTR_ENTRY(__idx) \ - ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) + (MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32))) #define SHARED_KEY_ENTRY(__idx) \ - ( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) + (SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry))) #define SHARED_KEY_MODE_ENTRY(__idx) \ - ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) ) + (SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32))) struct mac_wcid_entry { u8 mac[6]; @@ -1635,9 +1687,9 @@ struct mac_iveiv_entry { #define HW_BEACON_BASE7 0x5bc0 #define HW_BEACON_OFFSET(__index) \ - ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \ - (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \ - (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) ) + (((__index) < 4) ? (HW_BEACON_BASE0 + (__index * 0x0200)) : \ + (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \ + (HW_BEACON_BASE6 - ((__index - 6) * 0x0200)))) /* * BBP registers. @@ -1805,32 +1857,51 @@ struct mac_iveiv_entry { #define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) /* - * EEPROM ANTENNA config + * EEPROM NIC Configuration 0 * RXPATH: 1: 1R, 2: 2R, 3: 3R - * TXPATH: 1: 1T, 2: 2T - */ -#define EEPROM_ANTENNA 0x001a -#define EEPROM_ANTENNA_RXPATH FIELD16(0x000f) -#define EEPROM_ANTENNA_TXPATH FIELD16(0x00f0) -#define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0f00) - -/* - * EEPROM NIC config - * CARDBUS_ACCEL: 0 - enable, 1 - disable - */ -#define EEPROM_NIC 0x001b -#define EEPROM_NIC_HW_RADIO FIELD16(0x0001) -#define EEPROM_NIC_DYNAMIC_TX_AGC FIELD16(0x0002) -#define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0004) -#define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0008) -#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0010) -#define EEPROM_NIC_BW40M_SB_BG FIELD16(0x0020) -#define EEPROM_NIC_BW40M_SB_A FIELD16(0x0040) -#define EEPROM_NIC_WPS_PBC FIELD16(0x0080) -#define EEPROM_NIC_BW40M_BG FIELD16(0x0100) -#define EEPROM_NIC_BW40M_A FIELD16(0x0200) -#define EEPROM_NIC_ANT_DIVERSITY FIELD16(0x0800) -#define EEPROM_NIC_DAC_TEST FIELD16(0x8000) + * TXPATH: 1: 1T, 2: 2T, 3: 3T + * RF_TYPE: RFIC type + */ +#define EEPROM_NIC_CONF0 0x001a +#define EEPROM_NIC_CONF0_RXPATH FIELD16(0x000f) +#define EEPROM_NIC_CONF0_TXPATH FIELD16(0x00f0) +#define EEPROM_NIC_CONF0_RF_TYPE FIELD16(0x0f00) + +/* + * EEPROM NIC Configuration 1 + * HW_RADIO: 0: disable, 1: enable + * EXTERNAL_TX_ALC: 0: disable, 1: enable + * EXTERNAL_LNA_2G: 0: disable, 1: enable + * EXTERNAL_LNA_5G: 0: disable, 1: enable + * CARDBUS_ACCEL: 0: enable, 1: disable + * BW40M_SB_2G: 0: disable, 1: enable + * BW40M_SB_5G: 0: disable, 1: enable + * WPS_PBC: 0: disable, 1: enable + * BW40M_2G: 0: enable, 1: disable + * BW40M_5G: 0: enable, 1: disable + * BROADBAND_EXT_LNA: 0: disable, 1: enable + * ANT_DIVERSITY: 00: Disable, 01: Diversity, + * 10: Main antenna, 11: Aux antenna + * INTERNAL_TX_ALC: 0: disable, 1: enable + * BT_COEXIST: 0: disable, 1: enable + * DAC_TEST: 0: disable, 1: enable + */ +#define EEPROM_NIC_CONF1 0x001b +#define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001) +#define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002) +#define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G FIELD16(0x0004) +#define EEPROM_NIC_CONF1_EXTERNAL_LNA_5G FIELD16(0x0008) +#define EEPROM_NIC_CONF1_CARDBUS_ACCEL FIELD16(0x0010) +#define EEPROM_NIC_CONF1_BW40M_SB_2G FIELD16(0x0020) +#define EEPROM_NIC_CONF1_BW40M_SB_5G FIELD16(0x0040) +#define EEPROM_NIC_CONF1_WPS_PBC FIELD16(0x0080) +#define EEPROM_NIC_CONF1_BW40M_2G FIELD16(0x0100) +#define EEPROM_NIC_CONF1_BW40M_5G FIELD16(0x0200) +#define EEPROM_NIC_CONF1_BROADBAND_EXT_LNA FIELD16(0x400) +#define EEPROM_NIC_CONF1_ANT_DIVERSITY FIELD16(0x1800) +#define EEPROM_NIC_CONF1_INTERNAL_TX_ALC FIELD16(0x2000) +#define EEPROM_NIC_CONF1_BT_COEXIST FIELD16(0x4000) +#define EEPROM_NIC_CONF1_DAC_TEST FIELD16(0x8000) /* * EEPROM frequency @@ -1852,9 +1923,9 @@ struct mac_iveiv_entry { * POLARITY_GPIO_4: Polarity GPIO4 setting. * LED_MODE: Led mode. */ -#define EEPROM_LED1 0x001e -#define EEPROM_LED2 0x001f -#define EEPROM_LED3 0x0020 +#define EEPROM_LED_AG_CONF 0x001e +#define EEPROM_LED_ACT_CONF 0x001f +#define EEPROM_LED_POLARITY 0x0020 #define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001) #define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002) #define EEPROM_LED_POLARITY_ACT FIELD16(0x0004) @@ -1866,6 +1937,17 @@ struct mac_iveiv_entry { #define EEPROM_LED_LED_MODE FIELD16(0x1f00) /* + * EEPROM NIC Configuration 2 + * RX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream + * TX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream + * CRYSTAL: 00: Reserved, 01: One crystal, 10: Two crystal, 11: Reserved + */ +#define EEPROM_NIC_CONF2 0x0021 +#define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f) +#define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0) +#define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600) + +/* * EEPROM LNA */ #define EEPROM_LNA 0x0022 @@ -1915,7 +1997,7 @@ struct mac_iveiv_entry { /* * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power. - * This is delta in 40MHZ. + * This is delta in 40MHZ. * VALUE: Tx Power dalta value (MAX=4) * TYPE: 1: Plus the delta value, 0: minus the delta value * TXPOWER: Enable: @@ -1971,9 +2053,9 @@ struct mac_iveiv_entry { #define MCU_CURRENT 0x36 #define MCU_LED 0x50 #define MCU_LED_STRENGTH 0x51 -#define MCU_LED_1 0x52 -#define MCU_LED_2 0x53 -#define MCU_LED_3 0x54 +#define MCU_LED_AG_CONF 0x52 +#define MCU_LED_ACT_CONF 0x53 +#define MCU_LED_LED_POLARITY 0x54 #define MCU_RADAR 0x60 #define MCU_BOOT_SIGNAL 0x72 #define MCU_BBP_SIGNAL 0x80 @@ -1987,8 +2069,8 @@ struct mac_iveiv_entry { /* * DMA descriptor defines. */ -#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) ) -#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) +#define TXWI_DESC_SIZE (4 * sizeof(__le32)) +#define RXWI_DESC_SIZE (4 * sizeof(__le32)) /* * TX WI structure diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 5f00e00789d8..54917a281398 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -277,13 +277,17 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) unsigned int i; u32 reg; + /* + * Some devices are really slow to respond here. Wait a whole second + * before timing out. + */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) return 0; - msleep(1); + msleep(10); } ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); @@ -483,7 +487,7 @@ void rt2800_write_tx_data(struct queue_entry *entry, txdesc->key_idx : 0xff); rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, txdesc->length); - rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, txdesc->qid); + rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid); rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1); rt2x00_desc_write(txwi, 1, word); @@ -727,7 +731,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev) * that the TX_STA_FIFO stack has a size of 16. We stick to our * tx ring size for now. */ - for (i = 0; i < TX_ENTRIES; i++) { + for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) break; @@ -768,6 +772,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); unsigned int beacon_base; + unsigned int padding_len; u32 reg; /* @@ -802,11 +807,13 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); /* - * Write entire beacon with TXWI to register. + * Write entire beacon with TXWI and padding to register. */ + padding_len = roundup(entry->skb->len, 4) - entry->skb->len; + skb_pad(entry->skb, padding_len); beacon_base = HW_BEACON_OFFSET(entry->entry_idx); - rt2800_register_multiwrite(rt2x00dev, beacon_base, - entry->skb->data, entry->skb->len); + rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, + entry->skb->len + padding_len); /* * Enable beaconing again. @@ -824,7 +831,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) } EXPORT_SYMBOL_GPL(rt2800_write_beacon); -static void inline rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, +static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, unsigned int beacon_base) { int i; @@ -1144,6 +1151,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, const unsigned int flags) { u32 reg; + bool update_bssid = false; if (flags & CONFIG_UPDATE_TYPE) { /* @@ -1173,6 +1181,16 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, } if (flags & CONFIG_UPDATE_MAC) { + if (flags & CONFIG_UPDATE_TYPE && + conf->sync == TSF_SYNC_AP_NONE) { + /* + * The BSSID register has to be set to our own mac + * address in AP mode. + */ + memcpy(conf->bssid, conf->mac, sizeof(conf->mac)); + update_bssid = true; + } + if (!is_zero_ether_addr((const u8 *)conf->mac)) { reg = le32_to_cpu(conf->mac[1]); rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); @@ -1183,7 +1201,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, conf->mac, sizeof(conf->mac)); } - if (flags & CONFIG_UPDATE_BSSID) { + if ((flags & CONFIG_UPDATE_BSSID) || update_bssid) { if (!is_zero_ether_addr((const u8 *)conf->bssid)) { reg = le32_to_cpu(conf->bssid[1]); rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 3); @@ -1529,7 +1547,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2x00_rf(rt2x00dev, RF3020) || rt2x00_rf(rt2x00dev, RF3021) || rt2x00_rf(rt2x00dev, RF3022) || - rt2x00_rf(rt2x00dev, RF3052)) + rt2x00_rf(rt2x00dev, RF3052) || + rt2x00_rf(rt2x00dev, RF3320)) rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); else rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); @@ -1609,6 +1628,13 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, } msleep(1); + + /* + * Clear channel statistic counters + */ + rt2800_register_read(rt2x00dev, CH_IDLE_STA, ®); + rt2800_register_read(rt2x00dev, CH_BUSY_STA, ®); + rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, ®); } static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, @@ -1914,8 +1940,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST)) rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000002c); else @@ -2097,7 +2123,23 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); } - rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f); + /* + * The legacy driver also sets TXOP_CTRL_CFG_RESERVED_TRUN_EN to 1 + * although it is reserved. + */ + rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG, ®); + rt2x00_set_field32(®, TXOP_CTRL_CFG_TIMEOUT_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_AC_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_USER_MODE_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_MIMO_PS_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_RESERVED_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_LSIG_TXOP_EN, 0); + rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CCA_EN, 0); + rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CCA_DLY, 88); + rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CWMIN, 0); + rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg); + rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®); @@ -2134,7 +2176,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) SHARED_KEY_MODE_ENTRY(i), 0); for (i = 0; i < 256; i++) { - u32 wcid[2] = { 0xffffffff, 0x00ffffff }; + static const u32 wcid[2] = { 0xffffffff, 0x00ffffff }; rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), wcid, sizeof(wcid)); @@ -2227,6 +2269,17 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4); rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg); + /* + * Set up channel statistics timer + */ + rt2800_register_read(rt2x00dev, CH_TIME_CFG, ®); + rt2x00_set_field32(®, CH_TIME_CFG_EIFS_BUSY, 1); + rt2x00_set_field32(®, CH_TIME_CFG_NAV_BUSY, 1); + rt2x00_set_field32(®, CH_TIME_CFG_RX_BUSY, 1); + rt2x00_set_field32(®, CH_TIME_CFG_TX_BUSY, 1); + rt2x00_set_field32(®, CH_TIME_CFG_TMR_EN, 1); + rt2800_register_write(rt2x00dev, CH_TIME_CFG, reg); + return 0; } @@ -2344,10 +2397,10 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2x00_rt(rt2x00dev, RT3390)) { rt2800_bbp_read(rt2x00dev, 138, &value); - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) value |= 0x20; - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) value &= ~0x02; rt2800_bbp_write(rt2x00dev, 138, value); @@ -2559,8 +2612,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST)) rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); else rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); @@ -2633,10 +2686,10 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt(rt2x00dev, RT3090)) { rt2800_bbp_read(rt2x00dev, 138, &bbp); - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0); - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1); rt2800_bbp_write(rt2x00dev, 138, bbp); @@ -2735,16 +2788,16 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize LED control */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff, + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word); + rt2800_mcu_request(rt2x00dev, MCU_LED_AG_CONF, 0xff, word & 0xff, (word >> 8) & 0xff); - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff, + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word); + rt2800_mcu_request(rt2x00dev, MCU_LED_ACT_CONF, 0xff, word & 0xff, (word >> 8) & 0xff); - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff, + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word); + rt2800_mcu_request(rt2x00dev, MCU_LED_LED_POLARITY, 0xff, word & 0xff, (word >> 8) & 0xff); return 0; @@ -2838,38 +2891,41 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) EEPROM(rt2x00dev, "MAC: %pM\n", mac); } - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word); if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); - rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1); - rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); - rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2); + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1); + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820); + rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); } else if (rt2x00_rt(rt2x00dev, RT2860) || rt2x00_rt(rt2x00dev, RT2872)) { /* * There is a max of 2 RX streams for RT28x0 series */ - if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2) - rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); - rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); + if (rt2x00_get_field16(word, EEPROM_NIC_CONF0_RXPATH) > 2) + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2); + rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); } - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word); if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0); - rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0); - rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0); - rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0); - rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); - rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0); - rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0); - rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0); - rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0); - rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0); - rt2x00_set_field16(&word, EEPROM_NIC_ANT_DIVERSITY, 0); - rt2x00_set_field16(&word, EEPROM_NIC_DAC_TEST, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_HW_RADIO, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_CARDBUS_ACCEL, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_2G, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_5G, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_WPS_PBC, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_2G, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_5G, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BROADBAND_EXT_LNA, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_ANT_DIVERSITY, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_INTERNAL_TX_ALC, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BT_COEXIST, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_DAC_TEST, 0); + rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word); EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); } @@ -2884,9 +2940,9 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) LED_MODE_TXRX_ACTIVITY); rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0); rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8); + rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555); + rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221); + rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8); EEPROM(rt2x00dev, "Led Mode: 0x%04x\n", word); } @@ -2950,12 +3006,12 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Read EEPROM word for configuration. */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); /* * Identify RF chipset. */ - value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); + value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); rt2800_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), @@ -2981,7 +3037,8 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) !rt2x00_rf(rt2x00dev, RF2020) && !rt2x00_rf(rt2x00dev, RF3021) && !rt2x00_rf(rt2x00dev, RF3022) && - !rt2x00_rf(rt2x00dev, RF3052)) { + !rt2x00_rf(rt2x00dev, RF3052) && + !rt2x00_rf(rt2x00dev, RF3320)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); return -ENODEV; } @@ -2990,9 +3047,9 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) * Identify default antenna configuration. */ rt2x00dev->default_ant.tx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH); + rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH); rt2x00dev->default_ant.rx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH); + rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH); /* * Read frequency offset and RF programming sequence. @@ -3003,17 +3060,17 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Read external LNA informations. */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A)) + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G)) __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G)) __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); /* * Detect if this device has an hardware controlled radio. */ - if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO)) + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO)) __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); /* @@ -3225,7 +3282,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->max_report_rates = 7; rt2x00dev->hw->max_rate_tries = 1; - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); /* * Initialize hw_mode information. @@ -3245,7 +3302,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) } else if (rt2x00_rf(rt2x00dev, RF3020) || rt2x00_rf(rt2x00dev, RF2020) || rt2x00_rf(rt2x00dev, RF3021) || - rt2x00_rf(rt2x00dev, RF3022)) { + rt2x00_rf(rt2x00dev, RF3022) || + rt2x00_rf(rt2x00dev, RF3320)) { spec->num_channels = 14; spec->channels = rf_vals_3x; } else if (rt2x00_rf(rt2x00dev, RF3052)) { @@ -3268,11 +3326,11 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40; - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) >= 2) + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) >= 2) spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC; spec->ht.cap |= - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) << + rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) << IEEE80211_HT_CAP_RX_STBC_SHIFT; spec->ht.ampdu_factor = 3; @@ -3280,10 +3338,10 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->ht.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED | IEEE80211_HT_MCS_TX_RX_DIFF | - ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) << + ((rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) - 1) << IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); - switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) { + switch (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH)) { case 3: spec->ht.mcs.rx_mask[2] = 0xff; case 2: @@ -3502,6 +3560,37 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(rt2800_ampdu_action); +int rt2800_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + u32 idle, busy, busy_ext; + + if (idx != 0) + return -ENOENT; + + survey->channel = conf->channel; + + rt2800_register_read(rt2x00dev, CH_IDLE_STA, &idle); + rt2800_register_read(rt2x00dev, CH_BUSY_STA, &busy); + rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &busy_ext); + + if (idle || busy) { + survey->filled = SURVEY_INFO_CHANNEL_TIME | + SURVEY_INFO_CHANNEL_TIME_BUSY | + SURVEY_INFO_CHANNEL_TIME_EXT_BUSY; + + survey->channel_time = (idle + busy) / 1000; + survey->channel_time_busy = busy / 1000; + survey->channel_time_ext_busy = busy_ext / 1000; + } + + return 0; + +} +EXPORT_SYMBOL_GPL(rt2800_get_survey); + MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz"); MODULE_VERSION(DRV_VERSION); MODULE_DESCRIPTION("Ralink RT2800 library"); diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 81cbc92e7857..e3c995a9dec4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -199,5 +199,7 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn); +int rt2800_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey); #endif /* RT2800LIB_H */ diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 09a67905c230..aa97971a38af 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -84,20 +84,22 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); } -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) { - u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */ + void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); + + iounmap(base_addr); } #else static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) { } -#endif /* CONFIG_RT2800PCI_SOC */ +#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) { struct rt2x00_dev *rt2x00dev = eeprom->data; @@ -181,7 +183,78 @@ static inline int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev) static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) { } -#endif /* CONFIG_RT2800PCI_PCI */ +#endif /* CONFIG_PCI */ + +/* + * Queue handlers. + */ +static void rt2800pci_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + break; + case QID_BEACON: + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + break; + default: + break; + }; +} + +static void rt2800pci_kick_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + struct queue_entry *entry; + + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + entry = rt2x00queue_get_entry(queue, Q_INDEX); + rt2800_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), entry->entry_idx); + break; + case QID_MGMT: + entry = rt2x00queue_get_entry(queue, Q_INDEX); + rt2800_register_write(rt2x00dev, TX_CTX_IDX(5), entry->entry_idx); + break; + default: + break; + } +} + +static void rt2800pci_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + break; + case QID_BEACON: + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + break; + default: + break; + } +} /* * Firmware functions @@ -321,18 +394,6 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) /* * Device state switch handlers. */ -static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, - (state == STATE_RADIO_RX_ON) || - (state == STATE_RADIO_RX_ON_LINK)); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); -} - static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, enum dev_state state) { @@ -442,7 +503,7 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, * if the device is booting and wasn't asleep it will return * failure when attempting to wakeup. */ - rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); + rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2); if (state == STATE_AWAKE) { rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0); @@ -476,12 +537,6 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, rt2800pci_disable_radio(rt2x00dev); rt2800pci_set_state(rt2x00dev, STATE_SLEEP); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2800pci_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -567,41 +622,6 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry, } /* - * TX data initialization - */ -static void rt2800pci_kick_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); - unsigned int qidx; - - if (queue->qid == QID_MGMT) - qidx = 5; - else - qidx = queue->qid; - - rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), entry->entry_idx); -} - -static void rt2800pci_kill_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - if (queue->qid == QID_BEACON) { - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, 0); - return; - } - - rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, (queue->qid == QID_AC_BE)); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, (queue->qid == QID_AC_BK)); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, (queue->qid == QID_AC_VI)); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, (queue->qid == QID_AC_VO)); - rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); -} - -/* * RX control handlers */ static void rt2800pci_fill_rxdone(struct queue_entry *entry, @@ -668,14 +688,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) u32 status; u8 qid; - while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) { - /* Now remove the tx status from the FIFO */ - if (kfifo_out(&rt2x00dev->txstatus_fifo, &status, - sizeof(status)) != sizeof(status)) { - WARN_ON(1); - break; - } - + while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) { qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); if (qid >= QID_RX) { /* @@ -683,7 +696,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) * this tx status. */ WARNING(rt2x00dev, "Got TX status report with " - "unexpected pid %u, dropping", qid); + "unexpected pid %u, dropping\n", qid); break; } @@ -694,7 +707,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) * processing here and drop the tx status */ WARNING(rt2x00dev, "Got TX status for an unavailable " - "queue %u, dropping", qid); + "queue %u, dropping\n", qid); break; } @@ -704,7 +717,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) * and drop the tx status. */ WARNING(rt2x00dev, "Got TX status for an empty " - "queue %u, dropping", qid); + "queue %u, dropping\n", qid); break; } @@ -777,20 +790,13 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) * Since we have only one producer and one consumer we don't * need to lock the kfifo. */ - for (i = 0; i < TX_ENTRIES; i++) { + for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status); if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) break; - if (kfifo_is_full(&rt2x00dev->txstatus_fifo)) { - WARNING(rt2x00dev, "TX status FIFO overrun," - " drop tx status report.\n"); - break; - } - - if (kfifo_in(&rt2x00dev->txstatus_fifo, &status, - sizeof(status)) != sizeof(status)) { + if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) { WARNING(rt2x00dev, "TX status FIFO overrun," "drop tx status report.\n"); break; @@ -944,6 +950,8 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = { .get_tsf = rt2800_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, .ampdu_action = rt2800_ampdu_action, + .flush = rt2x00mac_flush, + .get_survey = rt2800_get_survey, }; static const struct rt2800_ops rt2800pci_rt2800_ops = { @@ -976,11 +984,12 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .link_stats = rt2800_link_stats, .reset_tuner = rt2800_reset_tuner, .link_tuner = rt2800_link_tuner, + .start_queue = rt2800pci_start_queue, + .kick_queue = rt2800pci_kick_queue, + .stop_queue = rt2800pci_stop_queue, .write_tx_desc = rt2800pci_write_tx_desc, .write_tx_data = rt2800_write_tx_data, .write_beacon = rt2800_write_beacon, - .kick_tx_queue = rt2800pci_kick_tx_queue, - .kill_tx_queue = rt2800pci_kill_tx_queue, .fill_rxdone = rt2800pci_fill_rxdone, .config_shared_key = rt2800_config_shared_key, .config_pairwise_key = rt2800_config_pairwise_key, @@ -992,21 +1001,21 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { }; static const struct data_queue_desc rt2800pci_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 128, .data_size = AGGREGATION_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2800pci_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 64, .data_size = AGGREGATION_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2800pci_queue_bcn = { - .entry_num = 8 * BEACON_ENTRIES, + .entry_num = 8, .data_size = 0, /* No DMA required for beacons */ .desc_size = TXWI_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), @@ -1034,12 +1043,15 @@ static const struct rt2x00_ops rt2800pci_ops = { /* * RT2800pci module information. */ -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) }, @@ -1047,12 +1059,10 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { { PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, -#ifdef CONFIG_RT2800PCI_RT30XX - { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, +#ifdef CONFIG_RT2800PCI_RT33XX + { PCI_DEVICE(0x1814, 0x3390), PCI_DEVICE_DATA(&rt2800pci_ops) }, #endif #ifdef CONFIG_RT2800PCI_RT35XX { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, @@ -1063,19 +1073,19 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { #endif { 0, } }; -#endif /* CONFIG_RT2800PCI_PCI */ +#endif /* CONFIG_PCI */ MODULE_AUTHOR(DRV_PROJECT); MODULE_VERSION(DRV_VERSION); MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver."); MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards"); -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI MODULE_FIRMWARE(FIRMWARE_RT2860); MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); -#endif /* CONFIG_RT2800PCI_PCI */ +#endif /* CONFIG_PCI */ MODULE_LICENSE("GPL"); -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) static int rt2800soc_probe(struct platform_device *pdev) { return rt2x00soc_probe(pdev, &rt2800pci_ops); @@ -1092,9 +1102,9 @@ static struct platform_driver rt2800soc_driver = { .suspend = rt2x00soc_suspend, .resume = rt2x00soc_resume, }; -#endif /* CONFIG_RT2800PCI_SOC */ +#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI static struct pci_driver rt2800pci_driver = { .name = KBUILD_MODNAME, .id_table = rt2800pci_device_table, @@ -1103,21 +1113,21 @@ static struct pci_driver rt2800pci_driver = { .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, }; -#endif /* CONFIG_RT2800PCI_PCI */ +#endif /* CONFIG_PCI */ static int __init rt2800pci_init(void) { int ret = 0; -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) ret = platform_driver_register(&rt2800soc_driver); if (ret) return ret; #endif -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI ret = pci_register_driver(&rt2800pci_driver); if (ret) { -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) platform_driver_unregister(&rt2800soc_driver); #endif return ret; @@ -1129,10 +1139,10 @@ static int __init rt2800pci_init(void) static void __exit rt2800pci_exit(void) { -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI pci_unregister_driver(&rt2800pci_driver); #endif -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) platform_driver_unregister(&rt2800soc_driver); #endif } diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h index 5a8dda9b5b5a..70e050d904c8 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.h +++ b/drivers/net/wireless/rt2x00/rt2800pci.h @@ -38,10 +38,10 @@ * Queue register offset macros */ #define TX_QUEUE_REG_OFFSET 0x10 -#define TX_BASE_PTR(__x) TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET) -#define TX_MAX_CNT(__x) TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET) -#define TX_CTX_IDX(__x) TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET) -#define TX_DTX_IDX(__x) TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET) +#define TX_BASE_PTR(__x) (TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET)) +#define TX_MAX_CNT(__x) (TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET)) +#define TX_CTX_IDX(__x) (TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) +#define TX_DTX_IDX(__x) (TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) /* * 8051 firmware image. @@ -52,8 +52,8 @@ /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 4 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 4 * sizeof(__le32) ) +#define TXD_DESC_SIZE (4 * sizeof(__le32)) +#define RXD_DESC_SIZE (4 * sizeof(__le32)) /* * TX descriptor format for TX, PRIO and Beacon Ring. diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 3dff56ec195a..b97a4a54ff4c 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -45,11 +45,60 @@ /* * Allow hardware encryption to be disabled. */ -static int modparam_nohwcrypt = 0; +static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); /* + * Queue handlers. + */ +static void rt2800usb_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + break; + case QID_BEACON: + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + break; + default: + break; + } +} + +static void rt2800usb_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + break; + case QID_BEACON: + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + break; + default: + break; + } +} + +/* * Firmware functions */ static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) @@ -107,18 +156,6 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev, /* * Device state switch handlers. */ -static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, - (state == STATE_RADIO_RX_ON) || - (state == STATE_RADIO_RX_ON_LINK)); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); -} - static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) { u32 reg; @@ -165,7 +202,8 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) * this limit so reduce the number to prevent errors. */ rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT, - ((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3); + ((rt2x00dev->ops->rx->entry_num * DATA_FRAME_SIZE) + / 1024) - 3); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg); @@ -183,9 +221,9 @@ static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) { if (state == STATE_AWAKE) - rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); + rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 2); else - rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); + rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2); return 0; } @@ -214,12 +252,6 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, rt2800usb_disable_radio(rt2x00dev); rt2800usb_set_state(rt2x00dev, STATE_SLEEP); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2800usb_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -245,6 +277,49 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, } /* + * Watchdog handlers + */ +static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u32 reg; + + rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); + if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) { + WARNING(rt2x00dev, "TX HW queue 0 timed out," + " invoke forced kick\n"); + + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012); + + for (i = 0; i < 10; i++) { + udelay(10); + if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) + break; + } + + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); + } + + rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); + if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) { + WARNING(rt2x00dev, "TX HW queue 1 timed out," + " invoke forced kick\n"); + + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a); + + for (i = 0; i < 10; i++) { + udelay(10); + if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) + break; + } + + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); + } + + rt2x00usb_watchdog(rt2x00dev); +} + +/* * TX descriptor initialization */ static __le32 *rt2800usb_get_txwi(struct queue_entry *entry) @@ -266,8 +341,14 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry, * Initialize TXINFO descriptor */ rt2x00_desc_read(txi, 0, &word); + + /* + * The size of TXINFO_W0_USB_DMA_TX_PKT_LEN is + * TXWI + 802.11 header + L2 pad + payload + pad, + * so need to decrease size of TXINFO and USB end pad. + */ rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, - entry->skb->len - TXINFO_DESC_SIZE); + entry->skb->len - TXINFO_DESC_SIZE - 4); rt2x00_set_field32(&word, TXINFO_W0_WIV, !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); @@ -285,22 +366,37 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry, skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; } -/* - * TX data initialization - */ -static int rt2800usb_get_tx_data_len(struct queue_entry *entry) +static void rt2800usb_write_tx_data(struct queue_entry *entry, + struct txentry_desc *txdesc) { - int length; + unsigned int len; + int err; + + rt2800_write_tx_data(entry, txdesc); /* - * The length _must_ include 4 bytes padding, - * it should always be multiple of 4, - * but it must _not_ be a multiple of the USB packet size. + * pad(1~3 bytes) is added after each 802.11 payload. + * USB end pad(4 bytes) is added at each USB bulk out packet end. + * TX frame format is : + * | TXINFO | TXWI | 802.11 header | L2 pad | payload | pad | USB end pad | + * |<------------- tx_pkt_len ------------->| */ - length = roundup(entry->skb->len + 4, 4); - length += (4 * !(length % entry->queue->usb_maxpacket)); + len = roundup(entry->skb->len, 4) + 4; + err = skb_padto(entry->skb, len); + if (unlikely(err)) { + WARNING(entry->queue->rt2x00dev, "TX SKB padding error, out of memory\n"); + return; + } - return length; + entry->skb->len = len; +} + +/* + * TX data initialization + */ +static int rt2800usb_get_tx_data_len(struct queue_entry *entry) +{ + return entry->skb->len; } /* @@ -335,14 +431,6 @@ static void rt2800usb_work_txdone(struct work_struct *work) } } -static void rt2800usb_kill_tx_queue(struct data_queue *queue) -{ - if (queue->qid == QID_BEACON) - rt2x00usb_register_write(queue->rt2x00dev, BCN_TIME_CFG, 0); - - rt2x00usb_kill_tx_queue(queue); -} - /* * RX control handlers */ @@ -507,6 +595,8 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = { .get_tsf = rt2800_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, .ampdu_action = rt2800_ampdu_action, + .flush = rt2x00mac_flush, + .get_survey = rt2800_get_survey, }; static const struct rt2800_ops rt2800usb_rt2800_ops = { @@ -535,13 +625,15 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .link_stats = rt2800_link_stats, .reset_tuner = rt2800_reset_tuner, .link_tuner = rt2800_link_tuner, - .watchdog = rt2x00usb_watchdog, + .watchdog = rt2800usb_watchdog, + .start_queue = rt2800usb_start_queue, + .kick_queue = rt2x00usb_kick_queue, + .stop_queue = rt2800usb_stop_queue, + .flush_queue = rt2x00usb_flush_queue, .write_tx_desc = rt2800usb_write_tx_desc, - .write_tx_data = rt2800_write_tx_data, + .write_tx_data = rt2800usb_write_tx_data, .write_beacon = rt2800_write_beacon, .get_tx_data_len = rt2800usb_get_tx_data_len, - .kick_tx_queue = rt2x00usb_kick_tx_queue, - .kill_tx_queue = rt2800usb_kill_tx_queue, .fill_rxdone = rt2800usb_fill_rxdone, .config_shared_key = rt2800_config_shared_key, .config_pairwise_key = rt2800_config_pairwise_key, @@ -553,21 +645,21 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { }; static const struct data_queue_desc rt2800usb_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 128, .data_size = AGGREGATION_SIZE, .desc_size = RXINFO_DESC_SIZE + RXWI_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt2800usb_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 64, .data_size = AGGREGATION_SIZE, .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt2800usb_queue_bcn = { - .entry_num = 8 * BEACON_ENTRIES, + .entry_num = 8, .data_size = MGMT_FRAME_SIZE, .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), @@ -599,11 +691,19 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Abocom */ { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* AirTies */ + { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Allwin */ { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Amit */ { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Askey */ @@ -612,8 +712,13 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, /* AzureWave */ { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Belkin */ { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -624,6 +729,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -632,17 +738,36 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, /* D-Link */ { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Draytek */ + { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Edimax */ + { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Encore */ + { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, /* EnGenius */ { USB_DEVICE(0x1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gigabyte */ { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Hawking */ { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -651,6 +776,10 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0e66, 0x0013), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e66, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e66, 0x0018), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* I-O DATA */ + { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Linksys */ { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -658,17 +787,44 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Motorola */ { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, /* MSI */ + { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Para */ + { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Pegatron */ + { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Philips */ { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Planex */ + { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Quanta */ + { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ralink */ + { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Samsung */ { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Siemens */ @@ -681,13 +837,22 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, /* SMC */ { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sparklan */ { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -701,101 +866,16 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Zinwell */ { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zyxel */ { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, -#ifdef CONFIG_RT2800USB_RT30XX - /* Abocom */ - { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* AirTies */ - { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Allwin */ - { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* ASUS */ - { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* AzureWave */ - { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Conceptronic */ - { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Corega */ - { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* D-Link */ - { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Draytek */ - { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Edimax */ - { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Encore */ - { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* EnGenius */ - { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Gigabyte */ - { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* I-O DATA */ - { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Logitec */ - { USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* MSI */ - { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Para */ - { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Pegatron */ - { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Planex */ - { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Quanta */ - { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, +#ifdef CONFIG_RT2800USB_RT33XX /* Ralink */ - { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ - { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* SMC */ - { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Zinwell */ - { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) }, #endif #ifdef CONFIG_RT2800USB_RT35XX /* Allwin */ @@ -809,12 +889,9 @@ static struct usb_device_id rt2800usb_device_table[] = { /* I-O DATA */ { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ralink */ - { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zinwell */ { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, #endif diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 0722badccf86..671ea3592610 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -40,8 +40,8 @@ /* * DMA descriptor defines. */ -#define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) -#define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) +#define TXINFO_DESC_SIZE (1 * sizeof(__le32)) +#define RXINFO_DESC_SIZE (1 * sizeof(__le32)) /* * TX Info structure diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index ab43e7ca2a23..84aaf393da43 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -66,7 +66,7 @@ #ifdef CONFIG_RT2X00_DEBUG #define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \ - DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, ##__args); + DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, ##__args) #else #define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \ do { } while (0) @@ -347,6 +347,10 @@ struct link { struct delayed_work watchdog_work; }; +enum rt2x00_delayed_flags { + DELAYED_UPDATE_BEACON, +}; + /* * Interface structure * Per interface configuration details, this structure @@ -354,22 +358,6 @@ struct link { */ struct rt2x00_intf { /* - * All fields within the rt2x00_intf structure - * must be protected with a spinlock. - */ - spinlock_t lock; - - /* - * MAC of the device. - */ - u8 mac[ETH_ALEN]; - - /* - * BBSID of the AP to associate with. - */ - u8 bssid[ETH_ALEN]; - - /* * beacon->skb must be protected with the mutex. */ struct mutex beacon_skb_mutex; @@ -384,8 +372,7 @@ struct rt2x00_intf { /* * Actions that needed rescheduling. */ - unsigned int delayed_flags; -#define DELAYED_UPDATE_BEACON 0x00000001 + unsigned long delayed_flags; /* * Software sequence counter, this is only required @@ -567,7 +554,15 @@ struct rt2x00lib_ops { struct link_qual *qual); void (*link_tuner) (struct rt2x00_dev *rt2x00dev, struct link_qual *qual, const u32 count); + + /* + * Data queue handlers. + */ void (*watchdog) (struct rt2x00_dev *rt2x00dev); + void (*start_queue) (struct data_queue *queue); + void (*kick_queue) (struct data_queue *queue); + void (*stop_queue) (struct data_queue *queue); + void (*flush_queue) (struct data_queue *queue); /* * TX control handlers @@ -579,8 +574,6 @@ struct rt2x00lib_ops { void (*write_beacon) (struct queue_entry *entry, struct txentry_desc *txdesc); int (*get_tx_data_len) (struct queue_entry *entry); - void (*kick_tx_queue) (struct data_queue *queue); - void (*kill_tx_queue) (struct data_queue *queue); /* * RX control handlers @@ -902,7 +895,7 @@ struct rt2x00_dev { /* * FIFO for storing tx status reports between isr and tasklet. */ - struct kfifo txstatus_fifo; + DECLARE_KFIFO_PTR(txstatus_fifo, u32); /* * Tasklet for processing tx status reports (rt2800pci). @@ -916,7 +909,7 @@ struct rt2x00_dev { * in those cases REGISTER_BUSY_COUNT attempts should be * taken with a REGISTER_BUSY_DELAY interval. */ -#define REGISTER_BUSY_COUNT 5 +#define REGISTER_BUSY_COUNT 100 #define REGISTER_BUSY_DELAY 100 /* @@ -1068,6 +1061,78 @@ struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, enum queue_index index); +/** + * rt2x00queue_pause_queue - Pause a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will pause the data queue locally, preventing + * new frames to be added to the queue (while the hardware is + * still allowed to run). + */ +void rt2x00queue_pause_queue(struct data_queue *queue); + +/** + * rt2x00queue_unpause_queue - unpause a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will unpause the data queue locally, allowing + * new frames to be added to the queue again. + */ +void rt2x00queue_unpause_queue(struct data_queue *queue); + +/** + * rt2x00queue_start_queue - Start a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will start handling all pending frames in the queue. + */ +void rt2x00queue_start_queue(struct data_queue *queue); + +/** + * rt2x00queue_stop_queue - Halt a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will stop all pending frames in the queue. + */ +void rt2x00queue_stop_queue(struct data_queue *queue); + +/** + * rt2x00queue_flush_queue - Flush a data queue + * @queue: Pointer to &struct data_queue. + * @drop: True to drop all pending frames. + * + * This function will flush the queue. After this call + * the queue is guarenteed to be empty. + */ +void rt2x00queue_flush_queue(struct data_queue *queue, bool drop); + +/** + * rt2x00queue_start_queues - Start all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * + * This function will loop through all available queues to start them + */ +void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00queue_stop_queues - Halt all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * + * This function will loop through all available queues to stop + * any pending frames. + */ +void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00queue_flush_queues - Flush all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @drop: True to drop all pending frames. + * + * This function will loop through all available queues to flush + * any pending frames. + */ +void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop); + /* * Debugfs handlers. */ @@ -1093,6 +1158,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, */ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); +void rt2x00lib_dmastart(struct queue_entry *entry); void rt2x00lib_dmadone(struct queue_entry *entry); void rt2x00lib_txdone(struct queue_entry *entry, struct txdone_entry_desc *txdesc); @@ -1134,6 +1200,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); +void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop); /* * Driver allocation handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 54ffb5aeb34e..e7f67d5eda52 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -62,13 +62,13 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, * This will prevent the device being confused when it wants * to ACK frames or consideres itself associated. */ - memset(&conf.mac, 0, sizeof(conf.mac)); + memset(conf.mac, 0, sizeof(conf.mac)); if (mac) - memcpy(&conf.mac, mac, ETH_ALEN); + memcpy(conf.mac, mac, ETH_ALEN); - memset(&conf.bssid, 0, sizeof(conf.bssid)); + memset(conf.bssid, 0, sizeof(conf.bssid)); if (bssid) - memcpy(&conf.bssid, bssid, ETH_ALEN); + memcpy(conf.bssid, bssid, ETH_ALEN); flags |= CONFIG_UPDATE_TYPE; if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) @@ -133,7 +133,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, */ if (!(ant->flags & ANTENNA_RX_DIVERSITY)) config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); - else if(config.rx == ANTENNA_SW_DIVERSITY) + else if (config.rx == ANTENNA_SW_DIVERSITY) config.rx = active->rx; if (!(ant->flags & ANTENNA_TX_DIVERSITY)) @@ -146,7 +146,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, * else the changes will be ignored by the device. */ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK); + rt2x00queue_stop_queue(rt2x00dev->rx); /* * Write new antenna setup to device and reset the link tuner. @@ -160,7 +160,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, memcpy(active, &config, sizeof(config)); if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); + rt2x00queue_start_queue(rt2x00dev->rx); } void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index fcdb6b0dc40f..c92db3264741 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -162,11 +162,11 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, struct timeval timestamp; u32 data_len; - do_gettimeofday(×tamp); - - if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) + if (likely(!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))) return; + do_gettimeofday(×tamp); + if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) { DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n"); return; @@ -339,18 +339,19 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file, return -ENOMEM; temp = data + - sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdma done\tdone\n"); + sprintf(data, "qid\tflags\t\tcount\tlimit\tlength\tindex\tdma done\tdone\n"); queue_for_each(intf->rt2x00dev, queue) { - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); - temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid, + temp += sprintf(temp, "%d\t0x%.8x\t%d\t%d\t%d\t%d\t%d\t\t%d\n", + queue->qid, (unsigned int)queue->flags, queue->count, queue->limit, queue->length, queue->index[Q_INDEX], queue->index[Q_INDEX_DMA_DONE], queue->index[Q_INDEX_DONE]); - spin_unlock_irqrestore(&queue->lock, irqflags); + spin_unlock_irqrestore(&queue->index_lock, irqflags); } size = strlen(data); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index d019830ca840..9597a03242cc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -66,20 +66,16 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) set_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags); /* - * Enable RX. + * Enable queues. */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); + rt2x00queue_start_queues(rt2x00dev); + rt2x00link_start_tuner(rt2x00dev); /* * Start watchdog monitoring. */ rt2x00link_start_watchdog(rt2x00dev); - /* - * Start the TX queues. - */ - ieee80211_wake_queues(rt2x00dev->hw); - return 0; } @@ -89,20 +85,16 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) return; /* - * Stop the TX queues in mac80211. - */ - ieee80211_stop_queues(rt2x00dev->hw); - rt2x00queue_stop_queues(rt2x00dev); - - /* * Stop watchdog monitoring. */ rt2x00link_stop_watchdog(rt2x00dev); /* - * Disable RX. + * Stop all queues */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); + rt2x00link_stop_tuner(rt2x00dev); + rt2x00queue_stop_queues(rt2x00dev); + rt2x00queue_flush_queues(rt2x00dev, true); /* * Disable radio. @@ -113,41 +105,11 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) rt2x00leds_led_radio(rt2x00dev, false); } -void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) -{ - /* - * When we are disabling the RX, we should also stop the link tuner. - */ - if (state == STATE_RADIO_RX_OFF) - rt2x00link_stop_tuner(rt2x00dev); - - rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); - - /* - * When we are enabling the RX, we should also start the link tuner. - */ - if (state == STATE_RADIO_RX_ON) - rt2x00link_start_tuner(rt2x00dev); -} - static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = data; struct rt2x00_intf *intf = vif_to_intf(vif); - int delayed_flags; - - /* - * Copy all data we need during this action under the protection - * of a spinlock. Otherwise race conditions might occur which results - * into an invalid configuration. - */ - spin_lock(&intf->lock); - - delayed_flags = intf->delayed_flags; - intf->delayed_flags = 0; - - spin_unlock(&intf->lock); /* * It is possible the radio was disabled while the work had been @@ -158,7 +120,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return; - if (delayed_flags & DELAYED_UPDATE_BEACON) + if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) rt2x00queue_update_beacon(rt2x00dev, vif, true); } @@ -251,8 +213,16 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); +void rt2x00lib_dmastart(struct queue_entry *entry) +{ + set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); + rt2x00queue_index_inc(entry->queue, Q_INDEX); +} +EXPORT_SYMBOL_GPL(rt2x00lib_dmastart); + void rt2x00lib_dmadone(struct queue_entry *entry) { + set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags); clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE); } @@ -264,11 +234,9 @@ void rt2x00lib_txdone(struct queue_entry *entry, struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); - unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); + unsigned int header_length, i; u8 rate_idx, rate_flags, retry_rates; u8 skbdesc_flags = skbdesc->flags; - unsigned int i; bool success; /* @@ -287,6 +255,11 @@ void rt2x00lib_txdone(struct queue_entry *entry, skbdesc->flags &= ~SKBDESC_DESC_IN_SKB; /* + * Determine the length of 802.11 header. + */ + header_length = ieee80211_get_hdrlen_from_skb(entry->skb); + + /* * Remove L2 padding which was added during */ if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) @@ -414,7 +387,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, * is reenabled when the txdone handler has finished. */ if (!rt2x00queue_threshold(entry->queue)) - ieee80211_wake_queue(rt2x00dev->hw, qid); + rt2x00queue_unpause_queue(entry->queue); } EXPORT_SYMBOL_GPL(rt2x00lib_txdone); @@ -486,6 +459,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry) unsigned int header_length; int rate_idx; + if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || + !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) + goto submit_entry; + if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) goto submit_entry; @@ -570,9 +547,11 @@ void rt2x00lib_rxdone(struct queue_entry *entry) entry->skb = skb; submit_entry: - rt2x00dev->ops->lib->clear_entry(entry); - rt2x00queue_index_inc(entry->queue, Q_INDEX); + entry->flags = 0; rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && + test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) + rt2x00dev->ops->lib->clear_entry(entry); } EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); @@ -681,7 +660,7 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry, { entry->flags = 0; entry->bitrate = rate->bitrate; - entry->hw_value =index; + entry->hw_value = index; entry->hw_value_short = index; if (rate->flags & DEV_RATE_SHORT_PREAMBLE) @@ -821,8 +800,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) /* * Allocate tx status FIFO for driver use. */ - if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags) && - rt2x00dev->ops->lib->txstatus_tasklet) { + if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags)) { /* * Allocate txstatus fifo and tasklet, we use a size of 512 * for the kfifo which is big enough to store 512/4=128 tx @@ -836,9 +814,10 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) return status; /* tasklet for processing the tx status reports. */ - tasklet_init(&rt2x00dev->txstatus_tasklet, - rt2x00dev->ops->lib->txstatus_tasklet, - (unsigned long)rt2x00dev); + if (rt2x00dev->ops->lib->txstatus_tasklet) + tasklet_init(&rt2x00dev->txstatus_tasklet, + rt2x00dev->ops->lib->txstatus_tasklet, + (unsigned long)rt2x00dev); } diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c index c637bcaec5f8..b7ad46ecaa1d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c @@ -40,8 +40,6 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, if (tx_info->control.sta) txdesc->mpdu_density = tx_info->control.sta->ht_cap.ampdu_density; - else - txdesc->mpdu_density = 0; txdesc->ba_size = 7; /* FIXME: What value is needed? */ diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 619da23b7b56..a105c500627b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -57,7 +57,7 @@ static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value) } #define RATE_MCS(__mode, __mcs) \ - ( (((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff) ) + ((((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff)) static inline int rt2x00_get_rate_mcs(const u16 mcs_value) { @@ -69,7 +69,6 @@ static inline int rt2x00_get_rate_mcs(const u16 mcs_value) */ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev); void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev); -void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state); /* * Initialization handlers. @@ -179,15 +178,6 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); /** - * rt2x00queue_stop_queues - Halt all data queues - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * - * This function will loop through all available queues to stop - * any pending outgoing frames. - */ -void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev); - -/** * rt2x00queue_init_queues - Initialize all data queues * @rt2x00dev: Pointer to &struct rt2x00_dev. * diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index b971d8798ebf..bfda60eaf4ef 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -67,7 +67,7 @@ (__avg).avg_weight ? \ ((((__avg).avg_weight * ((AVG_SAMPLES) - 1)) + \ ((__val) * (AVG_FACTOR))) / \ - (AVG_SAMPLES) ) : \ + (AVG_SAMPLES)) : \ ((__val) * (AVG_FACTOR)); \ __new.avg = __new.avg_weight / (AVG_FACTOR); \ __new; \ diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index c3c206a97d54..658542d2efe1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -104,7 +104,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) struct rt2x00_dev *rt2x00dev = hw->priv; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); enum data_queue_qid qid = skb_get_queue_mapping(skb); - struct data_queue *queue; + struct data_queue *queue = NULL; /* * Mac80211 might be calling this function while we are trying @@ -153,7 +153,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) goto exit_fail; if (rt2x00queue_threshold(queue)) - ieee80211_stop_queue(rt2x00dev->hw, qid); + rt2x00queue_pause_queue(queue); return NETDEV_TX_OK; @@ -268,7 +268,6 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, else rt2x00dev->intf_sta_count++; - spin_lock_init(&intf->lock); spin_lock_init(&intf->seqlock); mutex_init(&intf->beacon_skb_mutex); intf->beacon = entry; @@ -282,15 +281,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, * STA interfaces at this time, since this can cause * invalid behavior in the device. */ - memcpy(&intf->mac, vif->addr, ETH_ALEN); - if (vif->type == NL80211_IFTYPE_AP) { - memcpy(&intf->bssid, vif->addr, ETH_ALEN); - rt2x00lib_config_intf(rt2x00dev, intf, vif->type, - intf->mac, intf->bssid); - } else { - rt2x00lib_config_intf(rt2x00dev, intf, vif->type, - intf->mac, NULL); - } + rt2x00lib_config_intf(rt2x00dev, intf, vif->type, + vif->addr, NULL); /* * Some filters depend on the current working mode. We can force @@ -358,7 +350,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) * if for any reason the link tuner must be reset, this will be * handled by rt2x00lib_config(). */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK); + rt2x00queue_stop_queue(rt2x00dev->rx); /* * When we've just turned on the radio, we want to reprogram @@ -376,7 +368,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant); /* Turn RX back on */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); + rt2x00queue_start_queue(rt2x00dev->rx); return 0; } @@ -451,9 +443,7 @@ static void rt2x00mac_set_tim_iter(void *data, u8 *mac, vif->type != NL80211_IFTYPE_WDS) return; - spin_lock(&intf->lock); - intf->delayed_flags |= DELAYED_UPDATE_BEACON; - spin_unlock(&intf->lock); + set_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags); } int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, @@ -478,17 +468,17 @@ EXPORT_SYMBOL_GPL(rt2x00mac_set_tim); static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len) { if (key_len > NL80211_TKIP_DATA_OFFSET_ENCR_KEY) - memcpy(&crypto->key, + memcpy(crypto->key, &key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY], sizeof(crypto->key)); if (key_len > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY) - memcpy(&crypto->tx_mic, + memcpy(crypto->tx_mic, &key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY], sizeof(crypto->tx_mic)); if (key_len > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY) - memcpy(&crypto->rx_mic, + memcpy(crypto->rx_mic, &key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY], sizeof(crypto->rx_mic)); } @@ -498,7 +488,6 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_intf *intf = vif_to_intf(vif); int (*set_key) (struct rt2x00_dev *rt2x00dev, struct rt2x00lib_crypto *crypto, struct ieee80211_key_conf *key); @@ -522,7 +511,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (rt2x00dev->intf_sta_count) crypto.bssidx = 0; else - crypto.bssidx = intf->mac[5] & (rt2x00dev->ops->max_ap_intf - 1); + crypto.bssidx = vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1); crypto.cipher = rt2x00crypto_key_to_cipher(key); if (crypto.cipher == CIPHER_NONE) @@ -540,7 +529,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (crypto.cipher == CIPHER_TKIP) memcpy_tkip(&crypto, &key->key[0], key->keylen); else - memcpy(&crypto.key, &key->key[0], key->keylen); + memcpy(crypto.key, &key->key[0], key->keylen); /* * Each BSS has a maximum of 4 shared keys. * Shared key index values: @@ -620,22 +609,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return; - spin_lock(&intf->lock); - /* - * conf->bssid can be NULL if coming from the internal - * beacon update routine. - */ - if (changes & BSS_CHANGED_BSSID) - memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN); - - spin_unlock(&intf->lock); - - /* - * Call rt2x00_config_intf() outside of the spinlock context since - * the call will sleep for USB drivers. By using the ieee80211_if_conf - * values as arguments we make keep access to rt2x00_intf thread safe - * even without the lock. + * Update the BSSID. */ if (changes & BSS_CHANGED_BSSID) rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, @@ -719,3 +694,13 @@ void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw) wiphy_rfkill_set_hw_state(hw->wiphy, !active); } EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll); + +void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct data_queue *queue; + + tx_queue_for_each(rt2x00dev, queue) + rt2x00queue_flush_queue(queue, drop); +} +EXPORT_SYMBOL_GPL(rt2x00mac_flush); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 2449d785cf8d..73631c6fbb30 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -82,6 +82,13 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) skbdesc->desc_len = entry->queue->desc_size; /* + * DMA is already done, notify rt2x00lib that + * it finished successfully. + */ + rt2x00lib_dmastart(entry); + rt2x00lib_dmadone(entry); + + /* * Send the frame to rt2x00lib for further processing. */ rt2x00lib_rxdone(entry); @@ -105,7 +112,7 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, */ addr = dma_alloc_coherent(rt2x00dev->dev, queue->limit * queue->desc_size, - &dma, GFP_KERNEL | GFP_DMA); + &dma, GFP_KERNEL); if (!addr) return -ENOMEM; @@ -279,7 +286,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) rt2x00dev->irq = pci_dev->irq; rt2x00dev->name = pci_name(pci_dev); - if (pci_dev->is_pcie) + if (pci_is_pcie(pci_dev)) rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); else rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index b854d62ff99b..746ce8fe8cf4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -64,7 +64,7 @@ static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, const void *value, const u32 length) { - memcpy_toio(rt2x00dev->csr.base + offset, value, length); + __iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2); } /** diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index e360d287defb..ca82b3a91697 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -199,7 +199,12 @@ void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) { - unsigned int l2pad = L2PAD_SIZE(header_length); + /* + * L2 padding is only present if the skb contains more than just the + * IEEE 802.11 header. + */ + unsigned int l2pad = (skb->len > header_length) ? + L2PAD_SIZE(header_length) : 0; if (!l2pad) return; @@ -311,14 +316,6 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, memset(txdesc, 0, sizeof(*txdesc)); /* - * Initialize information from queue - */ - txdesc->qid = entry->queue->qid; - txdesc->cw_min = entry->queue->cw_min; - txdesc->cw_max = entry->queue->cw_max; - txdesc->aifs = entry->queue->aifs; - - /* * Header and frame information. */ txdesc->length = entry->skb->len; @@ -460,12 +457,9 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, rt2x00debug_dump_frame(queue->rt2x00dev, DUMP_FRAME_TX, entry->skb); } -static void rt2x00queue_kick_tx_queue(struct queue_entry *entry, +static void rt2x00queue_kick_tx_queue(struct data_queue *queue, struct txentry_desc *txdesc) { - struct data_queue *queue = entry->queue; - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - /* * Check if we need to kick the queue, there are however a few rules * 1) Don't kick unless this is the last in frame in a burst. @@ -477,7 +471,7 @@ static void rt2x00queue_kick_tx_queue(struct queue_entry *entry, */ if (rt2x00queue_threshold(queue) || !test_bit(ENTRY_TXD_BURST, &txdesc->flags)) - rt2x00dev->ops->lib->kick_tx_queue(queue); + queue->rt2x00dev->ops->lib->kick_queue(queue); } int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, @@ -567,7 +561,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, rt2x00queue_index_inc(queue, Q_INDEX); rt2x00queue_write_tx_descriptor(entry, &txdesc); - rt2x00queue_kick_tx_queue(entry, &txdesc); + rt2x00queue_kick_tx_queue(queue, &txdesc); return 0; } @@ -591,7 +585,7 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, rt2x00queue_free_skb(intf->beacon); if (!enable_beacon) { - rt2x00dev->ops->lib->kill_tx_queue(intf->beacon->queue); + rt2x00queue_stop_queue(intf->beacon->queue); mutex_unlock(&intf->beacon_skb_mutex); return 0; } @@ -649,10 +643,10 @@ void rt2x00queue_for_each_entry(struct data_queue *queue, * it should not be kicked during this run, since it * is part of another TX operation. */ - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); index_start = queue->index[start]; index_end = queue->index[end]; - spin_unlock_irqrestore(&queue->lock, irqflags); + spin_unlock_irqrestore(&queue->index_lock, irqflags); /* * Start from the TX done pointer, this guarentees that we will @@ -706,11 +700,11 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, return NULL; } - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); entry = &queue->entries[queue->index[index]]; - spin_unlock_irqrestore(&queue->lock, irqflags); + spin_unlock_irqrestore(&queue->index_lock, irqflags); return entry; } @@ -726,7 +720,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) return; } - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); queue->index[index]++; if (queue->index[index] >= queue->limit) @@ -741,15 +735,219 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) queue->count++; } - spin_unlock_irqrestore(&queue->lock, irqflags); + spin_unlock_irqrestore(&queue->index_lock, irqflags); } +void rt2x00queue_pause_queue(struct data_queue *queue) +{ + if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) || + !test_bit(QUEUE_STARTED, &queue->flags) || + test_and_set_bit(QUEUE_PAUSED, &queue->flags)) + return; + + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + /* + * For TX queues, we have to disable the queue + * inside mac80211. + */ + ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid); + break; + default: + break; + } +} +EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue); + +void rt2x00queue_unpause_queue(struct data_queue *queue) +{ + if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) || + !test_bit(QUEUE_STARTED, &queue->flags) || + !test_and_clear_bit(QUEUE_PAUSED, &queue->flags)) + return; + + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + /* + * For TX queues, we have to enable the queue + * inside mac80211. + */ + ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid); + break; + case QID_RX: + /* + * For RX we need to kick the queue now in order to + * receive frames. + */ + queue->rt2x00dev->ops->lib->kick_queue(queue); + default: + break; + } +} +EXPORT_SYMBOL_GPL(rt2x00queue_unpause_queue); + +void rt2x00queue_start_queue(struct data_queue *queue) +{ + mutex_lock(&queue->status_lock); + + if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) || + test_and_set_bit(QUEUE_STARTED, &queue->flags)) { + mutex_unlock(&queue->status_lock); + return; + } + + set_bit(QUEUE_PAUSED, &queue->flags); + + queue->rt2x00dev->ops->lib->start_queue(queue); + + rt2x00queue_unpause_queue(queue); + + mutex_unlock(&queue->status_lock); +} +EXPORT_SYMBOL_GPL(rt2x00queue_start_queue); + +void rt2x00queue_stop_queue(struct data_queue *queue) +{ + mutex_lock(&queue->status_lock); + + if (!test_and_clear_bit(QUEUE_STARTED, &queue->flags)) { + mutex_unlock(&queue->status_lock); + return; + } + + rt2x00queue_pause_queue(queue); + + queue->rt2x00dev->ops->lib->stop_queue(queue); + + mutex_unlock(&queue->status_lock); +} +EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue); + +void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) +{ + unsigned int i; + bool started; + bool tx_queue = + (queue->qid == QID_AC_VO) || + (queue->qid == QID_AC_VI) || + (queue->qid == QID_AC_BE) || + (queue->qid == QID_AC_BK); + + mutex_lock(&queue->status_lock); + + /* + * If the queue has been started, we must stop it temporarily + * to prevent any new frames to be queued on the device. If + * we are not dropping the pending frames, the queue must + * only be stopped in the software and not the hardware, + * otherwise the queue will never become empty on its own. + */ + started = test_bit(QUEUE_STARTED, &queue->flags); + if (started) { + /* + * Pause the queue + */ + rt2x00queue_pause_queue(queue); + + /* + * If we are not supposed to drop any pending + * frames, this means we must force a start (=kick) + * to the queue to make sure the hardware will + * start transmitting. + */ + if (!drop && tx_queue) + queue->rt2x00dev->ops->lib->kick_queue(queue); + } + + /* + * Check if driver supports flushing, we can only guarentee + * full support for flushing if the driver is able + * to cancel all pending frames (drop = true). + */ + if (drop && queue->rt2x00dev->ops->lib->flush_queue) + queue->rt2x00dev->ops->lib->flush_queue(queue); + + /* + * When we don't want to drop any frames, or when + * the driver doesn't fully flush the queue correcly, + * we must wait for the queue to become empty. + */ + for (i = 0; !rt2x00queue_empty(queue) && i < 100; i++) + msleep(10); + + /* + * The queue flush has failed... + */ + if (unlikely(!rt2x00queue_empty(queue))) + WARNING(queue->rt2x00dev, "Queue %d failed to flush", queue->qid); + + /* + * Restore the queue to the previous status + */ + if (started) + rt2x00queue_unpause_queue(queue); + + mutex_unlock(&queue->status_lock); +} +EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue); + +void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + + /* + * rt2x00queue_start_queue will call ieee80211_wake_queue + * for each queue after is has been properly initialized. + */ + tx_queue_for_each(rt2x00dev, queue) + rt2x00queue_start_queue(queue); + + rt2x00queue_start_queue(rt2x00dev->rx); +} +EXPORT_SYMBOL_GPL(rt2x00queue_start_queues); + +void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + + /* + * rt2x00queue_stop_queue will call ieee80211_stop_queue + * as well, but we are completely shutting doing everything + * now, so it is much safer to stop all TX queues at once, + * and use rt2x00queue_stop_queue for cleaning up. + */ + ieee80211_stop_queues(rt2x00dev->hw); + + tx_queue_for_each(rt2x00dev, queue) + rt2x00queue_stop_queue(queue); + + rt2x00queue_stop_queue(rt2x00dev->rx); +} +EXPORT_SYMBOL_GPL(rt2x00queue_stop_queues); + +void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop) +{ + struct data_queue *queue; + + tx_queue_for_each(rt2x00dev, queue) + rt2x00queue_flush_queue(queue, drop); + + rt2x00queue_flush_queue(rt2x00dev->rx, drop); +} +EXPORT_SYMBOL_GPL(rt2x00queue_flush_queues); + static void rt2x00queue_reset(struct data_queue *queue) { unsigned long irqflags; unsigned int i; - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); queue->count = 0; queue->length = 0; @@ -759,15 +957,7 @@ static void rt2x00queue_reset(struct data_queue *queue) queue->last_action[i] = jiffies; } - spin_unlock_irqrestore(&queue->lock, irqflags); -} - -void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - - txall_queue_for_each(rt2x00dev, queue) - rt2x00dev->ops->lib->kill_tx_queue(queue); + spin_unlock_irqrestore(&queue->index_lock, irqflags); } void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) @@ -778,11 +968,8 @@ void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) queue_for_each(rt2x00dev, queue) { rt2x00queue_reset(queue); - for (i = 0; i < queue->limit; i++) { + for (i = 0; i < queue->limit; i++) rt2x00dev->ops->lib->clear_entry(&queue->entries[i]); - if (queue->qid == QID_RX) - rt2x00queue_index_inc(queue, Q_INDEX); - } } } @@ -809,8 +996,8 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, return -ENOMEM; #define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \ - ( ((char *)(__base)) + ((__limit) * (__esize)) + \ - ((__index) * (__psize)) ) + (((char *)(__base)) + ((__limit) * (__esize)) + \ + ((__index) * (__psize))) for (i = 0; i < queue->limit; i++) { entries[i].flags = 0; @@ -911,7 +1098,8 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, struct data_queue *queue, enum data_queue_qid qid) { - spin_lock_init(&queue->lock); + mutex_init(&queue->status_lock); + spin_lock_init(&queue->index_lock); queue->rt2x00dev = rt2x00dev; queue->qid = qid; @@ -953,7 +1141,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) /* * Initialize queue parameters. * RX: qid = QID_RX - * TX: qid = QID_AC_BE + index + * TX: qid = QID_AC_VO + index * TX: cw_min: 2^5 = 32. * TX: cw_max: 2^10 = 1024. * BCN: qid = QID_BEACON @@ -961,7 +1149,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) */ rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX); - qid = QID_AC_BE; + qid = QID_AC_VO; tx_queue_for_each(rt2x00dev, queue) rt2x00queue_init(rt2x00dev, queue, qid++); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index d81d85f34866..fab8e2687f29 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -43,28 +43,12 @@ #define AGGREGATION_SIZE 3840 /** - * DOC: Number of entries per queue - * - * Under normal load without fragmentation, 12 entries are sufficient - * without the queue being filled up to the maximum. When using fragmentation - * and the queue threshold code, we need to add some additional margins to - * make sure the queue will never (or only under extreme load) fill up - * completely. - * Since we don't use preallocated DMA, having a large number of queue entries - * will have minimal impact on the memory requirements for the queue. - */ -#define RX_ENTRIES 24 -#define TX_ENTRIES 24 -#define BEACON_ENTRIES 1 -#define ATIM_ENTRIES 8 - -/** * enum data_queue_qid: Queue identification * + * @QID_AC_VO: AC VO queue + * @QID_AC_VI: AC VI queue * @QID_AC_BE: AC BE queue * @QID_AC_BK: AC BK queue - * @QID_AC_VI: AC VI queue - * @QID_AC_VO: AC VO queue * @QID_HCCA: HCCA queue * @QID_MGMT: MGMT queue (prio queue) * @QID_RX: RX queue @@ -73,10 +57,10 @@ * @QID_ATIM: Atim queue (value unspeficied, don't send it to device) */ enum data_queue_qid { - QID_AC_BE = 0, - QID_AC_BK = 1, - QID_AC_VI = 2, - QID_AC_VO = 3, + QID_AC_VO = 0, + QID_AC_VI = 1, + QID_AC_BE = 2, + QID_AC_BK = 3, QID_HCCA = 4, QID_MGMT = 13, QID_RX = 14, @@ -296,7 +280,6 @@ enum txentry_desc_flags { * Summary of information for the frame descriptor before sending a TX frame. * * @flags: Descriptor flags (See &enum queue_entry_flags). - * @qid: Queue identification (See &enum data_queue_qid). * @length: Length of the entire frame. * @header_length: Length of 802.11 header. * @length_high: PLCP length high word. @@ -309,11 +292,8 @@ enum txentry_desc_flags { * @rate_mode: Rate mode (See @enum rate_modulation). * @mpdu_density: MDPU density. * @retry_limit: Max number of retries. - * @aifs: AIFS value. * @ifs: IFS value. * @txop: IFS value for 11n capable chips. - * @cw_min: cwmin value. - * @cw_max: cwmax value. * @cipher: Cipher type used for encryption. * @key_idx: Key index used for encryption. * @iv_offset: Position where IV should be inserted by hardware. @@ -322,8 +302,6 @@ enum txentry_desc_flags { struct txentry_desc { unsigned long flags; - enum data_queue_qid qid; - u16 length; u16 header_length; @@ -339,11 +317,8 @@ struct txentry_desc { u16 mpdu_density; short retry_limit; - short aifs; short ifs; short txop; - short cw_min; - short cw_max; enum cipher cipher; u16 key_idx; @@ -365,12 +340,16 @@ struct txentry_desc { * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured * while transfering the data to the hardware. No TX status report will * be expected from the hardware. + * @ENTRY_DATA_STATUS_PENDING: The entry has been send to the device and + * returned. It is now waiting for the status reporting before the + * entry can be reused again. */ enum queue_entry_flags { ENTRY_BCN_ASSIGNED, ENTRY_OWNER_DEVICE_DATA, ENTRY_DATA_PENDING, - ENTRY_DATA_IO_FAILED + ENTRY_DATA_IO_FAILED, + ENTRY_DATA_STATUS_PENDING, }; /** @@ -417,13 +396,33 @@ enum queue_index { }; /** + * enum data_queue_flags: Status flags for data queues + * + * @QUEUE_STARTED: The queue has been started. Fox RX queues this means the + * device might be DMA'ing skbuffers. TX queues will accept skbuffers to + * be transmitted and beacon queues will start beaconing the configured + * beacons. + * @QUEUE_PAUSED: The queue has been started but is currently paused. + * When this bit is set, the queue has been stopped in mac80211, + * preventing new frames to be enqueued. However, a few frames + * might still appear shortly after the pausing... + */ +enum data_queue_flags { + QUEUE_STARTED, + QUEUE_PAUSED, +}; + +/** * struct data_queue: Data queue * * @rt2x00dev: Pointer to main &struct rt2x00dev where this queue belongs to. * @entries: Base address of the &struct queue_entry which are * part of this queue. * @qid: The queue identification, see &enum data_queue_qid. - * @lock: Spinlock to protect index handling. Whenever @index, @index_done or + * @flags: Entry flags, see &enum queue_entry_flags. + * @status_lock: The mutex for protecting the start/stop/flush + * handling on this queue. + * @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or * @index_crypt needs to be changed this lock should be grabbed to prevent * index corruption due to concurrency. * @count: Number of frames handled in the queue. @@ -446,8 +445,11 @@ struct data_queue { struct queue_entry *entries; enum data_queue_qid qid; + unsigned long flags; + + struct mutex status_lock; + spinlock_t index_lock; - spinlock_t lock; unsigned int count; unsigned short limit; unsigned short threshold; @@ -618,10 +620,10 @@ static inline int rt2x00queue_threshold(struct data_queue *queue) } /** - * rt2x00queue_timeout - Check if a timeout occured for STATUS reorts + * rt2x00queue_status_timeout - Check if a timeout occured for STATUS reports * @queue: Queue to check. */ -static inline int rt2x00queue_timeout(struct data_queue *queue) +static inline int rt2x00queue_status_timeout(struct data_queue *queue) { return time_after(queue->last_action[Q_INDEX_DMA_DONE], queue->last_action[Q_INDEX_DONE] + (HZ / 10)); diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index cef94621cef7..e8259ae48ced 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -83,10 +83,6 @@ enum dev_state { */ STATE_RADIO_ON, STATE_RADIO_OFF, - STATE_RADIO_RX_ON, - STATE_RADIO_RX_OFF, - STATE_RADIO_RX_ON_LINK, - STATE_RADIO_RX_OFF_LINK, STATE_RADIO_IRQ_ON, STATE_RADIO_IRQ_OFF, STATE_RADIO_IRQ_ON_ISR, diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c index fc98063de71d..2aa5c38022f3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.c +++ b/drivers/net/wireless/rt2x00/rt2x00soc.c @@ -40,6 +40,8 @@ static void rt2x00soc_free_reg(struct rt2x00_dev *rt2x00dev) kfree(rt2x00dev->eeprom); rt2x00dev->eeprom = NULL; + + iounmap(rt2x00dev->csr.base); } static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev) @@ -51,9 +53,9 @@ static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev) if (!res) return -ENODEV; - rt2x00dev->csr.base = (void __iomem *)KSEG1ADDR(res->start); + rt2x00dev->csr.base = ioremap(res->start, resource_size(res)); if (!rt2x00dev->csr.base) - goto exit; + return -ENOMEM; rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL); if (!rt2x00dev->eeprom) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index b3317df7a7d4..1a9937d5aff6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -195,7 +195,8 @@ static void rt2x00usb_work_txdone(struct work_struct *work) while (!rt2x00queue_empty(queue)) { entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || + !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) break; rt2x00usb_work_txdone_entry(entry); @@ -226,9 +227,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) * Schedule the delayed work for reading the TX status * from the device. */ - if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && - test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); + ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); } static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) @@ -237,8 +236,10 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); struct queue_entry_priv_usb *entry_priv = entry->priv_data; u32 length; + int status; - if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) + if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) || + test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) return; /* @@ -253,121 +254,15 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) entry->skb->data, length, rt2x00usb_interrupt_txdone, entry); - if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) { + status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); + if (status) { + if (status == -ENODEV) + clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); rt2x00lib_dmadone(entry); } } -void rt2x00usb_kick_tx_queue(struct data_queue *queue) -{ - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, - rt2x00usb_kick_tx_entry); -} -EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue); - -static void rt2x00usb_kill_tx_entry(struct queue_entry *entry) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct queue_entry_priv_usb *entry_priv = entry->priv_data; - struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; - - if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) - return; - - usb_kill_urb(entry_priv->urb); - - /* - * Kill guardian urb (if required by driver). - */ - if ((entry->queue->qid == QID_BEACON) && - (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))) - usb_kill_urb(bcn_priv->guardian_urb); -} - -void rt2x00usb_kill_tx_queue(struct data_queue *queue) -{ - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, - rt2x00usb_kill_tx_entry); -} -EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); - -static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - unsigned short threshold = queue->threshold; - - WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," - " invoke forced forced reset", queue->qid); - - /* - * Temporarily disable the TX queue, this will force mac80211 - * to use the other queues until this queue has been restored. - * - * Set the queue threshold to the queue limit. This prevents the - * queue from being enabled during the txdone handler. - */ - queue->threshold = queue->limit; - ieee80211_stop_queue(rt2x00dev->hw, queue->qid); - - /* - * Kill all entries in the queue, afterwards we need to - * wait a bit for all URBs to be cancelled. - */ - rt2x00usb_kill_tx_queue(queue); - - /* - * In case that a driver has overriden the txdone_work - * function, we invoke the TX done through there. - */ - rt2x00dev->txdone_work.func(&rt2x00dev->txdone_work); - - /* - * Security measure: if the driver did override the - * txdone_work function, and the hardware did arrive - * in a state which causes it to malfunction, it is - * possible that the driver couldn't handle the txdone - * event correctly. So after giving the driver the - * chance to cleanup, we now force a cleanup of any - * leftovers. - */ - if (!rt2x00queue_empty(queue)) { - WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," - " status handling failed, invoke hard reset", queue->qid); - rt2x00usb_work_txdone(&rt2x00dev->txdone_work); - } - - /* - * The queue has been reset, and mac80211 is allowed to use the - * queue again. - */ - queue->threshold = threshold; - ieee80211_wake_queue(rt2x00dev->hw, queue->qid); -} - -static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) -{ - WARNING(queue->rt2x00dev, "TX queue %d status timed out," - " invoke forced tx handler", queue->qid); - - ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work); -} - -void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - - tx_queue_for_each(rt2x00dev, queue) { - if (!rt2x00queue_empty(queue)) { - if (rt2x00queue_dma_timeout(queue)) - rt2x00usb_watchdog_tx_dma(queue); - if (rt2x00queue_timeout(queue)) - rt2x00usb_watchdog_tx_status(queue); - } - } -} -EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); - /* * RX data handlers. */ @@ -382,7 +277,8 @@ static void rt2x00usb_work_rxdone(struct work_struct *work) while (!rt2x00queue_empty(rt2x00dev->rx)) { entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE); - if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || + !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) break; /* @@ -424,11 +320,157 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) * Schedule the delayed work for reading the RX status * from the device. */ - if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && - test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); + ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); } +static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); + struct queue_entry_priv_usb *entry_priv = entry->priv_data; + int status; + + if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || + test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) + return; + + rt2x00lib_dmastart(entry); + + usb_fill_bulk_urb(entry_priv->urb, usb_dev, + usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint), + entry->skb->data, entry->skb->len, + rt2x00usb_interrupt_rxdone, entry); + + status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); + if (status) { + if (status == -ENODEV) + clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); + set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); + rt2x00lib_dmadone(entry); + } +} + +void rt2x00usb_kick_queue(struct data_queue *queue) +{ + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + if (!rt2x00queue_empty(queue)) + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00usb_kick_tx_entry); + break; + case QID_RX: + if (!rt2x00queue_full(queue)) + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00usb_kick_rx_entry); + break; + default: + break; + } +} +EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); + +static void rt2x00usb_flush_entry(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct queue_entry_priv_usb *entry_priv = entry->priv_data; + struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; + + if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + return; + + usb_kill_urb(entry_priv->urb); + + /* + * Kill guardian urb (if required by driver). + */ + if ((entry->queue->qid == QID_BEACON) && + (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))) + usb_kill_urb(bcn_priv->guardian_urb); +} + +void rt2x00usb_flush_queue(struct data_queue *queue) +{ + struct work_struct *completion; + unsigned int i; + + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00usb_flush_entry); + + /* + * Obtain the queue completion handler + */ + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + completion = &queue->rt2x00dev->txdone_work; + break; + case QID_RX: + completion = &queue->rt2x00dev->rxdone_work; + break; + default: + return; + } + + for (i = 0; i < 20; i++) { + /* + * Check if the driver is already done, otherwise we + * have to sleep a little while to give the driver/hw + * the oppurtunity to complete interrupt process itself. + */ + if (rt2x00queue_empty(queue)) + break; + + /* + * Schedule the completion handler manually, when this + * worker function runs, it should cleanup the queue. + */ + ieee80211_queue_work(queue->rt2x00dev->hw, completion); + + /* + * Wait for a little while to give the driver + * the oppurtunity to recover itself. + */ + msleep(10); + } +} +EXPORT_SYMBOL_GPL(rt2x00usb_flush_queue); + +static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) +{ + WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," + " invoke forced forced reset\n", queue->qid); + + rt2x00queue_flush_queue(queue, true); +} + +static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) +{ + WARNING(queue->rt2x00dev, "TX queue %d status timed out," + " invoke forced tx handler\n", queue->qid); + + ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work); +} + +void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + + tx_queue_for_each(rt2x00dev, queue) { + if (!rt2x00queue_empty(queue)) { + if (rt2x00queue_dma_timeout(queue)) + rt2x00usb_watchdog_tx_dma(queue); + if (rt2x00queue_status_timeout(queue)) + rt2x00usb_watchdog_tx_status(queue); + } + } +} +EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); + /* * Radio handlers */ @@ -436,12 +478,6 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) { rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0, REGISTER_TIMEOUT); - - /* - * The USB version of kill_tx_queue also works - * on the RX queue. - */ - rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev->rx); } EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); @@ -450,25 +486,10 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); */ void rt2x00usb_clear_entry(struct queue_entry *entry) { - struct usb_device *usb_dev = - to_usb_device_intf(entry->queue->rt2x00dev->dev); - struct queue_entry_priv_usb *entry_priv = entry->priv_data; - int pipe; - entry->flags = 0; - if (entry->queue->qid == QID_RX) { - pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); - usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, - entry->skb->data, entry->skb->len, - rt2x00usb_interrupt_rxdone, entry); - - set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) { - set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); - rt2x00lib_dmadone(entry); - } - } + if (entry->queue->qid == QID_RX) + rt2x00usb_kick_rx_entry(entry); } EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index c2d997f67b3e..6aaf51fc7ad8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -378,22 +378,22 @@ struct queue_entry_priv_usb_bcn { }; /** - * rt2x00usb_kick_tx_queue - Kick data queue + * rt2x00usb_kick_queue - Kick data queue * @queue: Data queue to kick * * This will walk through all entries of the queue and push all pending * frames to the hardware as a single burst. */ -void rt2x00usb_kick_tx_queue(struct data_queue *queue); +void rt2x00usb_kick_queue(struct data_queue *queue); /** - * rt2x00usb_kill_tx_queue - Kill data queue - * @queue: Data queue to kill + * rt2x00usb_flush_queue - Flush data queue + * @queue: Data queue to stop * * This will walk through all entries of the queue and kill all - * previously kicked frames before they can be send. + * URB's which were send to the device. */ -void rt2x00usb_kill_tx_queue(struct data_queue *queue); +void rt2x00usb_flush_queue(struct data_queue *queue); /** * rt2x00usb_watchdog - Watchdog for USB communication diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index af548c87f108..8de44dd401e0 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1140,6 +1140,106 @@ dynamic_cca_tune: } /* + * Queue handlers. + */ +static void rt61pci_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); + break; + case QID_BEACON: + rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + break; + default: + break; + } +} + +static void rt61pci_kick_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_AC_VO: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_AC_VI: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_AC_BE: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_AC_BK: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + default: + break; + } +} + +static void rt61pci_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_AC_VO: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_AC_VI: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_AC_BE: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_AC_BK: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_RX: + rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); + break; + case QID_BEACON: + rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + break; + default: + break; + } +} + +/* * Firmware functions */ static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) @@ -1616,18 +1716,6 @@ static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev) /* * Device state switch handlers. */ -static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); -} - static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, enum dev_state state) { @@ -1744,12 +1832,6 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, case STATE_RADIO_OFF: rt61pci_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt61pci_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -1789,10 +1871,10 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry, * Start writing the descriptor words. */ rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid); - rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); + rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid); + rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); @@ -1820,7 +1902,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry, rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); - if (txdesc->qid != QID_BEACON) { + if (entry->queue->qid != QID_BEACON) { rt2x00_desc_read(txd, 6, &word); rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, skbdesc->skb_dma); @@ -1866,8 +1948,8 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry, * Register descriptor details in skb frame descriptor. */ skbdesc->desc = txd; - skbdesc->desc_len = - (txdesc->qid == QID_BEACON) ? TXINFO_SIZE : TXD_DESC_SIZE; + skbdesc->desc_len = (entry->queue->qid == QID_BEACON) ? TXINFO_SIZE : + TXD_DESC_SIZE; } /* @@ -1879,6 +1961,7 @@ static void rt61pci_write_beacon(struct queue_entry *entry, struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct queue_entry_priv_pci *entry_priv = entry->priv_data; unsigned int beacon_base; + unsigned int padding_len; u32 reg; /* @@ -1900,13 +1983,16 @@ static void rt61pci_write_beacon(struct queue_entry *entry, rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); /* - * Write entire beacon with descriptor to register. + * Write entire beacon with descriptor and padding to register. */ + padding_len = roundup(entry->skb->len, 4) - entry->skb->len; + skb_pad(entry->skb, padding_len); beacon_base = HW_BEACON_OFFSET(entry->entry_idx); rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, entry_priv->desc, TXINFO_SIZE); rt2x00pci_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE, - entry->skb->data, entry->skb->len); + entry->skb->data, + entry->skb->len + padding_len); /* * Enable beaconing again. @@ -1928,37 +2014,6 @@ static void rt61pci_write_beacon(struct queue_entry *entry, entry->skb = NULL; } -static void rt61pci_kick_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, (queue->qid == QID_AC_BE)); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, (queue->qid == QID_AC_BK)); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, (queue->qid == QID_AC_VI)); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, (queue->qid == QID_AC_VO)); - rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); -} - -static void rt61pci_kill_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - if (queue->qid == QID_BEACON) { - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); - return; - } - - rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, (queue->qid == QID_AC_BE)); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, (queue->qid == QID_AC_BK)); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, (queue->qid == QID_AC_VI)); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, (queue->qid == QID_AC_VO)); - rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); -} - /* * RX control handlers */ @@ -2078,7 +2133,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) * that the TX_STA_FIFO stack has a size of 16. We stick to our * tx ring size for now. */ - for (i = 0; i < TX_ENTRIES; i++) { + for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { rt2x00pci_register_read(rt2x00dev, STA_CSR4, ®); if (!rt2x00_get_field32(reg, STA_CSR4_VALID)) break; @@ -2824,6 +2879,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .conf_tx = rt61pci_conf_tx, .get_tsf = rt61pci_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { @@ -2842,10 +2898,11 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .link_stats = rt61pci_link_stats, .reset_tuner = rt61pci_reset_tuner, .link_tuner = rt61pci_link_tuner, + .start_queue = rt61pci_start_queue, + .kick_queue = rt61pci_kick_queue, + .stop_queue = rt61pci_stop_queue, .write_tx_desc = rt61pci_write_tx_desc, .write_beacon = rt61pci_write_beacon, - .kick_tx_queue = rt61pci_kick_tx_queue, - .kill_tx_queue = rt61pci_kill_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, .config_shared_key = rt61pci_config_shared_key, .config_pairwise_key = rt61pci_config_pairwise_key, @@ -2857,21 +2914,21 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { }; static const struct data_queue_desc rt61pci_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt61pci_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt61pci_queue_bcn = { - .entry_num = 4 * BEACON_ENTRIES, + .entry_num = 4, .data_size = 0, /* No DMA required for beacons */ .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e2e728ab0b2e..e3cd6db76b0e 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -412,7 +412,7 @@ struct hw_pairwise_ta_entry { * DROP_VERSION_ERROR: Drop version error frame. * DROP_MULTICAST: Drop multicast frames. * DROP_BORADCAST: Drop broadcast frames. - * ROP_ACK_CTS: Drop received ACK and CTS. + * DROP_ACK_CTS: Drop received ACK and CTS. */ #define TXRX_CSR0 0x3040 #define TXRX_CSR0_RX_ACK_TIMEOUT FIELD32(0x000001ff) @@ -784,25 +784,25 @@ struct hw_pairwise_ta_entry { */ /* - * AC0_BASE_CSR: AC_BK base address. + * AC0_BASE_CSR: AC_VO base address. */ #define AC0_BASE_CSR 0x3400 #define AC0_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) /* - * AC1_BASE_CSR: AC_BE base address. + * AC1_BASE_CSR: AC_VI base address. */ #define AC1_BASE_CSR 0x3404 #define AC1_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) /* - * AC2_BASE_CSR: AC_VI base address. + * AC2_BASE_CSR: AC_BE base address. */ #define AC2_BASE_CSR 0x3408 #define AC2_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) /* - * AC3_BASE_CSR: AC_VO base address. + * AC3_BASE_CSR: AC_BK base address. */ #define AC3_BASE_CSR 0x340c #define AC3_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) @@ -814,7 +814,7 @@ struct hw_pairwise_ta_entry { #define MGMT_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) /* - * TX_RING_CSR0: TX Ring size for AC_BK, AC_BE, AC_VI, AC_VO. + * TX_RING_CSR0: TX Ring size for AC_VO, AC_VI, AC_BE, AC_BK. */ #define TX_RING_CSR0 0x3418 #define TX_RING_CSR0_AC0_RING_SIZE FIELD32(0x000000ff) @@ -833,10 +833,10 @@ struct hw_pairwise_ta_entry { /* * AIFSN_CSR: AIFSN for each EDCA AC. - * AIFSN0: For AC_BK. - * AIFSN1: For AC_BE. - * AIFSN2: For AC_VI. - * AIFSN3: For AC_VO. + * AIFSN0: For AC_VO. + * AIFSN1: For AC_VI. + * AIFSN2: For AC_BE. + * AIFSN3: For AC_BK. */ #define AIFSN_CSR 0x3420 #define AIFSN_CSR_AIFSN0 FIELD32(0x0000000f) @@ -846,10 +846,10 @@ struct hw_pairwise_ta_entry { /* * CWMIN_CSR: CWmin for each EDCA AC. - * CWMIN0: For AC_BK. - * CWMIN1: For AC_BE. - * CWMIN2: For AC_VI. - * CWMIN3: For AC_VO. + * CWMIN0: For AC_VO. + * CWMIN1: For AC_VI. + * CWMIN2: For AC_BE. + * CWMIN3: For AC_BK. */ #define CWMIN_CSR 0x3424 #define CWMIN_CSR_CWMIN0 FIELD32(0x0000000f) @@ -859,10 +859,10 @@ struct hw_pairwise_ta_entry { /* * CWMAX_CSR: CWmax for each EDCA AC. - * CWMAX0: For AC_BK. - * CWMAX1: For AC_BE. - * CWMAX2: For AC_VI. - * CWMAX3: For AC_VO. + * CWMAX0: For AC_VO. + * CWMAX1: For AC_VI. + * CWMAX2: For AC_BE. + * CWMAX3: For AC_BK. */ #define CWMAX_CSR 0x3428 #define CWMAX_CSR_CWMAX0 FIELD32(0x0000000f) @@ -883,14 +883,14 @@ struct hw_pairwise_ta_entry { /* * TX_CNTL_CSR: KICK/Abort TX. - * KICK_TX_AC0: For AC_BK. - * KICK_TX_AC1: For AC_BE. - * KICK_TX_AC2: For AC_VI. - * KICK_TX_AC3: For AC_VO. - * ABORT_TX_AC0: For AC_BK. - * ABORT_TX_AC1: For AC_BE. - * ABORT_TX_AC2: For AC_VI. - * ABORT_TX_AC3: For AC_VO. + * KICK_TX_AC0: For AC_VO. + * KICK_TX_AC1: For AC_VI. + * KICK_TX_AC2: For AC_BE. + * KICK_TX_AC3: For AC_BK. + * ABORT_TX_AC0: For AC_VO. + * ABORT_TX_AC1: For AC_VI. + * ABORT_TX_AC2: For AC_BE. + * ABORT_TX_AC3: For AC_BK. */ #define TX_CNTL_CSR 0x3430 #define TX_CNTL_CSR_KICK_TX_AC0 FIELD32(0x00000001) @@ -1010,18 +1010,18 @@ struct hw_pairwise_ta_entry { #define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040) /* - * AC_TXOP_CSR0: AC_BK/AC_BE TXOP register. - * AC0_TX_OP: For AC_BK, in unit of 32us. - * AC1_TX_OP: For AC_BE, in unit of 32us. + * AC_TXOP_CSR0: AC_VO/AC_VI TXOP register. + * AC0_TX_OP: For AC_VO, in unit of 32us. + * AC1_TX_OP: For AC_VI, in unit of 32us. */ #define AC_TXOP_CSR0 0x3474 #define AC_TXOP_CSR0_AC0_TX_OP FIELD32(0x0000ffff) #define AC_TXOP_CSR0_AC1_TX_OP FIELD32(0xffff0000) /* - * AC_TXOP_CSR1: AC_VO/AC_VI TXOP register. - * AC2_TX_OP: For AC_VI, in unit of 32us. - * AC3_TX_OP: For AC_VO, in unit of 32us. + * AC_TXOP_CSR1: AC_BE/AC_BK TXOP register. + * AC2_TX_OP: For AC_BE, in unit of 32us. + * AC3_TX_OP: For AC_BK, in unit of 32us. */ #define AC_TXOP_CSR1 0x3478 #define AC_TXOP_CSR1_AC2_TX_OP FIELD32(0x0000ffff) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 9be8089317e4..0b4e8590cbb7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -40,7 +40,7 @@ /* * Allow hardware encryption to be disabled. */ -static int modparam_nohwcrypt = 0; +static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -1031,6 +1031,55 @@ dynamic_cca_tune: } /* + * Queue handlers. + */ +static void rt73usb_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); + break; + case QID_BEACON: + rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); + break; + default: + break; + } +} + +static void rt73usb_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); + break; + case QID_BEACON: + rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); + break; + default: + break; + } +} + +/* * Firmware functions */ static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) @@ -1324,18 +1373,6 @@ static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev) /* * Device state switch handlers. */ -static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); -} - static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev) { /* @@ -1402,12 +1439,6 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, case STATE_RADIO_OFF: rt73usb_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt73usb_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -1472,10 +1503,10 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry, rt2x00_desc_write(txd, 0, word); rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid); - rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); + rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid); + rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); @@ -1515,6 +1546,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry, { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; unsigned int beacon_base; + unsigned int padding_len; u32 reg; /* @@ -1542,11 +1574,13 @@ static void rt73usb_write_beacon(struct queue_entry *entry, rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); /* - * Write entire beacon with descriptor to register. + * Write entire beacon with descriptor and padding to register. */ + padding_len = roundup(entry->skb->len, 4) - entry->skb->len; + skb_pad(entry->skb, padding_len); beacon_base = HW_BEACON_OFFSET(entry->entry_idx); - rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, - entry->skb->data, entry->skb->len); + rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, + entry->skb->len + padding_len); /* * Enable beaconing again. @@ -1582,14 +1616,6 @@ static int rt73usb_get_tx_data_len(struct queue_entry *entry) return length; } -static void rt73usb_kill_tx_queue(struct data_queue *queue) -{ - if (queue->qid == QID_BEACON) - rt2x00usb_register_write(queue->rt2x00dev, TXRX_CSR9, 0); - - rt2x00usb_kill_tx_queue(queue); -} - /* * RX control handlers */ @@ -2264,6 +2290,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .conf_tx = rt73usb_conf_tx, .get_tsf = rt73usb_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { @@ -2280,11 +2307,13 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .reset_tuner = rt73usb_reset_tuner, .link_tuner = rt73usb_link_tuner, .watchdog = rt2x00usb_watchdog, + .start_queue = rt73usb_start_queue, + .kick_queue = rt2x00usb_kick_queue, + .stop_queue = rt73usb_stop_queue, + .flush_queue = rt2x00usb_flush_queue, .write_tx_desc = rt73usb_write_tx_desc, .write_beacon = rt73usb_write_beacon, .get_tx_data_len = rt73usb_get_tx_data_len, - .kick_tx_queue = rt2x00usb_kick_tx_queue, - .kill_tx_queue = rt73usb_kill_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, .config_shared_key = rt73usb_config_shared_key, .config_pairwise_key = rt73usb_config_pairwise_key, @@ -2296,21 +2325,21 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { }; static const struct data_queue_desc rt73usb_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt73usb_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt73usb_queue_bcn = { - .entry_num = 4 * BEACON_ENTRIES, + .entry_num = 4, .data_size = MGMT_FRAME_SIZE, .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 44d5b2bebd39..9f6b470414d3 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -322,7 +322,7 @@ struct hw_pairwise_ta_entry { * DROP_VERSION_ERROR: Drop version error frame. * DROP_MULTICAST: Drop multicast frames. * DROP_BORADCAST: Drop broadcast frames. - * ROP_ACK_CTS: Drop received ACK and CTS. + * DROP_ACK_CTS: Drop received ACK and CTS. */ #define TXRX_CSR0 0x3040 #define TXRX_CSR0_RX_ACK_TIMEOUT FIELD32(0x000001ff) @@ -689,10 +689,10 @@ struct hw_pairwise_ta_entry { /* * AIFSN_CSR: AIFSN for each EDCA AC. - * AIFSN0: For AC_BK. - * AIFSN1: For AC_BE. - * AIFSN2: For AC_VI. - * AIFSN3: For AC_VO. + * AIFSN0: For AC_VO. + * AIFSN1: For AC_VI. + * AIFSN2: For AC_BE. + * AIFSN3: For AC_BK. */ #define AIFSN_CSR 0x0400 #define AIFSN_CSR_AIFSN0 FIELD32(0x0000000f) @@ -702,10 +702,10 @@ struct hw_pairwise_ta_entry { /* * CWMIN_CSR: CWmin for each EDCA AC. - * CWMIN0: For AC_BK. - * CWMIN1: For AC_BE. - * CWMIN2: For AC_VI. - * CWMIN3: For AC_VO. + * CWMIN0: For AC_VO. + * CWMIN1: For AC_VI. + * CWMIN2: For AC_BE. + * CWMIN3: For AC_BK. */ #define CWMIN_CSR 0x0404 #define CWMIN_CSR_CWMIN0 FIELD32(0x0000000f) @@ -715,10 +715,10 @@ struct hw_pairwise_ta_entry { /* * CWMAX_CSR: CWmax for each EDCA AC. - * CWMAX0: For AC_BK. - * CWMAX1: For AC_BE. - * CWMAX2: For AC_VI. - * CWMAX3: For AC_VO. + * CWMAX0: For AC_VO. + * CWMAX1: For AC_VI. + * CWMAX2: For AC_BE. + * CWMAX3: For AC_BK. */ #define CWMAX_CSR 0x0408 #define CWMAX_CSR_CWMAX0 FIELD32(0x0000000f) @@ -727,18 +727,18 @@ struct hw_pairwise_ta_entry { #define CWMAX_CSR_CWMAX3 FIELD32(0x0000f000) /* - * AC_TXOP_CSR0: AC_BK/AC_BE TXOP register. - * AC0_TX_OP: For AC_BK, in unit of 32us. - * AC1_TX_OP: For AC_BE, in unit of 32us. + * AC_TXOP_CSR0: AC_VO/AC_VI TXOP register. + * AC0_TX_OP: For AC_VO, in unit of 32us. + * AC1_TX_OP: For AC_VI, in unit of 32us. */ #define AC_TXOP_CSR0 0x040c #define AC_TXOP_CSR0_AC0_TX_OP FIELD32(0x0000ffff) #define AC_TXOP_CSR0_AC1_TX_OP FIELD32(0xffff0000) /* - * AC_TXOP_CSR1: AC_VO/AC_VI TXOP register. - * AC2_TX_OP: For AC_VI, in unit of 32us. - * AC3_TX_OP: For AC_VO, in unit of 32us. + * AC_TXOP_CSR1: AC_BE/AC_BK TXOP register. + * AC2_TX_OP: For AC_BE, in unit of 32us. + * AC3_TX_OP: For AC_BK, in unit of 32us. */ #define AC_TXOP_CSR1 0x0410 #define AC_TXOP_CSR1_AC2_TX_OP FIELD32(0x0000ffff) diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/rtl818x/Makefile index 93cbfbedb46d..997569076923 100644 --- a/drivers/net/wireless/rtl818x/Makefile +++ b/drivers/net/wireless/rtl818x/Makefile @@ -1,7 +1,2 @@ -rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o -rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o rtl8187_leds.o rtl8187_rfkill.o - -obj-$(CONFIG_RTL8180) += rtl8180.o -obj-$(CONFIG_RTL8187) += rtl8187.o - - +obj-$(CONFIG_RTL8180) += rtl8180/ +obj-$(CONFIG_RTL8187) += rtl8187/ diff --git a/drivers/net/wireless/rtl818x/rtl8180/Makefile b/drivers/net/wireless/rtl818x/rtl8180/Makefile new file mode 100644 index 000000000000..cb4fb8596f0b --- /dev/null +++ b/drivers/net/wireless/rtl818x/rtl8180/Makefile @@ -0,0 +1,5 @@ +rtl8180-objs := dev.o rtl8225.o sa2400.o max2820.o grf5101.o + +obj-$(CONFIG_RTL8180) += rtl8180.o + +ccflags-y += -Idrivers/net/wireless/rtl818x diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index 707c688da618..5851cbc1e957 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c @@ -24,10 +24,10 @@ #include <net/mac80211.h> #include "rtl8180.h" -#include "rtl8180_rtl8225.h" -#include "rtl8180_sa2400.h" -#include "rtl8180_max2820.h" -#include "rtl8180_grf5101.h" +#include "rtl8225.h" +#include "sa2400.h" +#include "max2820.h" +#include "grf5101.h" MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>"); MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); diff --git a/drivers/net/wireless/rtl818x/rtl8180_grf5101.c b/drivers/net/wireless/rtl818x/rtl8180/grf5101.c index 5cab9dfa8c07..5ee7589dd546 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_grf5101.c +++ b/drivers/net/wireless/rtl818x/rtl8180/grf5101.c @@ -25,7 +25,7 @@ #include <net/mac80211.h> #include "rtl8180.h" -#include "rtl8180_grf5101.h" +#include "grf5101.h" static const int grf5101_encode[] = { 0x0, 0x8, 0x4, 0xC, diff --git a/drivers/net/wireless/rtl818x/rtl8180_grf5101.h b/drivers/net/wireless/rtl818x/rtl8180/grf5101.h index 76647111bcff..76647111bcff 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_grf5101.h +++ b/drivers/net/wireless/rtl818x/rtl8180/grf5101.h diff --git a/drivers/net/wireless/rtl818x/rtl8180_max2820.c b/drivers/net/wireless/rtl818x/rtl8180/max2820.c index 16c4655181c0..667b3363d437 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_max2820.c +++ b/drivers/net/wireless/rtl818x/rtl8180/max2820.c @@ -24,7 +24,7 @@ #include <net/mac80211.h> #include "rtl8180.h" -#include "rtl8180_max2820.h" +#include "max2820.h" static const u32 max2820_chan[] = { 12, /* CH 1 */ diff --git a/drivers/net/wireless/rtl818x/rtl8180_max2820.h b/drivers/net/wireless/rtl818x/rtl8180/max2820.h index 61cf6d1e7d57..61cf6d1e7d57 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_max2820.h +++ b/drivers/net/wireless/rtl818x/rtl8180/max2820.h diff --git a/drivers/net/wireless/rtl818x/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h index 30523314da43..30523314da43 100644 --- a/drivers/net/wireless/rtl818x/rtl8180.h +++ b/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h diff --git a/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c index 69e4d4745dae..7c4574ba9d75 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c @@ -21,7 +21,7 @@ #include <net/mac80211.h> #include "rtl8180.h" -#include "rtl8180_rtl8225.h" +#include "rtl8225.h" static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data) { diff --git a/drivers/net/wireless/rtl818x/rtl8180_rtl8225.h b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.h index 310013a2d726..310013a2d726 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_rtl8225.h +++ b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.h diff --git a/drivers/net/wireless/rtl818x/rtl8180_sa2400.c b/drivers/net/wireless/rtl818x/rtl8180/sa2400.c index d064fcc5ec08..44771a6286af 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_sa2400.c +++ b/drivers/net/wireless/rtl818x/rtl8180/sa2400.c @@ -25,7 +25,7 @@ #include <net/mac80211.h> #include "rtl8180.h" -#include "rtl8180_sa2400.h" +#include "sa2400.h" static const u32 sa2400_chan[] = { 0x00096c, /* ch1 */ diff --git a/drivers/net/wireless/rtl818x/rtl8180_sa2400.h b/drivers/net/wireless/rtl818x/rtl8180/sa2400.h index a4aaa0d413f1..a4aaa0d413f1 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_sa2400.h +++ b/drivers/net/wireless/rtl818x/rtl8180/sa2400.h diff --git a/drivers/net/wireless/rtl818x/rtl8187/Makefile b/drivers/net/wireless/rtl818x/rtl8187/Makefile new file mode 100644 index 000000000000..7b6299268ecf --- /dev/null +++ b/drivers/net/wireless/rtl818x/rtl8187/Makefile @@ -0,0 +1,5 @@ +rtl8187-objs := dev.o rtl8225.o leds.o rfkill.o + +obj-$(CONFIG_RTL8187) += rtl8187.o + +ccflags-y += -Idrivers/net/wireless/rtl818x diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index 38fa8244cc96..6b82cac37ee3 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -29,11 +29,11 @@ #include <net/mac80211.h> #include "rtl8187.h" -#include "rtl8187_rtl8225.h" +#include "rtl8225.h" #ifdef CONFIG_RTL8187_LEDS -#include "rtl8187_leds.h" +#include "leds.h" #endif -#include "rtl8187_rfkill.h" +#include "rfkill.h" MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>"); MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); @@ -553,6 +553,46 @@ static int rtl8187b_init_status_urb(struct ieee80211_hw *dev) return ret; } +static void rtl8187_set_anaparam(struct rtl8187_priv *priv, bool rfon) +{ + u32 anaparam, anaparam2; + u8 anaparam3, reg; + + if (!priv->is_rtl8187b) { + if (rfon) { + anaparam = RTL8187_RTL8225_ANAPARAM_ON; + anaparam2 = RTL8187_RTL8225_ANAPARAM2_ON; + } else { + anaparam = RTL8187_RTL8225_ANAPARAM_OFF; + anaparam2 = RTL8187_RTL8225_ANAPARAM2_OFF; + } + } else { + if (rfon) { + anaparam = RTL8187B_RTL8225_ANAPARAM_ON; + anaparam2 = RTL8187B_RTL8225_ANAPARAM2_ON; + anaparam3 = RTL8187B_RTL8225_ANAPARAM3_ON; + } else { + anaparam = RTL8187B_RTL8225_ANAPARAM_OFF; + anaparam2 = RTL8187B_RTL8225_ANAPARAM2_OFF; + anaparam3 = RTL8187B_RTL8225_ANAPARAM3_OFF; + } + } + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + reg |= RTL818X_CONFIG3_ANAPARAM_WRITE; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, anaparam); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, anaparam2); + if (priv->is_rtl8187b) + rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, anaparam3); + reg &= ~RTL818X_CONFIG3_ANAPARAM_WRITE; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); +} + static int rtl8187_cmd_reset(struct ieee80211_hw *dev) { struct rtl8187_priv *priv = dev->priv; @@ -603,19 +643,7 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) int res; /* reset */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | - RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187_RTL8225_ANAPARAM_ON); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187_RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & - ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); + rtl8187_set_anaparam(priv, true); rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); @@ -629,17 +657,7 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) if (res) return res; - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187_RTL8225_ANAPARAM_ON); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187_RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + rtl8187_set_anaparam(priv, true); /* setup card */ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0); @@ -712,10 +730,9 @@ static const u8 rtl8187b_reg_table[][3] = { {0x58, 0x4B, 1}, {0x59, 0x00, 1}, {0x5A, 0x4B, 1}, {0x5B, 0x00, 1}, {0x60, 0x4B, 1}, {0x61, 0x09, 1}, {0x62, 0x4B, 1}, {0x63, 0x09, 1}, - {0xCE, 0x0F, 1}, {0xCF, 0x00, 1}, {0xE0, 0xFF, 1}, {0xE1, 0x0F, 1}, - {0xE2, 0x00, 1}, {0xF0, 0x4E, 1}, {0xF1, 0x01, 1}, {0xF2, 0x02, 1}, - {0xF3, 0x03, 1}, {0xF4, 0x04, 1}, {0xF5, 0x05, 1}, {0xF6, 0x06, 1}, - {0xF7, 0x07, 1}, {0xF8, 0x08, 1}, + {0xCE, 0x0F, 1}, {0xCF, 0x00, 1}, {0xF0, 0x4E, 1}, {0xF1, 0x01, 1}, + {0xF2, 0x02, 1}, {0xF3, 0x03, 1}, {0xF4, 0x04, 1}, {0xF5, 0x05, 1}, + {0xF6, 0x06, 1}, {0xF7, 0x07, 1}, {0xF8, 0x08, 1}, {0x4E, 0x00, 2}, {0x0C, 0x04, 2}, {0x21, 0x61, 2}, {0x22, 0x68, 2}, {0x23, 0x6F, 2}, {0x24, 0x76, 2}, {0x25, 0x7D, 2}, {0x26, 0x84, 2}, @@ -723,14 +740,13 @@ static const u8 rtl8187b_reg_table[][3] = { {0x52, 0x04, 2}, {0x53, 0xA0, 2}, {0x54, 0x1F, 2}, {0x55, 0x23, 2}, {0x56, 0x45, 2}, {0x57, 0x67, 2}, {0x58, 0x08, 2}, {0x59, 0x08, 2}, {0x5A, 0x08, 2}, {0x5B, 0x08, 2}, {0x60, 0x08, 2}, {0x61, 0x08, 2}, - {0x62, 0x08, 2}, {0x63, 0x08, 2}, {0x64, 0xCF, 2}, {0x72, 0x56, 2}, - {0x73, 0x9A, 2}, + {0x62, 0x08, 2}, {0x63, 0x08, 2}, {0x64, 0xCF, 2}, - {0x34, 0xF0, 0}, {0x35, 0x0F, 0}, {0x5B, 0x40, 0}, {0x84, 0x88, 0}, - {0x85, 0x24, 0}, {0x88, 0x54, 0}, {0x8B, 0xB8, 0}, {0x8C, 0x07, 0}, - {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, {0x95, 0x12, 0}, {0x96, 0x00, 0}, - {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, {0x9F, 0x10, 0}, {0xB4, 0x22, 0}, - {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x4C, 0x00, 2}, + {0x5B, 0x40, 0}, {0x84, 0x88, 0}, {0x85, 0x24, 0}, {0x88, 0x54, 0}, + {0x8B, 0xB8, 0}, {0x8C, 0x07, 0}, {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, + {0x95, 0x12, 0}, {0x96, 0x00, 0}, {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, + {0x9F, 0x10, 0}, {0xB4, 0x22, 0}, {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, + {0xEE, 0x00, 0}, {0x4C, 0x00, 2}, {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, {0x8E, 0x08, 0}, {0x8F, 0x00, 0} @@ -742,48 +758,34 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev) int res, i; u8 reg; - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - reg |= RTL818X_CONFIG3_ANAPARAM_WRITE | RTL818X_CONFIG3_GNT_SELECT; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187B_RTL8225_ANAPARAM2_ON); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187B_RTL8225_ANAPARAM_ON); - rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, - RTL8187B_RTL8225_ANAPARAM3_ON); + rtl8187_set_anaparam(priv, true); + /* Reset PLL sequence on 8187B. Realtek note: reduces power + * consumption about 30 mA */ rtl818x_iowrite8(priv, (u8 *)0xFF61, 0x10); reg = rtl818x_ioread8(priv, (u8 *)0xFF62); rtl818x_iowrite8(priv, (u8 *)0xFF62, reg & ~(1 << 5)); rtl818x_iowrite8(priv, (u8 *)0xFF62, reg | (1 << 5)); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - reg &= ~RTL818X_CONFIG3_ANAPARAM_WRITE; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); - res = rtl8187_cmd_reset(dev); if (res) return res; - rtl818x_iowrite16(priv, (__le16 *)0xFF2D, 0x0FFF); + rtl8187_set_anaparam(priv, true); + + /* BRSR (Basic Rate Set Register) on 8187B looks to be the same as + * RESP_RATE on 8187L in Realtek sources: each bit should be each + * one of the 12 rates, all are enabled */ + rtl818x_iowrite16(priv, (__le16 *)0xFF34, 0x0FFF); + reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT; rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); - reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); - reg |= RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT | - RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT; - rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); + /* Auto Rate Fallback Register (ARFR): 1M-54M setting */ rtl818x_iowrite16_idx(priv, (__le16 *)0xFFE0, 0x0FFF, 1); + rtl818x_iowrite8_idx(priv, (u8 *)0xFFE2, 0x00, 1); - rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); - rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); rtl818x_iowrite16_idx(priv, (__le16 *)0xFFD4, 0xFFFF, 1); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, @@ -811,16 +813,9 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev) rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00004001); + /* RFSW_CTRL register */ rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x569A, 2); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - reg |= RTL818X_CONFIG3_ANAPARAM_WRITE; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488); rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); @@ -929,6 +924,12 @@ static int rtl8187_start(struct ieee80211_hw *dev) priv->rx_conf = reg; rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); + reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); + reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT; + reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT; + reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT; + rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); + rtl818x_iowrite32(priv, &priv->map->TX_CONF, RTL818X_TX_CONF_HW_SEQNUM | RTL818X_TX_CONF_DISREQQSIZE | @@ -1002,6 +1003,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev) rtl818x_iowrite8(priv, &priv->map->CMD, reg); priv->rf->stop(dev); + rtl8187_set_anaparam(priv, false); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); reg = rtl818x_ioread8(priv, &priv->map->CONFIG4); diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187/leds.c index 4637337d5ce6..2e0de2f5f0f9 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187/leds.c @@ -20,7 +20,7 @@ #include <linux/eeprom_93cx6.h> #include "rtl8187.h" -#include "rtl8187_leds.h" +#include "leds.h" static void led_turn_on(struct work_struct *work) { diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.h b/drivers/net/wireless/rtl818x/rtl8187/leds.h index d743c96d4a20..d743c96d4a20 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.h +++ b/drivers/net/wireless/rtl818x/rtl8187/leds.h diff --git a/drivers/net/wireless/rtl818x/rtl8187_rfkill.c b/drivers/net/wireless/rtl818x/rtl8187/rfkill.c index 03555e1e0cab..34116719974a 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_rfkill.c +++ b/drivers/net/wireless/rtl818x/rtl8187/rfkill.c @@ -18,7 +18,7 @@ #include <net/mac80211.h> #include "rtl8187.h" -#include "rtl8187_rfkill.h" +#include "rfkill.h" static bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv) { diff --git a/drivers/net/wireless/rtl818x/rtl8187_rfkill.h b/drivers/net/wireless/rtl818x/rtl8187/rfkill.h index e12575e96d11..e12575e96d11 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_rfkill.h +++ b/drivers/net/wireless/rtl818x/rtl8187/rfkill.h diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h index 98878160a65a..0d7b1423f77b 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h @@ -16,7 +16,7 @@ #define RTL8187_H #include "rtl818x.h" -#include "rtl8187_leds.h" +#include "leds.h" #define RTL8187_EEPROM_TXPWR_BASE 0x05 #define RTL8187_EEPROM_MAC_ADDR 0x07 diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c index 97eebdcf7eb9..908903f721f5 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c @@ -21,7 +21,7 @@ #include <net/mac80211.h> #include "rtl8187.h" -#include "rtl8187_rtl8225.h" +#include "rtl8225.h" static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data) { @@ -898,29 +898,7 @@ static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev) static void rtl8225_rf_stop(struct ieee80211_hw *dev) { - u8 reg; - struct rtl8187_priv *priv = dev->priv; - rtl8225_write(dev, 0x4, 0x1f); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - if (!priv->is_rtl8187b) { - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187_RTL8225_ANAPARAM2_OFF); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187_RTL8225_ANAPARAM_OFF); - } else { - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187B_RTL8225_ANAPARAM2_OFF); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187B_RTL8225_ANAPARAM_OFF); - rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, - RTL8187B_RTL8225_ANAPARAM3_OFF); - } - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); } static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h b/drivers/net/wireless/rtl818x/rtl8187/rtl8225.h index 20c5b6ead0f6..20c5b6ead0f6 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h +++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8225.h diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig new file mode 100644 index 000000000000..7f6573f7f470 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/Kconfig @@ -0,0 +1,15 @@ +config RTL8192CE + tristate "Realtek RTL8192CE/RTL8188SE Wireless Network Adapter" + depends on MAC80211 && EXPERIMENTAL + select FW_LOADER + select RTLWIFI + ---help--- + This is the driver for Realtek RTL8192CE/RTL8188CE 802.11n PCIe + wireless network adapters. + + If you choose to build it as a module, it will be called rtl8192ce + +config RTLWIFI + tristate + depends on RTL8192CE + default m diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile new file mode 100644 index 000000000000..2a7a4384f8ee --- /dev/null +++ b/drivers/net/wireless/rtlwifi/Makefile @@ -0,0 +1,13 @@ +obj-$(CONFIG_RTLWIFI) += rtlwifi.o +rtlwifi-objs := \ + base.o \ + cam.o \ + core.o \ + debug.o \ + efuse.o \ + pci.o \ + ps.o \ + rc.o \ + regd.o + +obj-$(CONFIG_RTL8192CE) += rtl8192ce/ diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c new file mode 100644 index 000000000000..cf0b73e51fc2 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/base.c @@ -0,0 +1,956 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include <linux/ip.h> +#include "wifi.h" +#include "rc.h" +#include "base.h" +#include "efuse.h" +#include "cam.h" +#include "ps.h" +#include "regd.h" + +/* + *NOTICE!!!: This file will be very big, we hsould + *keep it clear under follwing roles: + * + *This file include follwing part, so, if you add new + *functions into this file, please check which part it + *should includes. or check if you should add new part + *for this file: + * + *1) mac80211 init functions + *2) tx information functions + *3) functions called by core.c + *4) wq & timer callback functions + *5) frame process functions + *6) sysfs functions + *7) ... + */ + +/********************************************************* + * + * mac80211 init functions + * + *********************************************************/ +static struct ieee80211_channel rtl_channeltable[] = { + {.center_freq = 2412, .hw_value = 1,}, + {.center_freq = 2417, .hw_value = 2,}, + {.center_freq = 2422, .hw_value = 3,}, + {.center_freq = 2427, .hw_value = 4,}, + {.center_freq = 2432, .hw_value = 5,}, + {.center_freq = 2437, .hw_value = 6,}, + {.center_freq = 2442, .hw_value = 7,}, + {.center_freq = 2447, .hw_value = 8,}, + {.center_freq = 2452, .hw_value = 9,}, + {.center_freq = 2457, .hw_value = 10,}, + {.center_freq = 2462, .hw_value = 11,}, + {.center_freq = 2467, .hw_value = 12,}, + {.center_freq = 2472, .hw_value = 13,}, + {.center_freq = 2484, .hw_value = 14,}, +}; + +static struct ieee80211_rate rtl_ratetable[] = { + {.bitrate = 10, .hw_value = 0x00,}, + {.bitrate = 20, .hw_value = 0x01,}, + {.bitrate = 55, .hw_value = 0x02,}, + {.bitrate = 110, .hw_value = 0x03,}, + {.bitrate = 60, .hw_value = 0x04,}, + {.bitrate = 90, .hw_value = 0x05,}, + {.bitrate = 120, .hw_value = 0x06,}, + {.bitrate = 180, .hw_value = 0x07,}, + {.bitrate = 240, .hw_value = 0x08,}, + {.bitrate = 360, .hw_value = 0x09,}, + {.bitrate = 480, .hw_value = 0x0a,}, + {.bitrate = 540, .hw_value = 0x0b,}, +}; + +static const struct ieee80211_supported_band rtl_band_2ghz = { + .band = IEEE80211_BAND_2GHZ, + + .channels = rtl_channeltable, + .n_channels = ARRAY_SIZE(rtl_channeltable), + + .bitrates = rtl_ratetable, + .n_bitrates = ARRAY_SIZE(rtl_ratetable), + + .ht_cap = {0}, +}; + +static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, + struct ieee80211_sta_ht_cap *ht_cap) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + ht_cap->ht_supported = true; + ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU; + + /* + *Maximum length of AMPDU that the STA can receive. + *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) + */ + ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + + /*Minimum MPDU start spacing , */ + ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; + + ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; + + /* + *hw->wiphy->bands[IEEE80211_BAND_2GHZ] + *base on ant_num + *rx_mask: RX mask + *if rx_ant =1 rx_mask[0]=0xff;==>MCS0-MCS7 + *if rx_ant =2 rx_mask[1]=0xff;==>MCS8-MCS15 + *if rx_ant >=3 rx_mask[2]=0xff; + *if BW_40 rx_mask[4]=0x01; + *highest supported RX rate + */ + if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_2T2R) { + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("1T2R or 2T2R\n")); + + ht_cap->mcs.rx_mask[0] = 0xFF; + ht_cap->mcs.rx_mask[1] = 0xFF; + ht_cap->mcs.rx_mask[4] = 0x01; + + ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS15; + } else if (get_rf_type(rtlphy) == RF_1T1R) { + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("1T1R\n")); + + ht_cap->mcs.rx_mask[0] = 0xFF; + ht_cap->mcs.rx_mask[1] = 0x00; + ht_cap->mcs.rx_mask[4] = 0x01; + + ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS7; + } +} + +static void _rtl_init_mac80211(struct ieee80211_hw *hw) +{ + struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct ieee80211_supported_band *sband; + + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); + + /* + * <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] + * to default value(1T1R) + */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, + sizeof(struct ieee80211_supported_band)); + + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + + /* <5> set hw caps */ + hw->flags = IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_AMPDU_AGGREGATION | /*PS*/ + /*IEEE80211_HW_SUPPORTS_PS | */ + /*IEEE80211_HW_PS_NULLFUNC_STACK | */ + /*IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */ + IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; + + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); + + hw->wiphy->rts_threshold = 2347; + + hw->queues = AC_MAX; + hw->extra_tx_headroom = RTL_TX_HEADER_SIZE; + + /* TODO: Correct this value for our hw */ + /* TODO: define these hard code value */ + hw->channel_change_time = 100; + hw->max_listen_interval = 5; + hw->max_rate_tries = 4; + /* hw->max_rates = 1; */ + + /* <6> mac address */ + if (is_valid_ether_addr(rtlefuse->dev_addr)) { + SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr); + } else { + u8 rtlmac[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 }; + get_random_bytes((rtlmac + (ETH_ALEN - 1)), 1); + SET_IEEE80211_PERM_ADDR(hw, rtlmac); + } + +} + +static void _rtl_init_deferred_work(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* <1> timer */ + init_timer(&rtlpriv->works.watchdog_timer); + setup_timer(&rtlpriv->works.watchdog_timer, + rtl_watch_dog_timer_callback, (unsigned long)hw); + + /* <2> work queue */ + rtlpriv->works.hw = hw; + rtlpriv->works.rtl_wq = alloc_workqueue(rtlpriv->cfg->name, 0, 0); + INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq, + (void *)rtl_watchdog_wq_callback); + INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, + (void *)rtl_ips_nic_off_wq_callback); + +} + +void rtl_deinit_deferred_work(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + del_timer_sync(&rtlpriv->works.watchdog_timer); + + cancel_delayed_work(&rtlpriv->works.watchdog_wq); + cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); +} + +void rtl_init_rfkill(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + bool radio_state; + bool blocked; + u8 valid = 0; + + radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); + + /*set init state to that of switch */ + rtlpriv->rfkill.rfkill_state = radio_state; + printk(KERN_INFO "rtlwifi: wireless switch is %s\n", + rtlpriv->rfkill.rfkill_state ? "on" : "off"); + + if (valid) { + rtlpriv->rfkill.rfkill_state = radio_state; + + blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1; + wiphy_rfkill_set_hw_state(hw->wiphy, blocked); + } + + wiphy_rfkill_start_polling(hw->wiphy); +} + +void rtl_deinit_rfkill(struct ieee80211_hw *hw) +{ + wiphy_rfkill_stop_polling(hw->wiphy); +} + +int rtl_init_core(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); + + /* <1> init mac80211 */ + _rtl_init_mac80211(hw); + rtlmac->hw = hw; + + /* <2> rate control register */ + if (rtl_rate_control_register()) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("rtl: Unable to register rtl_rc," + "use default RC !!\n")); + } else { + hw->rate_control_algorithm = "rtl_rc"; + } + + /* + * <3> init CRDA must come after init + * mac80211 hw in _rtl_init_mac80211. + */ + if (rtl_regd_init(hw, rtl_reg_notifier)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("REGD init failed\n")); + return 1; + } else { + /* CRDA regd hint must after init CRDA */ + if (regulatory_hint(hw->wiphy, rtlpriv->regd.alpha2)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("regulatory_hint fail\n")); + } + } + + /* <4> locks */ + mutex_init(&rtlpriv->locks.conf_mutex); + spin_lock_init(&rtlpriv->locks.ips_lock); + spin_lock_init(&rtlpriv->locks.irq_th_lock); + spin_lock_init(&rtlpriv->locks.h2c_lock); + spin_lock_init(&rtlpriv->locks.rf_ps_lock); + spin_lock_init(&rtlpriv->locks.rf_lock); + spin_lock_init(&rtlpriv->locks.lps_lock); + + rtlmac->link_state = MAC80211_NOLINK; + + /* <5> init deferred work */ + _rtl_init_deferred_work(hw); + + return 0; +} + +void rtl_deinit_core(struct ieee80211_hw *hw) +{ + /*RC*/ + rtl_rate_control_unregister(); +} + +void rtl_init_rx_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MGT_FILTER, + (u8 *) (&mac->rx_mgt_filter)); + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CTRL_FILTER, + (u8 *) (&mac->rx_ctrl_filter)); + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_DATA_FILTER, + (u8 *) (&mac->rx_data_filter)); +} + +/********************************************************* + * + * tx information functions + * + *********************************************************/ +static void _rtl_qurey_shortpreamble_mode(struct ieee80211_hw *hw, + struct rtl_tcb_desc *tcb_desc, + struct ieee80211_tx_info *info) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 rate_flag = info->control.rates[0].flags; + + tcb_desc->use_shortpreamble = false; + + /* 1M can only use Long Preamble. 11B spec */ + if (tcb_desc->hw_rate == rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]) + return; + else if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + tcb_desc->use_shortpreamble = true; + + return; +} + +static void _rtl_query_shortgi(struct ieee80211_hw *hw, + struct rtl_tcb_desc *tcb_desc, + struct ieee80211_tx_info *info) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 rate_flag = info->control.rates[0].flags; + + tcb_desc->use_shortgi = false; + + if (!mac->ht_enable) + return; + + if (!mac->sgi_40 && !mac->sgi_20) + return; + + if ((mac->bw_40 == true) && mac->sgi_40) + tcb_desc->use_shortgi = true; + else if ((mac->bw_40 == false) && mac->sgi_20) + tcb_desc->use_shortgi = true; + + if (!(rate_flag & IEEE80211_TX_RC_SHORT_GI)) + tcb_desc->use_shortgi = false; + +} + +static void _rtl_query_protection_mode(struct ieee80211_hw *hw, + struct rtl_tcb_desc *tcb_desc, + struct ieee80211_tx_info *info) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 rate_flag = info->control.rates[0].flags; + + /* Common Settings */ + tcb_desc->b_rts_stbc = false; + tcb_desc->b_cts_enable = false; + tcb_desc->rts_sc = 0; + tcb_desc->b_rts_bw = false; + tcb_desc->b_rts_use_shortpreamble = false; + tcb_desc->b_rts_use_shortgi = false; + + if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT) { + /* Use CTS-to-SELF in protection mode. */ + tcb_desc->b_rts_enable = true; + tcb_desc->b_cts_enable = true; + tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; + } else if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) { + /* Use RTS-CTS in protection mode. */ + tcb_desc->b_rts_enable = true; + tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; + } + +} + +static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, + struct rtl_tcb_desc *tcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { + if (mac->opmode == NL80211_IFTYPE_STATION) + tcb_desc->ratr_index = 0; + else if (mac->opmode == NL80211_IFTYPE_ADHOC) { + if (tcb_desc->b_multicast || tcb_desc->b_broadcast) { + tcb_desc->hw_rate = + rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; + tcb_desc->use_driver_rate = 1; + } else { + /* TODO */ + } + } + } + + if (rtlpriv->dm.b_useramask) { + /* TODO we will differentiate adhoc and station futrue */ + tcb_desc->mac_id = 0; + + if ((mac->mode == WIRELESS_MODE_N_24G) || + (mac->mode == WIRELESS_MODE_N_5G)) { + tcb_desc->ratr_index = RATR_INX_WIRELESS_NGB; + } else if (mac->mode & WIRELESS_MODE_G) { + tcb_desc->ratr_index = RATR_INX_WIRELESS_GB; + } else if (mac->mode & WIRELESS_MODE_B) { + tcb_desc->ratr_index = RATR_INX_WIRELESS_B; + } + } + +} + +static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, + struct rtl_tcb_desc *tcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + tcb_desc->b_packet_bw = false; + + if (!mac->bw_40 || !mac->ht_enable) + return; + + if (tcb_desc->b_multicast || tcb_desc->b_broadcast) + return; + + /*use legency rate, shall use 20MHz */ + if (tcb_desc->hw_rate <= rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]) + return; + + tcb_desc->b_packet_bw = true; +} + +static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u8 hw_rate; + + if (get_rf_type(rtlphy) == RF_2T2R) + hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS15]; + else + hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS7]; + + return hw_rate; +} + +void rtl_get_tcb_desc(struct ieee80211_hw *hw, + struct ieee80211_tx_info *info, + struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_rate *txrate; + u16 fc = le16_to_cpu(hdr->frame_control); + + memset(tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + + if (ieee80211_is_data(fc)) { + txrate = ieee80211_get_tx_rate(hw, info); + tcb_desc->hw_rate = txrate->hw_value; + + /* + *we set data rate RTL_RC_CCK_RATE1M + *in rtl_rc.c if skb is special data or + *mgt which need low data rate. + */ + + /* + *So tcb_desc->hw_rate is just used for + *special data and mgt frames + */ + if (tcb_desc->hw_rate < rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]) { + tcb_desc->use_driver_rate = true; + tcb_desc->ratr_index = 7; + + tcb_desc->hw_rate = + rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; + tcb_desc->disable_ratefallback = 1; + } else { + /* + *because hw will nerver use hw_rate + *when tcb_desc->use_driver_rate = false + *so we never set highest N rate here, + *and N rate will all be controled by FW + *when tcb_desc->use_driver_rate = false + */ + if (rtlmac->ht_enable) { + tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw); + } else { + if (rtlmac->mode == WIRELESS_MODE_B) { + tcb_desc->hw_rate = + rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]; + } else { + tcb_desc->hw_rate = + rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]; + } + } + } + + if (is_multicast_ether_addr(ieee80211_get_DA(hdr))) + tcb_desc->b_multicast = 1; + else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr))) + tcb_desc->b_broadcast = 1; + + _rtl_txrate_selectmode(hw, tcb_desc); + _rtl_query_bandwidth_mode(hw, tcb_desc); + _rtl_qurey_shortpreamble_mode(hw, tcb_desc, info); + _rtl_query_shortgi(hw, tcb_desc, info); + _rtl_query_protection_mode(hw, tcb_desc, info); + } else { + tcb_desc->use_driver_rate = true; + tcb_desc->ratr_index = 7; + tcb_desc->disable_ratefallback = 1; + tcb_desc->mac_id = 0; + + tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; + } +} +EXPORT_SYMBOL(rtl_get_tcb_desc); + +bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + u16 fc = le16_to_cpu(hdr->frame_control); + + if (ieee80211_is_auth(fc)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); + rtl_ips_nic_on(hw); + + mac->link_state = MAC80211_LINKING; + } + + return true; +} + +bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 fc = le16_to_cpu(hdr->frame_control); + u8 *act = (u8 *) (((u8 *) skb->data + MAC80211_3ADDR_LEN)); + u8 category; + + if (!ieee80211_is_action(fc)) + return true; + + category = *act; + act++; + switch (category) { + case ACT_CAT_BA: + switch (*act) { + case ACT_ADDBAREQ: + if (mac->act_scanning) + return false; + + RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, + ("%s ACT_ADDBAREQ From :" MAC_FMT "\n", + is_tx ? "Tx" : "Rx", MAC_ARG(hdr->addr2))); + break; + case ACT_ADDBARSP: + RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, + ("%s ACT_ADDBARSP From :" MAC_FMT "\n", + is_tx ? "Tx" : "Rx", MAC_ARG(hdr->addr2))); + break; + case ACT_DELBA: + RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, + ("ACT_ADDBADEL From :" MAC_FMT "\n", + MAC_ARG(hdr->addr2))); + break; + } + break; + default: + break; + } + + return true; +} + +/*should call before software enc*/ +u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u16 fc = le16_to_cpu(hdr->frame_control); + u16 ether_type; + u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb); + const struct iphdr *ip; + + if (!ieee80211_is_data(fc)) + goto end; + + if (ieee80211_is_nullfunc(fc)) + return true; + + ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len + + SNAP_SIZE + PROTOC_TYPE_SIZE); + ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE); + ether_type = ntohs(ether_type); + + if (ETH_P_IP == ether_type) { + if (IPPROTO_UDP == ip->protocol) { + struct udphdr *udp = (struct udphdr *)((u8 *) ip + + (ip->ihl << 2)); + if (((((u8 *) udp)[1] == 68) && + (((u8 *) udp)[3] == 67)) || + ((((u8 *) udp)[1] == 67) && + (((u8 *) udp)[3] == 68))) { + /* + * 68 : UDP BOOTP client + * 67 : UDP BOOTP server + */ + RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), + DBG_DMESG, ("dhcp %s !!\n", + (is_tx) ? "Tx" : "Rx")); + + if (is_tx) { + rtl_lps_leave(hw); + ppsc->last_delaylps_stamp_jiffies = + jiffies; + } + + return true; + } + } + } else if (ETH_P_ARP == ether_type) { + if (is_tx) { + rtl_lps_leave(hw); + ppsc->last_delaylps_stamp_jiffies = jiffies; + } + + return true; + } else if (ETH_P_PAE == ether_type) { + RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, + ("802.1X %s EAPOL pkt!!\n", (is_tx) ? "Tx" : "Rx")); + + if (is_tx) { + rtl_lps_leave(hw); + ppsc->last_delaylps_stamp_jiffies = jiffies; + } + + return true; + } else if (0x86DD == ether_type) { + return true; + } + +end: + return false; +} + +/********************************************************* + * + * functions called by core.c + * + *********************************************************/ +int rtl_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra, u16 tid, u16 *ssn) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_tid_data *tid_data; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, + ("on ra = %pM tid = %d\n", ra, tid)); + + if (unlikely(tid >= MAX_TID_COUNT)) + return -EINVAL; + + if (mac->tids[tid].agg.agg_state != RTL_AGG_OFF) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("Start AGG when state is not RTL_AGG_OFF !\n")); + return -ENXIO; + } + + tid_data = &mac->tids[tid]; + *ssn = SEQ_TO_SN(tid_data->seq_number); + + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, + ("HW queue is empty tid:%d\n", tid)); + tid_data->agg.agg_state = RTL_AGG_ON; + + ieee80211_start_tx_ba_cb_irqsafe(mac->vif, ra, tid); + + return 0; +} + +int rtl_tx_agg_stop(struct ieee80211_hw *hw, const u8 * ra, u16 tid) +{ + int ssn = -1; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_tid_data *tid_data; + + if (!ra) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("ra = NULL\n")); + return -EINVAL; + } + + if (unlikely(tid >= MAX_TID_COUNT)) + return -EINVAL; + + if (mac->tids[tid].agg.agg_state != RTL_AGG_ON) + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("Stopping AGG while state not ON or starting\n")); + + tid_data = &mac->tids[tid]; + ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; + + mac->tids[tid].agg.agg_state = RTL_AGG_OFF; + + ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, ra, tid); + + return 0; +} + +/********************************************************* + * + * wq & timer callback functions + * + *********************************************************/ +void rtl_watchdog_wq_callback(void *data) +{ + struct rtl_works *rtlworks = container_of_dwork_rtl(data, + struct rtl_works, + watchdog_wq); + struct ieee80211_hw *hw = rtlworks->hw; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + bool b_busytraffic = false; + bool b_higher_busytraffic = false; + bool b_higher_busyrxtraffic = false; + bool b_higher_busytxtraffic = false; + + u8 idx = 0; + u32 rx_cnt_inp4eriod = 0; + u32 tx_cnt_inp4eriod = 0; + u32 aver_rx_cnt_inperiod = 0; + u32 aver_tx_cnt_inperiod = 0; + + bool benter_ps = false; + + if (is_hal_stop(rtlhal)) + return; + + /* <1> Determine if action frame is allowed */ + if (mac->link_state > MAC80211_NOLINK) { + if (mac->cnt_after_linked < 20) + mac->cnt_after_linked++; + } else { + mac->cnt_after_linked = 0; + } + + /* <2> DM */ + rtlpriv->cfg->ops->dm_watchdog(hw); + + /* + *<3> to check if traffic busy, if + * busytraffic we don't change channel + */ + if (mac->link_state >= MAC80211_LINKED) { + + /* (1) get aver_rx_cnt_inperiod & aver_tx_cnt_inperiod */ + for (idx = 0; idx <= 2; idx++) { + rtlpriv->link_info.num_rx_in4period[idx] = + rtlpriv->link_info.num_rx_in4period[idx + 1]; + rtlpriv->link_info.num_tx_in4period[idx] = + rtlpriv->link_info.num_tx_in4period[idx + 1]; + } + rtlpriv->link_info.num_rx_in4period[3] = + rtlpriv->link_info.num_rx_inperiod; + rtlpriv->link_info.num_tx_in4period[3] = + rtlpriv->link_info.num_tx_inperiod; + for (idx = 0; idx <= 3; idx++) { + rx_cnt_inp4eriod += + rtlpriv->link_info.num_rx_in4period[idx]; + tx_cnt_inp4eriod += + rtlpriv->link_info.num_tx_in4period[idx]; + } + aver_rx_cnt_inperiod = rx_cnt_inp4eriod / 4; + aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4; + + /* (2) check traffic busy */ + if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) + b_busytraffic = true; + + /* Higher Tx/Rx data. */ + if (aver_rx_cnt_inperiod > 4000 || + aver_tx_cnt_inperiod > 4000) { + b_higher_busytraffic = true; + + /* Extremely high Rx data. */ + if (aver_rx_cnt_inperiod > 5000) + b_higher_busyrxtraffic = true; + else + b_higher_busytxtraffic = false; + } + + if (((rtlpriv->link_info.num_rx_inperiod + + rtlpriv->link_info.num_tx_inperiod) > 8) || + (rtlpriv->link_info.num_rx_inperiod > 2)) + benter_ps = false; + else + benter_ps = true; + + /* LeisurePS only work in infra mode. */ + if (benter_ps) + rtl_lps_enter(hw); + else + rtl_lps_leave(hw); + } + + rtlpriv->link_info.num_rx_inperiod = 0; + rtlpriv->link_info.num_tx_inperiod = 0; + + rtlpriv->link_info.b_busytraffic = b_busytraffic; + rtlpriv->link_info.b_higher_busytraffic = b_higher_busytraffic; + rtlpriv->link_info.b_higher_busyrxtraffic = b_higher_busyrxtraffic; + +} + +void rtl_watch_dog_timer_callback(unsigned long data) +{ + struct ieee80211_hw *hw = (struct ieee80211_hw *)data; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + queue_delayed_work(rtlpriv->works.rtl_wq, + &rtlpriv->works.watchdog_wq, 0); + + mod_timer(&rtlpriv->works.watchdog_timer, + jiffies + MSECS(RTL_WATCH_DOG_TIME)); +} + +/********************************************************* + * + * sysfs functions + * + *********************************************************/ +static ssize_t rtl_show_debug_level(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct ieee80211_hw *hw = dev_get_drvdata(d); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + return sprintf(buf, "0x%08X\n", rtlpriv->dbg.global_debuglevel); +} + +static ssize_t rtl_store_debug_level(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ieee80211_hw *hw = dev_get_drvdata(d); + struct rtl_priv *rtlpriv = rtl_priv(hw); + unsigned long val; + int ret; + + ret = strict_strtoul(buf, 0, &val); + if (ret) { + printk(KERN_DEBUG "%s is not in hex or decimal form.\n", buf); + } else { + rtlpriv->dbg.global_debuglevel = val; + printk(KERN_DEBUG "debuglevel:%x\n", + rtlpriv->dbg.global_debuglevel); + } + + return strnlen(buf, count); +} + +static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, + rtl_show_debug_level, rtl_store_debug_level); + +static struct attribute *rtl_sysfs_entries[] = { + + &dev_attr_debug_level.attr, + + NULL +}; + +/* + * "name" is folder name witch will be + * put in device directory like : + * sys/devices/pci0000:00/0000:00:1c.4/ + * 0000:06:00.0/rtl_sysfs + */ +struct attribute_group rtl_attribute_group = { + .name = "rtlsysfs", + .attrs = rtl_sysfs_entries, +}; + +MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>"); +MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>"); +MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); + +static int __init rtl_core_module_init(void) +{ + return 0; +} + +static void __exit rtl_core_module_exit(void) +{ +} + +module_init(rtl_core_module_init); +module_exit(rtl_core_module_exit); diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h new file mode 100644 index 000000000000..3de5a14745f1 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/base.h @@ -0,0 +1,120 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + *****************************************************************************/ + +#ifndef __RTL_BASE_H__ +#define __RTL_BASE_H__ + +#define RTL_DUMMY_OFFSET 0 +#define RTL_DUMMY_UNIT 8 +#define RTL_TX_DUMMY_SIZE (RTL_DUMMY_OFFSET * RTL_DUMMY_UNIT) +#define RTL_TX_DESC_SIZE 32 +#define RTL_TX_HEADER_SIZE (RTL_TX_DESC_SIZE + RTL_TX_DUMMY_SIZE) + +#define HT_AMSDU_SIZE_4K 3839 +#define HT_AMSDU_SIZE_8K 7935 + +#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */ +#define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */ + +#define RTL_RATE_COUNT_LEGACY 12 +#define RTL_CHANNEL_COUNT 14 + +#define FRAME_OFFSET_FRAME_CONTROL 0 +#define FRAME_OFFSET_DURATION 2 +#define FRAME_OFFSET_ADDRESS1 4 +#define FRAME_OFFSET_ADDRESS2 10 +#define FRAME_OFFSET_ADDRESS3 16 +#define FRAME_OFFSET_SEQUENCE 22 +#define FRAME_OFFSET_ADDRESS4 24 + +#define SET_80211_HDR_FRAME_CONTROL(_hdr, _val) \ + WRITEEF2BYTE(_hdr, _val) +#define SET_80211_HDR_TYPE_AND_SUBTYPE(_hdr, _val) \ + WRITEEF1BYTE(_hdr, _val) +#define SET_80211_HDR_PWR_MGNT(_hdr, _val) \ + SET_BITS_TO_LE_2BYTE(_hdr, 12, 1, _val) +#define SET_80211_HDR_TO_DS(_hdr, _val) \ + SET_BITS_TO_LE_2BYTE(_hdr, 8, 1, _val) + +#define SET_80211_PS_POLL_AID(_hdr, _val) \ + WRITEEF2BYTE(((u8 *)(_hdr)) + 2, _val) +#define SET_80211_PS_POLL_BSSID(_hdr, _val) \ + CP_MACADDR(((u8 *)(_hdr)) + 4, (u8 *)(_val)) +#define SET_80211_PS_POLL_TA(_hdr, _val) \ + CP_MACADDR(((u8 *)(_hdr)) + 10, (u8 *)(_val)) + +#define SET_80211_HDR_DURATION(_hdr, _val) \ + WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_DURATION, _val) +#define SET_80211_HDR_ADDRESS1(_hdr, _val) \ + CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8*)(_val)) +#define SET_80211_HDR_ADDRESS2(_hdr, _val) \ + CP_MACADDR((u8 *)(_hdr) + FRAME_OFFSET_ADDRESS2, (u8 *)(_val)) +#define SET_80211_HDR_ADDRESS3(_hdr, _val) \ + CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val)) +#define SET_80211_HDR_FRAGMENT_SEQUENCE(_hdr, _val) \ + WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_SEQUENCE, _val) + +#define SET_BEACON_PROBE_RSP_TIME_STAMP_LOW(__phdr, __val) \ + WRITEEF4BYTE(((u8 *)(__phdr)) + 24, __val) +#define SET_BEACON_PROBE_RSP_TIME_STAMP_HIGH(__phdr, __val) \ + WRITEEF4BYTE(((u8 *)(__phdr)) + 28, __val) +#define SET_BEACON_PROBE_RSP_BEACON_INTERVAL(__phdr, __val) \ + WRITEEF2BYTE(((u8 *)(__phdr)) + 32, __val) +#define GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) \ + READEF2BYTE(((u8 *)(__phdr)) + 34) +#define SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ + WRITEEF2BYTE(((u8 *)(__phdr)) + 34, __val) +#define MASK_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ + SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, \ + (GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) & (~(__val)))) + +int rtl_init_core(struct ieee80211_hw *hw); +void rtl_deinit_core(struct ieee80211_hw *hw); +void rtl_init_rx_config(struct ieee80211_hw *hw); +void rtl_init_rfkill(struct ieee80211_hw *hw); +void rtl_deinit_rfkill(struct ieee80211_hw *hw); + +void rtl_watch_dog_timer_callback(unsigned long data); +void rtl_deinit_deferred_work(struct ieee80211_hw *hw); + +bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); +bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); +u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); + +void rtl_watch_dog_timer_callback(unsigned long data); +int rtl_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra, + u16 tid, u16 *ssn); +int rtl_tx_agg_stop(struct ieee80211_hw *hw, const u8 *ra, u16 tid); +void rtl_watchdog_wq_callback(void *data); + +void rtl_get_tcb_desc(struct ieee80211_hw *hw, + struct ieee80211_tx_info *info, + struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc); + +extern struct attribute_group rtl_attribute_group; +#endif diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c new file mode 100644 index 000000000000..52c9c1367cac --- /dev/null +++ b/drivers/net/wireless/rtlwifi/cam.c @@ -0,0 +1,291 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + *****************************************************************************/ + +#include "wifi.h" +#include "cam.h" + +void rtl_cam_reset_sec_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->sec.use_defaultkey = false; + rtlpriv->sec.pairwise_enc_algorithm = NO_ENCRYPTION; + rtlpriv->sec.group_enc_algorithm = NO_ENCRYPTION; + memset(rtlpriv->sec.key_buf, 0, KEY_BUF_SIZE * MAX_KEY_LEN); + memset(rtlpriv->sec.key_len, 0, KEY_BUF_SIZE); + rtlpriv->sec.pairwise_key = NULL; +} + +static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, + u8 *mac_addr, u8 *key_cont_128, u16 us_config) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + u32 target_command; + u32 target_content = 0; + u8 entry_i; + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("key_cont_128:\n %x:%x:%x:%x:%x:%x\n", + key_cont_128[0], key_cont_128[1], + key_cont_128[2], key_cont_128[3], + key_cont_128[4], key_cont_128[5])); + + for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { + target_command = entry_i + CAM_CONTENT_COUNT * entry_no; + target_command = target_command | BIT(31) | BIT(16); + + if (entry_i == 0) { + target_content = (u32) (*(mac_addr + 0)) << 16 | + (u32) (*(mac_addr + 1)) << 24 | (u32) us_config; + + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], + target_content); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], + target_command); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_program_entry(): " + "WRITE %x: %x\n", + rtlpriv->cfg->maps[WCAMI], target_content)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("The Key ID is %d\n", entry_no)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_program_entry(): " + "WRITE %x: %x\n", + rtlpriv->cfg->maps[RWCAM], target_command)); + + } else if (entry_i == 1) { + + target_content = (u32) (*(mac_addr + 5)) << 24 | + (u32) (*(mac_addr + 4)) << 16 | + (u32) (*(mac_addr + 3)) << 8 | + (u32) (*(mac_addr + 2)); + + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], + target_content); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], + target_command); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_program_entry(): WRITE A4: %x\n", + target_content)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_program_entry(): WRITE A0: %x\n", + target_command)); + + } else { + + target_content = + (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 3)) << + 24 | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 2)) + << 16 | + (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 1)) << 8 + | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 0)); + + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], + target_content); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], + target_command); + udelay(100); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_program_entry(): WRITE A4: %x\n", + target_content)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_program_entry(): WRITE A0: %x\n", + target_command)); + } + } + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("after set key, usconfig:%x\n", us_config)); +} + +u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, + u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg, + u32 ul_default_key, u8 *key_content) +{ + u32 us_config; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, " + "ulUseDK=%x MacAddr" MAC_FMT "\n", + ul_entry_idx, ul_key_id, ul_enc_alg, + ul_default_key, MAC_ARG(mac_addr))); + + if (ul_key_id == TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("<=== ulKeyId exceed!\n")); + return 0; + } + + if (ul_default_key == 1) { + us_config = CFG_VALID | ((u16) (ul_enc_alg) << 2); + } else { + us_config = CFG_VALID | ((ul_enc_alg) << 2) | ul_key_id; + } + + rtl_cam_program_entry(hw, ul_entry_idx, mac_addr, + (u8 *) key_content, us_config); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("<===\n")); + + return 1; + +} +EXPORT_SYMBOL(rtl_cam_add_one_entry); + +int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, + u8 *mac_addr, u32 ul_key_id) +{ + u32 ul_command; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("key_idx:%d\n", ul_key_id)); + + ul_command = ul_key_id * CAM_CONTENT_COUNT; + ul_command = ul_command | BIT(31) | BIT(16); + + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 0); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_delete_one_entry(): WRITE A4: %x\n", 0)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_delete_one_entry(): WRITE A0: %x\n", ul_command)); + + return 0; + +} +EXPORT_SYMBOL(rtl_cam_delete_one_entry); + +void rtl_cam_reset_all_entry(struct ieee80211_hw *hw) +{ + u32 ul_command; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + ul_command = BIT(31) | BIT(30); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); +} +EXPORT_SYMBOL(rtl_cam_reset_all_entry); + +void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + u32 ul_command; + u32 ul_content; + u32 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; + + switch (rtlpriv->sec.pairwise_enc_algorithm) { + case WEP40_ENCRYPTION: + ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP40]; + break; + case WEP104_ENCRYPTION: + ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP104]; + break; + case TKIP_ENCRYPTION: + ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_TKIP]; + break; + case AESCCMP_ENCRYPTION: + ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; + break; + default: + ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; + } + + ul_content = (uc_index & 3) | ((u16) (ul_enc_algo) << 2); + + ul_content |= BIT(15); + ul_command = CAM_CONTENT_COUNT * uc_index; + ul_command = ul_command | BIT(31) | BIT(16); + + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_mark_invalid(): WRITE A4: %x\n", ul_content)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_mark_invalid(): WRITE A0: %x\n", ul_command)); +} +EXPORT_SYMBOL(rtl_cam_mark_invalid); + +void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + u32 ul_command; + u32 ul_content; + u32 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; + u8 entry_i; + + switch (rtlpriv->sec.pairwise_enc_algorithm) { + case WEP40_ENCRYPTION: + ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP40]; + break; + case WEP104_ENCRYPTION: + ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP104]; + break; + case TKIP_ENCRYPTION: + ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_TKIP]; + break; + case AESCCMP_ENCRYPTION: + ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; + break; + default: + ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; + } + + for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { + + if (entry_i == 0) { + ul_content = + (uc_index & 0x03) | ((u16) (ul_encalgo) << 2); + ul_content |= BIT(15); + + } else { + ul_content = 0; + } + + ul_command = CAM_CONTENT_COUNT * uc_index + entry_i; + ul_command = ul_command | BIT(31) | BIT(16); + + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("rtl_cam_empty_entry(): WRITE A4: %x\n", + ul_content)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("rtl_cam_empty_entry(): WRITE A0: %x\n", + ul_command)); + } + +} +EXPORT_SYMBOL(rtl_cam_empty_entry); diff --git a/drivers/net/wireless/rtlwifi/cam.h b/drivers/net/wireless/rtlwifi/cam.h new file mode 100644 index 000000000000..dd82f057d53d --- /dev/null +++ b/drivers/net/wireless/rtlwifi/cam.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + *****************************************************************************/ + +#ifndef __RTL_CAM_H_ +#define __RTL_CAM_H_ + +#define TOTAL_CAM_ENTRY 32 +#define CAM_CONTENT_COUNT 8 + +#define CFG_DEFAULT_KEY BIT(5) +#define CFG_VALID BIT(15) + +#define PAIRWISE_KEYIDX 0 +#define CAM_PAIRWISE_KEY_POSITION 4 + +#define CAM_CONFIG_USEDK 1 +#define CAM_CONFIG_NO_USEDK 0 + +extern void rtl_cam_reset_all_entry(struct ieee80211_hw *hw); +extern u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, + u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg, + u32 ul_default_key, u8 *key_content); +int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, + u32 ul_key_id); +void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index); +void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index); +void rtl_cam_reset_sec_info(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c new file mode 100644 index 000000000000..d6a924a05654 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/core.c @@ -0,0 +1,1029 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + *****************************************************************************/ + +#include "wifi.h" +#include "core.h" +#include "cam.h" +#include "base.h" +#include "ps.h" + +/*mutex for start & stop is must here. */ +static int rtl_op_start(struct ieee80211_hw *hw) +{ + int err = 0; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (!is_hal_stop(rtlhal)) + return 0; + if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) + return 0; + mutex_lock(&rtlpriv->locks.conf_mutex); + err = rtlpriv->intf_ops->adapter_start(hw); + if (err) + goto out; + rtl_watch_dog_timer_callback((unsigned long)hw); +out: + mutex_unlock(&rtlpriv->locks.conf_mutex); + return err; +} + +static void rtl_op_stop(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if (is_hal_stop(rtlhal)) + return; + + if (unlikely(ppsc->rfpwr_state == ERFOFF)) { + rtl_ips_nic_on(hw); + mdelay(1); + } + + mutex_lock(&rtlpriv->locks.conf_mutex); + + mac->link_state = MAC80211_NOLINK; + memset(mac->bssid, 0, 6); + + /*reset sec info */ + rtl_cam_reset_sec_info(hw); + + rtl_deinit_deferred_work(hw); + rtlpriv->intf_ops->adapter_stop(hw); + + mutex_unlock(&rtlpriv->locks.conf_mutex); +} + +static int rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) + goto err_free; + + if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) + goto err_free; + + + rtlpriv->intf_ops->adapter_tx(hw, skb); + + return NETDEV_TX_OK; + +err_free: + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} + +static int rtl_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + int err = 0; + + if (mac->vif) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("vif has been set!! mac->vif = 0x%p\n", mac->vif)); + return -EOPNOTSUPP; + } + + rtl_ips_nic_on(hw); + + mutex_lock(&rtlpriv->locks.conf_mutex); + switch (vif->type) { + case NL80211_IFTYPE_STATION: + if (mac->beacon_enabled == 1) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("NL80211_IFTYPE_STATION\n")); + mac->beacon_enabled = 0; + rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, + rtlpriv->cfg->maps + [RTL_IBSS_INT_MASKS]); + } + break; + case NL80211_IFTYPE_ADHOC: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("NL80211_IFTYPE_ADHOC\n")); + + mac->link_state = MAC80211_LINKED; + rtlpriv->cfg->ops->set_bcn_reg(hw); + break; + case NL80211_IFTYPE_AP: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("NL80211_IFTYPE_AP\n")); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("operation mode %d is not support!\n", vif->type)); + err = -EOPNOTSUPP; + goto out; + } + + mac->vif = vif; + mac->opmode = vif->type; + rtlpriv->cfg->ops->set_network_type(hw, vif->type); + memcpy(mac->mac_addr, vif->addr, ETH_ALEN); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); + +out: + mutex_unlock(&rtlpriv->locks.conf_mutex); + return err; +} + +static void rtl_op_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + mutex_lock(&rtlpriv->locks.conf_mutex); + + /* Free beacon resources */ + if ((mac->opmode == NL80211_IFTYPE_AP) || + (mac->opmode == NL80211_IFTYPE_ADHOC) || + (mac->opmode == NL80211_IFTYPE_MESH_POINT)) { + if (mac->beacon_enabled == 1) { + mac->beacon_enabled = 0; + rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, + rtlpriv->cfg->maps + [RTL_IBSS_INT_MASKS]); + } + } + + /* + *Note: We assume NL80211_IFTYPE_UNSPECIFIED as + *NO LINK for our hardware. + */ + mac->vif = NULL; + mac->link_state = MAC80211_NOLINK; + memset(mac->bssid, 0, 6); + mac->opmode = NL80211_IFTYPE_UNSPECIFIED; + rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); + + mutex_unlock(&rtlpriv->locks.conf_mutex); +} + + +static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct ieee80211_conf *conf = &hw->conf; + + mutex_lock(&rtlpriv->locks.conf_mutex); + if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/ + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("IEEE80211_CONF_CHANGE_LISTEN_INTERVAL\n")); + } + + /*For IPS */ + if (changed & IEEE80211_CONF_CHANGE_IDLE) { + if (hw->conf.flags & IEEE80211_CONF_IDLE) + rtl_ips_nic_off(hw); + else + rtl_ips_nic_on(hw); + } else { + /* + *although rfoff may not cause by ips, but we will + *check the reason in set_rf_power_state function + */ + if (unlikely(ppsc->rfpwr_state == ERFOFF)) + rtl_ips_nic_on(hw); + } + + /*For LPS */ + if (changed & IEEE80211_CONF_CHANGE_PS) { + if (conf->flags & IEEE80211_CONF_PS) + rtl_lps_enter(hw); + else + rtl_lps_leave(hw); + } + + if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("IEEE80211_CONF_CHANGE_RETRY_LIMITS %x\n", + hw->conf.long_frame_max_tx_count)); + mac->retry_long = hw->conf.long_frame_max_tx_count; + mac->retry_short = hw->conf.long_frame_max_tx_count; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT, + (u8 *) (&hw->conf. + long_frame_max_tx_count)); + } + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + struct ieee80211_channel *channel = hw->conf.channel; + u8 wide_chan = (u8) channel->hw_value; + + /* + *because we should back channel to + *current_network.chan in in scanning, + *So if set_chan == current_network.chan + *we should set it. + *because mac80211 tell us wrong bw40 + *info for cisco1253 bw20, so we modify + *it here based on UPPER & LOWER + */ + switch (hw->conf.channel_type) { + case NL80211_CHAN_HT20: + case NL80211_CHAN_NO_HT: + /* SC */ + mac->cur_40_prime_sc = + PRIME_CHNL_OFFSET_DONT_CARE; + rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20; + mac->bw_40 = false; + break; + case NL80211_CHAN_HT40MINUS: + /* SC */ + mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_UPPER; + rtlphy->current_chan_bw = + HT_CHANNEL_WIDTH_20_40; + mac->bw_40 = true; + + /*wide channel */ + wide_chan -= 2; + + break; + case NL80211_CHAN_HT40PLUS: + /* SC */ + mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_LOWER; + rtlphy->current_chan_bw = + HT_CHANNEL_WIDTH_20_40; + mac->bw_40 = true; + + /*wide channel */ + wide_chan += 2; + + break; + default: + mac->bw_40 = false; + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not processed\n")); + break; + } + + if (wide_chan <= 0) + wide_chan = 1; + rtlphy->current_channel = wide_chan; + + rtlpriv->cfg->ops->set_channel_access(hw); + rtlpriv->cfg->ops->switch_channel(hw); + rtlpriv->cfg->ops->set_bw_mode(hw, + hw->conf.channel_type); + } + + mutex_unlock(&rtlpriv->locks.conf_mutex); + + return 0; +} + +static void rtl_op_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *new_flags, u64 multicast) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + *new_flags &= RTL_SUPPORTED_FILTERS; + if (!changed_flags) + return; + + /*TODO: we disable broadcase now, so enable here */ + if (changed_flags & FIF_ALLMULTI) { + if (*new_flags & FIF_ALLMULTI) { + mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AM] | + rtlpriv->cfg->maps[MAC_RCR_AB]; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("Enable receive multicast frame.\n")); + } else { + mac->rx_conf &= ~(rtlpriv->cfg->maps[MAC_RCR_AM] | + rtlpriv->cfg->maps[MAC_RCR_AB]); + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("Disable receive multicast frame.\n")); + } + } + + if (changed_flags & FIF_FCSFAIL) { + if (*new_flags & FIF_FCSFAIL) { + mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACRC32]; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("Enable receive FCS error frame.\n")); + } else { + mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACRC32]; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("Disable receive FCS error frame.\n")); + } + } + + if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { + /* + *TODO: BIT(5) is probe response BIT(8) is beacon + *TODO: Use define for BIT(5) and BIT(8) + */ + if (*new_flags & FIF_BCN_PRBRESP_PROMISC) + mac->rx_mgt_filter |= (BIT(5) | BIT(8)); + else + mac->rx_mgt_filter &= ~(BIT(5) | BIT(8)); + } + + if (changed_flags & FIF_CONTROL) { + if (*new_flags & FIF_CONTROL) { + mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF]; + mac->rx_ctrl_filter |= RTL_SUPPORTED_CTRL_FILTER; + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("Enable receive control frame.\n")); + } else { + mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF]; + mac->rx_ctrl_filter &= ~RTL_SUPPORTED_CTRL_FILTER; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("Disable receive control frame.\n")); + } + } + + if (changed_flags & FIF_OTHER_BSS) { + if (*new_flags & FIF_OTHER_BSS) { + mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AAP]; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("Enable receive other BSS's frame.\n")); + } else { + mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_AAP]; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("Disable receive other BSS's frame.\n")); + } + } + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MGT_FILTER, + (u8 *) (&mac->rx_mgt_filter)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CTRL_FILTER, + (u8 *) (&mac->rx_ctrl_filter)); +} + +static int _rtl_get_hal_qnum(u16 queue) +{ + int qnum; + + switch (queue) { + case 0: + qnum = AC3_VO; + break; + case 1: + qnum = AC2_VI; + break; + case 2: + qnum = AC0_BE; + break; + case 3: + qnum = AC1_BK; + break; + default: + qnum = AC0_BE; + break; + } + return qnum; +} + +/* + *for mac80211 VO=0, VI=1, BE=2, BK=3 + *for rtl819x BE=0, BK=1, VI=2, VO=3 + */ +static int rtl_op_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *param) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + int aci; + + if (queue >= AC_MAX) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("queue number %d is incorrect!\n", queue)); + return -EINVAL; + } + + aci = _rtl_get_hal_qnum(queue); + mac->ac[aci].aifs = param->aifs; + mac->ac[aci].cw_min = param->cw_min; + mac->ac[aci].cw_max = param->cw_max; + mac->ac[aci].tx_op = param->txop; + memcpy(&mac->edca_param[aci], param, sizeof(*param)); + rtlpriv->cfg->ops->set_qos(hw, aci); + return 0; +} + +static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, u32 changed) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + mutex_lock(&rtlpriv->locks.conf_mutex); + + if ((vif->type == NL80211_IFTYPE_ADHOC) || + (vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_MESH_POINT)) { + + if ((changed & BSS_CHANGED_BEACON) || + (changed & BSS_CHANGED_BEACON_ENABLED && + bss_conf->enable_beacon)) { + + if (mac->beacon_enabled == 0) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + ("BSS_CHANGED_BEACON_ENABLED\n")); + + /*start hw beacon interrupt. */ + /*rtlpriv->cfg->ops->set_bcn_reg(hw); */ + mac->beacon_enabled = 1; + rtlpriv->cfg->ops->update_interrupt_mask(hw, + rtlpriv->cfg->maps + [RTL_IBSS_INT_MASKS], + 0); + } + } else { + if (mac->beacon_enabled == 1) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + ("ADHOC DISABLE BEACON\n")); + + mac->beacon_enabled = 0; + rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, + rtlpriv->cfg->maps + [RTL_IBSS_INT_MASKS]); + } + } + + if (changed & BSS_CHANGED_BEACON_INT) { + RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE, + ("BSS_CHANGED_BEACON_INT\n")); + mac->beacon_interval = bss_conf->beacon_int; + rtlpriv->cfg->ops->set_bcn_intv(hw); + } + } + + /*TODO: reference to enum ieee80211_bss_change */ + if (changed & BSS_CHANGED_ASSOC) { + if (bss_conf->assoc) { + mac->link_state = MAC80211_LINKED; + mac->cnt_after_linked = 0; + mac->assoc_id = bss_conf->aid; + memcpy(mac->bssid, bss_conf->bssid, 6); + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + ("BSS_CHANGED_ASSOC\n")); + } else { + if (mac->link_state == MAC80211_LINKED) + rtl_lps_leave(hw); + + mac->link_state = MAC80211_NOLINK; + memset(mac->bssid, 0, 6); + + /* reset sec info */ + rtl_cam_reset_sec_info(hw); + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + ("BSS_CHANGED_UN_ASSOC\n")); + } + } + + if (changed & BSS_CHANGED_ERP_CTS_PROT) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + ("BSS_CHANGED_ERP_CTS_PROT\n")); + mac->use_cts_protect = bss_conf->use_cts_prot; + } + + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("BSS_CHANGED_ERP_PREAMBLE use short preamble:%x\n", + bss_conf->use_short_preamble)); + + mac->short_preamble = bss_conf->use_short_preamble; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACK_PREAMBLE, + (u8 *) (&mac->short_preamble)); + } + + if (changed & BSS_CHANGED_ERP_SLOT) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + ("BSS_CHANGED_ERP_SLOT\n")); + + if (bss_conf->use_short_slot) + mac->slot_time = RTL_SLOT_TIME_9; + else + mac->slot_time = RTL_SLOT_TIME_20; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, + (u8 *) (&mac->slot_time)); + } + + if (changed & BSS_CHANGED_HT) { + struct ieee80211_sta *sta = NULL; + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + ("BSS_CHANGED_HT\n")); + + sta = ieee80211_find_sta(mac->vif, mac->bssid); + + if (sta) { + if (sta->ht_cap.ampdu_density > + mac->current_ampdu_density) + mac->current_ampdu_density = + sta->ht_cap.ampdu_density; + if (sta->ht_cap.ampdu_factor < + mac->current_ampdu_factor) + mac->current_ampdu_factor = + sta->ht_cap.ampdu_factor; + } + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SHORTGI_DENSITY, + (u8 *) (&mac->max_mss_density)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_FACTOR, + &mac->current_ampdu_factor); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_MIN_SPACE, + &mac->current_ampdu_density); + } + + if (changed & BSS_CHANGED_BSSID) { + struct ieee80211_sta *sta = NULL; + u32 basic_rates; + u8 i; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID, + (u8 *) bss_conf->bssid); + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + (MAC_FMT "\n", MAC_ARG(bss_conf->bssid))); + + memcpy(mac->bssid, bss_conf->bssid, 6); + if (is_valid_ether_addr(bss_conf->bssid)) { + switch (vif->type) { + case NL80211_IFTYPE_UNSPECIFIED: + break; + case NL80211_IFTYPE_ADHOC: + break; + case NL80211_IFTYPE_STATION: + break; + case NL80211_IFTYPE_AP: + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + rtlpriv->cfg->ops->set_network_type(hw, vif->type); + } else + rtlpriv->cfg->ops->set_network_type(hw, + NL80211_IFTYPE_UNSPECIFIED); + + memset(mac->mcs, 0, 16); + mac->ht_enable = false; + mac->sgi_40 = false; + mac->sgi_20 = false; + + if (!bss_conf->use_short_slot) + mac->mode = WIRELESS_MODE_B; + else + mac->mode = WIRELESS_MODE_G; + + sta = ieee80211_find_sta(mac->vif, mac->bssid); + + if (sta) { + if (sta->ht_cap.ht_supported) { + mac->mode = WIRELESS_MODE_N_24G; + mac->ht_enable = true; + } + + if (mac->ht_enable) { + u16 ht_cap = sta->ht_cap.cap; + memcpy(mac->mcs, (u8 *) (&sta->ht_cap.mcs), 16); + + for (i = 0; i < 16; i++) + RT_TRACE(rtlpriv, COMP_MAC80211, + DBG_LOUD, ("%x ", + mac->mcs[i])); + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("\n")); + + if (ht_cap & IEEE80211_HT_CAP_SGI_40) + mac->sgi_40 = true; + + if (ht_cap & IEEE80211_HT_CAP_SGI_20) + mac->sgi_20 = true; + + /* + * for cisco 1252 bw20 it's wrong + * if (ht_cap & + * IEEE80211_HT_CAP_SUP_WIDTH_20_40) { + * mac->bw_40 = true; + * } + */ + } + } + + /*mac80211 just give us CCK rates any time + *So we add G rate in basic rates when + not in B mode*/ + if (changed & BSS_CHANGED_BASIC_RATES) { + if (mac->mode == WIRELESS_MODE_B) + basic_rates = bss_conf->basic_rates | 0x00f; + else + basic_rates = bss_conf->basic_rates | 0xff0; + + if (!vif) + goto out; + + mac->basic_rates = basic_rates; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, + (u8 *) (&basic_rates)); + + if (rtlpriv->dm.b_useramask) + rtlpriv->cfg->ops->update_rate_mask(hw, 0); + else + rtlpriv->cfg->ops->update_rate_table(hw); + + } + } + + /* + * For FW LPS: + * To tell firmware we have connected + * to an AP. For 92SE/CE power save v2. + */ + if (changed & BSS_CHANGED_ASSOC) { + if (bss_conf->assoc) { + if (ppsc->b_fwctrl_lps) { + u8 mstatus = RT_MEDIA_CONNECT; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_JOINBSSRPT, + (u8 *) (&mstatus)); + ppsc->report_linked = true; + } + } else { + if (ppsc->b_fwctrl_lps) { + u8 mstatus = RT_MEDIA_DISCONNECT; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_JOINBSSRPT, + (u8 *)(&mstatus)); + ppsc->report_linked = false; + } + } + } + +out: + mutex_unlock(&rtlpriv->locks.conf_mutex); +} + +static u64 rtl_op_get_tsf(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u64 tsf; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&tsf)); + return tsf; +} + +static void rtl_op_set_tsf(struct ieee80211_hw *hw, u64 tsf) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0;; + + mac->tsf = tsf; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&bibss)); +} + +static void rtl_op_reset_tsf(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp = 0; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_DUAL_TSF_RST, (u8 *) (&tmp)); +} + +static void rtl_op_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) +{ + switch (cmd) { + case STA_NOTIFY_SLEEP: + break; + case STA_NOTIFY_AWAKE: + break; + default: + break; + } +} + +static int rtl_op_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 * ssn) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + switch (action) { + case IEEE80211_AMPDU_TX_START: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + ("IEEE80211_AMPDU_TX_START: TID:%d\n", tid)); + return rtl_tx_agg_start(hw, sta->addr, tid, ssn); + break; + case IEEE80211_AMPDU_TX_STOP: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + ("IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid)); + return rtl_tx_agg_stop(hw, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + ("IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid)); + break; + case IEEE80211_AMPDU_RX_START: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + ("IEEE80211_AMPDU_RX_START:TID:%d\n", tid)); + break; + case IEEE80211_AMPDU_RX_STOP: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + ("IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid)); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("IEEE80211_AMPDU_ERR!!!!:\n")); + return -EOPNOTSUPP; + } + return 0; +} + +static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + mac->act_scanning = true; + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("\n")); + + if (mac->link_state == MAC80211_LINKED) { + rtl_lps_leave(hw); + mac->link_state = MAC80211_LINKED_SCANNING; + } else + rtl_ips_nic_on(hw); + + rtlpriv->cfg->ops->led_control(hw, LED_CTL_SITE_SURVEY); + rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP); +} + +static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("\n")); + + rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE); + mac->act_scanning = false; + if (mac->link_state == MAC80211_LINKED_SCANNING) { + mac->link_state = MAC80211_LINKED; + + /* fix fwlps issue */ + rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); + + if (rtlpriv->dm.b_useramask) + rtlpriv->cfg->ops->update_rate_mask(hw, 0); + else + rtlpriv->cfg->ops->update_rate_table(hw); + + } + +} + +static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 key_type = NO_ENCRYPTION; + u8 key_idx; + bool group_key = false; + bool wep_only = false; + int err = 0; + u8 mac_addr[ETH_ALEN]; + u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + u8 zero_addr[ETH_ALEN] = { 0 }; + + if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("not open hw encryption\n")); + return -ENOSPC; /*User disabled HW-crypto */ + } + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("%s hardware based encryption for keyidx: %d, mac: %pM\n", + cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, + sta ? sta->addr : bcast_addr)); + rtlpriv->sec.being_setkey = true; + rtl_ips_nic_on(hw); + mutex_lock(&rtlpriv->locks.conf_mutex); + /* <1> get encryption alg */ + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + key_type = WEP40_ENCRYPTION; + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:WEP40\n")); + rtlpriv->sec.use_defaultkey = true; + break; + case WLAN_CIPHER_SUITE_WEP104: + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("alg:WEP104\n")); + key_type = WEP104_ENCRYPTION; + rtlpriv->sec.use_defaultkey = true; + break; + case WLAN_CIPHER_SUITE_TKIP: + key_type = TKIP_ENCRYPTION; + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:TKIP\n")); + if (mac->opmode == NL80211_IFTYPE_ADHOC) + rtlpriv->sec.use_defaultkey = true; + break; + case WLAN_CIPHER_SUITE_CCMP: + key_type = AESCCMP_ENCRYPTION; + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:CCMP\n")); + if (mac->opmode == NL80211_IFTYPE_ADHOC) + rtlpriv->sec.use_defaultkey = true; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("alg_err:%x!!!!:\n", key->cipher)); + goto out_unlock; + } + /* <2> get key_idx */ + key_idx = (u8) (key->keyidx); + if (key_idx > 3) + goto out_unlock; + /* <3> if pairwise key enable_hw_sec */ + group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE); + if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) || + rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { + if (rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION && + (key_type == WEP40_ENCRYPTION || + key_type == WEP104_ENCRYPTION)) + wep_only = true; + rtlpriv->sec.pairwise_enc_algorithm = key_type; + rtlpriv->cfg->ops->enable_hw_sec(hw); + } + /* <4> set key based on cmd */ + switch (cmd) { + case SET_KEY: + if (wep_only) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("set WEP(group/pairwise) key\n")); + /* Pairwise key with an assigned MAC address. */ + rtlpriv->sec.pairwise_enc_algorithm = key_type; + rtlpriv->sec.group_enc_algorithm = key_type; + /*set local buf about wep key. */ + memcpy(rtlpriv->sec.key_buf[key_idx], + key->key, key->keylen); + rtlpriv->sec.key_len[key_idx] = key->keylen; + memcpy(mac_addr, zero_addr, ETH_ALEN); + } else if (group_key) { /* group key */ + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("set group key\n")); + /* group key */ + rtlpriv->sec.group_enc_algorithm = key_type; + /*set local buf about group key. */ + memcpy(rtlpriv->sec.key_buf[key_idx], + key->key, key->keylen); + rtlpriv->sec.key_len[key_idx] = key->keylen; + memcpy(mac_addr, bcast_addr, ETH_ALEN); + } else { /* pairwise key */ + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("set pairwise key\n")); + if (!sta) { + RT_ASSERT(false, ("pairwise key withnot" + "mac_addr\n")); + err = -EOPNOTSUPP; + goto out_unlock; + } + /* Pairwise key with an assigned MAC address. */ + rtlpriv->sec.pairwise_enc_algorithm = key_type; + /*set local buf about pairwise key. */ + memcpy(rtlpriv->sec.key_buf[PAIRWISE_KEYIDX], + key->key, key->keylen); + rtlpriv->sec.key_len[PAIRWISE_KEYIDX] = key->keylen; + rtlpriv->sec.pairwise_key = + rtlpriv->sec.key_buf[PAIRWISE_KEYIDX]; + memcpy(mac_addr, sta->addr, ETH_ALEN); + } + rtlpriv->cfg->ops->set_key(hw, key_idx, mac_addr, + group_key, key_type, wep_only, + false); + /* <5> tell mac80211 do something: */ + /*must use sw generate IV, or can not work !!!!. */ + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + key->hw_key_idx = key_idx; + if (key_type == TKIP_ENCRYPTION) + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + break; + case DISABLE_KEY: + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("disable key delete one entry\n")); + /*set local buf about wep key. */ + memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen); + rtlpriv->sec.key_len[key_idx] = 0; + memcpy(mac_addr, zero_addr, ETH_ALEN); + /* + *mac80211 will delete entrys one by one, + *so don't use rtl_cam_reset_all_entry + *or clear all entry here. + */ + rtl_cam_delete_one_entry(hw, mac_addr, key_idx); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("cmd_err:%x!!!!:\n", cmd)); + } +out_unlock: + mutex_unlock(&rtlpriv->locks.conf_mutex); + rtlpriv->sec.being_setkey = false; + return err; +} + +static void rtl_op_rfkill_poll(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + bool radio_state; + bool blocked; + u8 valid = 0; + + if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) + return; + + mutex_lock(&rtlpriv->locks.conf_mutex); + + /*if Radio On return true here */ + radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); + + if (valid) { + if (unlikely(radio_state != rtlpriv->rfkill.rfkill_state)) { + rtlpriv->rfkill.rfkill_state = radio_state; + + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + (KERN_INFO "wireless radio switch turned %s\n", + radio_state ? "on" : "off")); + + blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1; + wiphy_rfkill_set_hw_state(hw->wiphy, blocked); + } + } + + mutex_unlock(&rtlpriv->locks.conf_mutex); +} + +const struct ieee80211_ops rtl_ops = { + .start = rtl_op_start, + .stop = rtl_op_stop, + .tx = rtl_op_tx, + .add_interface = rtl_op_add_interface, + .remove_interface = rtl_op_remove_interface, + .config = rtl_op_config, + .configure_filter = rtl_op_configure_filter, + .set_key = rtl_op_set_key, + .conf_tx = rtl_op_conf_tx, + .bss_info_changed = rtl_op_bss_info_changed, + .get_tsf = rtl_op_get_tsf, + .set_tsf = rtl_op_set_tsf, + .reset_tsf = rtl_op_reset_tsf, + .sta_notify = rtl_op_sta_notify, + .ampdu_action = rtl_op_ampdu_action, + .sw_scan_start = rtl_op_sw_scan_start, + .sw_scan_complete = rtl_op_sw_scan_complete, + .rfkill_poll = rtl_op_rfkill_poll, +}; diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h new file mode 100644 index 000000000000..0ef31c3c6196 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/core.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * Tmis program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * Tmis program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * tmis program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * Tme full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + *****************************************************************************/ + +#ifndef __RTL_CORE_H__ +#define __RTL_CORE_H__ + +#define RTL_SUPPORTED_FILTERS \ + (FIF_PROMISC_IN_BSS | \ + FIF_ALLMULTI | FIF_CONTROL | \ + FIF_OTHER_BSS | \ + FIF_FCSFAIL | \ + FIF_BCN_PRBRESP_PROMISC) + +#define RTL_SUPPORTED_CTRL_FILTER 0xFF + +extern const struct ieee80211_ops rtl_ops; +#endif diff --git a/drivers/net/wireless/rtlwifi/debug.c b/drivers/net/wireless/rtlwifi/debug.c new file mode 100644 index 000000000000..5fa73852cb66 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/debug.c @@ -0,0 +1,50 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * Tmis program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * Tmis program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * tmis program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * Tme full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + *****************************************************************************/ + +#include "wifi.h" + +void rtl_dbgp_flag_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 i; + + rtlpriv->dbg.global_debuglevel = DBG_EMERG; + + rtlpriv->dbg.global_debugcomponents = + COMP_ERR | COMP_FW | COMP_INIT | COMP_RECV | COMP_SEND | + COMP_MLME | COMP_SCAN | COMP_INTR | COMP_LED | COMP_SEC | + COMP_BEACON | COMP_RATE | COMP_RXDESC | COMP_DIG | COMP_TXAGC | + COMP_POWER | COMP_POWER_TRACKING | COMP_BB_POWERSAVING | COMP_SWAS | + COMP_RF | COMP_TURBO | COMP_RATR | COMP_CMD | + COMP_EFUSE | COMP_QOS | COMP_MAC80211 | COMP_REGD | COMP_CHAN; + + for (i = 0; i < DBGP_TYPE_MAX; i++) + rtlpriv->dbg.dbgp_type[i] = 0; + + /*Init Debug flag enable condition */ +} diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h new file mode 100644 index 000000000000..08bdec2ceda4 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/debug.h @@ -0,0 +1,212 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * Tmis program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * Tmis program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * tmis program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * Tme full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + *****************************************************************************/ + +#ifndef __RTL_DEBUG_H__ +#define __RTL_DEBUG_H__ + +/*-------------------------------------------------------------- + Debug level +--------------------------------------------------------------*/ +/* + *Fatal bug. + *For example, Tx/Rx/IO locked up, + *memory access violation, + *resource allocation failed, + *unexpected HW behavior, HW BUG + *and so on. + */ +#define DBG_EMERG 0 + +/* + *Abnormal, rare, or unexpeted cases. + *For example, Packet/IO Ctl canceled, + *device suprisely unremoved and so on. + */ +#define DBG_WARNING 2 + +/* + *Normal case driver developer should + *open, we can see link status like + *assoc/AddBA/DHCP/adapter start and + *so on basic and useful infromations. + */ +#define DBG_DMESG 3 + +/* + *Normal case with useful information + *about current SW or HW state. + *For example, Tx/Rx descriptor to fill, + *Tx/Rx descriptor completed status, + *SW protocol state change, dynamic + *mechanism state change and so on. + */ +#define DBG_LOUD 4 + +/* + *Normal case with detail execution + *flow or information. + */ +#define DBG_TRACE 5 + +/*-------------------------------------------------------------- + Define the rt_trace components +--------------------------------------------------------------*/ +#define COMP_ERR BIT(0) +#define COMP_FW BIT(1) +#define COMP_INIT BIT(2) /*For init/deinit */ +#define COMP_RECV BIT(3) /*For Rx. */ +#define COMP_SEND BIT(4) /*For Tx. */ +#define COMP_MLME BIT(5) /*For MLME. */ +#define COMP_SCAN BIT(6) /*For Scan. */ +#define COMP_INTR BIT(7) /*For interrupt Related. */ +#define COMP_LED BIT(8) /*For LED. */ +#define COMP_SEC BIT(9) /*For sec. */ +#define COMP_BEACON BIT(10) /*For beacon. */ +#define COMP_RATE BIT(11) /*For rate. */ +#define COMP_RXDESC BIT(12) /*For rx desc. */ +#define COMP_DIG BIT(13) /*For DIG */ +#define COMP_TXAGC BIT(14) /*For Tx power */ +#define COMP_HIPWR BIT(15) /*For High Power Mechanism */ +#define COMP_POWER BIT(16) /*For lps/ips/aspm. */ +#define COMP_POWER_TRACKING BIT(17) /*For TX POWER TRACKING */ +#define COMP_BB_POWERSAVING BIT(18) +#define COMP_SWAS BIT(19) /*For SW Antenna Switch */ +#define COMP_RF BIT(20) /*For RF. */ +#define COMP_TURBO BIT(21) /*For EDCA TURBO. */ +#define COMP_RATR BIT(22) +#define COMP_CMD BIT(23) +#define COMP_EFUSE BIT(24) +#define COMP_QOS BIT(25) +#define COMP_MAC80211 BIT(26) +#define COMP_REGD BIT(27) +#define COMP_CHAN BIT(28) + +/*-------------------------------------------------------------- + Define the rt_print components +--------------------------------------------------------------*/ +/* Define EEPROM and EFUSE check module bit*/ +#define EEPROM_W BIT(0) +#define EFUSE_PG BIT(1) +#define EFUSE_READ_ALL BIT(2) + +/* Define init check for module bit*/ +#define INIT_EEPROM BIT(0) +#define INIT_TxPower BIT(1) +#define INIT_IQK BIT(2) +#define INIT_RF BIT(3) + +/* Define PHY-BB/RF/MAC check module bit */ +#define PHY_BBR BIT(0) +#define PHY_BBW BIT(1) +#define PHY_RFR BIT(2) +#define PHY_RFW BIT(3) +#define PHY_MACR BIT(4) +#define PHY_MACW BIT(5) +#define PHY_ALLR BIT(6) +#define PHY_ALLW BIT(7) +#define PHY_TXPWR BIT(8) +#define PHY_PWRDIFF BIT(9) + +enum dbgp_flag_e { + FQOS = 0, + FTX = 1, + FRX = 2, + FSEC = 3, + FMGNT = 4, + FMLME = 5, + FRESOURCE = 6, + FBEACON = 7, + FISR = 8, + FPHY = 9, + FMP = 10, + FEEPROM = 11, + FPWR = 12, + FDM = 13, + FDBGCtrl = 14, + FC2H = 15, + FBT = 16, + FINIT = 17, + FIOCTL = 18, + DBGP_TYPE_MAX +}; + +#define RT_ASSERT(_exp, fmt) \ + do { \ + if (!(_exp)) { \ + printk(KERN_DEBUG "%s:%s(): ", KBUILD_MODNAME, \ + __func__); \ + printk fmt; \ + } \ + } while (0); + +#define RT_TRACE(rtlpriv, comp, level, fmt)\ + do { \ + if (unlikely(((comp) & rtlpriv->dbg.global_debugcomponents) && \ + ((level) <= rtlpriv->dbg.global_debuglevel))) {\ + printk(KERN_DEBUG "%s:%s():<%lx-%x> ", KBUILD_MODNAME, \ + __func__, in_interrupt(), in_atomic()); \ + printk fmt; \ + } \ + } while (0); + +#define RTPRINT(rtlpriv, dbgtype, dbgflag, printstr) \ + do { \ + if (unlikely(rtlpriv->dbg.dbgp_type[dbgtype] & dbgflag)) { \ + printk(KERN_DEBUG "%s: ", KBUILD_MODNAME); \ + printk printstr; \ + } \ + } while (0); + +#define RT_PRINT_DATA(rtlpriv, _comp, _level, _titlestring, _hexdata, \ + _hexdatalen) \ + do {\ + if (unlikely(((_comp) & rtlpriv->dbg.global_debugcomponents) &&\ + (_level <= rtlpriv->dbg.global_debuglevel))) { \ + int __i; \ + u8* ptr = (u8 *)_hexdata; \ + printk(KERN_DEBUG "%s: ", KBUILD_MODNAME); \ + printk("In process \"%s\" (pid %i):", current->comm,\ + current->pid); \ + printk(_titlestring); \ + for (__i = 0; __i < (int)_hexdatalen; __i++) { \ + printk("%02X%s", ptr[__i], (((__i + 1) % 4)\ + == 0) ? " " : " ");\ + if (((__i + 1) % 16) == 0) \ + printk("\n"); \ + } \ + printk(KERN_DEBUG "\n"); \ + } \ + } while (0); + +#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define MAC_ARG(x) \ + ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2],\ + ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5] + +void rtl_dbgp_flag_init(struct ieee80211_hw *hw); +#endif diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c new file mode 100644 index 000000000000..b8433f3a9bc2 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/efuse.c @@ -0,0 +1,1189 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * Tmis program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * Tmis program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * tmis program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * Tme full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "wifi.h" +#include "efuse.h" + +static const u8 MAX_PGPKT_SIZE = 9; +static const u8 PGPKT_DATA_SIZE = 8; +static const int EFUSE_MAX_SIZE = 512; + +static const u8 EFUSE_OOB_PROTECT_BYTES = 15; + +static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { + {0, 0, 0, 2}, + {0, 1, 0, 2}, + {0, 2, 0, 2}, + {1, 0, 0, 1}, + {1, 0, 1, 1}, + {1, 1, 0, 1}, + {1, 1, 1, 3}, + {1, 3, 0, 17}, + {3, 3, 1, 48}, + {10, 0, 0, 6}, + {10, 3, 0, 1}, + {10, 3, 1, 1}, + {11, 0, 0, 28} +}; + +static void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, + u8 *pbuf); +static void efuse_shadow_read_1byte(struct ieee80211_hw *hw, u16 offset, + u8 *value); +static void efuse_shadow_read_2byte(struct ieee80211_hw *hw, u16 offset, + u16 *value); +static void efuse_shadow_read_4byte(struct ieee80211_hw *hw, u16 offset, + u32 *value); +static void efuse_shadow_write_1byte(struct ieee80211_hw *hw, u16 offset, + u8 value); +static void efuse_shadow_write_2byte(struct ieee80211_hw *hw, u16 offset, + u16 value); +static void efuse_shadow_write_4byte(struct ieee80211_hw *hw, u16 offset, + u32 value); +static int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, + u8 *data); +static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, + u8 data); +static void efuse_read_all_map(struct ieee80211_hw *hw, u8 *efuse); +static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, + u8 *data); +static int efuse_pg_packet_write(struct ieee80211_hw *hw, u8 offset, + u8 word_en, u8 *data); +static void efuse_word_enable_data_read(u8 word_en, u8 *sourdata, + u8 *targetdata); +static u8 efuse_word_enable_data_write(struct ieee80211_hw *hw, + u16 efuse_addr, u8 word_en, u8 *data); +static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, + u8 pwrstate); +static u16 efuse_get_current_size(struct ieee80211_hw *hw); +static u8 efuse_calculate_word_cnts(u8 word_en); + +void efuse_initialize(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bytetemp; + u8 temp; + + bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN] + 1); + temp = bytetemp | 0x20; + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN] + 1, temp); + + bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL] + 1); + temp = bytetemp & 0xFE; + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL] + 1, temp); + + bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3); + temp = bytetemp | 0x80; + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3, temp); + + rtl_write_byte(rtlpriv, 0x2F8, 0x3); + + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0x72); + +} + +u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 data; + u8 bytetemp; + u8 temp; + u32 k = 0; + + if (address < EFUSE_REAL_CONTENT_LEN) { + temp = address & 0xFF; + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, + temp); + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 2); + temp = ((address >> 8) & 0x03) | (bytetemp & 0xFC); + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2, + temp); + + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3); + temp = bytetemp & 0x7F; + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, + temp); + + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3); + while (!(bytetemp & 0x80)) { + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg-> + maps[EFUSE_CTRL] + 3); + k++; + if (k == 1000) { + k = 0; + break; + } + } + data = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); + return data; + } else + return 0xFF; + +} +EXPORT_SYMBOL(efuse_read_1byte); + +void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bytetemp; + u8 temp; + u32 k = 0; + + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, + ("Addr=%x Data =%x\n", address, value)); + + if (address < EFUSE_REAL_CONTENT_LEN) { + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], value); + + temp = address & 0xFF; + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, + temp); + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 2); + + temp = ((address >> 8) & 0x03) | (bytetemp & 0xFC); + rtl_write_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 2, temp); + + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3); + temp = bytetemp | 0x80; + rtl_write_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3, temp); + + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3); + + while (bytetemp & 0x80) { + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg-> + maps[EFUSE_CTRL] + 3); + k++; + if (k == 100) { + k = 0; + break; + } + } + } + +} + +static void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 value32; + u8 readbyte; + u16 retry; + + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, + (_offset & 0xff)); + readbyte = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2); + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2, + ((_offset >> 8) & 0x03) | (readbyte & 0xfc)); + + readbyte = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3); + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, + (readbyte & 0x7f)); + + retry = 0; + value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); + while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < 10000)) { + value32 = rtl_read_dword(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL]); + retry++; + } + + udelay(50); + value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); + + *pbuf = (u8) (value32 & 0xff); +} + +void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 efuse_tbl[EFUSE_MAP_LEN]; + u8 rtemp8[1]; + u16 efuse_addr = 0; + u8 offset, wren; + u16 i; + u16 j; + u16 efuse_word[EFUSE_MAX_SECTION][EFUSE_MAX_WORD_UNIT]; + u16 efuse_utilized = 0; + u8 efuse_usage; + + if ((_offset + _size_byte) > EFUSE_MAP_LEN) { + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, + ("read_efuse(): Invalid offset(%#x) with read " + "bytes(%#x)!!\n", _offset, _size_byte)); + return; + } + + for (i = 0; i < EFUSE_MAX_SECTION; i++) + for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) + efuse_word[i][j] = 0xFFFF; + + read_efuse_byte(hw, efuse_addr, rtemp8); + if (*rtemp8 != 0xFF) { + efuse_utilized++; + RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, + ("Addr=%d\n", efuse_addr)); + efuse_addr++; + } + + while ((*rtemp8 != 0xFF) && (efuse_addr < EFUSE_REAL_CONTENT_LEN)) { + offset = ((*rtemp8 >> 4) & 0x0f); + + if (offset < EFUSE_MAX_SECTION) { + wren = (*rtemp8 & 0x0f); + RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, + ("offset-%d Worden=%x\n", offset, wren)); + + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { + if (!(wren & 0x01)) { + RTPRINT(rtlpriv, FEEPROM, + EFUSE_READ_ALL, ("Addr=%d\n", + efuse_addr)); + + read_efuse_byte(hw, efuse_addr, rtemp8); + efuse_addr++; + efuse_utilized++; + efuse_word[offset][i] = (*rtemp8 & 0xff); + + if (efuse_addr >= EFUSE_REAL_CONTENT_LEN) + break; + + RTPRINT(rtlpriv, FEEPROM, + EFUSE_READ_ALL, ("Addr=%d\n", + efuse_addr)); + + read_efuse_byte(hw, efuse_addr, rtemp8); + efuse_addr++; + efuse_utilized++; + efuse_word[offset][i] |= + (((u16)*rtemp8 << 8) & 0xff00); + + if (efuse_addr >= EFUSE_REAL_CONTENT_LEN) + break; + } + + wren >>= 1; + } + } + + RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, + ("Addr=%d\n", efuse_addr)); + read_efuse_byte(hw, efuse_addr, rtemp8); + if (*rtemp8 != 0xFF && (efuse_addr < 512)) { + efuse_utilized++; + efuse_addr++; + } + } + + for (i = 0; i < EFUSE_MAX_SECTION; i++) { + for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { + efuse_tbl[(i * 8) + (j * 2)] = + (efuse_word[i][j] & 0xff); + efuse_tbl[(i * 8) + ((j * 2) + 1)] = + ((efuse_word[i][j] >> 8) & 0xff); + } + } + + for (i = 0; i < _size_byte; i++) + pbuf[i] = efuse_tbl[_offset + i]; + + rtlefuse->efuse_usedbytes = efuse_utilized; + efuse_usage = (u8)((efuse_utilized * 100) / EFUSE_REAL_CONTENT_LEN); + rtlefuse->efuse_usedpercentage = efuse_usage; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_BYTES, + (u8 *)&efuse_utilized); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_USAGE, + (u8 *)&efuse_usage); +} + +bool efuse_shadow_update_chk(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 section_idx, i, Base; + u16 words_need = 0, hdr_num = 0, totalbytes, efuse_used; + bool bwordchanged, bresult = true; + + for (section_idx = 0; section_idx < 16; section_idx++) { + Base = section_idx * 8; + bwordchanged = false; + + for (i = 0; i < 8; i = i + 2) { + if ((rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i] != + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i]) || + (rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i + 1] != + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i + + 1])) { + words_need++; + bwordchanged = true; + } + } + + if (bwordchanged == true) + hdr_num++; + } + + totalbytes = hdr_num + words_need * 2; + efuse_used = rtlefuse->efuse_usedbytes; + + if ((totalbytes + efuse_used) >= + (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) + bresult = false; + + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, + ("efuse_shadow_update_chk(): totalbytes(%#x), " + "hdr_num(%#x), words_need(%#x), efuse_used(%d)\n", + totalbytes, hdr_num, words_need, efuse_used)); + + return bresult; +} + +void efuse_shadow_read(struct ieee80211_hw *hw, u8 type, + u16 offset, u32 *value) +{ + if (type == 1) + efuse_shadow_read_1byte(hw, offset, (u8 *) value); + else if (type == 2) + efuse_shadow_read_2byte(hw, offset, (u16 *) value); + else if (type == 4) + efuse_shadow_read_4byte(hw, offset, (u32 *) value); + +} + +void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, u16 offset, + u32 value) +{ + if (type == 1) + efuse_shadow_write_1byte(hw, offset, (u8) value); + else if (type == 2) + efuse_shadow_write_2byte(hw, offset, (u16) value); + else if (type == 4) + efuse_shadow_write_4byte(hw, offset, (u32) value); + +} + +bool efuse_shadow_update(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u16 i, offset, base; + u8 word_en = 0x0F; + u8 first_pg = false; + + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("--->\n")); + + if (!efuse_shadow_update_chk(hw)) { + efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); + memcpy((void *)&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], + (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); + + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, + ("<---efuse out of capacity!!\n")); + return false; + } + efuse_power_switch(hw, true, true); + + for (offset = 0; offset < 16; offset++) { + + word_en = 0x0F; + base = offset * 8; + + for (i = 0; i < 8; i++) { + if (first_pg == true) { + + word_en &= ~(BIT(i / 2)); + + rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] = + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]; + } else { + + if (rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] != + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]) { + word_en &= ~(BIT(i / 2)); + + rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] = + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]; + } + } + } + + if (word_en != 0x0F) { + u8 tmpdata[8]; + memcpy((void *)tmpdata, + (void *)(&rtlefuse-> + efuse_map[EFUSE_MODIFY_MAP][base]), 8); + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, + ("U-efuse\n"), tmpdata, 8); + + if (!efuse_pg_packet_write(hw, (u8) offset, word_en, + tmpdata)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("PG section(%#x) fail!!\n", offset)); + break; + } + } + + } + + efuse_power_switch(hw, true, false); + efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); + + memcpy((void *)&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], + (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); + + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("<---\n")); + return true; +} + +void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + if (rtlefuse->autoload_failflag == true) { + memset((void *)(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0]), 128, + 0xFF); + } else + efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); + + memcpy((void *)&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], + (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); + +} +EXPORT_SYMBOL(rtl_efuse_shadow_map_update); + +void efuse_force_write_vendor_Id(struct ieee80211_hw *hw) +{ + u8 tmpdata[8] = { 0xFF, 0xFF, 0xEC, 0x10, 0xFF, 0xFF, 0xFF, 0xFF }; + + efuse_power_switch(hw, true, true); + + efuse_pg_packet_write(hw, 1, 0xD, tmpdata); + + efuse_power_switch(hw, true, false); + +} + +void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx) +{ +} + +static void efuse_shadow_read_1byte(struct ieee80211_hw *hw, + u16 offset, u8 *value) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset]; +} + +static void efuse_shadow_read_2byte(struct ieee80211_hw *hw, + u16 offset, u16 *value) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset]; + *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] << 8; + +} + +static void efuse_shadow_read_4byte(struct ieee80211_hw *hw, + u16 offset, u32 *value) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset]; + *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] << 8; + *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 2] << 16; + *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 3] << 24; +} + +static void efuse_shadow_write_1byte(struct ieee80211_hw *hw, + u16 offset, u8 value) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] = value; +} + +static void efuse_shadow_write_2byte(struct ieee80211_hw *hw, + u16 offset, u16 value) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] = value & 0x00FF; + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] = value >> 8; + +} + +static void efuse_shadow_write_4byte(struct ieee80211_hw *hw, + u16 offset, u32 value) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] = + (u8) (value & 0x000000FF); + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] = + (u8) ((value >> 8) & 0x0000FF); + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 2] = + (u8) ((value >> 16) & 0x00FF); + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 3] = + (u8) ((value >> 24) & 0xFF); + +} + +static int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, u8 *data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmpidx = 0; + int bresult; + + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, + (u8) (addr & 0xff)); + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2, + ((u8) ((addr >> 8) & 0x03)) | + (rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 2) & + 0xFC)); + + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0x72); + + while (!(0x80 & rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3)) + && (tmpidx < 100)) { + tmpidx++; + } + + if (tmpidx < 100) { + *data = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); + bresult = true; + } else { + *data = 0xff; + bresult = false; + } + return bresult; +} + +static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmpidx = 0; + bool bresult; + + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, + ("Addr = %x Data=%x\n", addr, data)); + + rtl_write_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 1, (u8) (addr & 0xff)); + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2, + (rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + + 2) & 0xFC) | (u8) ((addr >> 8) & 0x03)); + + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], data); + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0xF2); + + while ((0x80 & rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3)) + && (tmpidx < 100)) { + tmpidx++; + } + + if (tmpidx < 100) + bresult = true; + else + bresult = false; + + return bresult; +} + +static void efuse_read_all_map(struct ieee80211_hw *hw, u8 * efuse) +{ + efuse_power_switch(hw, false, true); + read_efuse(hw, 0, 128, efuse); + efuse_power_switch(hw, false, false); +} + +static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, + u8 efuse_data, u8 offset, u8 *tmpdata, + u8 *readstate) +{ + bool bdataempty = true; + u8 hoffset; + u8 tmpidx; + u8 hworden; + u8 word_cnts; + + hoffset = (efuse_data >> 4) & 0x0F; + hworden = efuse_data & 0x0F; + word_cnts = efuse_calculate_word_cnts(hworden); + + if (hoffset == offset) { + for (tmpidx = 0; tmpidx < word_cnts * 2; tmpidx++) { + if (efuse_one_byte_read(hw, *efuse_addr + 1 + tmpidx, + &efuse_data)) { + tmpdata[tmpidx] = efuse_data; + if (efuse_data != 0xff) + bdataempty = true; + } + } + + if (bdataempty == true) + *readstate = PG_STATE_DATA; + else { + *efuse_addr = *efuse_addr + (word_cnts * 2) + 1; + *readstate = PG_STATE_HEADER; + } + + } else { + *efuse_addr = *efuse_addr + (word_cnts * 2) + 1; + *readstate = PG_STATE_HEADER; + } +} + +static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) +{ + u8 readstate = PG_STATE_HEADER; + + bool bcontinual = true; + + u8 efuse_data, word_cnts = 0; + u16 efuse_addr = 0; + u8 hworden; + u8 tmpdata[8]; + + if (data == NULL) + return false; + if (offset > 15) + return false; + + memset((void *)data, PGPKT_DATA_SIZE * sizeof(u8), 0xff); + memset((void *)tmpdata, PGPKT_DATA_SIZE * sizeof(u8), 0xff); + + while (bcontinual && (efuse_addr < EFUSE_MAX_SIZE)) { + if (readstate & PG_STATE_HEADER) { + if (efuse_one_byte_read(hw, efuse_addr, &efuse_data) + && (efuse_data != 0xFF)) + efuse_read_data_case1(hw, &efuse_addr, + efuse_data, + offset, tmpdata, + &readstate); + else + bcontinual = false; + } else if (readstate & PG_STATE_DATA) { + efuse_word_enable_data_read(hworden, tmpdata, data); + efuse_addr = efuse_addr + (word_cnts * 2) + 1; + readstate = PG_STATE_HEADER; + } + + } + + if ((data[0] == 0xff) && (data[1] == 0xff) && + (data[2] == 0xff) && (data[3] == 0xff) && + (data[4] == 0xff) && (data[5] == 0xff) && + (data[6] == 0xff) && (data[7] == 0xff)) + return false; + else + return true; + +} + +static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, + u8 efuse_data, u8 offset, int *bcontinual, + u8 *write_state, struct pgpkt_struct target_pkt, + int *repeat_times, int *bresult, u8 word_en) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct pgpkt_struct tmp_pkt; + int bdataempty = true; + u8 originaldata[8 * sizeof(u8)]; + u8 badworden = 0x0F; + u8 match_word_en, tmp_word_en; + u8 tmpindex; + u8 tmp_header = efuse_data; + u8 tmp_word_cnts; + + tmp_pkt.offset = (tmp_header >> 4) & 0x0F; + tmp_pkt.word_en = tmp_header & 0x0F; + tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en); + + if (tmp_pkt.offset != target_pkt.offset) { + efuse_addr = efuse_addr + (tmp_word_cnts * 2) + 1; + *write_state = PG_STATE_HEADER; + } else { + for (tmpindex = 0; tmpindex < (tmp_word_cnts * 2); tmpindex++) { + u16 address = *efuse_addr + 1 + tmpindex; + if (efuse_one_byte_read(hw, address, + &efuse_data) && (efuse_data != 0xFF)) + bdataempty = false; + } + + if (bdataempty == false) { + efuse_addr = efuse_addr + (tmp_word_cnts * 2) + 1; + *write_state = PG_STATE_HEADER; + } else { + match_word_en = 0x0F; + if (!((target_pkt.word_en & BIT(0)) | + (tmp_pkt.word_en & BIT(0)))) + match_word_en &= (~BIT(0)); + + if (!((target_pkt.word_en & BIT(1)) | + (tmp_pkt.word_en & BIT(1)))) + match_word_en &= (~BIT(1)); + + if (!((target_pkt.word_en & BIT(2)) | + (tmp_pkt.word_en & BIT(2)))) + match_word_en &= (~BIT(2)); + + if (!((target_pkt.word_en & BIT(3)) | + (tmp_pkt.word_en & BIT(3)))) + match_word_en &= (~BIT(3)); + + if ((match_word_en & 0x0F) != 0x0F) { + badworden = efuse_word_enable_data_write( + hw, *efuse_addr + 1, + tmp_pkt.word_en, + target_pkt.data); + + if (0x0F != (badworden & 0x0F)) { + u8 reorg_offset = offset; + u8 reorg_worden = badworden; + efuse_pg_packet_write(hw, reorg_offset, + reorg_worden, + originaldata); + } + + tmp_word_en = 0x0F; + if ((target_pkt.word_en & BIT(0)) ^ + (match_word_en & BIT(0))) + tmp_word_en &= (~BIT(0)); + + if ((target_pkt.word_en & BIT(1)) ^ + (match_word_en & BIT(1))) + tmp_word_en &= (~BIT(1)); + + if ((target_pkt.word_en & BIT(2)) ^ + (match_word_en & BIT(2))) + tmp_word_en &= (~BIT(2)); + + if ((target_pkt.word_en & BIT(3)) ^ + (match_word_en & BIT(3))) + tmp_word_en &= (~BIT(3)); + + if ((tmp_word_en & 0x0F) != 0x0F) { + *efuse_addr = efuse_get_current_size(hw); + target_pkt.offset = offset; + target_pkt.word_en = tmp_word_en; + } else + *bcontinual = false; + *write_state = PG_STATE_HEADER; + *repeat_times += 1; + if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { + *bcontinual = false; + *bresult = false; + } + } else { + *efuse_addr += (2 * tmp_word_cnts) + 1; + target_pkt.offset = offset; + target_pkt.word_en = word_en; + *write_state = PG_STATE_HEADER; + } + } + } + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, ("efuse PG_STATE_HEADER-1\n")); +} + +static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, + int *bcontinual, u8 *write_state, + struct pgpkt_struct target_pkt, + int *repeat_times, int *bresult) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct pgpkt_struct tmp_pkt; + u8 pg_header; + u8 tmp_header; + u8 originaldata[8 * sizeof(u8)]; + u8 tmp_word_cnts; + u8 badworden = 0x0F; + + pg_header = ((target_pkt.offset << 4) & 0xf0) | target_pkt.word_en; + efuse_one_byte_write(hw, *efuse_addr, pg_header); + efuse_one_byte_read(hw, *efuse_addr, &tmp_header); + + if (tmp_header == pg_header) + *write_state = PG_STATE_DATA; + else if (tmp_header == 0xFF) { + *write_state = PG_STATE_HEADER; + *repeat_times += 1; + if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { + *bcontinual = false; + *bresult = false; + } + } else { + tmp_pkt.offset = (tmp_header >> 4) & 0x0F; + tmp_pkt.word_en = tmp_header & 0x0F; + + tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en); + + memset((void *)originaldata, 8 * sizeof(u8), 0xff); + + if (efuse_pg_packet_read(hw, tmp_pkt.offset, originaldata)) { + badworden = efuse_word_enable_data_write(hw, + *efuse_addr + 1, tmp_pkt.word_en, + originaldata); + + if (0x0F != (badworden & 0x0F)) { + u8 reorg_offset = tmp_pkt.offset; + u8 reorg_worden = badworden; + efuse_pg_packet_write(hw, reorg_offset, + reorg_worden, + originaldata); + *efuse_addr = efuse_get_current_size(hw); + } else + *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + + 1; + } else + *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; + + *write_state = PG_STATE_HEADER; + *repeat_times += 1; + if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { + *bcontinual = false; + *bresult = false; + } + + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, + ("efuse PG_STATE_HEADER-2\n")); + } +} + +static int efuse_pg_packet_write(struct ieee80211_hw *hw, + u8 offset, u8 word_en, u8 *data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct pgpkt_struct target_pkt; + u8 write_state = PG_STATE_HEADER; + int bcontinual = true, bdataempty = true, bresult = true; + u16 efuse_addr = 0; + u8 efuse_data; + u8 target_word_cnts = 0; + u8 badworden = 0x0F; + static int repeat_times; + + if (efuse_get_current_size(hw) >= + (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) { + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, + ("efuse_pg_packet_write error\n")); + return false; + } + + target_pkt.offset = offset; + target_pkt.word_en = word_en; + + memset((void *)target_pkt.data, 8 * sizeof(u8), 0xFF); + + efuse_word_enable_data_read(word_en, data, target_pkt.data); + target_word_cnts = efuse_calculate_word_cnts(target_pkt.word_en); + + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, ("efuse Power ON\n")); + + while (bcontinual && (efuse_addr < + (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) { + + if (write_state == PG_STATE_HEADER) { + bdataempty = true; + badworden = 0x0F; + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, + ("efuse PG_STATE_HEADER\n")); + + if (efuse_one_byte_read(hw, efuse_addr, &efuse_data) && + (efuse_data != 0xFF)) + efuse_write_data_case1(hw, &efuse_addr, + efuse_data, offset, + &bcontinual, + &write_state, target_pkt, + &repeat_times, &bresult, + word_en); + else + efuse_write_data_case2(hw, &efuse_addr, + &bcontinual, + &write_state, + target_pkt, + &repeat_times, + &bresult); + + } else if (write_state == PG_STATE_DATA) { + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, + ("efuse PG_STATE_DATA\n")); + badworden = 0x0f; + badworden = + efuse_word_enable_data_write(hw, efuse_addr + 1, + target_pkt.word_en, + target_pkt.data); + + if ((badworden & 0x0F) == 0x0F) { + bcontinual = false; + } else { + efuse_addr = + efuse_addr + (2 * target_word_cnts) + 1; + + target_pkt.offset = offset; + target_pkt.word_en = badworden; + target_word_cnts = + efuse_calculate_word_cnts(target_pkt. + word_en); + write_state = PG_STATE_HEADER; + repeat_times++; + if (repeat_times > EFUSE_REPEAT_THRESHOLD_) { + bcontinual = false; + bresult = false; + } + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, + ("efuse PG_STATE_HEADER-3\n")); + } + } + } + + if (efuse_addr >= (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) { + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, + ("efuse_addr(%#x) Out of size!!\n", efuse_addr)); + } + + return true; +} + +static void efuse_word_enable_data_read(u8 word_en, + u8 *sourdata, u8 *targetdata) +{ + if (!(word_en & BIT(0))) { + targetdata[0] = sourdata[0]; + targetdata[1] = sourdata[1]; + } + + if (!(word_en & BIT(1))) { + targetdata[2] = sourdata[2]; + targetdata[3] = sourdata[3]; + } + + if (!(word_en & BIT(2))) { + targetdata[4] = sourdata[4]; + targetdata[5] = sourdata[5]; + } + + if (!(word_en & BIT(3))) { + targetdata[6] = sourdata[6]; + targetdata[7] = sourdata[7]; + } +} + +static u8 efuse_word_enable_data_write(struct ieee80211_hw *hw, + u16 efuse_addr, u8 word_en, u8 *data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 tmpaddr; + u16 start_addr = efuse_addr; + u8 badworden = 0x0F; + u8 tmpdata[8]; + + memset((void *)tmpdata, PGPKT_DATA_SIZE, 0xff); + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, + ("word_en = %x efuse_addr=%x\n", word_en, efuse_addr)); + + if (!(word_en & BIT(0))) { + tmpaddr = start_addr; + efuse_one_byte_write(hw, start_addr++, data[0]); + efuse_one_byte_write(hw, start_addr++, data[1]); + + efuse_one_byte_read(hw, tmpaddr, &tmpdata[0]); + efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[1]); + if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) + badworden &= (~BIT(0)); + } + + if (!(word_en & BIT(1))) { + tmpaddr = start_addr; + efuse_one_byte_write(hw, start_addr++, data[2]); + efuse_one_byte_write(hw, start_addr++, data[3]); + + efuse_one_byte_read(hw, tmpaddr, &tmpdata[2]); + efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[3]); + if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) + badworden &= (~BIT(1)); + } + + if (!(word_en & BIT(2))) { + tmpaddr = start_addr; + efuse_one_byte_write(hw, start_addr++, data[4]); + efuse_one_byte_write(hw, start_addr++, data[5]); + + efuse_one_byte_read(hw, tmpaddr, &tmpdata[4]); + efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[5]); + if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) + badworden &= (~BIT(2)); + } + + if (!(word_en & BIT(3))) { + tmpaddr = start_addr; + efuse_one_byte_write(hw, start_addr++, data[6]); + efuse_one_byte_write(hw, start_addr++, data[7]); + + efuse_one_byte_read(hw, tmpaddr, &tmpdata[6]); + efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[7]); + if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) + badworden &= (~BIT(3)); + } + + return badworden; +} + +static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tempval; + u16 tmpV16; + + if (pwrstate == true) { + tmpV16 = rtl_read_word(rtlpriv, + rtlpriv->cfg->maps[SYS_ISO_CTRL]); + if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { + tmpV16 |= rtlpriv->cfg->maps[EFUSE_PWC_EV12V]; + rtl_write_word(rtlpriv, + rtlpriv->cfg->maps[SYS_ISO_CTRL], + tmpV16); + } + + tmpV16 = rtl_read_word(rtlpriv, + rtlpriv->cfg->maps[SYS_FUNC_EN]); + if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_FEN_ELDR])) { + tmpV16 |= rtlpriv->cfg->maps[EFUSE_FEN_ELDR]; + rtl_write_word(rtlpriv, + rtlpriv->cfg->maps[SYS_FUNC_EN], tmpV16); + } + + tmpV16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_CLK]); + if ((!(tmpV16 & rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN])) || + (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_ANA8M]))) { + tmpV16 |= (rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN] | + rtlpriv->cfg->maps[EFUSE_ANA8M]); + rtl_write_word(rtlpriv, + rtlpriv->cfg->maps[SYS_CLK], tmpV16); + } + } + + if (pwrstate == true) { + if (bwrite == true) { + tempval = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_TEST] + + 3); + tempval &= 0x0F; + tempval |= (VOLTAGE_V25 << 4); + rtl_write_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_TEST] + 3, + (tempval | 0x80)); + } + + } else { + if (bwrite == true) { + tempval = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_TEST] + + 3); + rtl_write_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_TEST] + 3, + (tempval & 0x7F)); + } + + } + +} + +static u16 efuse_get_current_size(struct ieee80211_hw *hw) +{ + int bcontinual = true; + u16 efuse_addr = 0; + u8 hoffset, hworden; + u8 efuse_data, word_cnts; + + while (bcontinual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) + && (efuse_addr < EFUSE_MAX_SIZE)) { + if (efuse_data != 0xFF) { + hoffset = (efuse_data >> 4) & 0x0F; + hworden = efuse_data & 0x0F; + word_cnts = efuse_calculate_word_cnts(hworden); + efuse_addr = efuse_addr + (word_cnts * 2) + 1; + } else { + bcontinual = false; + } + } + + return efuse_addr; +} + +static u8 efuse_calculate_word_cnts(u8 word_en) +{ + u8 word_cnts = 0; + if (!(word_en & BIT(0))) + word_cnts++; + if (!(word_en & BIT(1))) + word_cnts++; + if (!(word_en & BIT(2))) + word_cnts++; + if (!(word_en & BIT(3))) + word_cnts++; + return word_cnts; +} + +void efuse_reset_loader(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 tmp_u2b; + + tmp_u2b = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN]); + rtl_write_word(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN], + (tmp_u2b & ~(BIT(12)))); + udelay(10000); + rtl_write_word(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN], + (tmp_u2b | BIT(12))); + udelay(10000); +} + +bool efuse_program_map(struct ieee80211_hw *hw, char *p_filename, u8 tabletype) +{ + return true; +} diff --git a/drivers/net/wireless/rtlwifi/efuse.h b/drivers/net/wireless/rtlwifi/efuse.h new file mode 100644 index 000000000000..2d39a4df181b --- /dev/null +++ b/drivers/net/wireless/rtlwifi/efuse.h @@ -0,0 +1,124 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL_EFUSE_H_ +#define __RTL_EFUSE_H_ + +#define EFUSE_REAL_CONTENT_LEN 512 +#define EFUSE_MAP_LEN 128 +#define EFUSE_MAX_SECTION 16 +#define EFUSE_MAX_WORD_UNIT 4 + +#define EFUSE_INIT_MAP 0 +#define EFUSE_MODIFY_MAP 1 + +#define PG_STATE_HEADER 0x01 +#define PG_STATE_WORD_0 0x02 +#define PG_STATE_WORD_1 0x04 +#define PG_STATE_WORD_2 0x08 +#define PG_STATE_WORD_3 0x10 +#define PG_STATE_DATA 0x20 + +#define PG_SWBYTE_H 0x01 +#define PG_SWBYTE_L 0x02 + +#define _POWERON_DELAY_ +#define _PRE_EXECUTE_READ_CMD_ + +#define EFUSE_REPEAT_THRESHOLD_ 3 + +struct efuse_map { + u8 offset; + u8 word_start; + u8 byte_start; + u8 byte_cnts; +}; + +struct pgpkt_struct { + u8 offset; + u8 word_en; + u8 data[8]; +}; + +enum efuse_data_item { + EFUSE_CHIP_ID = 0, + EFUSE_LDO_SETTING, + EFUSE_CLK_SETTING, + EFUSE_SDIO_SETTING, + EFUSE_CCCR, + EFUSE_SDIO_MODE, + EFUSE_OCR, + EFUSE_F0CIS, + EFUSE_F1CIS, + EFUSE_MAC_ADDR, + EFUSE_EEPROM_VER, + EFUSE_CHAN_PLAN, + EFUSE_TXPW_TAB +}; + +enum { + VOLTAGE_V25 = 0x03, + LDOE25_SHIFT = 28, +}; + +struct efuse_priv { + u8 id[2]; + u8 ldo_setting[2]; + u8 clk_setting[2]; + u8 cccr; + u8 sdio_mode; + u8 ocr[3]; + u8 cis0[17]; + u8 cis1[48]; + u8 mac_addr[6]; + u8 eeprom_verno; + u8 channel_plan; + u8 tx_power_b[14]; + u8 tx_power_g[14]; +}; + +extern void efuse_initialize(struct ieee80211_hw *hw); +extern u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address); +extern void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value); +extern void read_efuse(struct ieee80211_hw *hw, u16 _offset, + u16 _size_byte, u8 *pbuf); +extern void efuse_shadow_read(struct ieee80211_hw *hw, u8 type, + u16 offset, u32 *value); +extern void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, + u16 offset, u32 value); +extern bool efuse_shadow_update(struct ieee80211_hw *hw); +extern bool efuse_shadow_update_chk(struct ieee80211_hw *hw); +extern void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw); +extern void efuse_force_write_vendor_Id(struct ieee80211_hw *hw); +extern void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx); +extern bool efuse_program_map(struct ieee80211_hw *hw, + char *p_filename, u8 tabletype); +extern void efuse_reset_loader(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c new file mode 100644 index 000000000000..0fa36aa6701a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -0,0 +1,1945 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "core.h" +#include "wifi.h" +#include "pci.h" +#include "base.h" +#include "ps.h" + +static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { + INTEL_VENDOR_ID, + ATI_VENDOR_ID, + AMD_VENDOR_ID, + SIS_VENDOR_ID +}; + +/* Update PCI dependent default settings*/ +static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; + + ppsc->reg_rfps_level = 0; + ppsc->b_support_aspm = 0; + + /*Update PCI ASPM setting */ + ppsc->const_amdpci_aspm = rtlpci->const_amdpci_aspm; + switch (rtlpci->const_pci_aspm) { + case 0: + /*No ASPM */ + break; + + case 1: + /*ASPM dynamically enabled/disable. */ + ppsc->reg_rfps_level |= RT_RF_LPS_LEVEL_ASPM; + break; + + case 2: + /*ASPM with Clock Req dynamically enabled/disable. */ + ppsc->reg_rfps_level |= (RT_RF_LPS_LEVEL_ASPM | + RT_RF_OFF_LEVL_CLK_REQ); + break; + + case 3: + /* + * Always enable ASPM and Clock Req + * from initialization to halt. + * */ + ppsc->reg_rfps_level &= ~(RT_RF_LPS_LEVEL_ASPM); + ppsc->reg_rfps_level |= (RT_RF_PS_LEVEL_ALWAYS_ASPM | + RT_RF_OFF_LEVL_CLK_REQ); + break; + + case 4: + /* + * Always enable ASPM without Clock Req + * from initialization to halt. + * */ + ppsc->reg_rfps_level &= ~(RT_RF_LPS_LEVEL_ASPM | + RT_RF_OFF_LEVL_CLK_REQ); + ppsc->reg_rfps_level |= RT_RF_PS_LEVEL_ALWAYS_ASPM; + break; + } + + ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_HALT_NIC; + + /*Update Radio OFF setting */ + switch (rtlpci->const_hwsw_rfoff_d3) { + case 1: + if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM) + ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_ASPM; + break; + + case 2: + if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM) + ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_ASPM; + ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_HALT_NIC; + break; + + case 3: + ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_PCI_D3; + break; + } + + /*Set HW definition to determine if it supports ASPM. */ + switch (rtlpci->const_support_pciaspm) { + case 0:{ + /*Not support ASPM. */ + bool b_support_aspm = false; + ppsc->b_support_aspm = b_support_aspm; + break; + } + case 1:{ + /*Support ASPM. */ + bool b_support_aspm = true; + bool b_support_backdoor = true; + ppsc->b_support_aspm = b_support_aspm; + + /*if(priv->oem_id == RT_CID_TOSHIBA && + !priv->ndis_adapter.amd_l1_patch) + b_support_backdoor = false; */ + + ppsc->b_support_backdoor = b_support_backdoor; + + break; + } + case 2: + /*ASPM value set by chipset. */ + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) { + bool b_support_aspm = true; + ppsc->b_support_aspm = b_support_aspm; + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } +} + +static bool _rtl_pci_platform_switch_device_pci_aspm( + struct ieee80211_hw *hw, + u8 value) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + bool bresult = false; + + value |= 0x40; + + pci_write_config_byte(rtlpci->pdev, 0x80, value); + + return bresult; +} + +/*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/ +static bool _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 buffer; + bool bresult = false; + + buffer = value; + + pci_write_config_byte(rtlpci->pdev, 0x81, value); + bresult = true; + + return bresult; +} + +/*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/ +static void rtl_pci_disable_aspm(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; + u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport; + u8 num4bytes = pcipriv->ndis_adapter.num4bytes; + /*Retrieve original configuration settings. */ + u8 linkctrl_reg = pcipriv->ndis_adapter.linkctrl_reg; + u16 pcibridge_linkctrlreg = pcipriv->ndis_adapter. + pcibridge_linkctrlreg; + u16 aspmlevel = 0; + + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + ("PCI(Bridge) UNKNOWN.\n")); + + return; + } + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) { + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ); + _rtl_pci_switch_clk_req(hw, 0x0); + } + + if (1) { + /*for promising device will in L0 state after an I/O. */ + u8 tmp_u1b; + pci_read_config_byte(rtlpci->pdev, 0x80, &tmp_u1b); + } + + /*Set corresponding value. */ + aspmlevel |= BIT(0) | BIT(1); + linkctrl_reg &= ~aspmlevel; + pcibridge_linkctrlreg &= ~(BIT(0) | BIT(1)); + + _rtl_pci_platform_switch_device_pci_aspm(hw, linkctrl_reg); + udelay(50); + + /*4 Disable Pci Bridge ASPM */ + rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, + pcicfg_addrport + (num4bytes << 2)); + rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, pcibridge_linkctrlreg); + + udelay(50); + +} + +/* + *Enable RTL8192SE ASPM & Enable Pci Bridge ASPM for + *power saving We should follow the sequence to enable + *RTL8192SE first then enable Pci Bridge ASPM + *or the system will show bluescreen. + */ +static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 pcibridge_busnum = pcipriv->ndis_adapter.pcibridge_busnum; + u8 pcibridge_devnum = pcipriv->ndis_adapter.pcibridge_devnum; + u8 pcibridge_funcnum = pcipriv->ndis_adapter.pcibridge_funcnum; + u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; + u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport; + u8 num4bytes = pcipriv->ndis_adapter.num4bytes; + u16 aspmlevel; + u8 u_pcibridge_aspmsetting; + u8 u_device_aspmsetting; + + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + ("PCI(Bridge) UNKNOWN.\n")); + return; + } + + /*4 Enable Pci Bridge ASPM */ + rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, + pcicfg_addrport + (num4bytes << 2)); + + u_pcibridge_aspmsetting = + pcipriv->ndis_adapter.pcibridge_linkctrlreg | + rtlpci->const_hostpci_aspm_setting; + + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) + u_pcibridge_aspmsetting &= ~BIT(0); + + rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, u_pcibridge_aspmsetting); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("PlatformEnableASPM():PciBridge busnumber[%x], " + "DevNumbe[%x], funcnumber[%x], Write reg[%x] = %x\n", + pcibridge_busnum, pcibridge_devnum, pcibridge_funcnum, + (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10), + u_pcibridge_aspmsetting)); + + udelay(50); + + /*Get ASPM level (with/without Clock Req) */ + aspmlevel = rtlpci->const_devicepci_aspm_setting; + u_device_aspmsetting = pcipriv->ndis_adapter.linkctrl_reg; + + /*_rtl_pci_platform_switch_device_pci_aspm(dev,*/ + /*(priv->ndis_adapter.linkctrl_reg | ASPMLevel)); */ + + u_device_aspmsetting |= aspmlevel; + + _rtl_pci_platform_switch_device_pci_aspm(hw, u_device_aspmsetting); + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) { + _rtl_pci_switch_clk_req(hw, (ppsc->reg_rfps_level & + RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ); + } + udelay(200); +} + +static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport; + + bool status = false; + u8 offset_e0; + unsigned offset_e4; + + rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, + pcicfg_addrport + 0xE0); + rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, 0xA0); + + rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, + pcicfg_addrport + 0xE0); + rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &offset_e0); + + if (offset_e0 == 0xA0) { + rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, + pcicfg_addrport + 0xE4); + rtl_pci_raw_read_port_ulong(PCI_CONF_DATA, &offset_e4); + if (offset_e4 & BIT(23)) + status = true; + } + + return status; +} + +static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset; + u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport; + u8 linkctrl_reg; + u8 num4bBytes; + + num4bBytes = (capabilityoffset + 0x10) / 4; + + /*Read Link Control Register */ + rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, + pcicfg_addrport + (num4bBytes << 2)); + rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &linkctrl_reg); + + pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg; +} + +static void rtl_pci_parse_configuration(struct pci_dev *pdev, + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + + u8 tmp; + int pos; + u8 linkctrl_reg; + + /*Link Control Register */ + pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); + pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &linkctrl_reg); + pcipriv->ndis_adapter.linkctrl_reg = linkctrl_reg; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Link Control Register =%x\n", + pcipriv->ndis_adapter.linkctrl_reg)); + + pci_read_config_byte(pdev, 0x98, &tmp); + tmp |= BIT(4); + pci_write_config_byte(pdev, 0x98, tmp); + + tmp = 0x17; + pci_write_config_byte(pdev, 0x70f, tmp); +} + +static void _rtl_pci_initialize_adapter_common(struct ieee80211_hw *hw) +{ + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + _rtl_pci_update_default_setting(hw); + + if (ppsc->reg_rfps_level & RT_RF_PS_LEVEL_ALWAYS_ASPM) { + /*Always enable ASPM & Clock Req. */ + rtl_pci_enable_aspm(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_PS_LEVEL_ALWAYS_ASPM); + } + +} + +static void rtl_pci_init_aspm(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*close ASPM for AMD defaultly */ + rtlpci->const_amdpci_aspm = 0; + + /* + * ASPM PS mode. + * 0 - Disable ASPM, + * 1 - Enable ASPM without Clock Req, + * 2 - Enable ASPM with Clock Req, + * 3 - Alwyas Enable ASPM with Clock Req, + * 4 - Always Enable ASPM without Clock Req. + * set defult to RTL8192CE:3 RTL8192E:2 + * */ + rtlpci->const_pci_aspm = 3; + + /*Setting for PCI-E device */ + rtlpci->const_devicepci_aspm_setting = 0x03; + + /*Setting for PCI-E bridge */ + rtlpci->const_hostpci_aspm_setting = 0x02; + + /* + * In Hw/Sw Radio Off situation. + * 0 - Default, + * 1 - From ASPM setting without low Mac Pwr, + * 2 - From ASPM setting with low Mac Pwr, + * 3 - Bus D3 + * set default to RTL8192CE:0 RTL8192SE:2 + */ + rtlpci->const_hwsw_rfoff_d3 = 0; + + /* + * This setting works for those device with + * backdoor ASPM setting such as EPHY setting. + * 0 - Not support ASPM, + * 1 - Support ASPM, + * 2 - According to chipset. + */ + rtlpci->const_support_pciaspm = 1; + + _rtl_pci_initialize_adapter_common(hw); +} + +static void _rtl_pci_io_handler_init(struct device *dev, + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->io.dev = dev; + + rtlpriv->io.write8_async = pci_write8_async; + rtlpriv->io.write16_async = pci_write16_async; + rtlpriv->io.write32_async = pci_write32_async; + + rtlpriv->io.read8_sync = pci_read8_sync; + rtlpriv->io.read16_sync = pci_read16_sync; + rtlpriv->io.read32_sync = pci_read32_sync; + +} + +static void _rtl_pci_io_handler_release(struct ieee80211_hw *hw) +{ +} + +static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[prio]; + + while (skb_queue_len(&ring->queue)) { + struct rtl_tx_desc *entry = &ring->desc[ring->idx]; + struct sk_buff *skb; + struct ieee80211_tx_info *info; + + u8 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, true, + HW_DESC_OWN); + + /* + *beacon packet will only use the first + *descriptor defautly,and the own may not + *be cleared by the hardware + */ + if (own) + return; + ring->idx = (ring->idx + 1) % ring->entries; + + skb = __skb_dequeue(&ring->queue); + pci_unmap_single(rtlpci->pdev, + le32_to_cpu(rtlpriv->cfg->ops-> + get_desc((u8 *) entry, true, + HW_DESC_TXBUFF_ADDR)), + skb->len, PCI_DMA_TODEVICE); + + RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_TRACE, + ("new ring->idx:%d, " + "free: skb_queue_len:%d, free: seq:%x\n", + ring->idx, + skb_queue_len(&ring->queue), + *(u16 *) (skb->data + 22))); + + info = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(info); + + info->flags |= IEEE80211_TX_STAT_ACK; + /*info->status.rates[0].count = 1; */ + + ieee80211_tx_status_irqsafe(hw, skb); + + if ((ring->entries - skb_queue_len(&ring->queue)) + == 2) { + + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + ("more desc left, wake" + "skb_queue@%d,ring->idx = %d," + "skb_queue_len = 0x%d\n", + prio, ring->idx, + skb_queue_len(&ring->queue))); + + ieee80211_wake_queue(hw, + skb_get_queue_mapping + (skb)); + } + + skb = NULL; + } + + if (((rtlpriv->link_info.num_rx_inperiod + + rtlpriv->link_info.num_tx_inperiod) > 8) || + (rtlpriv->link_info.num_rx_inperiod > 2)) { + rtl_lps_leave(hw); + } +} + +static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + int rx_queue_idx = RTL_PCI_RX_MPDU_QUEUE; + + struct ieee80211_rx_status rx_status = { 0 }; + unsigned int count = rtlpci->rxringcount; + u8 own; + u8 tmp_one; + u32 bufferaddress; + bool unicast = false; + + struct rtl_stats stats = { + .signal = 0, + .noise = -98, + .rate = 0, + }; + + /*RX NORMAL PKT */ + while (count--) { + /*rx descriptor */ + struct rtl_rx_desc *pdesc = &rtlpci->rx_ring[rx_queue_idx].desc[ + rtlpci->rx_ring[rx_queue_idx].idx]; + /*rx pkt */ + struct sk_buff *skb = rtlpci->rx_ring[rx_queue_idx].rx_buf[ + rtlpci->rx_ring[rx_queue_idx].idx]; + + own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, + false, HW_DESC_OWN); + + if (own) { + /*wait data to be filled by hardware */ + return; + } else { + struct ieee80211_hdr *hdr; + u16 fc; + struct sk_buff *new_skb = NULL; + + rtlpriv->cfg->ops->query_rx_desc(hw, &stats, + &rx_status, + (u8 *) pdesc, skb); + + pci_unmap_single(rtlpci->pdev, + *((dma_addr_t *) skb->cb), + rtlpci->rxbuffersize, + PCI_DMA_FROMDEVICE); + + skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc, + false, + HW_DESC_RXPKT_LEN)); + skb_reserve(skb, + stats.rx_drvinfo_size + stats.rx_bufshift); + + /* + *NOTICE This can not be use for mac80211, + *this is done in mac80211 code, + *if you done here sec DHCP will fail + *skb_trim(skb, skb->len - 4); + */ + + hdr = (struct ieee80211_hdr *)(skb->data); + fc = le16_to_cpu(hdr->frame_control); + + if (!stats.b_crc) { + memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, + sizeof(rx_status)); + + if (is_broadcast_ether_addr(hdr->addr1)) + ;/*TODO*/ + else { + if (is_multicast_ether_addr(hdr->addr1)) + ;/*TODO*/ + else { + unicast = true; + rtlpriv->stats.rxbytesunicast += + skb->len; + } + } + + rtl_is_special_data(hw, skb, false); + + if (ieee80211_is_data(fc)) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_RX); + + if (unicast) + rtlpriv->link_info. + num_rx_inperiod++; + } + + if (unlikely(!rtl_action_proc(hw, skb, + false))) { + dev_kfree_skb_any(skb); + } else { + struct sk_buff *uskb = NULL; + u8 *pdata; + uskb = dev_alloc_skb(skb->len + 128); + memcpy(IEEE80211_SKB_RXCB(uskb), + &rx_status, + sizeof(rx_status)); + pdata = (u8 *)skb_put(uskb, skb->len); + memcpy(pdata, skb->data, skb->len); + dev_kfree_skb_any(skb); + + ieee80211_rx_irqsafe(hw, uskb); + } + } else { + dev_kfree_skb_any(skb); + } + + if (((rtlpriv->link_info.num_rx_inperiod + + rtlpriv->link_info.num_tx_inperiod) > 8) || + (rtlpriv->link_info.num_rx_inperiod > 2)) { + rtl_lps_leave(hw); + } + + new_skb = dev_alloc_skb(rtlpci->rxbuffersize); + if (unlikely(!new_skb)) { + RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), + DBG_DMESG, + ("can't alloc skb for rx\n")); + goto done; + } + skb = new_skb; + /*skb->dev = dev; */ + + rtlpci->rx_ring[rx_queue_idx].rx_buf[rtlpci-> + rx_ring + [rx_queue_idx]. + idx] = skb; + *((dma_addr_t *) skb->cb) = + pci_map_single(rtlpci->pdev, skb_tail_pointer(skb), + rtlpci->rxbuffersize, + PCI_DMA_FROMDEVICE); + + } +done: + bufferaddress = cpu_to_le32(*((dma_addr_t *) skb->cb)); + tmp_one = 1; + rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false, + HW_DESC_RXBUFF_ADDR, + (u8 *)&bufferaddress); + rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN, + (u8 *)&tmp_one); + rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, + HW_DESC_RXPKT_LEN, + (u8 *)&rtlpci->rxbuffersize); + + if (rtlpci->rx_ring[rx_queue_idx].idx == + rtlpci->rxringcount - 1) + rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, + HW_DESC_RXERO, + (u8 *)&tmp_one); + + rtlpci->rx_ring[rx_queue_idx].idx = + (rtlpci->rx_ring[rx_queue_idx].idx + 1) % + rtlpci->rxringcount; + } + +} + +void _rtl_pci_tx_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + int prio; + + for (prio = 0; prio < RTL_PCI_MAX_TX_QUEUE_COUNT; prio++) { + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[prio]; + + while (skb_queue_len(&ring->queue)) { + struct rtl_tx_desc *entry = &ring->desc[ring->idx]; + struct sk_buff *skb; + struct ieee80211_tx_info *info; + u8 own; + + /* + *beacon packet will only use the first + *descriptor defautly, and the own may not + *be cleared by the hardware, and + *beacon will free in prepare beacon + */ + if (prio == BEACON_QUEUE || prio == TXCMD_QUEUE || + prio == HCCA_QUEUE) + break; + + own = (u8)rtlpriv->cfg->ops->get_desc((u8 *)entry, + true, + HW_DESC_OWN); + + if (own) + break; + + skb = __skb_dequeue(&ring->queue); + pci_unmap_single(rtlpci->pdev, + le32_to_cpu(rtlpriv->cfg->ops-> + get_desc((u8 *) entry, + true, + HW_DESC_TXBUFF_ADDR)), + skb->len, PCI_DMA_TODEVICE); + + ring->idx = (ring->idx + 1) % ring->entries; + + info = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(info); + + info->flags |= IEEE80211_TX_STAT_ACK; + /*info->status.rates[0].count = 1; */ + + ieee80211_tx_status_irqsafe(hw, skb); + + if ((ring->entries - skb_queue_len(&ring->queue)) + == 2 && prio != BEACON_QUEUE) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("more desc left, wake " + "skb_queue@%d,ring->idx = %d," + "skb_queue_len = 0x%d\n", + prio, ring->idx, + skb_queue_len(&ring->queue))); + + ieee80211_wake_queue(hw, + skb_get_queue_mapping + (skb)); + } + + skb = NULL; + } + } +} + +static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) +{ + struct ieee80211_hw *hw = dev_id; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + unsigned long flags; + u32 inta = 0; + u32 intb = 0; + + if (rtlpci->irq_enabled == 0) + return IRQ_HANDLED; + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + + /*read ISR: 4/8bytes */ + rtlpriv->cfg->ops->interrupt_recognized(hw, &inta, &intb); + + /*Shared IRQ or HW disappared */ + if (!inta || inta == 0xffff) + goto done; + + /*<1> beacon related */ + if (inta & rtlpriv->cfg->maps[RTL_IMR_TBDOK]) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + ("beacon ok interrupt!\n")); + } + + if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_TBDER])) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + ("beacon err interrupt!\n")); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_BDOK]) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + ("beacon interrupt!\n")); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_BcnInt]) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + ("prepare beacon for interrupt!\n")); + tasklet_schedule(&rtlpriv->works.irq_prepare_bcn_tasklet); + } + + /*<3> Tx related */ + if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_TXFOVW])) + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("IMR_TXFOVW!\n")); + + if (inta & rtlpriv->cfg->maps[RTL_IMR_MGNTDOK]) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + ("Manage ok interrupt!\n")); + _rtl_pci_tx_isr(hw, MGNT_QUEUE); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_HIGHDOK]) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + ("HIGH_QUEUE ok interrupt!\n")); + _rtl_pci_tx_isr(hw, HIGH_QUEUE); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_BKDOK]) { + rtlpriv->link_info.num_tx_inperiod++; + + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + ("BK Tx OK interrupt!\n")); + _rtl_pci_tx_isr(hw, BK_QUEUE); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_BEDOK]) { + rtlpriv->link_info.num_tx_inperiod++; + + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + ("BE TX OK interrupt!\n")); + _rtl_pci_tx_isr(hw, BE_QUEUE); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_VIDOK]) { + rtlpriv->link_info.num_tx_inperiod++; + + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + ("VI TX OK interrupt!\n")); + _rtl_pci_tx_isr(hw, VI_QUEUE); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_VODOK]) { + rtlpriv->link_info.num_tx_inperiod++; + + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + ("Vo TX OK interrupt!\n")); + _rtl_pci_tx_isr(hw, VO_QUEUE); + } + + /*<2> Rx related */ + if (inta & rtlpriv->cfg->maps[RTL_IMR_ROK]) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, ("Rx ok interrupt!\n")); + tasklet_schedule(&rtlpriv->works.irq_tasklet); + } + + if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RDU])) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("rx descriptor unavailable!\n")); + tasklet_schedule(&rtlpriv->works.irq_tasklet); + } + + if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RXFOVW])) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("rx overflow !\n")); + tasklet_schedule(&rtlpriv->works.irq_tasklet); + } + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + return IRQ_HANDLED; + +done: + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + return IRQ_HANDLED; +} + +static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw) +{ + _rtl_pci_rx_interrupt(hw); +} + +static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; + struct ieee80211_hdr *hdr = NULL; + struct ieee80211_tx_info *info = NULL; + struct sk_buff *pskb = NULL; + struct rtl_tx_desc *pdesc = NULL; + unsigned int queue_index; + u8 temp_one = 1; + + ring = &rtlpci->tx_ring[BEACON_QUEUE]; + pskb = __skb_dequeue(&ring->queue); + if (pskb) + kfree_skb(pskb); + + /*NB: the beacon data buffer must be 32-bit aligned. */ + pskb = ieee80211_beacon_get(hw, mac->vif); + if (pskb == NULL) + return; + hdr = (struct ieee80211_hdr *)(pskb->data); + info = IEEE80211_SKB_CB(pskb); + + queue_index = BEACON_QUEUE; + + pdesc = &ring->desc[0]; + rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, + info, pskb, queue_index); + + __skb_queue_tail(&ring->queue, pskb); + + rtlpriv->cfg->ops->set_desc((u8 *) pdesc, true, HW_DESC_OWN, + (u8 *)&temp_one); + + return; +} + +static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 i; + + for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) + rtlpci->txringcount[i] = RT_TXDESC_NUM; + + /* + *we just alloc 2 desc for beacon queue, + *because we just need first desc in hw beacon. + */ + rtlpci->txringcount[BEACON_QUEUE] = 2; + + /* + *BE queue need more descriptor for performance + *consideration or, No more tx desc will happen, + *and may cause mac80211 mem leakage. + */ + rtlpci->txringcount[BE_QUEUE] = RT_TXDESC_NUM_BE_QUEUE; + + rtlpci->rxbuffersize = 9100; /*2048/1024; */ + rtlpci->rxringcount = RTL_PCI_MAX_RX_COUNT; /*64; */ +} + +static void _rtl_pci_init_struct(struct ieee80211_hw *hw, + struct pci_dev *pdev) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + rtlpci->up_first_time = true; + rtlpci->being_init_adapter = false; + + rtlhal->hw = hw; + rtlpci->pdev = pdev; + + ppsc->b_inactiveps = false; + ppsc->b_leisure_ps = true; + ppsc->b_fwctrl_lps = true; + ppsc->b_reg_fwctrl_lps = 3; + ppsc->reg_max_lps_awakeintvl = 5; + + if (ppsc->b_reg_fwctrl_lps == 1) + ppsc->fwctrl_psmode = FW_PS_MIN_MODE; + else if (ppsc->b_reg_fwctrl_lps == 2) + ppsc->fwctrl_psmode = FW_PS_MAX_MODE; + else if (ppsc->b_reg_fwctrl_lps == 3) + ppsc->fwctrl_psmode = FW_PS_DTIM_MODE; + + /*Tx/Rx related var */ + _rtl_pci_init_trx_var(hw); + + /*IBSS*/ mac->beacon_interval = 100; + + /*AMPDU*/ mac->min_space_cfg = 0; + mac->max_mss_density = 0; + /*set sane AMPDU defaults */ + mac->current_ampdu_density = 7; + mac->current_ampdu_factor = 3; + + /*QOS*/ rtlpci->acm_method = eAcmWay2_SW; + + /*task */ + tasklet_init(&rtlpriv->works.irq_tasklet, + (void (*)(unsigned long))_rtl_pci_irq_tasklet, + (unsigned long)hw); + tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, + (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, + (unsigned long)hw); +} + +static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, + unsigned int prio, unsigned int entries) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_tx_desc *ring; + dma_addr_t dma; + u32 nextdescaddress; + int i; + + ring = pci_alloc_consistent(rtlpci->pdev, + sizeof(*ring) * entries, &dma); + + if (!ring || (unsigned long)ring & 0xFF) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Cannot allocate TX ring (prio = %d)\n", prio)); + return -ENOMEM; + } + + memset(ring, 0, sizeof(*ring) * entries); + rtlpci->tx_ring[prio].desc = ring; + rtlpci->tx_ring[prio].dma = dma; + rtlpci->tx_ring[prio].idx = 0; + rtlpci->tx_ring[prio].entries = entries; + skb_queue_head_init(&rtlpci->tx_ring[prio].queue); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("queue:%d, ring_addr:%p\n", prio, ring)); + + for (i = 0; i < entries; i++) { + nextdescaddress = cpu_to_le32((u32) dma + + ((i + 1) % entries) * + sizeof(*ring)); + + rtlpriv->cfg->ops->set_desc((u8 *)&(ring[i]), + true, HW_DESC_TX_NEXTDESC_ADDR, + (u8 *)&nextdescaddress); + } + + return 0; +} + +static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_rx_desc *entry = NULL; + int i, rx_queue_idx; + u8 tmp_one = 1; + + /* + *rx_queue_idx 0:RX_MPDU_QUEUE + *rx_queue_idx 1:RX_CMD_QUEUE + */ + for (rx_queue_idx = 0; rx_queue_idx < RTL_PCI_MAX_RX_QUEUE; + rx_queue_idx++) { + rtlpci->rx_ring[rx_queue_idx].desc = + pci_alloc_consistent(rtlpci->pdev, + sizeof(*rtlpci->rx_ring[rx_queue_idx]. + desc) * rtlpci->rxringcount, + &rtlpci->rx_ring[rx_queue_idx].dma); + + if (!rtlpci->rx_ring[rx_queue_idx].desc || + (unsigned long)rtlpci->rx_ring[rx_queue_idx].desc & 0xFF) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Cannot allocate RX ring\n")); + return -ENOMEM; + } + + memset(rtlpci->rx_ring[rx_queue_idx].desc, 0, + sizeof(*rtlpci->rx_ring[rx_queue_idx].desc) * + rtlpci->rxringcount); + + rtlpci->rx_ring[rx_queue_idx].idx = 0; + + for (i = 0; i < rtlpci->rxringcount; i++) { + struct sk_buff *skb = + dev_alloc_skb(rtlpci->rxbuffersize); + u32 bufferaddress; + entry = &rtlpci->rx_ring[rx_queue_idx].desc[i]; + if (!skb) + return 0; + + /*skb->dev = dev; */ + + rtlpci->rx_ring[rx_queue_idx].rx_buf[i] = skb; + + /* + *just set skb->cb to mapping addr + *for pci_unmap_single use + */ + *((dma_addr_t *) skb->cb) = + pci_map_single(rtlpci->pdev, skb_tail_pointer(skb), + rtlpci->rxbuffersize, + PCI_DMA_FROMDEVICE); + + bufferaddress = cpu_to_le32(*((dma_addr_t *)skb->cb)); + rtlpriv->cfg->ops->set_desc((u8 *)entry, false, + HW_DESC_RXBUFF_ADDR, + (u8 *)&bufferaddress); + rtlpriv->cfg->ops->set_desc((u8 *)entry, false, + HW_DESC_RXPKT_LEN, + (u8 *)&rtlpci-> + rxbuffersize); + rtlpriv->cfg->ops->set_desc((u8 *) entry, false, + HW_DESC_RXOWN, + (u8 *)&tmp_one); + } + + rtlpriv->cfg->ops->set_desc((u8 *) entry, false, + HW_DESC_RXERO, (u8 *)&tmp_one); + } + return 0; +} + +static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw, + unsigned int prio) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[prio]; + + while (skb_queue_len(&ring->queue)) { + struct rtl_tx_desc *entry = &ring->desc[ring->idx]; + struct sk_buff *skb = __skb_dequeue(&ring->queue); + + pci_unmap_single(rtlpci->pdev, + le32_to_cpu(rtlpriv->cfg-> + ops->get_desc((u8 *) entry, true, + HW_DESC_TXBUFF_ADDR)), + skb->len, PCI_DMA_TODEVICE); + kfree_skb(skb); + ring->idx = (ring->idx + 1) % ring->entries; + } + + pci_free_consistent(rtlpci->pdev, + sizeof(*ring->desc) * ring->entries, + ring->desc, ring->dma); + ring->desc = NULL; +} + +static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci) +{ + int i, rx_queue_idx; + + /*rx_queue_idx 0:RX_MPDU_QUEUE */ + /*rx_queue_idx 1:RX_CMD_QUEUE */ + for (rx_queue_idx = 0; rx_queue_idx < RTL_PCI_MAX_RX_QUEUE; + rx_queue_idx++) { + for (i = 0; i < rtlpci->rxringcount; i++) { + struct sk_buff *skb = + rtlpci->rx_ring[rx_queue_idx].rx_buf[i]; + if (!skb) + continue; + + pci_unmap_single(rtlpci->pdev, + *((dma_addr_t *) skb->cb), + rtlpci->rxbuffersize, + PCI_DMA_FROMDEVICE); + kfree_skb(skb); + } + + pci_free_consistent(rtlpci->pdev, + sizeof(*rtlpci->rx_ring[rx_queue_idx]. + desc) * rtlpci->rxringcount, + rtlpci->rx_ring[rx_queue_idx].desc, + rtlpci->rx_ring[rx_queue_idx].dma); + rtlpci->rx_ring[rx_queue_idx].desc = NULL; + } +} + +static int _rtl_pci_init_trx_ring(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + int ret; + int i; + + ret = _rtl_pci_init_rx_ring(hw); + if (ret) + return ret; + + for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) { + ret = _rtl_pci_init_tx_ring(hw, i, + rtlpci->txringcount[i]); + if (ret) + goto err_free_rings; + } + + return 0; + +err_free_rings: + _rtl_pci_free_rx_ring(rtlpci); + + for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) + if (rtlpci->tx_ring[i].desc) + _rtl_pci_free_tx_ring(hw, i); + + return 1; +} + +static int _rtl_pci_deinit_trx_ring(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 i; + + /*free rx rings */ + _rtl_pci_free_rx_ring(rtlpci); + + /*free tx rings */ + for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) + _rtl_pci_free_tx_ring(hw, i); + + return 0; +} + +int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + int i, rx_queue_idx; + unsigned long flags; + u8 tmp_one = 1; + + /*rx_queue_idx 0:RX_MPDU_QUEUE */ + /*rx_queue_idx 1:RX_CMD_QUEUE */ + for (rx_queue_idx = 0; rx_queue_idx < RTL_PCI_MAX_RX_QUEUE; + rx_queue_idx++) { + /* + *force the rx_ring[RX_MPDU_QUEUE/ + *RX_CMD_QUEUE].idx to the first one + */ + if (rtlpci->rx_ring[rx_queue_idx].desc) { + struct rtl_rx_desc *entry = NULL; + + for (i = 0; i < rtlpci->rxringcount; i++) { + entry = &rtlpci->rx_ring[rx_queue_idx].desc[i]; + rtlpriv->cfg->ops->set_desc((u8 *) entry, + false, + HW_DESC_RXOWN, + (u8 *)&tmp_one); + } + rtlpci->rx_ring[rx_queue_idx].idx = 0; + } + } + + /* + *after reset, release previous pending packet, + *and force the tx idx to the first one + */ + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) { + if (rtlpci->tx_ring[i].desc) { + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[i]; + + while (skb_queue_len(&ring->queue)) { + struct rtl_tx_desc *entry = + &ring->desc[ring->idx]; + struct sk_buff *skb = + __skb_dequeue(&ring->queue); + + pci_unmap_single(rtlpci->pdev, + le32_to_cpu(rtlpriv->cfg->ops-> + get_desc((u8 *) + entry, + true, + HW_DESC_TXBUFF_ADDR)), + skb->len, PCI_DMA_TODEVICE); + kfree_skb(skb); + ring->idx = (ring->idx + 1) % ring->entries; + } + ring->idx = 0; + } + } + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + + return 0; +} + +unsigned int _rtl_mac_to_hwqueue(u16 fc, + unsigned int mac80211_queue_index) +{ + unsigned int hw_queue_index; + + if (unlikely(ieee80211_is_beacon(fc))) { + hw_queue_index = BEACON_QUEUE; + goto out; + } + + if (ieee80211_is_mgmt(fc)) { + hw_queue_index = MGNT_QUEUE; + goto out; + } + + switch (mac80211_queue_index) { + case 0: + hw_queue_index = VO_QUEUE; + break; + case 1: + hw_queue_index = VI_QUEUE; + break; + case 2: + hw_queue_index = BE_QUEUE;; + break; + case 3: + hw_queue_index = BK_QUEUE; + break; + default: + hw_queue_index = BE_QUEUE; + RT_ASSERT(false, ("QSLT_BE queue, skb_queue:%d\n", + mac80211_queue_index)); + break; + } + +out: + return hw_queue_index; +} + +int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct rtl8192_tx_ring *ring; + struct rtl_tx_desc *pdesc; + u8 idx; + unsigned int queue_index, hw_queue; + unsigned long flags; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + u16 fc = le16_to_cpu(hdr->frame_control); + u8 *pda_addr = hdr->addr1; + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + /*ssn */ + u8 *qc = NULL; + u8 tid = 0; + u16 seq_number = 0; + u8 own; + u8 temp_one = 1; + + if (ieee80211_is_mgmt(fc)) + rtl_tx_mgmt_proc(hw, skb); + rtl_action_proc(hw, skb, true); + + queue_index = skb_get_queue_mapping(skb); + hw_queue = _rtl_mac_to_hwqueue(fc, queue_index); + + if (is_multicast_ether_addr(pda_addr)) + rtlpriv->stats.txbytesmulticast += skb->len; + else if (is_broadcast_ether_addr(pda_addr)) + rtlpriv->stats.txbytesbroadcast += skb->len; + else + rtlpriv->stats.txbytesunicast += skb->len; + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + + ring = &rtlpci->tx_ring[hw_queue]; + if (hw_queue != BEACON_QUEUE) + idx = (ring->idx + skb_queue_len(&ring->queue)) % + ring->entries; + else + idx = 0; + + pdesc = &ring->desc[idx]; + own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, + true, HW_DESC_OWN); + + if ((own == 1) && (hw_queue != BEACON_QUEUE)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("No more TX desc@%d, ring->idx = %d," + "idx = %d, skb_queue_len = 0x%d\n", + hw_queue, ring->idx, idx, + skb_queue_len(&ring->queue))); + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + return skb->len; + } + + /* + *if(ieee80211_is_nullfunc(fc)) { + * spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + * return 1; + *} + */ + + if (ieee80211_is_data_qos(fc)) { + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + + seq_number = mac->tids[tid].seq_number; + seq_number &= IEEE80211_SCTL_SEQ; + /* + *hdr->seq_ctrl = hdr->seq_ctrl & + *cpu_to_le16(IEEE80211_SCTL_FRAG); + *hdr->seq_ctrl |= cpu_to_le16(seq_number); + */ + + seq_number += 1; + } + + if (ieee80211_is_data(fc)) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); + + rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, + info, skb, hw_queue); + + __skb_queue_tail(&ring->queue, skb); + + rtlpriv->cfg->ops->set_desc((u8 *) pdesc, true, + HW_DESC_OWN, (u8 *)&temp_one); + + if (!ieee80211_has_morefrags(hdr->frame_control)) { + if (qc) + mac->tids[tid].seq_number = seq_number; + } + + if ((ring->entries - skb_queue_len(&ring->queue)) < 2 && + hw_queue != BEACON_QUEUE) { + + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + ("less desc left, stop skb_queue@%d, " + "ring->idx = %d," + "idx = %d, skb_queue_len = 0x%d\n", + hw_queue, ring->idx, idx, + skb_queue_len(&ring->queue))); + + ieee80211_stop_queue(hw, skb_get_queue_mapping(skb)); + } + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + + rtlpriv->cfg->ops->tx_polling(hw, hw_queue); + + return 0; +} + +void rtl_pci_deinit(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + _rtl_pci_deinit_trx_ring(hw); + + synchronize_irq(rtlpci->pdev->irq); + tasklet_kill(&rtlpriv->works.irq_tasklet); + + flush_workqueue(rtlpriv->works.rtl_wq); + destroy_workqueue(rtlpriv->works.rtl_wq); + +} + +int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int err; + + _rtl_pci_init_struct(hw, pdev); + + err = _rtl_pci_init_trx_ring(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("tx ring initialization failed")); + return err; + } + + return 1; +} + +int rtl_pci_start(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + int err; + + rtl_pci_reset_trx_ring(hw); + + rtlpci->driver_is_goingto_unload = false; + err = rtlpriv->cfg->ops->hw_init(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + ("Failed to config hardware!\n")); + return err; + } + + rtlpriv->cfg->ops->enable_interrupt(hw); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("enable_interrupt OK\n")); + + rtl_init_rx_config(hw); + + /*should after adapter start and interrupt enable. */ + set_hal_start(rtlhal); + + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + + rtlpci->up_first_time = false; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("OK\n")); + return 0; +} + +void rtl_pci_stop(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + unsigned long flags; + u8 RFInProgressTimeOut = 0; + + /* + *should before disable interrrupt&adapter + *and will do it immediately. + */ + set_hal_stop(rtlhal); + + rtlpriv->cfg->ops->disable_interrupt(hw); + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); + while (ppsc->rfchange_inprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); + if (RFInProgressTimeOut > 100) { + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); + break; + } + mdelay(1); + RFInProgressTimeOut++; + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); + } + ppsc->rfchange_inprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); + + rtlpci->driver_is_goingto_unload = true; + rtlpriv->cfg->ops->hw_disable(hw); + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); + + rtl_pci_enable_aspm(hw); +} + +static bool _rtl_pci_find_adapter(struct pci_dev *pdev, + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct pci_dev *bridge_pdev = pdev->bus->self; + u16 venderid; + u16 deviceid; + u8 revisionid; + u16 irqline; + u8 tmp; + + venderid = pdev->vendor; + deviceid = pdev->device; + pci_read_config_byte(pdev, 0x8, &revisionid); + pci_read_config_word(pdev, 0x3C, &irqline); + + if (deviceid == RTL_PCI_8192_DID || + deviceid == RTL_PCI_0044_DID || + deviceid == RTL_PCI_0047_DID || + deviceid == RTL_PCI_8192SE_DID || + deviceid == RTL_PCI_8174_DID || + deviceid == RTL_PCI_8173_DID || + deviceid == RTL_PCI_8172_DID || + deviceid == RTL_PCI_8171_DID) { + switch (revisionid) { + case RTL_PCI_REVISION_ID_8192PCIE: + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + ("8192 PCI-E is found - " + "vid/did=%x/%x\n", venderid, deviceid)); + rtlhal->hw_type = HARDWARE_TYPE_RTL8192E; + break; + case RTL_PCI_REVISION_ID_8192SE: + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + ("8192SE is found - " + "vid/did=%x/%x\n", venderid, deviceid)); + rtlhal->hw_type = HARDWARE_TYPE_RTL8192SE; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("Err: Unknown device - " + "vid/did=%x/%x\n", venderid, deviceid)); + rtlhal->hw_type = HARDWARE_TYPE_RTL8192SE; + break; + + } + } else if (deviceid == RTL_PCI_8192CET_DID || + deviceid == RTL_PCI_8192CE_DID || + deviceid == RTL_PCI_8191CE_DID || + deviceid == RTL_PCI_8188CE_DID) { + rtlhal->hw_type = HARDWARE_TYPE_RTL8192CE; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + ("8192C PCI-E is found - " + "vid/did=%x/%x\n", venderid, deviceid)); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("Err: Unknown device -" + " vid/did=%x/%x\n", venderid, deviceid)); + + rtlhal->hw_type = RTL_DEFAULT_HARDWARE_TYPE; + } + + /*find bus info */ + pcipriv->ndis_adapter.busnumber = pdev->bus->number; + pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); + pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn); + + /*find bridge info */ + pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor; + for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) { + if (bridge_pdev->vendor == pcibridge_vendors[tmp]) { + pcipriv->ndis_adapter.pcibridge_vendor = tmp; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + ("Pci Bridge Vendor is found index: %d\n", + tmp)); + break; + } + } + + if (pcipriv->ndis_adapter.pcibridge_vendor != + PCI_BRIDGE_VENDOR_UNKNOWN) { + pcipriv->ndis_adapter.pcibridge_busnum = + bridge_pdev->bus->number; + pcipriv->ndis_adapter.pcibridge_devnum = + PCI_SLOT(bridge_pdev->devfn); + pcipriv->ndis_adapter.pcibridge_funcnum = + PCI_FUNC(bridge_pdev->devfn); + pcipriv->ndis_adapter.pcibridge_pciehdr_offset = + pci_pcie_cap(bridge_pdev); + pcipriv->ndis_adapter.pcicfg_addrport = + (pcipriv->ndis_adapter.pcibridge_busnum << 16) | + (pcipriv->ndis_adapter.pcibridge_devnum << 11) | + (pcipriv->ndis_adapter.pcibridge_funcnum << 8) | (1 << 31); + pcipriv->ndis_adapter.num4bytes = + (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10) / 4; + + rtl_pci_get_linkcontrol_field(hw); + + if (pcipriv->ndis_adapter.pcibridge_vendor == + PCI_BRIDGE_VENDOR_AMD) { + pcipriv->ndis_adapter.amd_l1_patch = + rtl_pci_get_amd_l1_patch(hw); + } + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + ("pcidev busnumber:devnumber:funcnumber:" + "vendor:link_ctl %d:%d:%d:%x:%x\n", + pcipriv->ndis_adapter.busnumber, + pcipriv->ndis_adapter.devnumber, + pcipriv->ndis_adapter.funcnumber, + pdev->vendor, pcipriv->ndis_adapter.linkctrl_reg)); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + ("pci_bridge busnumber:devnumber:funcnumber:vendor:" + "pcie_cap:link_ctl_reg:amd %d:%d:%d:%x:%x:%x:%x\n", + pcipriv->ndis_adapter.pcibridge_busnum, + pcipriv->ndis_adapter.pcibridge_devnum, + pcipriv->ndis_adapter.pcibridge_funcnum, + pcibridge_vendors[pcipriv->ndis_adapter.pcibridge_vendor], + pcipriv->ndis_adapter.pcibridge_pciehdr_offset, + pcipriv->ndis_adapter.pcibridge_linkctrlreg, + pcipriv->ndis_adapter.amd_l1_patch)); + + rtl_pci_parse_configuration(pdev, hw); + + return true; +} + +int __devinit rtl_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct ieee80211_hw *hw = NULL; + + struct rtl_priv *rtlpriv = NULL; + struct rtl_pci_priv *pcipriv = NULL; + struct rtl_pci *rtlpci; + unsigned long pmem_start, pmem_len, pmem_flags; + int err; + + err = pci_enable_device(pdev); + if (err) { + RT_ASSERT(false, + ("%s : Cannot enable new PCI device\n", + pci_name(pdev))); + return err; + } + + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { + RT_ASSERT(false, ("Unable to obtain 32bit DMA " + "for consistent allocations\n")); + pci_disable_device(pdev); + return -ENOMEM; + } + } + + pci_set_master(pdev); + + hw = ieee80211_alloc_hw(sizeof(struct rtl_pci_priv) + + sizeof(struct rtl_priv), &rtl_ops); + if (!hw) { + RT_ASSERT(false, + ("%s : ieee80211 alloc failed\n", pci_name(pdev))); + err = -ENOMEM; + goto fail1; + } + + SET_IEEE80211_DEV(hw, &pdev->dev); + pci_set_drvdata(pdev, hw); + + rtlpriv = hw->priv; + pcipriv = (void *)rtlpriv->priv; + pcipriv->dev.pdev = pdev; + + /* + *init dbgp flags before all + *other functions, because we will + *use it in other funtions like + *RT_TRACE/RT_PRINT/RTL_PRINT_DATA + *you can not use these macro + *before this + */ + rtl_dbgp_flag_init(hw); + + /* MEM map */ + err = pci_request_regions(pdev, KBUILD_MODNAME); + if (err) { + RT_ASSERT(false, ("Can't obtain PCI resources\n")); + return err; + } + + pmem_start = pci_resource_start(pdev, 2); + pmem_len = pci_resource_len(pdev, 2); + pmem_flags = pci_resource_flags(pdev, 2); + + /*shared mem start */ + rtlpriv->io.pci_mem_start = + (unsigned long)pci_iomap(pdev, 2, pmem_len); + if (rtlpriv->io.pci_mem_start == 0) { + RT_ASSERT(false, ("Can't map PCI mem\n")); + goto fail2; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + ("mem mapped space: start: 0x%08lx len:%08lx " + "flags:%08lx, after map:0x%08lx\n", + pmem_start, pmem_len, pmem_flags, + rtlpriv->io.pci_mem_start)); + + /* Disable Clk Request */ + pci_write_config_byte(pdev, 0x81, 0); + /* leave D3 mode */ + pci_write_config_byte(pdev, 0x44, 0); + pci_write_config_byte(pdev, 0x04, 0x06); + pci_write_config_byte(pdev, 0x04, 0x07); + + /* init cfg & intf_ops */ + rtlpriv->rtlhal.interface = INTF_PCI; + rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); + rtlpriv->intf_ops = &rtl_pci_ops; + + /* find adapter */ + _rtl_pci_find_adapter(pdev, hw); + + /* Init IO handler */ + _rtl_pci_io_handler_init(&pdev->dev, hw); + + /*like read eeprom and so on */ + rtlpriv->cfg->ops->read_eeprom_info(hw); + + if (rtlpriv->cfg->ops->init_sw_vars(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Can't init_sw_vars.\n")); + goto fail3; + } + + rtlpriv->cfg->ops->init_sw_leds(hw); + + /*aspm */ + rtl_pci_init_aspm(hw); + + /* Init mac80211 sw */ + err = rtl_init_core(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Can't allocate sw for mac80211.\n")); + goto fail3; + } + + /* Init PCI sw */ + err = !rtl_pci_init(hw, pdev); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Failed to init PCI.\n")); + goto fail3; + } + + err = ieee80211_register_hw(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Can't register mac80211 hw.\n")); + goto fail3; + } else { + rtlpriv->mac80211.mac80211_registered = 1; + } + + err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("failed to create sysfs device attributes\n")); + goto fail3; + } + + /*init rfkill */ + rtl_init_rfkill(hw); + + rtlpci = rtl_pcidev(pcipriv); + err = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt, + IRQF_SHARED, KBUILD_MODNAME, hw); + if (err) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + ("%s: failed to register IRQ handler\n", + wiphy_name(hw->wiphy))); + goto fail3; + } else { + rtlpci->irq_alloc = 1; + } + + set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); + return 0; + +fail3: + pci_set_drvdata(pdev, NULL); + rtl_deinit_core(hw); + _rtl_pci_io_handler_release(hw); + ieee80211_free_hw(hw); + + if (rtlpriv->io.pci_mem_start != 0) + pci_iounmap(pdev, (void *)rtlpriv->io.pci_mem_start); + +fail2: + pci_release_regions(pdev); + +fail1: + + pci_disable_device(pdev); + + return -ENODEV; + +} +EXPORT_SYMBOL(rtl_pci_probe); + +void rtl_pci_disconnect(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); + struct rtl_mac *rtlmac = rtl_mac(rtlpriv); + + clear_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); + + sysfs_remove_group(&pdev->dev.kobj, &rtl_attribute_group); + + /*ieee80211_unregister_hw will call ops_stop */ + if (rtlmac->mac80211_registered == 1) { + ieee80211_unregister_hw(hw); + rtlmac->mac80211_registered = 0; + } else { + rtl_deinit_deferred_work(hw); + rtlpriv->intf_ops->adapter_stop(hw); + } + + /*deinit rfkill */ + rtl_deinit_rfkill(hw); + + rtl_pci_deinit(hw); + rtl_deinit_core(hw); + rtlpriv->cfg->ops->deinit_sw_leds(hw); + _rtl_pci_io_handler_release(hw); + rtlpriv->cfg->ops->deinit_sw_vars(hw); + + if (rtlpci->irq_alloc) { + free_irq(rtlpci->pdev->irq, hw); + rtlpci->irq_alloc = 0; + } + + if (rtlpriv->io.pci_mem_start != 0) { + pci_iounmap(pdev, (void *)rtlpriv->io.pci_mem_start); + pci_release_regions(pdev); + } + + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + + ieee80211_free_hw(hw); +} +EXPORT_SYMBOL(rtl_pci_disconnect); + +/*************************************** +kernel pci power state define: +PCI_D0 ((pci_power_t __force) 0) +PCI_D1 ((pci_power_t __force) 1) +PCI_D2 ((pci_power_t __force) 2) +PCI_D3hot ((pci_power_t __force) 3) +PCI_D3cold ((pci_power_t __force) 4) +PCI_UNKNOWN ((pci_power_t __force) 5) + +This function is called when system +goes into suspend state mac80211 will +call rtl_mac_stop() from the mac80211 +suspend function first, So there is +no need to call hw_disable here. +****************************************/ +int rtl_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} +EXPORT_SYMBOL(rtl_pci_suspend); + +int rtl_pci_resume(struct pci_dev *pdev) +{ + int ret; + + pci_set_power_state(pdev, PCI_D0); + ret = pci_enable_device(pdev); + if (ret) { + RT_ASSERT(false, ("ERR: <======\n")); + return ret; + } + + pci_restore_state(pdev); + + return 0; +} +EXPORT_SYMBOL(rtl_pci_resume); + +struct rtl_intf_ops rtl_pci_ops = { + .adapter_start = rtl_pci_start, + .adapter_stop = rtl_pci_stop, + .adapter_tx = rtl_pci_tx, + .reset_trx_ring = rtl_pci_reset_trx_ring, + + .disable_aspm = rtl_pci_disable_aspm, + .enable_aspm = rtl_pci_enable_aspm, +}; diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h new file mode 100644 index 000000000000..d36a66939958 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/pci.h @@ -0,0 +1,302 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL_PCI_H__ +#define __RTL_PCI_H__ + +#include <linux/pci.h> +/* +1: MSDU packet queue, +2: Rx Command Queue +*/ +#define RTL_PCI_RX_MPDU_QUEUE 0 +#define RTL_PCI_RX_CMD_QUEUE 1 +#define RTL_PCI_MAX_RX_QUEUE 2 + +#define RTL_PCI_MAX_RX_COUNT 64 +#define RTL_PCI_MAX_TX_QUEUE_COUNT 9 + +#define RT_TXDESC_NUM 128 +#define RT_TXDESC_NUM_BE_QUEUE 256 + +#define BK_QUEUE 0 +#define BE_QUEUE 1 +#define VI_QUEUE 2 +#define VO_QUEUE 3 +#define BEACON_QUEUE 4 +#define TXCMD_QUEUE 5 +#define MGNT_QUEUE 6 +#define HIGH_QUEUE 7 +#define HCCA_QUEUE 8 + +#define RTL_PCI_DEVICE(vend, dev, cfg) \ + .vendor = (vend), \ + .device = (dev), \ + .subvendor = PCI_ANY_ID, \ + .subdevice = PCI_ANY_ID,\ + .driver_data = (kernel_ulong_t)&(cfg) + +#define INTEL_VENDOR_ID 0x8086 +#define SIS_VENDOR_ID 0x1039 +#define ATI_VENDOR_ID 0x1002 +#define ATI_DEVICE_ID 0x7914 +#define AMD_VENDOR_ID 0x1022 + +#define PCI_MAX_BRIDGE_NUMBER 255 +#define PCI_MAX_DEVICES 32 +#define PCI_MAX_FUNCTION 8 + +#define PCI_CONF_ADDRESS 0x0CF8 /*PCI Configuration Space Address */ +#define PCI_CONF_DATA 0x0CFC /*PCI Configuration Space Data */ + +#define PCI_CLASS_BRIDGE_DEV 0x06 +#define PCI_SUBCLASS_BR_PCI_TO_PCI 0x04 +#define PCI_CAPABILITY_ID_PCI_EXPRESS 0x10 +#define PCI_CAP_ID_EXP 0x10 + +#define U1DONTCARE 0xFF +#define U2DONTCARE 0xFFFF +#define U4DONTCARE 0xFFFFFFFF + +#define RTL_PCI_8192_DID 0x8192 /*8192 PCI-E */ +#define RTL_PCI_8192SE_DID 0x8192 /*8192 SE */ +#define RTL_PCI_8174_DID 0x8174 /*8192 SE */ +#define RTL_PCI_8173_DID 0x8173 /*8191 SE Crab */ +#define RTL_PCI_8172_DID 0x8172 /*8191 SE RE */ +#define RTL_PCI_8171_DID 0x8171 /*8191 SE Unicron */ +#define RTL_PCI_0045_DID 0x0045 /*8190 PCI for Ceraga */ +#define RTL_PCI_0046_DID 0x0046 /*8190 Cardbus for Ceraga */ +#define RTL_PCI_0044_DID 0x0044 /*8192e PCIE for Ceraga */ +#define RTL_PCI_0047_DID 0x0047 /*8192e Express Card for Ceraga */ +#define RTL_PCI_700F_DID 0x700F +#define RTL_PCI_701F_DID 0x701F +#define RTL_PCI_DLINK_DID 0x3304 +#define RTL_PCI_8192CET_DID 0x8191 /*8192ce */ +#define RTL_PCI_8192CE_DID 0x8178 /*8192ce */ +#define RTL_PCI_8191CE_DID 0x8177 /*8192ce */ +#define RTL_PCI_8188CE_DID 0x8176 /*8192ce */ +#define RTL_PCI_8192CU_DID 0x8191 /*8192ce */ +#define RTL_PCI_8192DE_DID 0x092D /*8192ce */ +#define RTL_PCI_8192DU_DID 0x092D /*8192ce */ + +/*8192 support 16 pages of IO registers*/ +#define RTL_MEM_MAPPED_IO_RANGE_8190PCI 0x1000 +#define RTL_MEM_MAPPED_IO_RANGE_8192PCIE 0x4000 +#define RTL_MEM_MAPPED_IO_RANGE_8192SE 0x4000 +#define RTL_MEM_MAPPED_IO_RANGE_8192CE 0x4000 +#define RTL_MEM_MAPPED_IO_RANGE_8192DE 0x4000 + +#define RTL_PCI_REVISION_ID_8190PCI 0x00 +#define RTL_PCI_REVISION_ID_8192PCIE 0x01 +#define RTL_PCI_REVISION_ID_8192SE 0x10 +#define RTL_PCI_REVISION_ID_8192CE 0x1 +#define RTL_PCI_REVISION_ID_8192DE 0x0 + +#define RTL_DEFAULT_HARDWARE_TYPE HARDWARE_TYPE_RTL8192CE + +enum pci_bridge_vendor { + PCI_BRIDGE_VENDOR_INTEL = 0x0, /*0b'0000,0001 */ + PCI_BRIDGE_VENDOR_ATI, /*0b'0000,0010*/ + PCI_BRIDGE_VENDOR_AMD, /*0b'0000,0100*/ + PCI_BRIDGE_VENDOR_SIS, /*0b'0000,1000*/ + PCI_BRIDGE_VENDOR_UNKNOWN, /*0b'0100,0000*/ + PCI_BRIDGE_VENDOR_MAX, +}; + +struct rtl_rx_desc { + u32 dword[8]; +} __packed; + +struct rtl_tx_desc { + u32 dword[16]; +} __packed; + +struct rtl_tx_cmd_desc { + u32 dword[16]; +} __packed; + +struct rtl8192_tx_ring { + struct rtl_tx_desc *desc; + dma_addr_t dma; + unsigned int idx; + unsigned int entries; + struct sk_buff_head queue; +}; + +struct rtl8192_rx_ring { + struct rtl_rx_desc *desc; + dma_addr_t dma; + unsigned int idx; + struct sk_buff *rx_buf[RTL_PCI_MAX_RX_COUNT]; +}; + +struct rtl_pci { + struct pci_dev *pdev; + + bool driver_is_goingto_unload; + bool up_first_time; + bool being_init_adapter; + bool irq_enabled; + + /*Tx */ + struct rtl8192_tx_ring tx_ring[RTL_PCI_MAX_TX_QUEUE_COUNT]; + int txringcount[RTL_PCI_MAX_TX_QUEUE_COUNT]; + u32 transmit_config; + + /*Rx */ + struct rtl8192_rx_ring rx_ring[RTL_PCI_MAX_RX_QUEUE]; + int rxringcount; + u16 rxbuffersize; + u32 receive_config; + + /*irq */ + u8 irq_alloc; + u32 irq_mask[2]; + + /*Bcn control register setting */ + u32 reg_bcn_ctrl_val; + + /*ASPM*/ u8 const_pci_aspm; + u8 const_amdpci_aspm; + u8 const_hwsw_rfoff_d3; + u8 const_support_pciaspm; + /*pci-e bridge */ + u8 const_hostpci_aspm_setting; + /*pci-e device */ + u8 const_devicepci_aspm_setting; + /*If it supports ASPM, Offset[560h] = 0x40, + otherwise Offset[560h] = 0x00. */ + bool b_support_aspm; + bool b_support_backdoor; + + /*QOS & EDCA */ + enum acm_method acm_method; +}; + +struct mp_adapter { + u8 linkctrl_reg; + + u8 busnumber; + u8 devnumber; + u8 funcnumber; + + u8 pcibridge_busnum; + u8 pcibridge_devnum; + u8 pcibridge_funcnum; + + u8 pcibridge_vendor; + u16 pcibridge_vendorid; + u16 pcibridge_deviceid; + + u32 pcicfg_addrport; + u8 num4bytes; + + u8 pcibridge_pciehdr_offset; + u8 pcibridge_linkctrlreg; + + bool amd_l1_patch; +}; + +struct rtl_pci_priv { + struct rtl_pci dev; + struct mp_adapter ndis_adapter; + struct rtl_led_ctl ledctl; +}; + +#define rtl_pcipriv(hw) (((struct rtl_pci_priv *)(rtl_priv(hw))->priv)) +#define rtl_pcidev(pcipriv) (&((pcipriv)->dev)) + +int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw); + +extern struct rtl_intf_ops rtl_pci_ops; + +int __devinit rtl_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id); +void rtl_pci_disconnect(struct pci_dev *pdev); +int rtl_pci_suspend(struct pci_dev *pdev, pm_message_t state); +int rtl_pci_resume(struct pci_dev *pdev); + +static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr) +{ + return 0xff & readb((u8 *) rtlpriv->io.pci_mem_start + addr); +} + +static inline u16 pci_read16_sync(struct rtl_priv *rtlpriv, u32 addr) +{ + return readw((u8 *) rtlpriv->io.pci_mem_start + addr); +} + +static inline u32 pci_read32_sync(struct rtl_priv *rtlpriv, u32 addr) +{ + return readl((u8 *) rtlpriv->io.pci_mem_start + addr); +} + +static inline void pci_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val) +{ + writeb(val, (u8 *) rtlpriv->io.pci_mem_start + addr); +} + +static inline void pci_write16_async(struct rtl_priv *rtlpriv, + u32 addr, u16 val) +{ + writew(val, (u8 *) rtlpriv->io.pci_mem_start + addr); +} + +static inline void pci_write32_async(struct rtl_priv *rtlpriv, + u32 addr, u32 val) +{ + writel(val, (u8 *) rtlpriv->io.pci_mem_start + addr); +} + +static inline void rtl_pci_raw_write_port_ulong(u32 port, u32 val) +{ + outl(val, port); +} + +static inline void rtl_pci_raw_write_port_uchar(u32 port, u8 val) +{ + outb(val, port); +} + +static inline void rtl_pci_raw_read_port_uchar(u32 port, u8 *pval) +{ + *pval = inb(port); +} + +static inline void rtl_pci_raw_read_port_ushort(u32 port, u16 *pval) +{ + *pval = inw(port); +} + +static inline void rtl_pci_raw_read_port_ulong(u32 port, u32 *pval) +{ + *pval = inl(port); +} + +#endif diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c new file mode 100644 index 000000000000..d2326c13449e --- /dev/null +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -0,0 +1,493 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "wifi.h" +#include "base.h" +#include "ps.h" + +bool rtl_ps_enable_nic(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool init_status = true; + + /*<1> reset trx ring */ + if (rtlhal->interface == INTF_PCI) + rtlpriv->intf_ops->reset_trx_ring(hw); + + if (is_hal_stop(rtlhal)) + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("Driver is already down!\n")); + + /*<2> Enable Adapter */ + rtlpriv->cfg->ops->hw_init(hw); + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + /*init_status = false; */ + + /*<3> Enable Interrupt */ + rtlpriv->cfg->ops->enable_interrupt(hw); + + /*<enable timer> */ + rtl_watch_dog_timer_callback((unsigned long)hw); + + return init_status; +} +EXPORT_SYMBOL(rtl_ps_enable_nic); + +bool rtl_ps_disable_nic(struct ieee80211_hw *hw) +{ + bool status = true; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /*<1> Stop all timer */ + rtl_deinit_deferred_work(hw); + + /*<2> Disable Interrupt */ + rtlpriv->cfg->ops->disable_interrupt(hw); + + /*<3> Disable Adapter */ + rtlpriv->cfg->ops->hw_disable(hw); + + return status; +} +EXPORT_SYMBOL(rtl_ps_disable_nic); + +bool rtl_ps_set_rf_state(struct ieee80211_hw *hw, + enum rf_pwrstate state_toset, + u32 changesource, bool protect_or_not) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + enum rf_pwrstate rtstate; + bool b_actionallowed = false; + u16 rfwait_cnt = 0; + unsigned long flag; + + /*protect_or_not = true; */ + + if (protect_or_not) + goto no_protect; + + /* + *Only one thread can change + *the RF state at one time, and others + *should wait to be executed. + */ + while (true) { + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + if (ppsc->rfchange_inprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, + flag); + + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("RF Change in progress!" + "Wait to set..state_toset(%d).\n", + state_toset)); + + /* Set RF after the previous action is done. */ + while (ppsc->rfchange_inprogress) { + rfwait_cnt++; + mdelay(1); + + /* + *Wait too long, return false to avoid + *to be stuck here. + */ + if (rfwait_cnt > 100) + return false; + } + } else { + ppsc->rfchange_inprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, + flag); + break; + } + } + +no_protect: + rtstate = ppsc->rfpwr_state; + + switch (state_toset) { + case ERFON: + ppsc->rfoff_reason &= (~changesource); + + if ((changesource == RF_CHANGE_BY_HW) && + (ppsc->b_hwradiooff == true)) { + ppsc->b_hwradiooff = false; + } + + if (!ppsc->rfoff_reason) { + ppsc->rfoff_reason = 0; + b_actionallowed = true; + } + + break; + + case ERFOFF: + + if ((changesource == RF_CHANGE_BY_HW) + && (ppsc->b_hwradiooff == false)) { + ppsc->b_hwradiooff = true; + } + + ppsc->rfoff_reason |= changesource; + b_actionallowed = true; + break; + + case ERFSLEEP: + ppsc->rfoff_reason |= changesource; + b_actionallowed = true; + break; + + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + + if (b_actionallowed) + rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset); + + if (!protect_or_not) { + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } + + return b_actionallowed; +} +EXPORT_SYMBOL(rtl_ps_set_rf_state); + +static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + ppsc->b_swrf_processing = true; + + if (ppsc->inactive_pwrstate == ERFON && rtlhal->interface == INTF_PCI) { + if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM) && + rtlhal->interface == INTF_PCI) { + rtlpriv->intf_ops->disable_aspm(hw); + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + } + } + + rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate, + RF_CHANGE_BY_IPS, false); + + if (ppsc->inactive_pwrstate == ERFOFF && + rtlhal->interface == INTF_PCI) { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { + rtlpriv->intf_ops->enable_aspm(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + } + } + + ppsc->b_swrf_processing = false; +} + +void rtl_ips_nic_off_wq_callback(void *data) +{ + struct rtl_works *rtlworks = + container_of_dwork_rtl(data, struct rtl_works, ips_nic_off_wq); + struct ieee80211_hw *hw = rtlworks->hw; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + enum rf_pwrstate rtstate; + + if (mac->opmode != NL80211_IFTYPE_STATION) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("not station return\n")); + return; + } + + if (is_hal_stop(rtlhal)) + return; + + if (rtlpriv->sec.being_setkey) + return; + + if (ppsc->b_inactiveps) { + rtstate = ppsc->rfpwr_state; + + /* + *Do not enter IPS in the following conditions: + *(1) RF is already OFF or Sleep + *(2) b_swrf_processing (indicates the IPS is still under going) + *(3) Connectted (only disconnected can trigger IPS) + *(4) IBSS (send Beacon) + *(5) AP mode (send Beacon) + *(6) monitor mode (rcv packet) + */ + + if (rtstate == ERFON && + !ppsc->b_swrf_processing && + (mac->link_state == MAC80211_NOLINK) && + !mac->act_scanning) { + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + ("IPSEnter(): Turn off RF.\n")); + + ppsc->inactive_pwrstate = ERFOFF; + ppsc->b_in_powersavemode = true; + + /*rtl_pci_reset_trx_ring(hw); */ + _rtl_ps_inactive_ps(hw); + } + } +} + +void rtl_ips_nic_off(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* + *because when link with ap, mac80211 will ask us + *to disable nic quickly after scan before linking, + *this will cause link failed, so we delay 100ms here + */ + queue_delayed_work(rtlpriv->works.rtl_wq, + &rtlpriv->works.ips_nic_off_wq, MSECS(100)); +} + +void rtl_ips_nic_on(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + enum rf_pwrstate rtstate; + unsigned long flags; + + spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags); + + if (ppsc->b_inactiveps) { + rtstate = ppsc->rfpwr_state; + + if (rtstate != ERFON && + !ppsc->b_swrf_processing && + ppsc->rfoff_reason <= RF_CHANGE_BY_IPS) { + + ppsc->inactive_pwrstate = ERFON; + ppsc->b_in_powersavemode = false; + + _rtl_ps_inactive_ps(hw); + } + } + + spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags); +} + +/*for FW LPS*/ + +/* + *Determine if we can set Fw into PS mode + *in current condition.Return TRUE if it + *can enter PS mode. + */ +static bool rtl_get_fwlps_doze(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u32 ps_timediff; + + ps_timediff = jiffies_to_msecs(jiffies - + ppsc->last_delaylps_stamp_jiffies); + + if (ps_timediff < 2000) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("Delay enter Fw LPS for DHCP, ARP," + " or EAPOL exchanging state.\n")); + return false; + } + + if (mac->link_state != MAC80211_LINKED) + return false; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) + return false; + + return true; +} + +/* Change current and default preamble mode.*/ +static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 rpwm_val, fw_pwrmode; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) + return; + + if (mac->link_state != MAC80211_LINKED) + return; + + if (ppsc->dot11_psmode == rt_psmode) + return; + + /* Update power save mode configured. */ + ppsc->dot11_psmode = rt_psmode; + + /* + *<FW control LPS> + *1. Enter PS mode + * Set RPWM to Fw to turn RF off and send H2C fw_pwrmode + * cmd to set Fw into PS mode. + *2. Leave PS mode + * Send H2C fw_pwrmode cmd to Fw to set Fw into Active + * mode and set RPWM to turn RF on. + */ + + if ((ppsc->b_fwctrl_lps) && (ppsc->b_leisure_ps) && + ppsc->report_linked) { + bool b_fw_current_inps; + if (ppsc->dot11_psmode == EACTIVE) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + ("FW LPS leave ps_mode:%x\n", + FW_PS_ACTIVE_MODE)); + + rpwm_val = 0x0C; /* RF on */ + fw_pwrmode = FW_PS_ACTIVE_MODE; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + (u8 *) (&rpwm_val)); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_PWRMODE, + (u8 *) (&fw_pwrmode)); + b_fw_current_inps = false; + + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_FW_PSMODE_STATUS, + (u8 *) (&b_fw_current_inps)); + + } else { + if (rtl_get_fwlps_doze(hw)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + ("FW LPS enter ps_mode:%x\n", + ppsc->fwctrl_psmode)); + + rpwm_val = 0x02; /* RF off */ + b_fw_current_inps = true; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_FW_PSMODE_STATUS, + (u8 *) (&b_fw_current_inps)); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_PWRMODE, + (u8 *) (&ppsc->fwctrl_psmode)); + + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_SET_RPWM, + (u8 *) (&rpwm_val)); + } else { + /* Reset the power save related parameters. */ + ppsc->dot11_psmode = EACTIVE; + } + } + } +} + +/*Enter the leisure power save mode.*/ +void rtl_lps_enter(struct ieee80211_hw *hw) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + unsigned long flag; + + if (!(ppsc->b_fwctrl_lps && ppsc->b_leisure_ps)) + return; + + if (rtlpriv->sec.being_setkey) + return; + + if (rtlpriv->link_info.b_busytraffic) + return; + + /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */ + if (mac->cnt_after_linked < 5) + return; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) + return; + + if (mac->link_state != MAC80211_LINKED) + return; + + spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); + + if (ppsc->b_leisure_ps) { + /* Idle for a while if we connect to AP a while ago. */ + if (mac->cnt_after_linked >= 2) { + if (ppsc->dot11_psmode == EACTIVE) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("Enter 802.11 power save mode...\n")); + + rtl_lps_set_psmode(hw, EAUTOPS); + } + } + } + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); +} + +/*Leave the leisure power save mode.*/ +void rtl_lps_leave(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + unsigned long flag; + + spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); + + if (ppsc->b_fwctrl_lps && ppsc->b_leisure_ps) { + if (ppsc->dot11_psmode != EACTIVE) { + + /*FIX ME */ + rtlpriv->cfg->ops->enable_interrupt(hw); + + if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && + RT_IN_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM) && + rtlhal->interface == INTF_PCI) { + rtlpriv->intf_ops->disable_aspm(hw); + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM); + } + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("Busy Traffic,Leave 802.11 power save..\n")); + + rtl_lps_set_psmode(hw, EACTIVE); + } + } + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); +} diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h new file mode 100644 index 000000000000..ae56da801a23 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/ps.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __REALTEK_RTL_PCI_PS_H__ +#define __REALTEK_RTL_PCI_PS_H__ + +bool rtl_ps_set_rf_state(struct ieee80211_hw *hw, + enum rf_pwrstate state_toset, u32 changesource, + bool protect_or_not); +bool rtl_ps_enable_nic(struct ieee80211_hw *hw); +bool rtl_ps_disable_nic(struct ieee80211_hw *hw); +void rtl_ips_nic_off(struct ieee80211_hw *hw); +void rtl_ips_nic_on(struct ieee80211_hw *hw); +void rtl_ips_nic_off_wq_callback(void *data); +void rtl_lps_enter(struct ieee80211_hw *hw); +void rtl_lps_leave(struct ieee80211_hw *hw); +#endif diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c new file mode 100644 index 000000000000..91634107434a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rc.c @@ -0,0 +1,329 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "wifi.h" +#include "base.h" +#include "rc.h" + +/* + *Finds the highest rate index we can use + *if skb is special data like DHCP/EAPOL, we set should + *it to lowest rate CCK_1M, otherwise we set rate to + *CCK11M or OFDM_54M based on wireless mode. + */ +static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, + struct sk_buff *skb, bool not_data) +{ + struct rtl_mac *rtlmac = rtl_mac(rtlpriv); + + /* + *mgt use 1M, although we have check it + *before this function use rate_control_send_low, + *we still check it here + */ + if (not_data) + return rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; + + /* + *this rate is no use for true rate, firmware + *will control rate at all it just used for + *1.show in iwconfig in B/G mode + *2.in rtl_get_tcb_desc when we check rate is + * 1M we will not use FW rate but user rate. + */ + if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true)) { + return rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; + } else { + if (rtlmac->mode == WIRELESS_MODE_B) + return rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]; + else + return rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]; + } +} + +static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, + struct ieee80211_tx_rate *rate, + struct ieee80211_tx_rate_control *txrc, + u8 tries, u8 rix, int rtsctsenable, + bool not_data) +{ + struct rtl_mac *mac = rtl_mac(rtlpriv); + + rate->count = tries; + rate->idx = (rix > 0x2) ? rix : 0x2; + + if (!not_data) { + if (txrc->short_preamble) + rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; + if (mac->bw_40) + rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + if (mac->sgi_20 || mac->sgi_40) + rate->flags |= IEEE80211_TX_RC_SHORT_GI; + if (mac->ht_enable) + rate->flags |= IEEE80211_TX_RC_MCS; + } +} + +static void rtl_get_rate(void *ppriv, struct ieee80211_sta *sta, + void *priv_sta, struct ieee80211_tx_rate_control *txrc) +{ + struct rtl_priv *rtlpriv = ppriv; + struct sk_buff *skb = txrc->skb; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_rate *rates = tx_info->control.rates; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + __le16 fc = hdr->frame_control; + u8 try_per_rate, i, rix; + bool not_data = !ieee80211_is_data(fc); + + if (rate_control_send_low(sta, priv_sta, txrc)) + return; + + rix = _rtl_rc_get_highest_rix(rtlpriv, skb, not_data); + + try_per_rate = 1; + _rtl_rc_rate_set_series(rtlpriv, &rates[0], txrc, + try_per_rate, rix, 1, not_data); + + if (!not_data) { + for (i = 1; i < 4; i++) + _rtl_rc_rate_set_series(rtlpriv, &rates[i], + txrc, i, (rix - i), 1, + not_data); + } +} + +static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, u16 tid) +{ + struct rtl_mac *mac = rtl_mac(rtlpriv); + + if (mac->act_scanning) + return false; + + if (mac->cnt_after_linked < 3) + return false; + + if (mac->tids[tid].agg.agg_state == RTL_AGG_OFF) + return true; + + return false; +} + +/*mac80211 Rate Control callbacks*/ +static void rtl_tx_status(void *ppriv, + struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = ppriv; + struct rtl_mac *mac = rtl_mac(rtlpriv); + struct ieee80211_hdr *hdr; + __le16 fc; + + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + + if (!priv_sta || !ieee80211_is_data(fc)) + return; + + if (rtl_is_special_data(mac->hw, skb, true)) + return; + + if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) + || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) + return; + + /* Check if aggregation has to be enabled for this tid */ + if (conf_is_ht(&mac->hw->conf) && + !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { + if (ieee80211_is_data_qos(fc)) { + u8 *qc, tid; + + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & 0xf; + + if (_rtl_tx_aggr_check(rtlpriv, tid)) + ieee80211_start_tx_ba_session(sta, tid, 5000); + } + } +} + +static void rtl_rate_init(void *ppriv, + struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) +{ + struct rtl_priv *rtlpriv = ppriv; + struct rtl_mac *mac = rtl_mac(rtlpriv); + u8 is_ht = conf_is_ht(&mac->hw->conf); + + if ((mac->opmode == NL80211_IFTYPE_STATION) || + (mac->opmode == NL80211_IFTYPE_MESH_POINT) || + (mac->opmode == NL80211_IFTYPE_ADHOC)) { + + switch (sband->band) { + case IEEE80211_BAND_2GHZ: + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_G; + if (is_ht) + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_NGB; + break; + case IEEE80211_BAND_5GHZ: + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_A; + if (is_ht) + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_NGB; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("Invalid band\n")); + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_NGB; + break; + } + + RT_TRACE(rtlpriv, COMP_RATE, DBG_DMESG, + ("Choosing rate table index: %d\n", + rtlpriv->rate_priv->cur_ratetab_idx)); + + } + +} + +static void rtl_rate_update(void *ppriv, + struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + u32 changed, + enum nl80211_channel_type oper_chan_type) +{ + struct rtl_priv *rtlpriv = ppriv; + struct rtl_mac *mac = rtl_mac(rtlpriv); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + bool oper_cw40 = false, oper_sgi40; + bool local_cw40 = mac->bw_40; + bool local_sgi40 = mac->sgi_40; + u8 is_ht = conf_is_ht(&mac->hw->conf); + + if (changed & IEEE80211_RC_HT_CHANGED) { + if (mac->opmode != NL80211_IFTYPE_STATION) + return; + + if (rtlhal->hw->conf.channel_type == NL80211_CHAN_HT40MINUS || + rtlhal->hw->conf.channel_type == NL80211_CHAN_HT40PLUS) + oper_cw40 = true; + + oper_sgi40 = mac->sgi_40; + + if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) { + switch (sband->band) { + case IEEE80211_BAND_2GHZ: + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_G; + if (is_ht) + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_NGB; + break; + case IEEE80211_BAND_5GHZ: + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_A; + if (is_ht) + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_NGB; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Invalid band\n")); + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_NGB; + break; + } + } + } +} + +static void *rtl_rate_alloc(struct ieee80211_hw *hw, + struct dentry *debugfsdir) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + return rtlpriv; +} + +static void rtl_rate_free(void *rtlpriv) +{ + return; +} + +static void *rtl_rate_alloc_sta(void *ppriv, + struct ieee80211_sta *sta, gfp_t gfp) +{ + struct rtl_priv *rtlpriv = ppriv; + struct rtl_rate_priv *rate_priv; + + rate_priv = kzalloc(sizeof(struct rtl_rate_priv), gfp); + if (!rate_priv) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Unable to allocate private rc structure\n")); + return NULL; + } + + rtlpriv->rate_priv = rate_priv; + + return rate_priv; +} + +static void rtl_rate_free_sta(void *rtlpriv, + struct ieee80211_sta *sta, void *priv_sta) +{ + struct rtl_rate_priv *rate_priv = priv_sta; + kfree(rate_priv); +} + +static struct rate_control_ops rtl_rate_ops = { + .module = NULL, + .name = "rtl_rc", + .alloc = rtl_rate_alloc, + .free = rtl_rate_free, + .alloc_sta = rtl_rate_alloc_sta, + .free_sta = rtl_rate_free_sta, + .rate_init = rtl_rate_init, + .rate_update = rtl_rate_update, + .tx_status = rtl_tx_status, + .get_rate = rtl_get_rate, +}; + +int rtl_rate_control_register(void) +{ + return ieee80211_rate_control_register(&rtl_rate_ops); +} + +void rtl_rate_control_unregister(void) +{ + ieee80211_rate_control_unregister(&rtl_rate_ops); +} diff --git a/drivers/net/wireless/rtlwifi/rc.h b/drivers/net/wireless/rtlwifi/rc.h new file mode 100644 index 000000000000..b4667c035f0b --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rc.h @@ -0,0 +1,40 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL_RC_H__ +#define __RTL_RC_H__ + +struct rtl_rate_priv { + u8 cur_ratetab_idx; + u8 ht_cap; +}; + +int rtl_rate_control_register(void); +void rtl_rate_control_unregister(void); +#endif diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c new file mode 100644 index 000000000000..3336ca999dfd --- /dev/null +++ b/drivers/net/wireless/rtlwifi/regd.c @@ -0,0 +1,400 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "wifi.h" +#include "regd.h" + +static struct country_code_to_enum_rd allCountries[] = { + {COUNTRY_CODE_FCC, "US"}, + {COUNTRY_CODE_IC, "US"}, + {COUNTRY_CODE_ETSI, "EC"}, + {COUNTRY_CODE_SPAIN, "EC"}, + {COUNTRY_CODE_FRANCE, "EC"}, + {COUNTRY_CODE_MKK, "JP"}, + {COUNTRY_CODE_MKK1, "JP"}, + {COUNTRY_CODE_ISRAEL, "EC"}, + {COUNTRY_CODE_TELEC, "JP"}, + {COUNTRY_CODE_MIC, "JP"}, + {COUNTRY_CODE_GLOBAL_DOMAIN, "JP"}, + {COUNTRY_CODE_WORLD_WIDE_13, "EC"}, + {COUNTRY_CODE_TELEC_NETGEAR, "EC"}, +}; + +/* + *Only these channels all allow active + *scan on all world regulatory domains + */ +#define RTL819x_2GHZ_CH01_11 \ + REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) + +/* + *We enable active scan on these a case + *by case basis by regulatory domain + */ +#define RTL819x_2GHZ_CH12_13 \ + REG_RULE(2467-10, 2472+10, 40, 0, 20,\ + NL80211_RRF_PASSIVE_SCAN) + +#define RTL819x_2GHZ_CH14 \ + REG_RULE(2484-10, 2484+10, 40, 0, 20, \ + NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_NO_OFDM) + +static const struct ieee80211_regdomain rtl_regdom_11 = { + .n_reg_rules = 1, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_global = { + .n_reg_rules = 3, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + RTL819x_2GHZ_CH14, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_world = { + .n_reg_rules = 2, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + } +}; + +static bool _rtl_is_radar_freq(u16 center_freq) +{ + return (center_freq >= 5260 && center_freq <= 5700); +} + +static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) +{ + enum ieee80211_band band; + struct ieee80211_supported_band *sband; + const struct ieee80211_reg_rule *reg_rule; + struct ieee80211_channel *ch; + unsigned int i; + u32 bandwidth = 0; + int r; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + + if (!wiphy->bands[band]) + continue; + + sband = wiphy->bands[band]; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + if (_rtl_is_radar_freq(ch->center_freq) || + (ch->flags & IEEE80211_CHAN_RADAR)) + continue; + if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { + r = freq_reg_info(wiphy, ch->center_freq, + bandwidth, ®_rule); + if (r) + continue; + + /* + *If 11d had a rule for this channel ensure + *we enable adhoc/beaconing if it allows us to + *use it. Note that we would have disabled it + *by applying our static world regdomain by + *default during init, prior to calling our + *regulatory_hint(). + */ + + if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) + ch->flags &= ~IEEE80211_CHAN_NO_IBSS; + if (!(reg_rule-> + flags & NL80211_RRF_PASSIVE_SCAN)) + ch->flags &= + ~IEEE80211_CHAN_PASSIVE_SCAN; + } else { + if (ch->beacon_found) + ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_PASSIVE_SCAN); + } + } + } +} + +/* Allows active scan scan on Ch 12 and 13 */ +static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator + initiator) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + const struct ieee80211_reg_rule *reg_rule; + u32 bandwidth = 0; + int r; + + sband = wiphy->bands[IEEE80211_BAND_2GHZ]; + + /* + *If no country IE has been received always enable active scan + *on these channels. This is only done for specific regulatory SKUs + */ + if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { + ch = &sband->channels[11]; /* CH 12 */ + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + ch = &sband->channels[12]; /* CH 13 */ + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + return; + } + + /* + *If a country IE has been recieved check its rule for this + *channel first before enabling active scan. The passive scan + *would have been enforced by the initial processing of our + *custom regulatory domain. + */ + + ch = &sband->channels[11]; /* CH 12 */ + r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); + if (!r) { + if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + } + + ch = &sband->channels[12]; /* CH 13 */ + r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); + if (!r) { + if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + } +} + +/* + *Always apply Radar/DFS rules on + *freq range 5260 MHz - 5700 MHz + */ +static void _rtl_reg_apply_radar_flags(struct wiphy *wiphy) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + unsigned int i; + + if (!wiphy->bands[IEEE80211_BAND_5GHZ]) + return; + + sband = wiphy->bands[IEEE80211_BAND_5GHZ]; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + if (!_rtl_is_radar_freq(ch->center_freq)) + continue; + + /* + *We always enable radar detection/DFS on this + *frequency range. Additionally we also apply on + *this frequency range: + *- If STA mode does not yet have DFS supports disable + * active scanning + *- If adhoc mode does not support DFS yet then disable + * adhoc in the frequency. + *- If AP mode does not yet support radar detection/DFS + *do not allow AP mode + */ + if (!(ch->flags & IEEE80211_CHAN_DISABLED)) + ch->flags |= IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_PASSIVE_SCAN; + } +} + +static void _rtl_reg_apply_world_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator, + struct rtl_regulatory *reg) +{ + _rtl_reg_apply_beaconing_flags(wiphy, initiator); + _rtl_reg_apply_active_scan_flags(wiphy, initiator); + return; +} + +static void _rtl_dump_channel_map(struct wiphy *wiphy) +{ + enum ieee80211_band band; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + unsigned int i; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!wiphy->bands[band]) + continue; + sband = wiphy->bands[band]; + for (i = 0; i < sband->n_channels; i++) + ch = &sband->channels[i]; + } +} + +static int _rtl_reg_notifier_apply(struct wiphy *wiphy, + struct regulatory_request *request, + struct rtl_regulatory *reg) +{ + /* We always apply this */ + _rtl_reg_apply_radar_flags(wiphy); + + switch (request->initiator) { + case NL80211_REGDOM_SET_BY_DRIVER: + case NL80211_REGDOM_SET_BY_CORE: + case NL80211_REGDOM_SET_BY_USER: + break; + case NL80211_REGDOM_SET_BY_COUNTRY_IE: + _rtl_reg_apply_world_flags(wiphy, request->initiator, reg); + break; + } + + _rtl_dump_channel_map(wiphy); + + return 0; +} + +static const struct ieee80211_regdomain *_rtl_regdomain_select( + struct rtl_regulatory *reg) +{ + switch (reg->country_code) { + case COUNTRY_CODE_FCC: + case COUNTRY_CODE_IC: + return &rtl_regdom_11; + case COUNTRY_CODE_ETSI: + case COUNTRY_CODE_SPAIN: + case COUNTRY_CODE_FRANCE: + case COUNTRY_CODE_ISRAEL: + case COUNTRY_CODE_TELEC_NETGEAR: + return &rtl_regdom_world; + case COUNTRY_CODE_MKK: + case COUNTRY_CODE_MKK1: + case COUNTRY_CODE_TELEC: + case COUNTRY_CODE_MIC: + return &rtl_regdom_global; + case COUNTRY_CODE_GLOBAL_DOMAIN: + return &rtl_regdom_global; + case COUNTRY_CODE_WORLD_WIDE_13: + return &rtl_regdom_world; + default: + return &rtl_regdom_world; + } +} + +static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg, + struct wiphy *wiphy, + int (*reg_notifier) (struct wiphy *wiphy, + struct regulatory_request * + request)) +{ + const struct ieee80211_regdomain *regd; + + wiphy->reg_notifier = reg_notifier; + wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY; + wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS; + regd = _rtl_regdomain_select(reg); + wiphy_apply_custom_regulatory(wiphy, regd); + _rtl_reg_apply_radar_flags(wiphy); + _rtl_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg); + return 0; +} + +static struct country_code_to_enum_rd *_rtl_regd_find_country(u16 countrycode) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(allCountries); i++) { + if (allCountries[i].countrycode == countrycode) + return &allCountries[i]; + } + return NULL; +} + +int rtl_regd_init(struct ieee80211_hw *hw, + int (*reg_notifier) (struct wiphy *wiphy, + struct regulatory_request *request)) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct wiphy *wiphy = hw->wiphy; + struct country_code_to_enum_rd *country = NULL; + + if (wiphy == NULL || &rtlpriv->regd == NULL) + return -EINVAL; + + /* force the channel plan to world wide 13 */ + rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13; + + RT_TRACE(rtlpriv, COMP_REGD, DBG_TRACE, + (KERN_DEBUG "rtl: EEPROM regdomain: 0x%0x\n", + rtlpriv->regd.country_code)); + + if (rtlpriv->regd.country_code >= COUNTRY_CODE_MAX) { + RT_TRACE(rtlpriv, COMP_REGD, DBG_DMESG, + (KERN_DEBUG "rtl: EEPROM indicates invalid contry code" + "world wide 13 should be used\n")); + + rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13; + } + + country = _rtl_regd_find_country(rtlpriv->regd.country_code); + + if (country) { + rtlpriv->regd.alpha2[0] = country->isoName[0]; + rtlpriv->regd.alpha2[1] = country->isoName[1]; + } else { + rtlpriv->regd.alpha2[0] = '0'; + rtlpriv->regd.alpha2[1] = '0'; + } + + RT_TRACE(rtlpriv, COMP_REGD, DBG_TRACE, + (KERN_DEBUG "rtl: Country alpha2 being used: %c%c\n", + rtlpriv->regd.alpha2[0], rtlpriv->regd.alpha2[1])); + + _rtl_regd_init_wiphy(&rtlpriv->regd, wiphy, reg_notifier); + + return 0; +} + +int rtl_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_REGD, DBG_LOUD, ("\n")); + + return _rtl_reg_notifier_apply(wiphy, request, &rtlpriv->regd); +} diff --git a/drivers/net/wireless/rtlwifi/regd.h b/drivers/net/wireless/rtlwifi/regd.h new file mode 100644 index 000000000000..4cdbc4ae76d4 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/regd.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL_REGD_H__ +#define __RTL_REGD_H__ + +struct country_code_to_enum_rd { + u16 countrycode; + const char *isoName; +}; + +enum country_code_type_t { + COUNTRY_CODE_FCC = 0, + COUNTRY_CODE_IC = 1, + COUNTRY_CODE_ETSI = 2, + COUNTRY_CODE_SPAIN = 3, + COUNTRY_CODE_FRANCE = 4, + COUNTRY_CODE_MKK = 5, + COUNTRY_CODE_MKK1 = 6, + COUNTRY_CODE_ISRAEL = 7, + COUNTRY_CODE_TELEC = 8, + COUNTRY_CODE_MIC = 9, + COUNTRY_CODE_GLOBAL_DOMAIN = 10, + COUNTRY_CODE_WORLD_WIDE_13 = 11, + COUNTRY_CODE_TELEC_NETGEAR = 12, + + /*add new channel plan above this line */ + COUNTRY_CODE_MAX +}; + +int rtl_regd_init(struct ieee80211_hw *hw, + int (*reg_notifier) (struct wiphy *wiphy, + struct regulatory_request *request)); +int rtl_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile b/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile new file mode 100644 index 000000000000..0f0be7c763b8 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile @@ -0,0 +1,12 @@ +rtl8192ce-objs := \ + dm.o \ + fw.o \ + hw.o \ + led.o \ + phy.o \ + rf.o \ + sw.o \ + table.o \ + trx.o + +obj-$(CONFIG_RTL8192CE) += rtl8192ce.o diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h new file mode 100644 index 000000000000..83cd64895292 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -0,0 +1,257 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92C_DEF_H__ +#define __RTL92C_DEF_H__ + +#define HAL_RETRY_LIMIT_INFRA 48 +#define HAL_RETRY_LIMIT_AP_ADHOC 7 + +#define PHY_RSSI_SLID_WIN_MAX 100 +#define PHY_LINKQUALITY_SLID_WIN_MAX 20 +#define PHY_BEACON_RSSI_SLID_WIN_MAX 10 + +#define RESET_DELAY_8185 20 + +#define RT_IBSS_INT_MASKS (IMR_BCNINT | IMR_TBDOK | IMR_TBDER) +#define RT_AC_INT_MASKS (IMR_VIDOK | IMR_VODOK | IMR_BEDOK|IMR_BKDOK) + +#define NUM_OF_FIRMWARE_QUEUE 10 +#define NUM_OF_PAGES_IN_FW 0x100 +#define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x07 +#define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x07 +#define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x07 +#define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x07 +#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA 0x0 +#define NUM_OF_PAGE_IN_FW_QUEUE_CMD 0x0 +#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x02 +#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH 0x02 +#define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x2 +#define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0xA1 + +#define NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM 0x026 +#define NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM 0x048 +#define NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM 0x048 +#define NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM 0x026 +#define NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM 0x00 + +#define MAX_LINES_HWCONFIG_TXT 1000 +#define MAX_BYTES_LINE_HWCONFIG_TXT 256 + +#define SW_THREE_WIRE 0 +#define HW_THREE_WIRE 2 + +#define BT_DEMO_BOARD 0 +#define BT_QA_BOARD 1 +#define BT_FPGA 2 + +#define RX_SMOOTH_FACTOR 20 + +#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 +#define HAL_PRIME_CHNL_OFFSET_LOWER 1 +#define HAL_PRIME_CHNL_OFFSET_UPPER 2 + +#define MAX_H2C_QUEUE_NUM 10 + +#define RX_MPDU_QUEUE 0 +#define RX_CMD_QUEUE 1 +#define RX_MAX_QUEUE 2 +#define AC2QUEUEID(_AC) (_AC) + +#define C2H_RX_CMD_HDR_LEN 8 +#define GET_C2H_CMD_CMD_LEN(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 0, 16) +#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 16, 8) +#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 24, 7) +#define GET_C2H_CMD_CONTINUE(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 31, 1) +#define GET_C2H_CMD_CONTENT(__prxhdr) \ + ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) + +#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) +#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) +#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) + +#define CHIP_VER_B BIT(4) +#define CHIP_92C_BITMASK BIT(0) +#define CHIP_92C_1T2R 0x03 +#define CHIP_92C 0x01 +#define CHIP_88C 0x00 + +enum version_8192c { + VERSION_A_CHIP_92C = 0x01, + VERSION_A_CHIP_88C = 0x00, + VERSION_B_CHIP_92C = 0x11, + VERSION_B_CHIP_88C = 0x10, + VERSION_UNKNOWN = 0x88, +}; + +#define IS_CHIP_VER_B(version) ((version & CHIP_VER_B) ? true : false) +#define IS_92C_SERIAL(version) ((version & CHIP_92C_BITMASK) ? true : false) + +enum rtl819x_loopback_e { + RTL819X_NO_LOOPBACK = 0, + RTL819X_MAC_LOOPBACK = 1, + RTL819X_DMA_LOOPBACK = 2, + RTL819X_CCK_LOOPBACK = 3, +}; + +enum rf_optype { + RF_OP_BY_SW_3WIRE = 0, + RF_OP_BY_FW, + RF_OP_MAX +}; + +enum rf_power_state { + RF_ON, + RF_OFF, + RF_SLEEP, + RF_SHUT_DOWN, +}; + +enum power_save_mode { + POWER_SAVE_MODE_ACTIVE, + POWER_SAVE_MODE_SAVE, +}; + +enum power_polocy_config { + POWERCFG_MAX_POWER_SAVINGS, + POWERCFG_GLOBAL_POWER_SAVINGS, + POWERCFG_LOCAL_POWER_SAVINGS, + POWERCFG_LENOVO, +}; + +enum interface_select_pci { + INTF_SEL1_MINICARD = 0, + INTF_SEL0_PCIE = 1, + INTF_SEL2_RSV = 2, + INTF_SEL3_RSV = 3, +}; + +enum hal_fw_c2h_cmd_id { + HAL_FW_C2H_CMD_Read_MACREG = 0, + HAL_FW_C2H_CMD_Read_BBREG = 1, + HAL_FW_C2H_CMD_Read_RFREG = 2, + HAL_FW_C2H_CMD_Read_EEPROM = 3, + HAL_FW_C2H_CMD_Read_EFUSE = 4, + HAL_FW_C2H_CMD_Read_CAM = 5, + HAL_FW_C2H_CMD_Get_BasicRate = 6, + HAL_FW_C2H_CMD_Get_DataRate = 7, + HAL_FW_C2H_CMD_Survey = 8, + HAL_FW_C2H_CMD_SurveyDone = 9, + HAL_FW_C2H_CMD_JoinBss = 10, + HAL_FW_C2H_CMD_AddSTA = 11, + HAL_FW_C2H_CMD_DelSTA = 12, + HAL_FW_C2H_CMD_AtimDone = 13, + HAL_FW_C2H_CMD_TX_Report = 14, + HAL_FW_C2H_CMD_CCX_Report = 15, + HAL_FW_C2H_CMD_DTM_Report = 16, + HAL_FW_C2H_CMD_TX_Rate_Statistics = 17, + HAL_FW_C2H_CMD_C2HLBK = 18, + HAL_FW_C2H_CMD_C2HDBG = 19, + HAL_FW_C2H_CMD_C2HFEEDBACK = 20, + HAL_FW_C2H_CMD_MAX +}; + +enum rtl_desc_qsel { + QSLT_BK = 0x2, + QSLT_BE = 0x0, + QSLT_VI = 0x5, + QSLT_VO = 0x7, + QSLT_BEACON = 0x10, + QSLT_HIGH = 0x11, + QSLT_MGNT = 0x12, + QSLT_CMD = 0x13, +}; + +enum rtl_desc92c_rate { + DESC92C_RATE1M = 0x00, + DESC92C_RATE2M = 0x01, + DESC92C_RATE5_5M = 0x02, + DESC92C_RATE11M = 0x03, + + DESC92C_RATE6M = 0x04, + DESC92C_RATE9M = 0x05, + DESC92C_RATE12M = 0x06, + DESC92C_RATE18M = 0x07, + DESC92C_RATE24M = 0x08, + DESC92C_RATE36M = 0x09, + DESC92C_RATE48M = 0x0a, + DESC92C_RATE54M = 0x0b, + + DESC92C_RATEMCS0 = 0x0c, + DESC92C_RATEMCS1 = 0x0d, + DESC92C_RATEMCS2 = 0x0e, + DESC92C_RATEMCS3 = 0x0f, + DESC92C_RATEMCS4 = 0x10, + DESC92C_RATEMCS5 = 0x11, + DESC92C_RATEMCS6 = 0x12, + DESC92C_RATEMCS7 = 0x13, + DESC92C_RATEMCS8 = 0x14, + DESC92C_RATEMCS9 = 0x15, + DESC92C_RATEMCS10 = 0x16, + DESC92C_RATEMCS11 = 0x17, + DESC92C_RATEMCS12 = 0x18, + DESC92C_RATEMCS13 = 0x19, + DESC92C_RATEMCS14 = 0x1a, + DESC92C_RATEMCS15 = 0x1b, + DESC92C_RATEMCS15_SG = 0x1c, + DESC92C_RATEMCS32 = 0x20, +}; + +struct phy_sts_cck_8192s_t { + u8 adc_pwdb_X[4]; + u8 sq_rpt; + u8 cck_agc_rpt; +}; + +struct h2c_cmd_8192c { + u8 element_id; + u32 cmd_len; + u8 *p_cmdbuffer; +}; + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c new file mode 100644 index 000000000000..62e7c64e087b --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c @@ -0,0 +1,1473 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" + +struct dig_t dm_digtable; +static struct ps_t dm_pstable; + +static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { + 0x7f8001fe, + 0x788001e2, + 0x71c001c7, + 0x6b8001ae, + 0x65400195, + 0x5fc0017f, + 0x5a400169, + 0x55400155, + 0x50800142, + 0x4c000130, + 0x47c0011f, + 0x43c0010f, + 0x40000100, + 0x3c8000f2, + 0x390000e4, + 0x35c000d7, + 0x32c000cb, + 0x300000c0, + 0x2d4000b5, + 0x2ac000ab, + 0x288000a2, + 0x26000098, + 0x24000090, + 0x22000088, + 0x20000080, + 0x1e400079, + 0x1c800072, + 0x1b00006c, + 0x19800066, + 0x18000060, + 0x16c0005b, + 0x15800056, + 0x14400051, + 0x1300004c, + 0x12000048, + 0x11000044, + 0x10000040, +}; + +static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, + {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, + {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, + {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, + {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, + {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, + {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, + {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, + {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, + {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, + {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, + {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, + {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, + {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, + {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, + {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, + {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, + {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, + {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, + {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, + {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, + {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} +}; + +static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, + {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, + {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, + {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, + {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, + {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, + {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, + {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, + {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, + {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, + {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, + {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, + {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, + {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, + {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, + {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, + {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, + {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} +}; + +static void rtl92c_dm_diginit(struct ieee80211_hw *hw) +{ + dm_digtable.dig_enable_flag = true; + dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; + dm_digtable.cur_igvalue = 0x20; + dm_digtable.pre_igvalue = 0x0; + dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT; + dm_digtable.presta_connectstate = DIG_STA_DISCONNECT; + dm_digtable.curmultista_connectstate = DIG_MULTISTA_DISCONNECT; + dm_digtable.rssi_lowthresh = DM_DIG_THRESH_LOW; + dm_digtable.rssi_highthresh = DM_DIG_THRESH_HIGH; + dm_digtable.fa_lowthresh = DM_FALSEALARM_THRESH_LOW; + dm_digtable.fa_highthresh = DM_FALSEALARM_THRESH_HIGH; + dm_digtable.rx_gain_range_max = DM_DIG_MAX; + dm_digtable.rx_gain_range_min = DM_DIG_MIN; + dm_digtable.backoff_val = DM_DIG_BACKOFF_DEFAULT; + dm_digtable.backoff_val_range_max = DM_DIG_BACKOFF_MAX; + dm_digtable.backoff_val_range_min = DM_DIG_BACKOFF_MIN; + dm_digtable.pre_cck_pd_state = CCK_PD_STAGE_MAX; + dm_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX; +} + +static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + long rssi_val_min = 0; + + if ((dm_digtable.curmultista_connectstate == DIG_MULTISTA_CONNECT) && + (dm_digtable.cursta_connectctate == DIG_STA_CONNECT)) { + if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb != 0) + rssi_val_min = + (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb > + rtlpriv->dm.undecorated_smoothed_pwdb) ? + rtlpriv->dm.undecorated_smoothed_pwdb : + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + else + rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb; + } else if (dm_digtable.cursta_connectctate == DIG_STA_CONNECT || + dm_digtable.cursta_connectctate == DIG_STA_BEFORE_CONNECT) { + rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb; + } else if (dm_digtable.curmultista_connectstate == + DIG_MULTISTA_CONNECT) { + rssi_val_min = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + } + + return (u8) rssi_val_min; +} + +static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) +{ + u32 ret_value; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); + falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); + falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); + falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); + falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); + falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail; + + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1); + ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); + falsealm_cnt->cnt_cck_fail = ret_value; + + ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3); + falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; + falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail + + falsealm_cnt->cnt_cck_fail); + + rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0); + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0); + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + ("cnt_parity_fail = %d, cnt_rate_illegal = %d, " + "cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", + falsealm_cnt->cnt_parity_fail, + falsealm_cnt->cnt_rate_illegal, + falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail)); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + ("cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", + falsealm_cnt->cnt_ofdm_fail, + falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all)); +} + +static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 value_igi = dm_digtable.cur_igvalue; + + if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) + value_igi--; + else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1) + value_igi += 0; + else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2) + value_igi++; + else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2) + value_igi += 2; + if (value_igi > DM_DIG_FA_UPPER) + value_igi = DM_DIG_FA_UPPER; + else if (value_igi < DM_DIG_FA_LOWER) + value_igi = DM_DIG_FA_LOWER; + if (rtlpriv->falsealm_cnt.cnt_all > 10000) + value_igi = 0x32; + + dm_digtable.cur_igvalue = value_igi; + rtl92c_dm_write_dig(hw); +} + +static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->falsealm_cnt.cnt_all > dm_digtable.fa_highthresh) { + if ((dm_digtable.backoff_val - 2) < + dm_digtable.backoff_val_range_min) + dm_digtable.backoff_val = + dm_digtable.backoff_val_range_min; + else + dm_digtable.backoff_val -= 2; + } else if (rtlpriv->falsealm_cnt.cnt_all < dm_digtable.fa_lowthresh) { + if ((dm_digtable.backoff_val + 2) > + dm_digtable.backoff_val_range_max) + dm_digtable.backoff_val = + dm_digtable.backoff_val_range_max; + else + dm_digtable.backoff_val += 2; + } + + if ((dm_digtable.rssi_val_min + 10 - dm_digtable.backoff_val) > + dm_digtable.rx_gain_range_max) + dm_digtable.cur_igvalue = dm_digtable.rx_gain_range_max; + else if ((dm_digtable.rssi_val_min + 10 - + dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min) + dm_digtable.cur_igvalue = dm_digtable.rx_gain_range_min; + else + dm_digtable.cur_igvalue = dm_digtable.rssi_val_min + 10 - + dm_digtable.backoff_val; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + ("rssi_val_min = %x backoff_val %x\n", + dm_digtable.rssi_val_min, dm_digtable.backoff_val)); + + rtl92c_dm_write_dig(hw); +} + +static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) +{ + static u8 binitialized; /* initialized to false */ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long rssi_strength = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + bool b_multi_sta = false; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) + b_multi_sta = true; + + if ((b_multi_sta == false) || (dm_digtable.cursta_connectctate != + DIG_STA_DISCONNECT)) { + binitialized = false; + dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; + return; + } else if (binitialized == false) { + binitialized = true; + dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; + dm_digtable.cur_igvalue = 0x20; + rtl92c_dm_write_dig(hw); + } + + if (dm_digtable.curmultista_connectstate == DIG_MULTISTA_CONNECT) { + if ((rssi_strength < dm_digtable.rssi_lowthresh) && + (dm_digtable.dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) { + + if (dm_digtable.dig_ext_port_stage == + DIG_EXT_PORT_STAGE_2) { + dm_digtable.cur_igvalue = 0x20; + rtl92c_dm_write_dig(hw); + } + + dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_1; + } else if (rssi_strength > dm_digtable.rssi_highthresh) { + dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_2; + rtl92c_dm_ctrl_initgain_by_fa(hw); + } + } else if (dm_digtable.dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) { + dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; + dm_digtable.cur_igvalue = 0x20; + rtl92c_dm_write_dig(hw); + } + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + ("curmultista_connectstate = " + "%x dig_ext_port_stage %x\n", + dm_digtable.curmultista_connectstate, + dm_digtable.dig_ext_port_stage)); +} + +static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + ("presta_connectstate = %x," + " cursta_connectctate = %x\n", + dm_digtable.presta_connectstate, + dm_digtable.cursta_connectctate)); + + if (dm_digtable.presta_connectstate == dm_digtable.cursta_connectctate + || dm_digtable.cursta_connectctate == DIG_STA_BEFORE_CONNECT + || dm_digtable.cursta_connectctate == DIG_STA_CONNECT) { + + if (dm_digtable.cursta_connectctate != DIG_STA_DISCONNECT) { + dm_digtable.rssi_val_min = + rtl92c_dm_initial_gain_min_pwdb(hw); + rtl92c_dm_ctrl_initgain_by_rssi(hw); + } + } else { + dm_digtable.rssi_val_min = 0; + dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; + dm_digtable.backoff_val = DM_DIG_BACKOFF_DEFAULT; + dm_digtable.cur_igvalue = 0x20; + dm_digtable.pre_igvalue = 0; + rtl92c_dm_write_dig(hw); + } +} + +static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (dm_digtable.cursta_connectctate == DIG_STA_CONNECT) { + dm_digtable.rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw); + + if (dm_digtable.pre_cck_pd_state == CCK_PD_STAGE_LowRssi) { + if (dm_digtable.rssi_val_min <= 25) + dm_digtable.cur_cck_pd_state = + CCK_PD_STAGE_LowRssi; + else + dm_digtable.cur_cck_pd_state = + CCK_PD_STAGE_HighRssi; + } else { + if (dm_digtable.rssi_val_min <= 20) + dm_digtable.cur_cck_pd_state = + CCK_PD_STAGE_LowRssi; + else + dm_digtable.cur_cck_pd_state = + CCK_PD_STAGE_HighRssi; + } + } else { + dm_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX; + } + + if (dm_digtable.pre_cck_pd_state != dm_digtable.cur_cck_pd_state) { + if (dm_digtable.cur_cck_pd_state == CCK_PD_STAGE_LowRssi) { + if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800) + dm_digtable.cur_cck_fa_state = + CCK_FA_STAGE_High; + else + dm_digtable.cur_cck_fa_state = CCK_FA_STAGE_Low; + + if (dm_digtable.pre_cck_fa_state != + dm_digtable.cur_cck_fa_state) { + if (dm_digtable.cur_cck_fa_state == + CCK_FA_STAGE_Low) + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, + 0x83); + else + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, + 0xcd); + + dm_digtable.pre_cck_fa_state = + dm_digtable.cur_cck_fa_state; + } + + rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40); + + if (IS_92C_SERIAL(rtlhal->version)) + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, + MASKBYTE2, 0xd7); + } else { + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); + rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47); + + if (IS_92C_SERIAL(rtlhal->version)) + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, + MASKBYTE2, 0xd3); + } + dm_digtable.pre_cck_pd_state = dm_digtable.cur_cck_pd_state; + } + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + ("CCKPDStage=%x\n", dm_digtable.cur_cck_pd_state)); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + ("is92C=%x\n", IS_92C_SERIAL(rtlhal->version))); +} + +static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + if (mac->act_scanning == true) + return; + + if ((mac->link_state > MAC80211_NOLINK) && + (mac->link_state < MAC80211_LINKED)) + dm_digtable.cursta_connectctate = DIG_STA_BEFORE_CONNECT; + else if (mac->link_state >= MAC80211_LINKED) + dm_digtable.cursta_connectctate = DIG_STA_CONNECT; + else + dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT; + + rtl92c_dm_initial_gain_sta(hw); + rtl92c_dm_initial_gain_multi_sta(hw); + rtl92c_dm_cck_packet_detection_thresh(hw); + + dm_digtable.presta_connectstate = dm_digtable.cursta_connectctate; + +} + +static void rtl92c_dm_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->dm.b_dm_initialgain_enable == false) + return; + if (dm_digtable.dig_enable_flag == false) + return; + + rtl92c_dm_ctrl_initgain_by_twoport(hw); + +} + +static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.bdynamic_txpower_enable = false; + + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; +} + +static void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undecorated_smoothed_pwdb; + + if (!rtlpriv->dm.bdynamic_txpower_enable) + return; + + if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + ("Not connected to any\n")); + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + undecorated_smoothed_pwdb = + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("AP Client PWDB = 0x%lx\n", + undecorated_smoothed_pwdb)); + } else { + undecorated_smoothed_pwdb = + rtlpriv->dm.undecorated_smoothed_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("STA Default Port PWDB = 0x%lx\n", + undecorated_smoothed_pwdb)); + } + } else { + undecorated_smoothed_pwdb = + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("AP Ext Port PWDB = 0x%lx\n", + undecorated_smoothed_pwdb)); + } + + if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n")); + } else if ((undecorated_smoothed_pwdb < + (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && + (undecorated_smoothed_pwdb >= + TX_POWER_NEAR_FIELD_THRESH_LVL1)) { + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n")); + } else if (undecorated_smoothed_pwdb < + (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("TXHIGHPWRLEVEL_NORMAL\n")); + } + + if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("PHY_SetTxPowerLevel8192S() Channel = %d\n", + rtlphy->current_channel)); + rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); + } + + rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; +} + +void rtl92c_dm_write_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + ("cur_igvalue = 0x%x, " + "pre_igvalue = 0x%x, backoff_val = %d\n", + dm_digtable.cur_igvalue, dm_digtable.pre_igvalue, + dm_digtable.backoff_val)); + + if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) { + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, + dm_digtable.cur_igvalue); + rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f, + dm_digtable.cur_igvalue); + + dm_digtable.pre_igvalue = dm_digtable.cur_igvalue; + } +} + +static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff; + + u8 h2c_parameter[3] = { 0 }; + + return; + + if (tmpentry_max_pwdb != 0) { + rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb = + tmpentry_max_pwdb; + } else { + rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb = 0; + } + + if (tmpentry_min_pwdb != 0xff) { + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb = + tmpentry_min_pwdb; + } else { + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb = 0; + } + + h2c_parameter[2] = (u8) (rtlpriv->dm.undecorated_smoothed_pwdb & 0xFF); + h2c_parameter[0] = 0; + + rtl92c_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, h2c_parameter); +} + +void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + rtlpriv->dm.bcurrent_turbo_edca = false; + rtlpriv->dm.bis_any_nonbepkts = false; + rtlpriv->dm.bis_cur_rdlstate = false; +} + +static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + static u64 last_txok_cnt; + static u64 last_rxok_cnt; + u64 cur_txok_cnt; + u64 cur_rxok_cnt; + u32 edca_be_ul = 0x5ea42b; + u32 edca_be_dl = 0x5ea42b; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) + goto dm_checkedcaturbo_exit; + + if (mac->link_state != MAC80211_LINKED) { + rtlpriv->dm.bcurrent_turbo_edca = false; + return; + } + + if (!mac->ht_enable) { /*FIX MERGE */ + if (!(edca_be_ul & 0xffff0000)) + edca_be_ul |= 0x005e0000; + + if (!(edca_be_dl & 0xffff0000)) + edca_be_dl |= 0x005e0000; + } + + if ((!rtlpriv->dm.bis_any_nonbepkts) && + (!rtlpriv->dm.b_disable_framebursting)) { + cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; + cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; + if (cur_rxok_cnt > 4 * cur_txok_cnt) { + if (!rtlpriv->dm.bis_cur_rdlstate || + !rtlpriv->dm.bcurrent_turbo_edca) { + rtl_write_dword(rtlpriv, + REG_EDCA_BE_PARAM, + edca_be_dl); + rtlpriv->dm.bis_cur_rdlstate = true; + } + } else { + if (rtlpriv->dm.bis_cur_rdlstate || + !rtlpriv->dm.bcurrent_turbo_edca) { + rtl_write_dword(rtlpriv, + REG_EDCA_BE_PARAM, + edca_be_ul); + rtlpriv->dm.bis_cur_rdlstate = false; + } + } + rtlpriv->dm.bcurrent_turbo_edca = true; + } else { + if (rtlpriv->dm.bcurrent_turbo_edca) { + u8 tmp = AC0_BE; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_AC_PARAM, + (u8 *) (&tmp)); + rtlpriv->dm.bcurrent_turbo_edca = false; + } + } + +dm_checkedcaturbo_exit: + rtlpriv->dm.bis_any_nonbepkts = false; + last_txok_cnt = rtlpriv->stats.txbytesunicast; + last_rxok_cnt = rtlpriv->stats.rxbytesunicast; +} + +static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw + *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 thermalvalue, delta, delta_lck, delta_iqk; + long ele_a, ele_d, temp_cck, val_x, value32; + long val_y, ele_c; + u8 ofdm_index[2], cck_index, ofdm_index_old[2], cck_index_old; + int i; + bool is2t = IS_92C_SERIAL(rtlhal->version); + u8 txpwr_level[2] = {0, 0}; + u8 ofdm_min_index = 6, rf; + + rtlpriv->dm.btxpower_trackingInit = true; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + ("rtl92c_dm_txpower_tracking_callback_thermalmeter\n")); + + thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x " + "eeprom_thermalmeter 0x%x\n", + thermalvalue, rtlpriv->dm.thermalvalue, + rtlefuse->eeprom_thermalmeter)); + + rtl92c_phy_ap_calibrate(hw, (thermalvalue - + rtlefuse->eeprom_thermalmeter)); + if (is2t) + rf = 2; + else + rf = 1; + + if (thermalvalue) { + ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD) & MASKOFDM_D; + + for (i = 0; i < OFDM_TABLE_LENGTH; i++) { + if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { + ofdm_index_old[0] = (u8) i; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + ("Initial pathA ele_d reg0x%x = 0x%lx, " + "ofdm_index=0x%x\n", + ROFDM0_XATXIQIMBALANCE, + ele_d, ofdm_index_old[0])); + break; + } + } + + if (is2t) { + ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, + MASKDWORD) & MASKOFDM_D; + + for (i = 0; i < OFDM_TABLE_LENGTH; i++) { + if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { + ofdm_index_old[1] = (u8) i; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, + DBG_LOUD, + ("Initial pathB ele_d reg0x%x = " + "0x%lx, ofdm_index=0x%x\n", + ROFDM0_XBTXIQIMBALANCE, ele_d, + ofdm_index_old[1])); + break; + } + } + } + + temp_cck = + rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK; + + for (i = 0; i < CCK_TABLE_LENGTH; i++) { + if (rtlpriv->dm.b_cck_inch14) { + if (memcmp((void *)&temp_cck, + (void *)&cckswing_table_ch14[i][2], + 4) == 0) { + cck_index_old = (u8) i; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, + DBG_LOUD, + ("Initial reg0x%x = 0x%lx, " + "cck_index=0x%x, ch 14 %d\n", + RCCK0_TXFILTER2, temp_cck, + cck_index_old, + rtlpriv->dm.b_cck_inch14)); + break; + } + } else { + if (memcmp((void *)&temp_cck, + (void *) + &cckswing_table_ch1ch13[i][2], + 4) == 0) { + cck_index_old = (u8) i; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, + DBG_LOUD, + ("Initial reg0x%x = 0x%lx, " + "cck_index=0x%x, ch14 %d\n", + RCCK0_TXFILTER2, temp_cck, + cck_index_old, + rtlpriv->dm.b_cck_inch14)); + break; + } + } + } + + if (!rtlpriv->dm.thermalvalue) { + rtlpriv->dm.thermalvalue = + rtlefuse->eeprom_thermalmeter; + rtlpriv->dm.thermalvalue_lck = thermalvalue; + rtlpriv->dm.thermalvalue_iqk = thermalvalue; + for (i = 0; i < rf; i++) + rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; + rtlpriv->dm.cck_index = cck_index_old; + } + + delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? + (thermalvalue - rtlpriv->dm.thermalvalue) : + (rtlpriv->dm.thermalvalue - thermalvalue); + + delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ? + (thermalvalue - rtlpriv->dm.thermalvalue_lck) : + (rtlpriv->dm.thermalvalue_lck - thermalvalue); + + delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ? + (thermalvalue - rtlpriv->dm.thermalvalue_iqk) : + (rtlpriv->dm.thermalvalue_iqk - thermalvalue); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x " + "eeprom_thermalmeter 0x%x delta 0x%x " + "delta_lck 0x%x delta_iqk 0x%x\n", + thermalvalue, rtlpriv->dm.thermalvalue, + rtlefuse->eeprom_thermalmeter, delta, delta_lck, + delta_iqk)); + + if (delta_lck > 1) { + rtlpriv->dm.thermalvalue_lck = thermalvalue; + rtl92c_phy_lc_calibrate(hw); + } + + if (delta > 0 && rtlpriv->dm.txpower_track_control) { + if (thermalvalue > rtlpriv->dm.thermalvalue) { + for (i = 0; i < rf; i++) + rtlpriv->dm.ofdm_index[i] -= delta; + rtlpriv->dm.cck_index -= delta; + } else { + for (i = 0; i < rf; i++) + rtlpriv->dm.ofdm_index[i] += delta; + rtlpriv->dm.cck_index += delta; + } + + if (is2t) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + ("temp OFDM_A_index=0x%x, " + "OFDM_B_index=0x%x," + "cck_index=0x%x\n", + rtlpriv->dm.ofdm_index[0], + rtlpriv->dm.ofdm_index[1], + rtlpriv->dm.cck_index)); + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + ("temp OFDM_A_index=0x%x," + "cck_index=0x%x\n", + rtlpriv->dm.ofdm_index[0], + rtlpriv->dm.cck_index)); + } + + if (thermalvalue > rtlefuse->eeprom_thermalmeter) { + for (i = 0; i < rf; i++) + ofdm_index[i] = + rtlpriv->dm.ofdm_index[i] + + 1; + cck_index = rtlpriv->dm.cck_index + 1; + } else { + for (i = 0; i < rf; i++) + ofdm_index[i] = + rtlpriv->dm.ofdm_index[i]; + cck_index = rtlpriv->dm.cck_index; + } + + for (i = 0; i < rf; i++) { + if (txpwr_level[i] >= 0 && + txpwr_level[i] <= 26) { + if (thermalvalue > + rtlefuse->eeprom_thermalmeter) { + if (delta < 5) + ofdm_index[i] -= 1; + + else + ofdm_index[i] -= 2; + } else if (delta > 5 && thermalvalue < + rtlefuse-> + eeprom_thermalmeter) { + ofdm_index[i] += 1; + } + } else if (txpwr_level[i] >= 27 && + txpwr_level[i] <= 32 + && thermalvalue > + rtlefuse->eeprom_thermalmeter) { + if (delta < 5) + ofdm_index[i] -= 1; + + else + ofdm_index[i] -= 2; + } else if (txpwr_level[i] >= 32 && + txpwr_level[i] <= 38 && + thermalvalue > + rtlefuse->eeprom_thermalmeter + && delta > 5) { + ofdm_index[i] -= 1; + } + } + + if (txpwr_level[i] >= 0 && txpwr_level[i] <= 26) { + if (thermalvalue > + rtlefuse->eeprom_thermalmeter) { + if (delta < 5) + cck_index -= 1; + + else + cck_index -= 2; + } else if (delta > 5 && thermalvalue < + rtlefuse->eeprom_thermalmeter) { + cck_index += 1; + } + } else if (txpwr_level[i] >= 27 && + txpwr_level[i] <= 32 && + thermalvalue > + rtlefuse->eeprom_thermalmeter) { + if (delta < 5) + cck_index -= 1; + + else + cck_index -= 2; + } else if (txpwr_level[i] >= 32 && + txpwr_level[i] <= 38 && + thermalvalue > rtlefuse->eeprom_thermalmeter + && delta > 5) { + cck_index -= 1; + } + + for (i = 0; i < rf; i++) { + if (ofdm_index[i] > OFDM_TABLE_SIZE - 1) + ofdm_index[i] = OFDM_TABLE_SIZE - 1; + + else if (ofdm_index[i] < ofdm_min_index) + ofdm_index[i] = ofdm_min_index; + } + + if (cck_index > CCK_TABLE_SIZE - 1) + cck_index = CCK_TABLE_SIZE - 1; + else if (cck_index < 0) + cck_index = 0; + + if (is2t) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + ("new OFDM_A_index=0x%x, " + "OFDM_B_index=0x%x," + "cck_index=0x%x\n", + ofdm_index[0], ofdm_index[1], + cck_index)); + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + ("new OFDM_A_index=0x%x," + "cck_index=0x%x\n", + ofdm_index[0], cck_index)); + } + } + + if (rtlpriv->dm.txpower_track_control && delta != 0) { + ele_d = + (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22; + val_x = rtlphy->reg_e94; + val_y = rtlphy->reg_e9c; + + if (val_x != 0) { + if ((val_x & 0x00000200) != 0) + val_x = val_x | 0xFFFFFC00; + ele_a = ((val_x * ele_d) >> 8) & 0x000003FF; + + if ((val_y & 0x00000200) != 0) + val_y = val_y | 0xFFFFFC00; + ele_c = ((val_y * ele_d) >> 8) & 0x000003FF; + + value32 = (ele_d << 22) | + ((ele_c & 0x3F) << 16) | ele_a; + + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD, value32); + + value32 = (ele_c & 0x000003C0) >> 6; + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, + value32); + + value32 = ((val_x * ele_d) >> 7) & 0x01; + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(31), value32); + + value32 = ((val_y * ele_d) >> 7) & 0x01; + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(29), value32); + } else { + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD, + ofdmswing_table[ofdm_index[0]]); + + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, + 0x00); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(31) | BIT(29), 0x00); + } + + if (!rtlpriv->dm.b_cck_inch14) { + rtl_write_byte(rtlpriv, 0xa22, + cckswing_table_ch1ch13[cck_index] + [0]); + rtl_write_byte(rtlpriv, 0xa23, + cckswing_table_ch1ch13[cck_index] + [1]); + rtl_write_byte(rtlpriv, 0xa24, + cckswing_table_ch1ch13[cck_index] + [2]); + rtl_write_byte(rtlpriv, 0xa25, + cckswing_table_ch1ch13[cck_index] + [3]); + rtl_write_byte(rtlpriv, 0xa26, + cckswing_table_ch1ch13[cck_index] + [4]); + rtl_write_byte(rtlpriv, 0xa27, + cckswing_table_ch1ch13[cck_index] + [5]); + rtl_write_byte(rtlpriv, 0xa28, + cckswing_table_ch1ch13[cck_index] + [6]); + rtl_write_byte(rtlpriv, 0xa29, + cckswing_table_ch1ch13[cck_index] + [7]); + } else { + rtl_write_byte(rtlpriv, 0xa22, + cckswing_table_ch14[cck_index] + [0]); + rtl_write_byte(rtlpriv, 0xa23, + cckswing_table_ch14[cck_index] + [1]); + rtl_write_byte(rtlpriv, 0xa24, + cckswing_table_ch14[cck_index] + [2]); + rtl_write_byte(rtlpriv, 0xa25, + cckswing_table_ch14[cck_index] + [3]); + rtl_write_byte(rtlpriv, 0xa26, + cckswing_table_ch14[cck_index] + [4]); + rtl_write_byte(rtlpriv, 0xa27, + cckswing_table_ch14[cck_index] + [5]); + rtl_write_byte(rtlpriv, 0xa28, + cckswing_table_ch14[cck_index] + [6]); + rtl_write_byte(rtlpriv, 0xa29, + cckswing_table_ch14[cck_index] + [7]); + } + + if (is2t) { + ele_d = (ofdmswing_table[ofdm_index[1]] & + 0xFFC00000) >> 22; + + val_x = rtlphy->reg_eb4; + val_y = rtlphy->reg_ebc; + + if (val_x != 0) { + if ((val_x & 0x00000200) != 0) + val_x = val_x | 0xFFFFFC00; + ele_a = ((val_x * ele_d) >> 8) & + 0x000003FF; + + if ((val_y & 0x00000200) != 0) + val_y = val_y | 0xFFFFFC00; + ele_c = ((val_y * ele_d) >> 8) & + 0x00003FF; + + value32 = (ele_d << 22) | + ((ele_c & 0x3F) << 16) | ele_a; + rtl_set_bbreg(hw, + ROFDM0_XBTXIQIMBALANCE, + MASKDWORD, value32); + + value32 = (ele_c & 0x000003C0) >> 6; + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, + MASKH4BITS, value32); + + value32 = ((val_x * ele_d) >> 7) & 0x01; + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(27), value32); + + value32 = ((val_y * ele_d) >> 7) & 0x01; + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(25), value32); + } else { + rtl_set_bbreg(hw, + ROFDM0_XBTXIQIMBALANCE, + MASKDWORD, + ofdmswing_table[ofdm_index + [1]]); + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, + MASKH4BITS, 0x00); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(27) | BIT(25), 0x00); + } + + } + } + + if (delta_iqk > 3) { + rtlpriv->dm.thermalvalue_iqk = thermalvalue; + rtl92c_phy_iq_calibrate(hw, false); + } + + if (rtlpriv->dm.txpower_track_control) + rtlpriv->dm.thermalvalue = thermalvalue; + } + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("<===\n")); + +} + +static void rtl92c_dm_initialize_txpower_tracking_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.btxpower_tracking = true; + rtlpriv->dm.btxpower_trackingInit = false; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + ("pMgntInfo->btxpower_tracking = %d\n", + rtlpriv->dm.btxpower_tracking)); +} + +static void rtl92c_dm_initialize_txpower_tracking(struct ieee80211_hw *hw) +{ + rtl92c_dm_initialize_txpower_tracking_thermalmeter(hw); +} + +static void rtl92c_dm_txpower_tracking_directcall(struct ieee80211_hw *hw) +{ + rtl92c_dm_txpower_tracking_callback_thermalmeter(hw); +} + +static void rtl92c_dm_check_txpower_tracking_thermal_meter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + static u8 tm_trigger; + + if (!rtlpriv->dm.btxpower_tracking) + return; + + if (!tm_trigger) { + rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK, + 0x60); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + ("Trigger 92S Thermal Meter!!\n")); + tm_trigger = 1; + return; + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + ("Schedule TxPowerTracking direct call!!\n")); + rtl92c_dm_txpower_tracking_directcall(hw); + tm_trigger = 0; + } +} + +void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw) +{ + rtl92c_dm_check_txpower_tracking_thermal_meter(hw); +} + +void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rate_adaptive *p_ra = &(rtlpriv->ra); + + p_ra->ratr_state = DM_RATR_STA_INIT; + p_ra->pre_ratr_state = DM_RATR_STA_INIT; + + if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) + rtlpriv->dm.b_useramask = true; + else + rtlpriv->dm.b_useramask = false; + +} + +static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rate_adaptive *p_ra = &(rtlpriv->ra); + u32 low_rssithresh_for_ra, high_rssithresh_for_ra; + + if (is_hal_stop(rtlhal)) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + ("<---- driver is going to unload\n")); + return; + } + + if (!rtlpriv->dm.b_useramask) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + ("<---- driver does not control rate adaptive mask\n")); + return; + } + + if (mac->link_state == MAC80211_LINKED) { + + switch (p_ra->pre_ratr_state) { + case DM_RATR_STA_HIGH: + high_rssithresh_for_ra = 50; + low_rssithresh_for_ra = 20; + break; + case DM_RATR_STA_MIDDLE: + high_rssithresh_for_ra = 55; + low_rssithresh_for_ra = 20; + break; + case DM_RATR_STA_LOW: + high_rssithresh_for_ra = 50; + low_rssithresh_for_ra = 25; + break; + default: + high_rssithresh_for_ra = 50; + low_rssithresh_for_ra = 20; + break; + } + + if (rtlpriv->dm.undecorated_smoothed_pwdb > + (long)high_rssithresh_for_ra) + p_ra->ratr_state = DM_RATR_STA_HIGH; + else if (rtlpriv->dm.undecorated_smoothed_pwdb > + (long)low_rssithresh_for_ra) + p_ra->ratr_state = DM_RATR_STA_MIDDLE; + else + p_ra->ratr_state = DM_RATR_STA_LOW; + + if (p_ra->pre_ratr_state != p_ra->ratr_state) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + ("RSSI = %ld\n", + rtlpriv->dm.undecorated_smoothed_pwdb)); + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + ("RSSI_LEVEL = %d\n", p_ra->ratr_state)); + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + ("PreState = %d, CurState = %d\n", + p_ra->pre_ratr_state, p_ra->ratr_state)); + + rtlpriv->cfg->ops->update_rate_mask(hw, + p_ra->ratr_state); + + p_ra->pre_ratr_state = p_ra->ratr_state; + } + } +} + +static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) +{ + dm_pstable.pre_ccastate = CCA_MAX; + dm_pstable.cur_ccasate = CCA_MAX; + dm_pstable.pre_rfstate = RF_MAX; + dm_pstable.cur_rfstate = RF_MAX; + dm_pstable.rssi_val_min = 0; +} + +static void rtl92c_dm_1r_cca(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + if (dm_pstable.rssi_val_min != 0) { + if (dm_pstable.pre_ccastate == CCA_2R) { + if (dm_pstable.rssi_val_min >= 35) + dm_pstable.cur_ccasate = CCA_1R; + else + dm_pstable.cur_ccasate = CCA_2R; + } else { + if (dm_pstable.rssi_val_min <= 30) + dm_pstable.cur_ccasate = CCA_2R; + else + dm_pstable.cur_ccasate = CCA_1R; + } + } else { + dm_pstable.cur_ccasate = CCA_MAX; + } + + if (dm_pstable.pre_ccastate != dm_pstable.cur_ccasate) { + if (dm_pstable.cur_ccasate == CCA_1R) { + if (get_rf_type(rtlphy) == RF_2T2R) { + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, + MASKBYTE0, 0x13); + rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x20); + } else { + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, + MASKBYTE0, 0x23); + rtl_set_bbreg(hw, 0xe70, 0x7fc00000, 0x10c); + } + } else { + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, + 0x33); + rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x63); + } + dm_pstable.pre_ccastate = dm_pstable.cur_ccasate; + } + + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, ("CCAStage = %s\n", + (dm_pstable.cur_ccasate == + 0) ? "1RCCA" : "2RCCA")); +} + +void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) +{ + static u8 initialize; + static u32 reg_874, reg_c70, reg_85c, reg_a74; + + if (initialize == 0) { + reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, + MASKDWORD) & 0x1CC000) >> 14; + + reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1, + MASKDWORD) & BIT(3)) >> 3; + + reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, + MASKDWORD) & 0xFF000000) >> 24; + + reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & 0xF000) >> 12; + + initialize = 1; + } + + if (!bforce_in_normal) { + if (dm_pstable.rssi_val_min != 0) { + if (dm_pstable.pre_rfstate == RF_NORMAL) { + if (dm_pstable.rssi_val_min >= 30) + dm_pstable.cur_rfstate = RF_SAVE; + else + dm_pstable.cur_rfstate = RF_NORMAL; + } else { + if (dm_pstable.rssi_val_min <= 25) + dm_pstable.cur_rfstate = RF_NORMAL; + else + dm_pstable.cur_rfstate = RF_SAVE; + } + } else { + dm_pstable.cur_rfstate = RF_MAX; + } + } else { + dm_pstable.cur_rfstate = RF_NORMAL; + } + + if (dm_pstable.pre_rfstate != dm_pstable.cur_rfstate) { + if (dm_pstable.cur_rfstate == RF_SAVE) { + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, + 0x1C0000, 0x2); + rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0); + rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, + 0xFF000000, 0x63); + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, + 0xC000, 0x2); + rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3); + rtl_set_bbreg(hw, 0x818, BIT(28), 0x0); + rtl_set_bbreg(hw, 0x818, BIT(28), 0x1); + } else { + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, + 0x1CC000, reg_874); + rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), + reg_c70); + rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000, + reg_85c); + rtl_set_bbreg(hw, 0xa74, 0xF000, reg_a74); + rtl_set_bbreg(hw, 0x818, BIT(28), 0x0); + } + + dm_pstable.pre_rfstate = dm_pstable.cur_rfstate; + } +} + +static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (((mac->link_state == MAC80211_NOLINK)) && + (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { + dm_pstable.rssi_val_min = 0; + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, + ("Not connected to any\n")); + } + + if (mac->link_state == MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + dm_pstable.rssi_val_min = + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, + ("AP Client PWDB = 0x%lx\n", + dm_pstable.rssi_val_min)); + } else { + dm_pstable.rssi_val_min = + rtlpriv->dm.undecorated_smoothed_pwdb; + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, + ("STA Default Port PWDB = 0x%lx\n", + dm_pstable.rssi_val_min)); + } + } else { + dm_pstable.rssi_val_min = + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, + ("AP Ext Port PWDB = 0x%lx\n", + dm_pstable.rssi_val_min)); + } + + if (IS_92C_SERIAL(rtlhal->version)) + rtl92c_dm_1r_cca(hw); +} + +void rtl92c_dm_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; + rtl92c_dm_diginit(hw); + rtl92c_dm_init_dynamic_txpower(hw); + rtl92c_dm_init_edca_turbo(hw); + rtl92c_dm_init_rate_adaptive_mask(hw); + rtl92c_dm_initialize_txpower_tracking(hw); + rtl92c_dm_init_dynamic_bb_powersaving(hw); +} + +void rtl92c_dm_watchdog(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool b_fw_current_inpsmode = false; + bool b_fw_ps_awake = true; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *) (&b_fw_current_inpsmode)); + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, + (u8 *) (&b_fw_ps_awake)); + + if ((ppsc->rfpwr_state == ERFON) && ((!b_fw_current_inpsmode) && + b_fw_ps_awake) + && (!ppsc->rfchange_inprogress)) { + rtl92c_dm_pwdb_monitor(hw); + rtl92c_dm_dig(hw); + rtl92c_dm_false_alarm_counter_statistics(hw); + rtl92c_dm_dynamic_bb_powersaving(hw); + rtl92c_dm_dynamic_txpower(hw); + rtl92c_dm_check_txpower_tracking(hw); + rtl92c_dm_refresh_rate_adaptive_mask(hw); + rtl92c_dm_check_edca_turbo(hw); + } +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h new file mode 100644 index 000000000000..463439e4074c --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h @@ -0,0 +1,196 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92C_DM_H__ +#define __RTL92C_DM_H__ + +#define HAL_DM_DIG_DISABLE BIT(0) +#define HAL_DM_HIPWR_DISABLE BIT(1) + +#define OFDM_TABLE_LENGTH 37 +#define CCK_TABLE_LENGTH 33 + +#define OFDM_TABLE_SIZE 37 +#define CCK_TABLE_SIZE 33 + +#define BW_AUTO_SWITCH_HIGH_LOW 25 +#define BW_AUTO_SWITCH_LOW_HIGH 30 + +#define DM_DIG_THRESH_HIGH 40 +#define DM_DIG_THRESH_LOW 35 + +#define DM_FALSEALARM_THRESH_LOW 400 +#define DM_FALSEALARM_THRESH_HIGH 1000 + +#define DM_DIG_MAX 0x3e +#define DM_DIG_MIN 0x1e + +#define DM_DIG_FA_UPPER 0x32 +#define DM_DIG_FA_LOWER 0x20 +#define DM_DIG_FA_TH0 0x20 +#define DM_DIG_FA_TH1 0x100 +#define DM_DIG_FA_TH2 0x200 + +#define DM_DIG_BACKOFF_MAX 12 +#define DM_DIG_BACKOFF_MIN -4 +#define DM_DIG_BACKOFF_DEFAULT 10 + +#define RXPATHSELECTION_SS_TH_lOW 30 +#define RXPATHSELECTION_DIFF_TH 18 + +#define DM_RATR_STA_INIT 0 +#define DM_RATR_STA_HIGH 1 +#define DM_RATR_STA_MIDDLE 2 +#define DM_RATR_STA_LOW 3 + +#define CTS2SELF_THVAL 30 +#define REGC38_TH 20 + +#define WAIOTTHVal 25 + +#define TXHIGHPWRLEVEL_NORMAL 0 +#define TXHIGHPWRLEVEL_LEVEL1 1 +#define TXHIGHPWRLEVEL_LEVEL2 2 +#define TXHIGHPWRLEVEL_BT1 3 +#define TXHIGHPWRLEVEL_BT2 4 + +#define DM_TYPE_BYFW 0 +#define DM_TYPE_BYDRIVER 1 + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 + +struct ps_t { + u8 pre_ccastate; + u8 cur_ccasate; + u8 pre_rfstate; + u8 cur_rfstate; + long rssi_val_min; +}; + +struct dig_t { + u8 dig_enable_flag; + u8 dig_ext_port_stage; + u32 rssi_lowthresh; + u32 rssi_highthresh; + u32 fa_lowthresh; + u32 fa_highthresh; + u8 cursta_connectctate; + u8 presta_connectstate; + u8 curmultista_connectstate; + u8 pre_igvalue; + u8 cur_igvalue; + char backoff_val; + char backoff_val_range_max; + char backoff_val_range_min; + u8 rx_gain_range_max; + u8 rx_gain_range_min; + u8 rssi_val_min; + u8 pre_cck_pd_state; + u8 cur_cck_pd_state; + u8 pre_cck_fa_state; + u8 cur_cck_fa_state; + u8 pre_ccastate; + u8 cur_ccasate; +}; + +struct swat_t { + u8 failure_cnt; + u8 try_flag; + u8 stop_trying; + long pre_rssi; + long trying_threshold; + u8 cur_antenna; + u8 pre_antenna; +}; + +enum tag_dynamic_init_gain_operation_type_definition { + DIG_TYPE_THRESH_HIGH = 0, + DIG_TYPE_THRESH_LOW = 1, + DIG_TYPE_BACKOFF = 2, + DIG_TYPE_RX_GAIN_MIN = 3, + DIG_TYPE_RX_GAIN_MAX = 4, + DIG_TYPE_ENABLE = 5, + DIG_TYPE_DISABLE = 6, + DIG_OP_TYPE_MAX +}; + +enum tag_cck_packet_detection_threshold_type_definition { + CCK_PD_STAGE_LowRssi = 0, + CCK_PD_STAGE_HighRssi = 1, + CCK_FA_STAGE_Low = 2, + CCK_FA_STAGE_High = 3, + CCK_PD_STAGE_MAX = 4, +}; + +enum dm_1r_cca_e { + CCA_1R = 0, + CCA_2R = 1, + CCA_MAX = 2, +}; + +enum dm_rf_e { + RF_SAVE = 0, + RF_NORMAL = 1, + RF_MAX = 2, +}; + +enum dm_sw_ant_switch_e { + ANS_ANTENNA_B = 1, + ANS_ANTENNA_A = 2, + ANS_ANTENNA_MAX = 3, +}; + +enum dm_dig_ext_port_alg_e { + DIG_EXT_PORT_STAGE_0 = 0, + DIG_EXT_PORT_STAGE_1 = 1, + DIG_EXT_PORT_STAGE_2 = 2, + DIG_EXT_PORT_STAGE_3 = 3, + DIG_EXT_PORT_STAGE_MAX = 4, +}; + +enum dm_dig_connect_e { + DIG_STA_DISCONNECT = 0, + DIG_STA_CONNECT = 1, + DIG_STA_BEFORE_CONNECT = 2, + DIG_MULTISTA_DISCONNECT = 3, + DIG_MULTISTA_CONNECT = 4, + DIG_CONNECT_MAX +}; + +extern struct dig_t dm_digtable; +void rtl92c_dm_init(struct ieee80211_hw *hw); +void rtl92c_dm_watchdog(struct ieee80211_hw *hw); +void rtl92c_dm_write_dig(struct ieee80211_hw *hw); +void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw); +void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw); +void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); +void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/fw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/fw.c new file mode 100644 index 000000000000..11dd22b987e7 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/fw.c @@ -0,0 +1,804 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include <linux/firmware.h> +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "fw.h" +#include "table.h" + +static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) { + u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + if (enable) + value32 |= MCUFWDL_EN; + else + value32 &= ~MCUFWDL_EN; + rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); + } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) { + u8 tmp; + if (enable) { + + tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, + tmp | 0x04); + + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); + + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); + rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); + } else { + + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); + + rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00); + } + } +} + +static void _rtl92c_fw_block_write(struct ieee80211_hw *hw, + const u8 *buffer, u32 size) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 blockSize = sizeof(u32); + u8 *bufferPtr = (u8 *) buffer; + u32 *pu4BytePtr = (u32 *) buffer; + u32 i, offset, blockCount, remainSize; + + blockCount = size / blockSize; + remainSize = size % blockSize; + + for (i = 0; i < blockCount; i++) { + offset = i * blockSize; + rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset), + *(pu4BytePtr + i)); + } + + if (remainSize) { + offset = blockCount * blockSize; + bufferPtr += offset; + for (i = 0; i < remainSize; i++) { + rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS + + offset + i), *(bufferPtr + i)); + } + } +} + +static void _rtl92c_fw_page_write(struct ieee80211_hw *hw, + u32 page, const u8 *buffer, u32 size) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 value8; + u8 u8page = (u8) (page & 0x07); + + value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page; + + rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8); + _rtl92c_fw_block_write(hw, buffer, size); +} + +static void _rtl92c_fill_dummy(u8 *pfwbuf, u32 *pfwlen) +{ + u32 fwlen = *pfwlen; + u8 remain = (u8) (fwlen % 4); + + remain = (remain == 0) ? 0 : (4 - remain); + + while (remain > 0) { + pfwbuf[fwlen] = 0; + fwlen++; + remain--; + } + + *pfwlen = fwlen; +} + +static void _rtl92c_write_fw(struct ieee80211_hw *hw, + enum version_8192c version, u8 *buffer, u32 size) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool is_version_b; + u8 *bufferPtr = (u8 *) buffer; + + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size)); + + is_version_b = IS_CHIP_VER_B(version); + if (is_version_b) { + u32 pageNums, remainSize; + u32 page, offset; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) + _rtl92c_fill_dummy(bufferPtr, &size); + + pageNums = size / FW_8192C_PAGE_SIZE; + remainSize = size % FW_8192C_PAGE_SIZE; + + if (pageNums > 4) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Page numbers should not greater then 4\n")); + } + + for (page = 0; page < pageNums; page++) { + offset = page * FW_8192C_PAGE_SIZE; + _rtl92c_fw_page_write(hw, page, (bufferPtr + offset), + FW_8192C_PAGE_SIZE); + } + + if (remainSize) { + offset = pageNums * FW_8192C_PAGE_SIZE; + page = pageNums; + _rtl92c_fw_page_write(hw, page, (bufferPtr + offset), + remainSize); + } + } else { + _rtl92c_fw_block_write(hw, buffer, size); + } +} + +static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int err = -EIO; + u32 counter = 0; + u32 value32; + + do { + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) && + (!(value32 & FWDL_ChkSum_rpt))); + + if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("chksum report faill ! REG_MCUFWDL:0x%08x .\n", + value32)); + goto exit; + } + + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + ("Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32)); + + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + value32 |= MCUFWDL_RDY; + value32 &= ~WINTINI_RDY; + rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); + + counter = 0; + + do { + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + if (value32 & WINTINI_RDY) { + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + ("Polling FW ready success!!" + " REG_MCUFWDL:0x%08x .\n", + value32)); + err = 0; + goto exit; + } + + mdelay(FW_8192C_POLLING_DELAY); + + } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT); + + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32)); + +exit: + return err; +} + +int rtl92c_download_fw(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl92c_firmware_header *pfwheader; + u8 *pfwdata; + u32 fwsize; + int err; + enum version_8192c version = rtlhal->version; + + const struct firmware *firmware = NULL; + + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Failed to request firmware!\n")); + return 1; + } + + if (firmware->size > 0x4000) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Firmware is too big!\n")); + release_firmware(firmware); + return 1; + } + + memcpy(rtlhal->pfirmware, firmware->data, firmware->size); + fwsize = firmware->size; + release_firmware(firmware); + + pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; + pfwdata = (u8 *) rtlhal->pfirmware; + + if (IS_FW_HEADER_EXIST(pfwheader)) { + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + ("Firmware Version(%d), Signature(%#x),Size(%d)\n", + pfwheader->version, pfwheader->signature, + (uint)sizeof(struct rtl92c_firmware_header))); + + pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header); + fwsize = fwsize - sizeof(struct rtl92c_firmware_header); + } + + _rtl92c_enable_fw_download(hw, true); + _rtl92c_write_fw(hw, version, pfwdata, fwsize); + _rtl92c_enable_fw_download(hw, false); + + err = _rtl92c_fw_free_to_go(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Firmware is not ready to run!\n")); + } else { + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + ("Firmware is ready to run!\n")); + } + + return 0; +} + +static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 val_hmetfr, val_mcutst_1; + bool result = false; + + val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); + val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum)); + + if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0) + result = true; + return result; +} + +static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, u8 *p_cmdbuffer) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 boxnum; + u16 box_reg, box_extreg; + u8 u1b_tmp; + bool isfw_read = false; + u8 buf_index; + bool bwrite_sucess = false; + u8 wait_h2c_limmit = 100; + u8 wait_writeh2c_limmit = 100; + u8 boxcontent[4], boxextcontent[2]; + u32 h2c_waitcounter = 0; + unsigned long flag; + u8 idx; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n")); + + while (true) { + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + if (rtlhal->b_h2c_setinprogress) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("H2C set in progress! Wait to set.." + "element_id(%d).\n", element_id)); + + while (rtlhal->b_h2c_setinprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, + flag); + h2c_waitcounter++; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("Wait 100 us (%d times)...\n", + h2c_waitcounter)); + udelay(100); + + if (h2c_waitcounter > 1000) + return; + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, + flag); + } + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + } else { + rtlhal->b_h2c_setinprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + break; + } + } + + while (!bwrite_sucess) { + wait_writeh2c_limmit--; + if (wait_writeh2c_limmit == 0) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Write H2C fail because no trigger " + "for FW INT!\n")); + break; + } + + boxnum = rtlhal->last_hmeboxnum; + switch (boxnum) { + case 0: + box_reg = REG_HMEBOX_0; + box_extreg = REG_HMEBOX_EXT_0; + break; + case 1: + box_reg = REG_HMEBOX_1; + box_extreg = REG_HMEBOX_EXT_1; + break; + case 2: + box_reg = REG_HMEBOX_2; + box_extreg = REG_HMEBOX_EXT_2; + break; + case 3: + box_reg = REG_HMEBOX_3; + box_extreg = REG_HMEBOX_EXT_3; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + + isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum); + while (!isfw_read) { + + wait_h2c_limmit--; + if (wait_h2c_limmit == 0) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("Wating too long for FW read " + "clear HMEBox(%d)!\n", boxnum)); + break; + } + + udelay(10); + + isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum); + u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF); + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("Wating for FW read clear HMEBox(%d)!!! " + "0x1BF = %2x\n", boxnum, u1b_tmp)); + } + + if (!isfw_read) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("Write H2C register BOX[%d] fail!!!!! " + "Fw do not read.\n", boxnum)); + break; + } + + memset(boxcontent, 0, sizeof(boxcontent)); + memset(boxextcontent, 0, sizeof(boxextcontent)); + boxcontent[0] = element_id; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("Write element_id box_reg(%4x) = %2x\n", + box_reg, element_id)); + + switch (cmd_len) { + case 1: + boxcontent[0] &= ~(BIT(7)); + memcpy((u8 *) (boxcontent) + 1, + p_cmdbuffer + buf_index, 1); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 2: + boxcontent[0] &= ~(BIT(7)); + memcpy((u8 *) (boxcontent) + 1, + p_cmdbuffer + buf_index, 2); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 3: + boxcontent[0] &= ~(BIT(7)); + memcpy((u8 *) (boxcontent) + 1, + p_cmdbuffer + buf_index, 3); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 4: + boxcontent[0] |= (BIT(7)); + memcpy((u8 *) (boxextcontent), + p_cmdbuffer + buf_index, 2); + memcpy((u8 *) (boxcontent) + 1, + p_cmdbuffer + buf_index + 2, 2); + + for (idx = 0; idx < 2; idx++) { + rtl_write_byte(rtlpriv, box_extreg + idx, + boxextcontent[idx]); + } + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 5: + boxcontent[0] |= (BIT(7)); + memcpy((u8 *) (boxextcontent), + p_cmdbuffer + buf_index, 2); + memcpy((u8 *) (boxcontent) + 1, + p_cmdbuffer + buf_index + 2, 3); + + for (idx = 0; idx < 2; idx++) { + rtl_write_byte(rtlpriv, box_extreg + idx, + boxextcontent[idx]); + } + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + + bwrite_sucess = true; + + rtlhal->last_hmeboxnum = boxnum + 1; + if (rtlhal->last_hmeboxnum == 4) + rtlhal->last_hmeboxnum = 0; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("pHalData->last_hmeboxnum = %d\n", + rtlhal->last_hmeboxnum)); + } + + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + rtlhal->b_h2c_setinprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n")); +} + +void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, u8 *p_cmdbuffer) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 tmp_cmdbuf[2]; + + if (rtlhal->bfw_ready == false) { + RT_ASSERT(false, ("return H2C cmd because of Fw " + "download fail!!!\n")); + return; + } + + memset(tmp_cmdbuf, 0, 8); + memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len); + _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); + + return; +} + +void rtl92c_firmware_selfreset(struct ieee80211_hw *hw) +{ + u8 u1b_tmp; + u8 delay = 100; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20); + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + + while (u1b_tmp & BIT(2)) { + delay--; + if (delay == 0) { + RT_ASSERT(false, ("8051 reset fail.\n")); + break; + } + udelay(50); + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + } +} + +void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1_h2c_set_pwrmode[3] = {0}; + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode)); + + SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); + SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1); + SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, + ppsc->reg_max_lps_awakeintvl); + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n", + u1_h2c_set_pwrmode, 3); + rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode); + +} + +static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring; + struct rtl_tx_desc *pdesc; + u8 own; + unsigned long flags; + struct sk_buff *pskb = NULL; + + ring = &rtlpci->tx_ring[BEACON_QUEUE]; + + pskb = __skb_dequeue(&ring->queue); + if (pskb) + kfree_skb(pskb); + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + + pdesc = &ring->desc[0]; + own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN); + + rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); + + __skb_queue_tail(&ring->queue, skb); + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + + rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); + + return true; +} + +#define BEACON_PG 0 /*->1*/ +#define PSPOLL_PG 2 +#define NULL_PG 3 +#define PROBERSP_PG 4 /*->5*/ + +#define TOTAL_RESERVED_PKT_LEN 768 + +static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { + /* page 0 beacon */ + 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, + 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, + 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, + 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, + 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, + 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, + 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 1 beacon */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 2 ps-poll */ + 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 3 null */ + 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 4 probe_resp */ + 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, + 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, + 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, + 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, + 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, + 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, + 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, + 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, + 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 5 probe_resp */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct sk_buff *skb = NULL; + + u32 totalpacketlen; + bool rtstatus; + u8 u1RsvdPageLoc[3] = {0}; + bool b_dlok = false; + + u8 *beacon; + u8 *p_pspoll; + u8 *nullfunc; + u8 *p_probersp; + /*--------------------------------------------------------- + (1) beacon + ---------------------------------------------------------*/ + beacon = &reserved_page_packet[BEACON_PG * 128]; + SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); + SET_80211_HDR_ADDRESS3(beacon, mac->bssid); + + /*------------------------------------------------------- + (2) ps-poll + --------------------------------------------------------*/ + p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; + SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); + SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); + SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); + + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); + + /*-------------------------------------------------------- + (3) null data + ---------------------------------------------------------*/ + nullfunc = &reserved_page_packet[NULL_PG * 128]; + SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); + SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); + SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); + + /*--------------------------------------------------------- + (4) probe response + ----------------------------------------------------------*/ + p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; + SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); + SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); + SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG); + + totalpacketlen = TOTAL_RESERVED_PKT_LEN; + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", + &reserved_page_packet[0], totalpacketlen); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", + u1RsvdPageLoc, 3); + + + skb = dev_alloc_skb(totalpacketlen); + memcpy((u8 *) skb_put(skb, totalpacketlen), + &reserved_page_packet, totalpacketlen); + + rtstatus = _rtl92c_cmd_send_packet(hw, skb); + + if (rtstatus) + b_dlok = true; + + if (b_dlok) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("Set RSVD page location to Fw.\n")); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "H2C_RSVDPAGE:\n", + u1RsvdPageLoc, 3); + rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE, + sizeof(u1RsvdPageLoc), u1RsvdPageLoc); + } else + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("Set RSVD page location to Fw FAIL!!!!!!.\n")); +} + +void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) +{ + u8 u1_joinbssrpt_parm[1] = {0}; + + SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); + + rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/fw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/fw.h new file mode 100644 index 000000000000..3db33bd14666 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/fw.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92C__FW__H__ +#define __RTL92C__FW__H__ + +#define FW_8192C_SIZE 0x3000 +#define FW_8192C_START_ADDRESS 0x1000 +#define FW_8192C_END_ADDRESS 0x3FFF +#define FW_8192C_PAGE_SIZE 4096 +#define FW_8192C_POLLING_DELAY 5 +#define FW_8192C_POLLING_TIMEOUT_COUNT 100 + +#define IS_FW_HEADER_EXIST(_pfwhdr) \ + ((_pfwhdr->signature&0xFFF0) == 0x92C0 ||\ + (_pfwhdr->signature&0xFFF0) == 0x88C0) + +struct rtl92c_firmware_header { + u16 signature; + u8 category; + u8 function; + u16 version; + u8 subversion; + u8 rsvd1; + u8 month; + u8 date; + u8 hour; + u8 minute; + u16 ramcodeSize; + u16 rsvd2; + u32 svnindex; + u32 rsvd3; + u32 rsvd4; + u32 rsvd5; +}; + +enum rtl8192c_h2c_cmd { + H2C_AP_OFFLOAD = 0, + H2C_SETPWRMODE = 1, + H2C_JOINBSSRPT = 2, + H2C_RSVDPAGE = 3, + H2C_RSSI_REPORT = 5, + H2C_RA_MASK = 6, + MAX_H2CCMD +}; + +#define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0)) + +#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) +#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) + +int rtl92c_download_fw(struct ieee80211_hw *hw); +void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, + u32 cmd_len, u8 *p_cmdbuffer); +void rtl92c_firmware_selfreset(struct ieee80211_hw *hw); +void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); +void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); +void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c new file mode 100644 index 000000000000..1c41a0c93506 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -0,0 +1,2162 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../efuse.h" +#include "../base.h" +#include "../cam.h" +#include "../ps.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "led.h" +#include "hw.h" + +#define LLT_CONFIG 5 + +static void _rtl92ce_set_bcn_ctrl_reg(struct ieee80211_hw *hw, + u8 set_bits, u8 clear_bits) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpci->reg_bcn_ctrl_val |= set_bits; + rtlpci->reg_bcn_ctrl_val &= ~clear_bits; + + rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); +} + +static void _rtl92ce_stop_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl92ce_resume_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte |= BIT(0); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl92ce_enable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(1)); +} + +static void _rtl92ce_disable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl92ce_set_bcn_ctrl_reg(hw, BIT(1), 0); +} + +void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + switch (variable) { + case HW_VAR_RCR: + *((u32 *) (val)) = rtlpci->receive_config; + break; + case HW_VAR_RF_STATE: + *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; + break; + case HW_VAR_FWLPS_RF_ON:{ + enum rf_pwrstate rfState; + u32 val_rcr; + + rtlpriv->cfg->ops->get_hw_reg(hw, + HW_VAR_RF_STATE, + (u8 *) (&rfState)); + if (rfState == ERFOFF) { + *((bool *) (val)) = true; + } else { + val_rcr = rtl_read_dword(rtlpriv, REG_RCR); + val_rcr &= 0x00070000; + if (val_rcr) + *((bool *) (val)) = false; + else + *((bool *) (val)) = true; + } + break; + } + case HW_VAR_FW_PSMODE_STATUS: + *((bool *) (val)) = ppsc->b_fw_current_inpsmode; + break; + case HW_VAR_CORRECT_TSF:{ + u64 tsf; + u32 *ptsf_low = (u32 *)&tsf; + u32 *ptsf_high = ((u32 *)&tsf) + 1; + + *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); + *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + + *((u64 *) (val)) = tsf; + + break; + } + case HW_VAR_MGT_FILTER: + *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP0); + break; + case HW_VAR_CTRL_FILTER: + *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP1); + break; + case HW_VAR_DATA_FILTER: + *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP2); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } +} + +void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 idx; + + switch (variable) { + case HW_VAR_ETHER_ADDR:{ + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_MACID + idx), + val[idx]); + } + break; + } + case HW_VAR_BASIC_RATE:{ + u16 b_rate_cfg = ((u16 *) val)[0]; + u8 rate_index = 0; + b_rate_cfg = b_rate_cfg & 0x15f; + b_rate_cfg |= 0x01; + rtl_write_byte(rtlpriv, REG_RRSR, b_rate_cfg & 0xff); + rtl_write_byte(rtlpriv, REG_RRSR + 1, + (b_rate_cfg >> 8)&0xff); + while (b_rate_cfg > 0x1) { + b_rate_cfg = (b_rate_cfg >> 1); + rate_index++; + } + rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, + rate_index); + break; + } + case HW_VAR_BSSID:{ + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_BSSID + idx), + val[idx]); + } + break; + } + case HW_VAR_SIFS:{ + rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); + rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); + + rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); + rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); + + if (!mac->ht_enable) + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, + 0x0e0e); + else + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, + *((u16 *) val)); + break; + } + case HW_VAR_SLOT_TIME:{ + u8 e_aci; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + ("HW_VAR_SLOT_TIME %x\n", val[0])); + + rtl_write_byte(rtlpriv, REG_SLOT, val[0]); + + for (e_aci = 0; e_aci < AC_MAX; e_aci++) { + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_AC_PARAM, + (u8 *) (&e_aci)); + } + break; + } + case HW_VAR_ACK_PREAMBLE:{ + u8 reg_tmp; + u8 short_preamble = (bool) (*(u8 *) val); + reg_tmp = (mac->cur_40_prime_sc) << 5; + if (short_preamble) + reg_tmp |= 0x80; + + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp); + break; + } + case HW_VAR_AMPDU_MIN_SPACE:{ + u8 min_spacing_to_set; + u8 sec_min_space; + + min_spacing_to_set = *((u8 *) val); + if (min_spacing_to_set <= 7) { + sec_min_space = 0; + + if (min_spacing_to_set < sec_min_space) + min_spacing_to_set = sec_min_space; + + mac->min_space_cfg = ((mac->min_space_cfg & + 0xf8) | + min_spacing_to_set); + + *val = min_spacing_to_set; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + ("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", + mac->min_space_cfg)); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + } + break; + } + case HW_VAR_SHORTGI_DENSITY:{ + u8 density_to_set; + + density_to_set = *((u8 *) val); + mac->min_space_cfg |= (density_to_set << 3); + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + ("Set HW_VAR_SHORTGI_DENSITY: %#x\n", + mac->min_space_cfg)); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + + break; + } + case HW_VAR_AMPDU_FACTOR:{ + u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; + + u8 factor_toset; + u8 *p_regtoset = NULL; + u8 index = 0; + + p_regtoset = regtoset_normal; + + factor_toset = *((u8 *) val); + if (factor_toset <= 3) { + factor_toset = (1 << (factor_toset + 2)); + if (factor_toset > 0xf) + factor_toset = 0xf; + + for (index = 0; index < 4; index++) { + if ((p_regtoset[index] & 0xf0) > + (factor_toset << 4)) + p_regtoset[index] = + (p_regtoset[index] & 0x0f) | + (factor_toset << 4); + + if ((p_regtoset[index] & 0x0f) > + factor_toset) + p_regtoset[index] = + (p_regtoset[index] & 0xf0) | + (factor_toset); + + rtl_write_byte(rtlpriv, + (REG_AGGLEN_LMT + index), + p_regtoset[index]); + + } + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + ("Set HW_VAR_AMPDU_FACTOR: %#x\n", + factor_toset)); + } + break; + } + case HW_VAR_AC_PARAM:{ + u8 e_aci = *((u8 *) val); + u32 u4b_ac_param = 0; + + u4b_ac_param |= (u32) mac->ac[e_aci].aifs; + u4b_ac_param |= ((u32) mac->ac[e_aci].cw_min + & 0xF) << AC_PARAM_ECW_MIN_OFFSET; + u4b_ac_param |= ((u32) mac->ac[e_aci].cw_max & + 0xF) << AC_PARAM_ECW_MAX_OFFSET; + u4b_ac_param |= (u32) mac->ac[e_aci].tx_op + << AC_PARAM_TXOP_LIMIT_OFFSET; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + ("queue:%x, ac_param:%x\n", e_aci, + u4b_ac_param)); + + switch (e_aci) { + case AC1_BK: + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, + u4b_ac_param); + break; + case AC0_BE: + rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, + u4b_ac_param); + break; + case AC2_VI: + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, + u4b_ac_param); + break; + case AC3_VO: + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, + u4b_ac_param); + break; + default: + RT_ASSERT(false, + ("SetHwReg8185(): invalid aci: %d !\n", + e_aci)); + break; + } + + if (rtlpci->acm_method != eAcmWay2_SW) + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_ACM_CTRL, + (u8 *) (&e_aci)); + break; + } + case HW_VAR_ACM_CTRL:{ + u8 e_aci = *((u8 *) val); + union aci_aifsn *p_aci_aifsn = + (union aci_aifsn *)(&(mac->ac[0].aifs)); + u8 acm = p_aci_aifsn->f.acm; + u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); + + acm_ctrl = + acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); + + if (acm) { + switch (e_aci) { + case AC0_BE: + acm_ctrl |= AcmHw_BeqEn; + break; + case AC2_VI: + acm_ctrl |= AcmHw_ViqEn; + break; + case AC3_VO: + acm_ctrl |= AcmHw_VoqEn; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("HW_VAR_ACM_CTRL acm set " + "failed: eACI is %d\n", acm)); + break; + } + } else { + switch (e_aci) { + case AC0_BE: + acm_ctrl &= (~AcmHw_BeqEn); + break; + case AC2_VI: + acm_ctrl &= (~AcmHw_ViqEn); + break; + case AC3_VO: + acm_ctrl &= (~AcmHw_BeqEn); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + } + + RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, + ("SetHwReg8190pci(): [HW_VAR_ACM_CTRL] " + "Write 0x%X\n", acm_ctrl)); + rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); + break; + } + case HW_VAR_RCR:{ + rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]); + rtlpci->receive_config = ((u32 *) (val))[0]; + break; + } + case HW_VAR_RETRY_LIMIT:{ + u8 retry_limit = ((u8 *) (val))[0]; + + rtl_write_word(rtlpriv, REG_RL, + retry_limit << RETRY_LIMIT_SHORT_SHIFT | + retry_limit << RETRY_LIMIT_LONG_SHIFT); + break; + } + case HW_VAR_DUAL_TSF_RST: + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); + break; + case HW_VAR_EFUSE_BYTES: + rtlefuse->efuse_usedbytes = *((u16 *) val); + break; + case HW_VAR_EFUSE_USAGE: + rtlefuse->efuse_usedpercentage = *((u8 *) val); + break; + case HW_VAR_IO_CMD: + rtl92c_phy_set_io_cmd(hw, (*(enum io_type *)val)); + break; + case HW_VAR_WPA_CONFIG: + rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *) val)); + break; + case HW_VAR_SET_RPWM:{ + u8 rpwm_val; + + rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); + udelay(1); + + if (rpwm_val & BIT(7)) { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, + (*(u8 *) val)); + } else { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, + ((*(u8 *) val) | BIT(7))); + } + + break; + } + case HW_VAR_H2C_FW_PWRMODE:{ + u8 psmode = (*(u8 *) val); + + if ((psmode != FW_PS_ACTIVE_MODE) && + (!IS_92C_SERIAL(rtlhal->version))) { + rtl92c_dm_rf_saving(hw, true); + } + + rtl92c_set_fw_pwrmode_cmd(hw, (*(u8 *) val)); + break; + } + case HW_VAR_FW_PSMODE_STATUS: + ppsc->b_fw_current_inpsmode = *((bool *) val); + break; + case HW_VAR_H2C_FW_JOINBSSRPT:{ + u8 mstatus = (*(u8 *) val); + u8 tmp_regcr, tmp_reg422; + bool b_recover = false; + + if (mstatus == RT_MEDIA_CONNECT) { + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, + NULL); + + tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, + (tmp_regcr | BIT(0))); + + _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(3)); + _rtl92ce_set_bcn_ctrl_reg(hw, BIT(4), 0); + + tmp_reg422 = + rtl_read_byte(rtlpriv, + REG_FWHW_TXQ_CTRL + 2); + if (tmp_reg422 & BIT(6)) + b_recover = true; + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, + tmp_reg422 & (~BIT(6))); + + rtl92c_set_fw_rsvdpagepkt(hw, 0); + + _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); + _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4)); + + if (b_recover) { + rtl_write_byte(rtlpriv, + REG_FWHW_TXQ_CTRL + 2, + tmp_reg422); + } + + rtl_write_byte(rtlpriv, REG_CR + 1, + (tmp_regcr & ~(BIT(0)))); + } + rtl92c_set_fw_joinbss_report_cmd(hw, (*(u8 *) val)); + + break; + } + case HW_VAR_AID:{ + u16 u2btmp; + u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); + u2btmp &= 0xC000; + rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | + mac->assoc_id)); + + break; + } + case HW_VAR_CORRECT_TSF:{ + u8 btype_ibss = ((u8 *) (val))[0]; + + /*btype_ibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? + 1 : 0;*/ + + if (btype_ibss == true) + _rtl92ce_stop_tx_beacon(hw); + + _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(3)); + + rtl_write_dword(rtlpriv, REG_TSFTR, + (u32) (mac->tsf & 0xffffffff)); + rtl_write_dword(rtlpriv, REG_TSFTR + 4, + (u32) ((mac->tsf >> 32)&0xffffffff)); + + _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); + + if (btype_ibss == true) + _rtl92ce_resume_tx_beacon(hw); + + break; + + } + case HW_VAR_MGT_FILTER: + rtl_write_word(rtlpriv, REG_RXFLTMAP0, *(u16 *) val); + break; + case HW_VAR_CTRL_FILTER: + rtl_write_word(rtlpriv, REG_RXFLTMAP1, *(u16 *) val); + break; + case HW_VAR_DATA_FILTER: + rtl_write_word(rtlpriv, REG_RXFLTMAP2, *(u16 *) val); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case " + "not process\n")); + break; + } +} + +static bool _rtl92ce_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool status = true; + long count = 0; + u32 value = _LLT_INIT_ADDR(address) | + _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS); + + rtl_write_dword(rtlpriv, REG_LLT_INIT, value); + + do { + value = rtl_read_dword(rtlpriv, REG_LLT_INIT); + if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) + break; + + if (count > POLLING_LLT_THRESHOLD) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Failed to polling write LLT done at " + "address %d!\n", address)); + status = false; + break; + } + } while (++count); + + return status; +} + +static bool _rtl92ce_llt_table_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + unsigned short i; + u8 txpktbuf_bndy; + u8 maxPage; + bool status; + +#if LLT_CONFIG == 1 + maxPage = 255; + txpktbuf_bndy = 252; +#elif LLT_CONFIG == 2 + maxPage = 127; + txpktbuf_bndy = 124; +#elif LLT_CONFIG == 3 + maxPage = 255; + txpktbuf_bndy = 174; +#elif LLT_CONFIG == 4 + maxPage = 255; + txpktbuf_bndy = 246; +#elif LLT_CONFIG == 5 + maxPage = 255; + txpktbuf_bndy = 246; +#endif + +#if LLT_CONFIG == 1 + rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x1c); + rtl_write_dword(rtlpriv, REG_RQPN, 0x80a71c1c); +#elif LLT_CONFIG == 2 + rtl_write_dword(rtlpriv, REG_RQPN, 0x845B1010); +#elif LLT_CONFIG == 3 + rtl_write_dword(rtlpriv, REG_RQPN, 0x84838484); +#elif LLT_CONFIG == 4 + rtl_write_dword(rtlpriv, REG_RQPN, 0x80bd1c1c); +#elif LLT_CONFIG == 5 + rtl_write_word(rtlpriv, REG_RQPN_NPQ, 0x0000); + + rtl_write_dword(rtlpriv, REG_RQPN, 0x80b01c29); +#endif + + rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x27FF0000 | txpktbuf_bndy)); + rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_PBP, 0x11); + rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); + + for (i = 0; i < (txpktbuf_bndy - 1); i++) { + status = _rtl92ce_llt_write(hw, i, i + 1); + if (true != status) + return status; + } + + status = _rtl92ce_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); + if (true != status) + return status; + + for (i = txpktbuf_bndy; i < maxPage; i++) { + status = _rtl92ce_llt_write(hw, i, (i + 1)); + if (true != status) + return status; + } + + status = _rtl92ce_llt_write(hw, maxPage, txpktbuf_bndy); + if (true != status) + return status; + + return true; +} + +static void _rtl92ce_gen_refresh_led_state(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + + if (rtlpci->up_first_time) + return; + + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) + rtl92ce_sw_led_on(hw, pLed0); + else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) + rtl92ce_sw_led_on(hw, pLed0); + else + rtl92ce_sw_led_off(hw, pLed0); + +} + +static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + unsigned char bytetmp; + unsigned short wordtmp; + u16 retry; + + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F); + + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0); + udelay(2); + + rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); + udelay(2); + + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); + udelay(2); + + retry = 0; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("reg0xec:%x:%x\n", + rtl_read_dword(rtlpriv, 0xEC), + bytetmp)); + + while ((bytetmp & BIT(0)) && retry < 1000) { + retry++; + udelay(50); + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("reg0xec:%x:%x\n", + rtl_read_dword(rtlpriv, + 0xEC), + bytetmp)); + udelay(50); + } + + rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x1012); + + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82); + udelay(2); + + rtl_write_word(rtlpriv, REG_CR, 0x2ff); + + if (_rtl92ce_llt_table_init(hw) == false) + return false;; + + rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); + rtl_write_byte(rtlpriv, REG_HISRE, 0xff); + + rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x27ff); + + wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); + wordtmp &= 0xf; + wordtmp |= 0xF771; + rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); + + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); + + rtl_write_byte(rtlpriv, 0x4d0, 0x0); + + rtl_write_dword(rtlpriv, REG_BCNQ_DESA, + ((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_MGQ_DESA, + (u64) rtlpci->tx_ring[MGNT_QUEUE].dma & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VOQ_DESA, + (u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VIQ_DESA, + (u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BEQ_DESA, + (u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BKQ_DESA, + (u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_HQ_DESA, + (u64) rtlpci->tx_ring[HIGH_QUEUE].dma & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_RX_DESA, + (u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma & + DMA_BIT_MASK(32)); + + if (IS_92C_SERIAL(rtlhal->version)) + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x77); + else + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x22); + + rtl_write_dword(rtlpriv, REG_INT_MIG, 0); + + bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6)); + do { + retry++; + bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); + } while ((retry < 200) && (bytetmp & BIT(7))); + + _rtl92ce_gen_refresh_led_state(hw); + + rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); + + return true;; +} + +static void _rtl92ce_hw_configure(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 reg_bw_opmode; + u32 reg_ratr, reg_prsr; + + reg_bw_opmode = BW_OPMODE_20MHZ; + reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | + RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + + rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8); + + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + + rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr); + + rtl_write_byte(rtlpriv, REG_SLOT, 0x09); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0); + + rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80); + + rtl_write_word(rtlpriv, REG_RL, 0x0707); + + rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802); + + rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); + + rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); + rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); + + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); + + rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); + + rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff); + + rtlpci->reg_bcn_ctrl_val = 0x1f; + rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); + + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + + rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); + rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); + + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + + rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666); + + rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); + + rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010); + rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010); + + rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010); + + rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010); + + rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff); + rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff); + +} + +static void _rtl92ce_enable_aspm_back_door(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + rtl_write_byte(rtlpriv, 0x34b, 0x93); + rtl_write_word(rtlpriv, 0x350, 0x870c); + rtl_write_byte(rtlpriv, 0x352, 0x1); + + if (ppsc->b_support_backdoor) + rtl_write_byte(rtlpriv, 0x349, 0x1b); + else + rtl_write_byte(rtlpriv, 0x349, 0x03); + + rtl_write_word(rtlpriv, 0x350, 0x2718); + rtl_write_byte(rtlpriv, 0x352, 0x1); +} + +void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 sec_reg_value; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", + rtlpriv->sec.pairwise_enc_algorithm, + rtlpriv->sec.group_enc_algorithm)); + + if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("not open " + "hw encryption\n")); + return; + } + + sec_reg_value = SCR_TxEncEnable | SCR_RxDecEnable; + + if (rtlpriv->sec.use_defaultkey) { + sec_reg_value |= SCR_TxUseDK; + sec_reg_value |= SCR_RxUseDK; + } + + sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); + + rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("The SECR-value %x\n", sec_reg_value)); + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); + +} + +int rtl92ce_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + static bool iqk_initialized; /* initialized to false */ + bool rtstatus = true; + bool is92c; + int err; + u8 tmp_u1b; + + rtlpci->being_init_adapter = true; + rtlpriv->intf_ops->disable_aspm(hw); + rtstatus = _rtl92ce_init_mac(hw); + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Init MAC failed\n")); + err = 1; + return err; + } + + err = rtl92c_download_fw(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("Failed to download FW. Init HW " + "without FW now..\n")); + err = 1; + rtlhal->bfw_ready = false; + return err; + } else { + rtlhal->bfw_ready = true; + } + + rtlhal->last_hmeboxnum = 0; + rtl92c_phy_mac_config(hw); + rtl92c_phy_bb_config(hw); + rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; + rtl92c_phy_rf_config(hw); + rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); + _rtl92ce_hw_configure(hw); + rtl_cam_reset_all_entry(hw); + rtl92ce_enable_hw_security_config(hw); + ppsc->rfpwr_state = ERFON; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); + _rtl92ce_enable_aspm_back_door(hw); + rtlpriv->intf_ops->enable_aspm(hw); + if (ppsc->rfpwr_state == ERFON) { + rtl92c_phy_set_rfpath_switch(hw, 1); + if (iqk_initialized) + rtl92c_phy_iq_calibrate(hw, true); + else { + rtl92c_phy_iq_calibrate(hw, false); + iqk_initialized = true; + } + + rtl92c_dm_check_txpower_tracking(hw); + rtl92c_phy_lc_calibrate(hw); + } + + is92c = IS_92C_SERIAL(rtlhal->version); + tmp_u1b = efuse_read_1byte(hw, 0x1FA); + if (!(tmp_u1b & BIT(0))) { + rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("PA BIAS path A\n")); + } + + if (!(tmp_u1b & BIT(1)) && is92c) { + rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0F, 0x05); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("PA BIAS path B\n")); + } + + if (!(tmp_u1b & BIT(4))) { + tmp_u1b = rtl_read_byte(rtlpriv, 0x16); + tmp_u1b &= 0x0F; + rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80); + udelay(10); + rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("under 1.5V\n")); + } + rtl92c_dm_init(hw); + rtlpci->being_init_adapter = false; + return err; +} + +static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + enum version_8192c version = VERSION_UNKNOWN; + u32 value32; + + value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); + if (value32 & TRP_VAUX_EN) { + version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C : + VERSION_A_CHIP_88C; + } else { + version = (value32 & TYPE_ID) ? VERSION_B_CHIP_92C : + VERSION_B_CHIP_88C; + } + + switch (version) { + case VERSION_B_CHIP_92C: + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Chip Version ID: VERSION_B_CHIP_92C.\n")); + break; + case VERSION_B_CHIP_88C: + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Chip Version ID: VERSION_B_CHIP_88C.\n")); + break; + case VERSION_A_CHIP_92C: + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Chip Version ID: VERSION_A_CHIP_92C.\n")); + break; + case VERSION_A_CHIP_88C: + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Chip Version ID: VERSION_A_CHIP_88C.\n")); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Chip Version ID: Unknown. Bug?\n")); + break; + } + + switch (version & 0x3) { + case CHIP_88C: + rtlphy->rf_type = RF_1T1R; + break; + case CHIP_92C: + rtlphy->rf_type = RF_2T2R; + break; + case CHIP_92C_1T2R: + rtlphy->rf_type = RF_1T2R; + break; + default: + rtlphy->rf_type = RF_1T1R; + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("ERROR RF_Type is set!!")); + break; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ? + "RF_2T2R" : "RF_1T1R")); + + return version; +} + +static int _rtl92ce_set_media_status(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bt_msr = rtl_read_byte(rtlpriv, MSR); + enum led_ctl_mode ledaction = LED_CTL_NO_LINK; + bt_msr &= 0xfc; + + if (type == NL80211_IFTYPE_UNSPECIFIED || + type == NL80211_IFTYPE_STATION) { + _rtl92ce_stop_tx_beacon(hw); + _rtl92ce_enable_bcn_sub_func(hw); + } else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_AP) { + _rtl92ce_resume_tx_beacon(hw); + _rtl92ce_disable_bcn_sub_func(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("Set HW_VAR_MEDIA_STATUS: " + "No such media status(%x).\n", type)); + } + + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + bt_msr |= MSR_NOLINK; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Set Network type to NO LINK!\n")); + break; + case NL80211_IFTYPE_ADHOC: + bt_msr |= MSR_ADHOC; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Set Network type to Ad Hoc!\n")); + break; + case NL80211_IFTYPE_STATION: + bt_msr |= MSR_INFRA; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Set Network type to STA!\n")); + break; + case NL80211_IFTYPE_AP: + bt_msr |= MSR_AP; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Set Network type to AP!\n")); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Network type %d not support!\n", type)); + return 1; + break; + + } + + rtl_write_byte(rtlpriv, (MSR), bt_msr); + rtlpriv->cfg->ops->led_control(hw, ledaction); + if ((bt_msr & 0xfc) == MSR_AP) + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); + else + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); + return 0; +} + +static void _rtl92ce_set_check_bssid(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR); + u8 filterout_non_associated_bssid = false; + + switch (type) { + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_STATION: + filterout_non_associated_bssid = true; + break; + case NL80211_IFTYPE_UNSPECIFIED: + case NL80211_IFTYPE_AP: + default: + break; + } + + if (filterout_non_associated_bssid == true) { + reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, + (u8 *) (®_rcr)); + _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4)); + } else if (filterout_non_associated_bssid == false) { + reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); + _rtl92ce_set_bcn_ctrl_reg(hw, BIT(4), 0); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_RCR, (u8 *) (®_rcr)); + } +} + +int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) +{ + if (_rtl92ce_set_media_status(hw, type)) + return -EOPNOTSUPP; + _rtl92ce_set_check_bssid(hw, type); + return 0; +} + +void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + u32 u4b_ac_param; + + rtl92c_dm_init_edca_turbo(hw); + + u4b_ac_param = (u32) mac->ac[aci].aifs; + u4b_ac_param |= + ((u32) mac->ac[aci].cw_min & 0xF) << AC_PARAM_ECW_MIN_OFFSET; + u4b_ac_param |= + ((u32) mac->ac[aci].cw_max & 0xF) << AC_PARAM_ECW_MAX_OFFSET; + u4b_ac_param |= (u32) mac->ac[aci].tx_op << AC_PARAM_TXOP_LIMIT_OFFSET; + RT_TRACE(rtlpriv, COMP_QOS, DBG_DMESG, + ("queue:%x, ac_param:%x aifs:%x cwmin:%x cwmax:%x txop:%x\n", + aci, u4b_ac_param, mac->ac[aci].aifs, mac->ac[aci].cw_min, + mac->ac[aci].cw_max, mac->ac[aci].tx_op)); + switch (aci) { + case AC1_BK: + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param); + break; + case AC0_BE: + rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); + break; + case AC2_VI: + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, u4b_ac_param); + break; + case AC3_VO: + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, u4b_ac_param); + break; + default: + RT_ASSERT(false, ("invalid aci: %d !\n", aci)); + break; + } +} + +void rtl92ce_enable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); + rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); + rtlpci->irq_enabled = true; +} + +void rtl92ce_disable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED); + rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); + rtlpci->irq_enabled = false; +} + +static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 u1b_tmp; + + rtlpriv->intf_ops->enable_aspm(hw); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0); + if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->bfw_ready) + rtl92c_firmware_selfreset(hw); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51); + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000); + u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL); + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00FF0000 | + (u1b_tmp << 8)); + rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790); + rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); + rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10); +} + +void rtl92ce_card_disable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + enum nl80211_iftype opmode; + + mac->link_state = MAC80211_NOLINK; + opmode = NL80211_IFTYPE_UNSPECIFIED; + _rtl92ce_set_media_status(hw, opmode); + if (rtlpci->driver_is_goingto_unload || + ppsc->rfoff_reason > RF_CHANGE_BY_PS) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + _rtl92ce_poweroff_adapter(hw); +} + +void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; + rtl_write_dword(rtlpriv, ISR, *p_inta); + + /* + * *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; + * rtl_write_dword(rtlpriv, ISR + 4, *p_intb); + */ +} + +void rtl92ce_set_beacon_related_registers(struct ieee80211_hw *hw) +{ + + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval, atim_window; + + bcn_interval = mac->beacon_interval; + atim_window = 2; /*FIX MERGE */ + rtl92ce_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); + rtl_write_byte(rtlpriv, 0x606, 0x30); + rtl92ce_enable_interrupt(hw); +} + +void rtl92ce_set_beacon_interval(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval = mac->beacon_interval; + + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + ("beacon_interval:%d\n", bcn_interval)); + rtl92ce_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl92ce_enable_interrupt(hw); +} + +void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, + ("add_msr:%x, rm_msr:%x\n", add_msr, rm_msr)); + if (add_msr) + rtlpci->irq_mask[0] |= add_msr; + if (rm_msr) + rtlpci->irq_mask[0] &= (~rm_msr); + rtl92ce_disable_interrupt(hw); + rtl92ce_enable_interrupt(hw); +} + +static u8 _rtl92c_get_chnl_group(u8 chnl) +{ + u8 group; + + if (chnl < 3) + group = 0; + else if (chnl < 9) + group = 1; + else + group = 2; + return group; +} + +static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, + u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 rf_path, index, tempval; + u16 i; + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 3; i++) { + if (!autoload_fail) { + rtlefuse-> + eeprom_chnlarea_txpwr_cck[rf_path][i] = + hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i]; + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = + hwinfo[EEPROM_TXPOWERHT40_1S + rf_path * 3 + + i]; + } else { + rtlefuse-> + eeprom_chnlarea_txpwr_cck[rf_path][i] = + EEPROM_DEFAULT_TXPOWERLEVEL; + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = + EEPROM_DEFAULT_TXPOWERLEVEL; + } + } + } + + for (i = 0; i < 3; i++) { + if (!autoload_fail) + tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i]; + else + tempval = EEPROM_DEFAULT_HT40_2SDIFF; + rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_A][i] = + (tempval & 0xf); + rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_B][i] = + ((tempval & 0xf0) >> 4); + } + + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + ("RF(%d) EEPROM CCK Area(%d) = 0x%x\n", rf_path, + i, + rtlefuse-> + eeprom_chnlarea_txpwr_cck[rf_path][i])); + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + ("RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][i])); + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + ("RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path] + [i])); + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 14; i++) { + index = _rtl92c_get_chnl_group((u8) i); + + rtlefuse->txpwrlevel_cck[rf_path][i] = + rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][index]; + rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][index]; + + if ((rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] - + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][index]) + > 0) { + rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path] + [index] - + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path] + [index]; + } else { + rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0; + } + } + + for (i = 0; i < 14; i++) { + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = " + "[0x%x / 0x%x / 0x%x]\n", rf_path, i, + rtlefuse->txpwrlevel_cck[rf_path][i], + rtlefuse->txpwrlevel_ht40_1s[rf_path][i], + rtlefuse->txpwrlevel_ht40_2s[rf_path][i])); + } + } + + for (i = 0; i < 3; i++) { + if (!autoload_fail) { + rtlefuse->eeprom_pwrlimit_ht40[i] = + hwinfo[EEPROM_TXPWR_GROUP + i]; + rtlefuse->eeprom_pwrlimit_ht20[i] = + hwinfo[EEPROM_TXPWR_GROUP + 3 + i]; + } else { + rtlefuse->eeprom_pwrlimit_ht40[i] = 0; + rtlefuse->eeprom_pwrlimit_ht20[i] = 0; + } + } + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 14; i++) { + index = _rtl92c_get_chnl_group((u8) i); + + if (rf_path == RF90_PATH_A) { + rtlefuse->pwrgroup_ht20[rf_path][i] = + (rtlefuse->eeprom_pwrlimit_ht20[index] + & 0xf); + rtlefuse->pwrgroup_ht40[rf_path][i] = + (rtlefuse->eeprom_pwrlimit_ht40[index] + & 0xf); + } else if (rf_path == RF90_PATH_B) { + rtlefuse->pwrgroup_ht20[rf_path][i] = + ((rtlefuse->eeprom_pwrlimit_ht20[index] + & 0xf0) >> 4); + rtlefuse->pwrgroup_ht40[rf_path][i] = + ((rtlefuse->eeprom_pwrlimit_ht40[index] + & 0xf0) >> 4); + } + + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF-%d pwrgroup_ht20[%d] = 0x%x\n", + rf_path, i, + rtlefuse->pwrgroup_ht20[rf_path][i])); + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF-%d pwrgroup_ht40[%d] = 0x%x\n", + rf_path, i, + rtlefuse->pwrgroup_ht40[rf_path][i])); + } + } + + for (i = 0; i < 14; i++) { + index = _rtl92c_get_chnl_group((u8) i); + + if (!autoload_fail) + tempval = hwinfo[EEPROM_TXPOWERHT20DIFF + index]; + else + tempval = EEPROM_DEFAULT_HT20_DIFF; + + rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF); + rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] = + ((tempval >> 4) & 0xF); + + if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] & BIT(3)) + rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] |= 0xF0; + + if (rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] & BIT(3)) + rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] |= 0xF0; + + index = _rtl92c_get_chnl_group((u8) i); + + if (!autoload_fail) + tempval = hwinfo[EEPROM_TXPOWER_OFDMDIFF + index]; + else + tempval = EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; + + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = (tempval & 0xF); + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] = + ((tempval >> 4) & 0xF); + } + + rtlefuse->legacy_ht_txpowerdiff = + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; + + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i, + rtlefuse->txpwr_ht20diff[RF90_PATH_A][i])); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i, + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i])); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i, + rtlefuse->txpwr_ht20diff[RF90_PATH_B][i])); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i, + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i])); + + if (!autoload_fail) + rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); + else + rtlefuse->eeprom_regulatory = 0; + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory)); + + if (!autoload_fail) { + rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; + rtlefuse->eeprom_tssi[RF90_PATH_B] = hwinfo[EEPROM_TSSI_B]; + } else { + rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; + rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; + } + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("TSSI_A = 0x%x, TSSI_B = 0x%x\n", + rtlefuse->eeprom_tssi[RF90_PATH_A], + rtlefuse->eeprom_tssi[RF90_PATH_B])); + + if (!autoload_fail) + tempval = hwinfo[EEPROM_THERMAL_METER]; + else + tempval = EEPROM_DEFAULT_THERMALMETER; + rtlefuse->eeprom_thermalmeter = (tempval & 0x1f); + + if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail) + rtlefuse->b_apk_thermalmeterignore = true; + + rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter)); +} + +static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u16 i, usvalue; + u8 hwinfo[HWSET_MAX_SIZE]; + u16 eeprom_id; + + if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { + rtl_efuse_shadow_map_update(hw); + + memcpy((void *)hwinfo, + (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + HWSET_MAX_SIZE); + } else if (rtlefuse->epromtype == EEPROM_93C46) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("RTL819X Not boot from eeprom, check it !!")); + } + + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, ("MAP\n"), + hwinfo, HWSET_MAX_SIZE); + + eeprom_id = *((u16 *)&hwinfo[0]); + if (eeprom_id != RTL8190_EEPROM_ID) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("EEPROM ID(%#x) is invalid!!\n", eeprom_id)); + rtlefuse->autoload_failflag = true; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n")); + rtlefuse->autoload_failflag = false; + } + + if (rtlefuse->autoload_failflag == true) + return; + + for (i = 0; i < 6; i += 2) { + usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; + *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr))); + + _rtl92ce_read_txpower_info_from_hwpg(hw, + rtlefuse->autoload_failflag, + hwinfo); + + rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; + rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; + rtlefuse->b_txpwr_fromeprom = true; + rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID]; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid)); + + if (rtlhal->oem_id == RT_CID_DEFAULT) { + switch (rtlefuse->eeprom_oemid) { + case EEPROM_CID_DEFAULT: + if (rtlefuse->eeprom_did == 0x8176) { + if ((rtlefuse->eeprom_svid == 0x103C && + rtlefuse->eeprom_smid == 0x1629)) + rtlhal->oem_id = RT_CID_819x_HP; + else + rtlhal->oem_id = RT_CID_DEFAULT; + } else { + rtlhal->oem_id = RT_CID_DEFAULT; + } + break; + case EEPROM_CID_TOSHIBA: + rtlhal->oem_id = RT_CID_TOSHIBA; + break; + case EEPROM_CID_QMI: + rtlhal->oem_id = RT_CID_819x_QMI; + break; + case EEPROM_CID_WHQL: + default: + rtlhal->oem_id = RT_CID_DEFAULT; + break; + + } + } + +} + +static void _rtl92ce_hal_customized_behavior(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + switch (rtlhal->oem_id) { + case RT_CID_819x_HP: + pcipriv->ledctl.bled_opendrain = true; + break; + case RT_CID_819x_Lenovo: + case RT_CID_DEFAULT: + case RT_CID_TOSHIBA: + case RT_CID_CCX: + case RT_CID_819x_Acer: + case RT_CID_WHQL: + default: + break; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + ("RT Customized ID: 0x%02X\n", rtlhal->oem_id)); +} + +void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_u1b; + + rtlhal->version = _rtl92ce_read_chip_version(hw); + if (get_rf_type(rtlphy) == RF_1T1R) + rtlpriv->dm.brfpath_rxenable[0] = true; + else + rtlpriv->dm.brfpath_rxenable[0] = + rtlpriv->dm.brfpath_rxenable[1] = true; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("VersionID = 0x%4x\n", + rtlhal->version)); + tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); + if (tmp_u1b & BIT(4)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EEPROM\n")); + rtlefuse->epromtype = EEPROM_93C46; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EFUSE\n")); + rtlefuse->epromtype = EEPROM_BOOT_EFUSE; + } + if (tmp_u1b & BIT(5)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n")); + rtlefuse->autoload_failflag = false; + _rtl92ce_read_adapter_info(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Autoload ERR!!\n")); + } + + _rtl92ce_hal_customized_behavior(hw); +} + +void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + u32 ratr_value = (u32) mac->basic_rates; + u8 *p_mcsrate = mac->mcs; + u8 ratr_index = 0; + u8 b_nmode = mac->ht_enable; + u8 mimo_ps = 1; + u16 shortgi_rate; + u32 tmp_ratr_value; + u8 b_curtxbw_40mhz = mac->bw_40; + u8 b_curshortgi_40mhz = mac->sgi_40; + u8 b_curshortgi_20mhz = mac->sgi_20; + enum wireless_mode wirelessmode = mac->mode; + + ratr_value |= EF2BYTE((*(u16 *) (p_mcsrate))) << 12; + + switch (wirelessmode) { + case WIRELESS_MODE_B: + if (ratr_value & 0x0000000c) + ratr_value &= 0x0000000d; + else + ratr_value &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_value &= 0x00000FF5; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + b_nmode = 1; + if (mimo_ps == 0) { + ratr_value &= 0x0007F005; + } else { + u32 ratr_mask; + + if (get_rf_type(rtlphy) == RF_1T2R || + get_rf_type(rtlphy) == RF_1T1R) + ratr_mask = 0x000ff005; + else + ratr_mask = 0x0f0ff005; + + ratr_value &= ratr_mask; + } + break; + default: + if (rtlphy->rf_type == RF_1T2R) + ratr_value &= 0x000ff0ff; + else + ratr_value &= 0x0f0ff0ff; + + break; + } + + ratr_value &= 0x0FFFFFFF; + + if (b_nmode && ((b_curtxbw_40mhz && + b_curshortgi_40mhz) || (!b_curtxbw_40mhz && + b_curshortgi_20mhz))) { + + ratr_value |= 0x10000000; + tmp_ratr_value = (ratr_value >> 12); + + for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { + if ((1 << shortgi_rate) & tmp_ratr_value) + break; + } + + shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | + (shortgi_rate << 4) | (shortgi_rate); + } + + rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + ("%x\n", rtl_read_dword(rtlpriv, REG_ARFR0))); +} + +void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u32 ratr_bitmap = (u32) mac->basic_rates; + u8 *p_mcsrate = mac->mcs; + u8 ratr_index; + u8 b_curtxbw_40mhz = mac->bw_40; + u8 b_curshortgi_40mhz = mac->sgi_40; + u8 b_curshortgi_20mhz = mac->sgi_20; + enum wireless_mode wirelessmode = mac->mode; + bool b_shortgi = false; + u8 rate_mask[5]; + u8 macid = 0; + u8 mimops = 1; + + ratr_bitmap |= (p_mcsrate[1] << 20) | (p_mcsrate[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + ratr_index = RATR_INX_WIRELESS_B; + if (ratr_bitmap & 0x0000000c) + ratr_bitmap &= 0x0000000d; + else + ratr_bitmap &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_index = RATR_INX_WIRELESS_GB; + + if (rssi_level == 1) + ratr_bitmap &= 0x00000f00; + else if (rssi_level == 2) + ratr_bitmap &= 0x00000ff0; + else + ratr_bitmap &= 0x00000ff5; + break; + case WIRELESS_MODE_A: + ratr_index = RATR_INX_WIRELESS_A; + ratr_bitmap &= 0x00000ff0; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + ratr_index = RATR_INX_WIRELESS_NGB; + + if (mimops == 0) { + if (rssi_level == 1) + ratr_bitmap &= 0x00070000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0007f000; + else + ratr_bitmap &= 0x0007f005; + } else { + if (rtlphy->rf_type == RF_1T2R || + rtlphy->rf_type == RF_1T1R) { + if (b_curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff005; + } + } else { + if (b_curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x0f0f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f0ff000; + else + ratr_bitmap &= 0x0f0ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x0f0f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f0ff000; + else + ratr_bitmap &= 0x0f0ff005; + } + } + } + + if ((b_curtxbw_40mhz && b_curshortgi_40mhz) || + (!b_curtxbw_40mhz && b_curshortgi_20mhz)) { + + if (macid == 0) + b_shortgi = true; + else if (macid == 1) + b_shortgi = false; + } + break; + default: + ratr_index = RATR_INX_WIRELESS_NGB; + + if (rtlphy->rf_type == RF_1T2R) + ratr_bitmap &= 0x000ff0ff; + else + ratr_bitmap &= 0x0f0ff0ff; + break; + } + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + ("ratr_bitmap :%x\n", ratr_bitmap)); + *(u32 *)&rate_mask = EF4BYTE((ratr_bitmap & 0x0fffffff) | + (ratr_index << 28)); + rate_mask[4] = macid | (b_shortgi ? 0x20 : 0x00) | 0x80; + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("Rate_index:%x, " + "ratr_val:%x, %x:%x:%x:%x:%x\n", + ratr_index, ratr_bitmap, + rate_mask[0], rate_mask[1], + rate_mask[2], rate_mask[3], + rate_mask[4])); + rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); +} + +void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 sifs_timer; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, + (u8 *)&mac->slot_time); + if (!mac->ht_enable) + sifs_timer = 0x0a0a; + else + sifs_timer = 0x1010; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); +} + +bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; + u8 u1tmp; + bool b_actuallyset = false; + unsigned long flag; + + if ((rtlpci->up_first_time == 1) || (rtlpci->being_init_adapter)) + return false; + + if (ppsc->b_swrf_processing) + return false; + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + if (ppsc->rfchange_inprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + return false; + } else { + ppsc->rfchange_inprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } + + cur_rfstate = ppsc->rfpwr_state; + + if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) { + rtlpriv->intf_ops->disable_aspm(hw); + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + } + + rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv, + REG_MAC_PINMUX_CFG)&~(BIT(3))); + + u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); + e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF; + + if ((ppsc->b_hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + ("GPIOChangeRF - HW Radio ON, RF ON\n")); + + e_rfpowerstate_toset = ERFON; + ppsc->b_hwradiooff = false; + b_actuallyset = true; + } else if ((ppsc->b_hwradiooff == false) + && (e_rfpowerstate_toset == ERFOFF)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + ("GPIOChangeRF - HW Radio OFF, RF OFF\n")); + + e_rfpowerstate_toset = ERFOFF; + ppsc->b_hwradiooff = true; + b_actuallyset = true; + } + + if (b_actuallyset) { + if (e_rfpowerstate_toset == ERFON) { + if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) { + rtlpriv->intf_ops->disable_aspm(hw); + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + } + } + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + + if (e_rfpowerstate_toset == ERFOFF) { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { + rtlpriv->intf_ops->enable_aspm(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + } + } + + } else if (e_rfpowerstate_toset == ERFOFF || cur_rfstate == ERFOFF) { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { + rtlpriv->intf_ops->enable_aspm(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + } + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } else { + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } + + *valid = 1; + return !ppsc->b_hwradiooff; + +} + +void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 *macaddr = p_macaddr; + u32 entry_id = 0; + bool is_pairwise = false; + + static u8 cam_const_addr[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} + }; + static u8 cam_const_broad[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + if (clear_all) { + u8 idx = 0; + u8 cam_offset = 0; + u8 clear_number = 5; + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("clear_all\n")); + + for (idx = 0; idx < clear_number; idx++) { + rtl_cam_mark_invalid(hw, cam_offset + idx); + rtl_cam_empty_entry(hw, cam_offset + idx); + + if (idx < 5) { + memset(rtlpriv->sec.key_buf[idx], 0, + MAX_KEY_LEN); + rtlpriv->sec.key_len[idx] = 0; + } + } + + } else { + switch (enc_algo) { + case WEP40_ENCRYPTION: + enc_algo = CAM_WEP40; + break; + case WEP104_ENCRYPTION: + enc_algo = CAM_WEP104; + break; + case TKIP_ENCRYPTION: + enc_algo = CAM_TKIP; + break; + case AESCCMP_ENCRYPTION: + enc_algo = CAM_AES; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case " + "not process\n")); + enc_algo = CAM_TKIP; + break; + } + + if (is_wepkey || rtlpriv->sec.use_defaultkey) { + macaddr = cam_const_addr[key_index]; + entry_id = key_index; + } else { + if (is_group) { + macaddr = cam_const_broad; + entry_id = key_index; + } else { + key_index = PAIRWISE_KEYIDX; + entry_id = CAM_PAIRWISE_KEY_POSITION; + is_pairwise = true; + } + } + + if (rtlpriv->sec.key_len[key_index] == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("delete one entry\n")); + rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("The insert KEY length is %d\n", + rtlpriv->sec.key_len[PAIRWISE_KEYIDX])); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("The insert KEY is %x %x\n", + rtlpriv->sec.key_buf[0][0], + rtlpriv->sec.key_buf[0][1])); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("add one entry\n")); + if (is_pairwise) { + RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, + "Pairwiase Key content :", + rtlpriv->sec.pairwise_key, + rtlpriv->sec. + key_len[PAIRWISE_KEYIDX]); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("set Pairwiase key\n")); + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec. + key_buf[key_index]); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("set group key\n")); + + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_cam_add_one_entry(hw, + rtlefuse->dev_addr, + PAIRWISE_KEYIDX, + CAM_PAIRWISE_KEY_POSITION, + enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf + [entry_id]); + } + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + + } + } +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h new file mode 100644 index 000000000000..305c819c8c78 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92CE_HW_H__ +#define __RTL92CE_HW_H__ + +void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw); +void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb); +int rtl92ce_hw_init(struct ieee80211_hw *hw); +void rtl92ce_card_disable(struct ieee80211_hw *hw); +void rtl92ce_enable_interrupt(struct ieee80211_hw *hw); +void rtl92ce_disable_interrupt(struct ieee80211_hw *hw); +int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); +void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci); +void rtl92ce_set_beacon_related_registers(struct ieee80211_hw *hw); +void rtl92ce_set_beacon_interval(struct ieee80211_hw *hw); +void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr); +void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw); +void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level); +void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw); +bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); +void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw); +void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all); + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c new file mode 100644 index 000000000000..78a0569208ea --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c @@ -0,0 +1,144 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "reg.h" +#include "led.h" + +void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + u8 ledcfg; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + ("LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin)); + + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + rtl_write_byte(rtlpriv, + REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6)); + break; + case LED_PIN_LED1: + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + pled->b_ledon = true; +} + +void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + u8 ledcfg; + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + ("LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin)); + + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg &= 0xf0; + if (pcipriv->ledctl.bled_opendrain == true) + rtl_write_byte(rtlpriv, REG_LEDCFG2, + (ledcfg | BIT(1) | BIT(5) | BIT(6))); + else + rtl_write_byte(rtlpriv, REG_LEDCFG2, + (ledcfg | BIT(3) | BIT(5) | BIT(6))); + break; + case LED_PIN_LED1: + ledcfg &= 0x0f; + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3))); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + pled->b_ledon = false; +} + +void rtl92ce_init_sw_leds(struct ieee80211_hw *hw) +{ +} + +void rtl92ce_deinit_sw_leds(struct ieee80211_hw *hw) +{ +} + +void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + switch (ledaction) { + case LED_CTL_POWER_ON: + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + rtl92ce_sw_led_on(hw, pLed0); + break; + case LED_CTL_POWER_OFF: + rtl92ce_sw_led_off(hw, pLed0); + break; + default: + break; + } +} + +void rtl92ce_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && + (ledaction == LED_CTL_TX || + ledaction == LED_CTL_RX || + ledaction == LED_CTL_SITE_SURVEY || + ledaction == LED_CTL_LINK || + ledaction == LED_CTL_NO_LINK || + ledaction == LED_CTL_START_TO_LINK || + ledaction == LED_CTL_POWER_ON)) { + return; + } + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n", + ledaction)); + _rtl92ce_sw_led_control(hw, ledaction); +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/rtlwifi/rtl8192ce/led.h new file mode 100644 index 000000000000..10da3018f4b7 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.h @@ -0,0 +1,41 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92CE_LED_H__ +#define __RTL92CE_LED_H__ + +void rtl92ce_init_sw_leds(struct ieee80211_hw *hw); +void rtl92ce_deinit_sw_leds(struct ieee80211_hw *hw); +void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92ce_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); +void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction); + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c new file mode 100644 index 000000000000..45044117139a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c @@ -0,0 +1,2676 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../ps.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" +#include "table.h" + +static u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset); +static void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data); +static u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset); +static void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data); +static u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask); +static bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); +static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); +static bool _rtl92c_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype); +static bool _rtl92c_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype); +static void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); +static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, + enum swchnlcmd_id cmdid, u32 para1, + u32 para2, u32 msdelay); +static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay); +static u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + long power_indbm); +static bool _rtl92c_phy_config_rf_external_pa(struct ieee80211_hw *hw, + enum radio_path rfpath); +static long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u8 txpwridx); +u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 returnvalue, originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), " + "bitmask(%#x)\n", regaddr, + bitmask)); + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); + returnvalue = (originalvalue & bitmask) >> bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("BBR MASK=0x%x " + "Addr[0x%x]=0x%x\n", bitmask, + regaddr, originalvalue)); + + return returnvalue; + +} + +void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," + " data(%#x)\n", regaddr, bitmask, + data)); + + if (bitmask != MASKDWORD) { + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); + data = ((originalvalue & (~bitmask)) | (data << bitshift)); + } + + rtl_write_dword(rtlpriv, regaddr, data); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," + " data(%#x)\n", regaddr, bitmask, + data)); + +} + +u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, readback_value, bitshift; + struct rtl_phy *rtlphy = &(rtlpriv->phy); + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), " + "rfpath(%#x), bitmask(%#x)\n", + regaddr, rfpath, bitmask)); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + if (rtlphy->rf_mode != RF_OP_BY_FW) { + original_value = _rtl92c_phy_rf_serial_read(hw, + rfpath, regaddr); + } else { + original_value = _rtl92c_phy_fw_rf_serial_read(hw, + rfpath, regaddr); + } + + bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); + readback_value = (original_value & bitmask) >> bitshift; + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + ("regaddr(%#x), rfpath(%#x), " + "bitmask(%#x), original_value(%#x)\n", + regaddr, rfpath, bitmask, original_value)); + + return readback_value; +} + +void rtl92c_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 original_value, bitshift; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + ("regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath)); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + if (rtlphy->rf_mode != RF_OP_BY_FW) { + if (bitmask != RFREG_OFFSET_MASK) { + original_value = _rtl92c_phy_rf_serial_read(hw, + rfpath, + regaddr); + bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); + data = + ((original_value & (~bitmask)) | + (data << bitshift)); + } + + _rtl92c_phy_rf_serial_write(hw, rfpath, regaddr, data); + } else { + if (bitmask != RFREG_OFFSET_MASK) { + original_value = _rtl92c_phy_fw_rf_serial_read(hw, + rfpath, + regaddr); + bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); + data = + ((original_value & (~bitmask)) | + (data << bitshift)); + } + _rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data); + } + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), " + "bitmask(%#x), data(%#x), " + "rfpath(%#x)\n", regaddr, + bitmask, data, rfpath)); +} + +static u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset) +{ + RT_ASSERT(false, ("deprecated!\n")); + return 0; +} + +static void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data) +{ + RT_ASSERT(false, ("deprecated!\n")); +} + +static u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + u32 newoffset; + u32 tmplong, tmplong2; + u8 rfpi_enable = 0; + u32 retvalue; + + offset &= 0x3f; + newoffset = offset; + if (RT_CANNOT_IO(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("return all one\n")); + return 0xFFFFFFFF; + } + tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); + if (rfpath == RF90_PATH_A) + tmplong2 = tmplong; + else + tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); + tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | + (newoffset << 23) | BLSSIREADEDGE; + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, + tmplong & (~BLSSIREADEDGE)); + mdelay(1); + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); + mdelay(1); + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, + tmplong | BLSSIREADEDGE); + mdelay(1); + if (rfpath == RF90_PATH_A) + rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, + BIT(8)); + else if (rfpath == RF90_PATH_B) + rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, + BIT(8)); + if (rfpi_enable) + retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi, + BLSSIREADBACKDATA); + else + retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback, + BLSSIREADBACKDATA); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFR-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rflssi_readback, + retvalue)); + return retvalue; +} + +static void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data) +{ + u32 data_and_addr; + u32 newoffset; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + + if (RT_CANNOT_IO(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("stop\n")); + return; + } + offset &= 0x3f; + newoffset = offset; + data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; + rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFW-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rf3wire_offset, + data_and_addr)); +} + +static u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask) +{ + u32 i; + + for (i = 0; i <= 31; i++) { + if (((bitmask >> i) & 0x1) == 1) + break; + } + return i; +} + +static void _rtl92c_phy_bb_config_1t(struct ieee80211_hw *hw) +{ + rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2); + rtl_set_bbreg(hw, RFPGA1_TXINFO, 0x300033, 0x200022); + rtl_set_bbreg(hw, RCCK0_AFESETTING, MASKBYTE3, 0x45); + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23); + rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, 0x30, 0x1); + rtl_set_bbreg(hw, 0xe74, 0x0c000000, 0x2); + rtl_set_bbreg(hw, 0xe78, 0x0c000000, 0x2); + rtl_set_bbreg(hw, 0xe7c, 0x0c000000, 0x2); + rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2); + rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2); +} + +bool rtl92c_phy_mac_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool is92c = IS_92C_SERIAL(rtlhal->version); + bool rtstatus = _rtl92c_phy_config_mac_with_headerfile(hw); + + if (is92c) + rtl_write_byte(rtlpriv, 0x14, 0x71); + return rtstatus; +} + +bool rtl92c_phy_bb_config(struct ieee80211_hw *hw) +{ + bool rtstatus = true; + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 regval; + u32 regvaldw; + u8 b_reg_hwparafile = 1; + + _rtl92c_phy_init_bb_rf_register_definition(hw); + regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, + regval | BIT(13) | BIT(0) | BIT(1)); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); + rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, + FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | + FEN_BB_GLB_RSTn | FEN_BBRSTB); + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); + regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); + rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); + if (b_reg_hwparafile == 1) + rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); + return rtstatus; +} + +bool rtl92c_phy_rf_config(struct ieee80211_hw *hw) +{ + return rtl92c_phy_rf6052_config(hw); +} + +static bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + bool rtstatus; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("==>\n")); + rtstatus = _rtl92c_phy_config_bb_with_headerfile(hw, + BASEBAND_CONFIG_PHY_REG); + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Write BB Reg Fail!!")); + return false; + } + if (rtlphy->rf_type == RF_1T2R) { + _rtl92c_phy_bb_config_1t(hw); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Config to 1T!!\n")); + } + if (rtlefuse->autoload_failflag == false) { + rtlphy->pwrgroup_cnt = 0; + rtstatus = _rtl92c_phy_config_bb_with_pgheaderfile(hw, + BASEBAND_CONFIG_PHY_REG); + } + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("BB_PG Reg Fail!!")); + return false; + } + rtstatus = _rtl92c_phy_config_bb_with_headerfile(hw, + BASEBAND_CONFIG_AGC_TAB); + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("AGC Table Fail\n")); + return false; + } + rtlphy->bcck_high_power = (bool) (rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + 0x200)); + return true; +} + +static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + u32 arraylength; + u32 *ptrarray; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Read Rtl819XMACPHY_Array\n")); + arraylength = MAC_2T_ARRAYLENGTH; + ptrarray = RTL8192CEMAC_2T_ARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Img:RTL8192CEMAC_2T_ARRAY\n")); + for (i = 0; i < arraylength; i = i + 2) + rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); + return true; +} + +void rtl92c_phy_config_bb_external_pa(struct ieee80211_hw *hw) +{ +} + +static bool _rtl92c_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype) +{ + int i; + u32 *phy_regarray_table; + u32 *agctab_array_table; + u16 phy_reg_arraylen, agctab_arraylen; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (IS_92C_SERIAL(rtlhal->version)) { + agctab_arraylen = AGCTAB_2TARRAYLENGTH; + agctab_array_table = RTL8192CEAGCTAB_2TARRAY; + phy_reg_arraylen = PHY_REG_2TARRAY_LENGTH; + phy_regarray_table = RTL8192CEPHY_REG_2TARRAY; + } else { + agctab_arraylen = AGCTAB_1TARRAYLENGTH; + agctab_array_table = RTL8192CEAGCTAB_1TARRAY; + phy_reg_arraylen = PHY_REG_1TARRAY_LENGTH; + phy_regarray_table = RTL8192CEPHY_REG_1TARRAY; + } + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_reg_arraylen; i = i + 2) { + if (phy_regarray_table[i] == 0xfe) + mdelay(50); + else if (phy_regarray_table[i] == 0xfd) + mdelay(5); + else if (phy_regarray_table[i] == 0xfc) + mdelay(1); + else if (phy_regarray_table[i] == 0xfb) + udelay(50); + else if (phy_regarray_table[i] == 0xfa) + udelay(5); + else if (phy_regarray_table[i] == 0xf9) + udelay(1); + rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD, + phy_regarray_table[i + 1]); + udelay(1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("The phy_regarray_table[0] is %x" + " Rtl819XPHY_REGArray[1] is %x\n", + phy_regarray_table[i], + phy_regarray_table[i + 1])); + } + rtl92c_phy_config_bb_external_pa(hw); + } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { + for (i = 0; i < agctab_arraylen; i = i + 2) { + rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD, + agctab_array_table[i + 1]); + udelay(1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("The agctab_array_table[0] is " + "%x Rtl819XPHY_REGArray[1] is %x\n", + agctab_array_table[i], + agctab_array_table[i + 1])); + } + } + return true; +} + +static void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, + u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + if (regaddr == RTXAGC_A_RATE18_06) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][0])); + } + if (regaddr == RTXAGC_A_RATE54_24) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][1])); + } + if (regaddr == RTXAGC_A_CCK1_MCS32) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][6])); + } + if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][7])); + } + if (regaddr == RTXAGC_A_MCS03_MCS00) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][2])); + } + if (regaddr == RTXAGC_A_MCS07_MCS04) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][3])); + } + if (regaddr == RTXAGC_A_MCS11_MCS08) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][4])); + } + if (regaddr == RTXAGC_A_MCS15_MCS12) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][5])); + } + if (regaddr == RTXAGC_B_RATE18_06) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][8])); + } + if (regaddr == RTXAGC_B_RATE54_24) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] = + data; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][9])); + } + + if (regaddr == RTXAGC_B_CCK1_55_MCS32) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] = + data; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][14])); + } + + if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] = + data; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][15])); + } + + if (regaddr == RTXAGC_B_MCS03_MCS00) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] = + data; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][10])); + } + + if (regaddr == RTXAGC_B_MCS07_MCS04) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] = + data; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][11])); + } + + if (regaddr == RTXAGC_B_MCS11_MCS08) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] = + data; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][12])); + } + + if (regaddr == RTXAGC_B_MCS15_MCS12) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] = + data; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][13])); + + rtlphy->pwrgroup_cnt++; + } +} + +static bool _rtl92c_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int i; + u32 *phy_regarray_table_pg; + u16 phy_regarray_pg_len; + + phy_regarray_pg_len = PHY_REG_ARRAY_PGLENGTH; + phy_regarray_table_pg = RTL8192CEPHY_REG_ARRAY_PG; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_regarray_pg_len; i = i + 3) { + if (phy_regarray_table_pg[i] == 0xfe) + mdelay(50); + else if (phy_regarray_table_pg[i] == 0xfd) + mdelay(5); + else if (phy_regarray_table_pg[i] == 0xfc) + mdelay(1); + else if (phy_regarray_table_pg[i] == 0xfb) + udelay(50); + else if (phy_regarray_table_pg[i] == 0xfa) + udelay(5); + else if (phy_regarray_table_pg[i] == 0xf9) + udelay(1); + + _rtl92c_store_pwrIndex_diffrate_offset(hw, + phy_regarray_table_pg[i], + phy_regarray_table_pg[i + 1], + phy_regarray_table_pg[i + 2]); + } + } else { + + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + ("configtype != BaseBand_Config_PHY_REG\n")); + } + return true; +} + +static bool _rtl92c_phy_config_rf_external_pa(struct ieee80211_hw *hw, + enum radio_path rfpath) +{ + return true; +} + +bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath) +{ + + int i; + bool rtstatus = true; + u32 *radioa_array_table; + u32 *radiob_array_table; + u16 radioa_arraylen, radiob_arraylen; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (IS_92C_SERIAL(rtlhal->version)) { + radioa_arraylen = RADIOA_2TARRAYLENGTH; + radioa_array_table = RTL8192CERADIOA_2TARRAY; + radiob_arraylen = RADIOB_2TARRAYLENGTH; + radiob_array_table = RTL8192CE_RADIOB_2TARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Radio_A:RTL8192CERADIOA_2TARRAY\n")); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Radio_B:RTL8192CE_RADIOB_2TARRAY\n")); + } else { + radioa_arraylen = RADIOA_1TARRAYLENGTH; + radioa_array_table = RTL8192CE_RADIOA_1TARRAY; + radiob_arraylen = RADIOB_1TARRAYLENGTH; + radiob_array_table = RTL8192CE_RADIOB_1TARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Radio_A:RTL8192CE_RADIOA_1TARRAY\n")); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Radio_B:RTL8192CE_RADIOB_1TARRAY\n")); + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Radio No %x\n", rfpath)); + rtstatus = true; + switch (rfpath) { + case RF90_PATH_A: + for (i = 0; i < radioa_arraylen; i = i + 2) { + if (radioa_array_table[i] == 0xfe) + mdelay(50); + else if (radioa_array_table[i] == 0xfd) + mdelay(5); + else if (radioa_array_table[i] == 0xfc) + mdelay(1); + else if (radioa_array_table[i] == 0xfb) + udelay(50); + else if (radioa_array_table[i] == 0xfa) + udelay(5); + else if (radioa_array_table[i] == 0xf9) + udelay(1); + else { + rtl_set_rfreg(hw, rfpath, radioa_array_table[i], + RFREG_OFFSET_MASK, + radioa_array_table[i + 1]); + udelay(1); + } + } + _rtl92c_phy_config_rf_external_pa(hw, rfpath); + break; + case RF90_PATH_B: + for (i = 0; i < radiob_arraylen; i = i + 2) { + if (radiob_array_table[i] == 0xfe) { + mdelay(50); + } else if (radiob_array_table[i] == 0xfd) + mdelay(5); + else if (radiob_array_table[i] == 0xfc) + mdelay(1); + else if (radiob_array_table[i] == 0xfb) + udelay(50); + else if (radiob_array_table[i] == 0xfa) + udelay(5); + else if (radiob_array_table[i] == 0xf9) + udelay(1); + else { + rtl_set_rfreg(hw, rfpath, radiob_array_table[i], + RFREG_OFFSET_MASK, + radiob_array_table[i + 1]); + udelay(1); + } + } + break; + case RF90_PATH_C: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + case RF90_PATH_D: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + return true; +} + +void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + rtlphy->default_initialgain[0] = + (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[1] = + (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[2] = + (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[3] = + (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Default initial gain (c50=0x%x, " + "c58=0x%x, c60=0x%x, c68=0x%x\n", + rtlphy->default_initialgain[0], + rtlphy->default_initialgain[1], + rtlphy->default_initialgain[2], + rtlphy->default_initialgain[3])); + + rtlphy->framesync = (u8) rtl_get_bbreg(hw, + ROFDM0_RXDETECTOR3, MASKBYTE0); + rtlphy->framesync_c34 = rtl_get_bbreg(hw, + ROFDM0_RXDETECTOR2, MASKDWORD); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Default framesync (0x%x) = 0x%x\n", + ROFDM0_RXDETECTOR3, rtlphy->framesync)); +} + +static void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; + + rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = + RFPGA0_XA_LSSIPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = + RFPGA0_XB_LSSIPARAMETER; + + rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = rFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = rFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER; + + rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; + + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; + + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; + + rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control = + RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control = + RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control = + RFPGA0_XCD_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control = + RFPGA0_XCD_SWITCHCONTROL; + + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; + + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; + + rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance = + ROFDM0_XARXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance = + ROFDM0_XBRXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance = + ROFDM0_XCRXIQIMBANLANCE; + rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance = + ROFDM0_XDRXIQIMBALANCE; + + rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; + rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; + rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; + + rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance = + ROFDM0_XATXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance = + ROFDM0_XBTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance = + ROFDM0_XCTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance = + ROFDM0_XDTXIQIMBALANCE; + + rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; + rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE; + rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE; + + rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback = + RFPGA0_XA_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback = + RFPGA0_XB_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback = + RFPGA0_XC_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback = + RFPGA0_XD_LSSIREADBACK; + + rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi = + TRANSCEIVEA_HSPI_READBACK; + rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi = + TRANSCEIVEB_HSPI_READBACK; + +} + +void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 txpwr_level; + long txpwr_dbm; + + txpwr_level = rtlphy->cur_cck_txpwridx; + txpwr_dbm = _rtl92c_phy_txpwr_idx_to_dbm(hw, + WIRELESS_MODE_B, txpwr_level); + txpwr_level = rtlphy->cur_ofdm24g_txpwridx + + rtlefuse->legacy_ht_txpowerdiff; + if (_rtl92c_phy_txpwr_idx_to_dbm(hw, + WIRELESS_MODE_G, + txpwr_level) > txpwr_dbm) + txpwr_dbm = + _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, + txpwr_level); + txpwr_level = rtlphy->cur_ofdm24g_txpwridx; + if (_rtl92c_phy_txpwr_idx_to_dbm(hw, + WIRELESS_MODE_N_24G, + txpwr_level) > txpwr_dbm) + txpwr_dbm = + _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, + txpwr_level); + *powerlevel = txpwr_dbm; +} + +static void _rtl92c_get_txpower_index(struct ieee80211_hw *hw, u8 channel, + u8 *cckpowerlevel, u8 *ofdmpowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 index = (channel - 1); + + cckpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_cck[RF90_PATH_A][index]; + cckpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_cck[RF90_PATH_B][index]; + if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_1T1R) { + ofdmpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index]; + ofdmpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index]; + } else if (get_rf_type(rtlphy) == RF_2T2R) { + ofdmpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index]; + ofdmpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index]; + } +} + +static void _rtl92c_ccxpower_index_check(struct ieee80211_hw *hw, + u8 channel, u8 *cckpowerlevel, + u8 *ofdmpowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; + rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; +} + +void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 cckpowerlevel[2], ofdmpowerlevel[2]; + + if (rtlefuse->b_txpwr_fromeprom == false) + return; + _rtl92c_get_txpower_index(hw, channel, + &cckpowerlevel[0], &ofdmpowerlevel[0]); + _rtl92c_ccxpower_index_check(hw, + channel, &cckpowerlevel[0], + &ofdmpowerlevel[0]); + rtl92c_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]); + rtl92c_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel); +} + +bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 idx; + u8 rf_path; + + u8 ccktxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw, + WIRELESS_MODE_B, + power_indbm); + u8 ofdmtxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw, + WIRELESS_MODE_N_24G, + power_indbm); + if (ofdmtxpwridx - rtlefuse->legacy_ht_txpowerdiff > 0) + ofdmtxpwridx -= rtlefuse->legacy_ht_txpowerdiff; + else + ofdmtxpwridx = 0; + RT_TRACE(rtlpriv, COMP_TXAGC, DBG_TRACE, + ("%lx dBm, ccktxpwridx = %d, ofdmtxpwridx = %d\n", + power_indbm, ccktxpwridx, ofdmtxpwridx)); + for (idx = 0; idx < 14; idx++) { + for (rf_path = 0; rf_path < 2; rf_path++) { + rtlefuse->txpwrlevel_cck[rf_path][idx] = ccktxpwridx; + rtlefuse->txpwrlevel_ht40_1s[rf_path][idx] = + ofdmtxpwridx; + rtlefuse->txpwrlevel_ht40_2s[rf_path][idx] = + ofdmtxpwridx; + } + } + rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); + return true; +} + +void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval) +{ +} + +static u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + long power_indbm) +{ + u8 txpwridx; + long offset; + + switch (wirelessmode) { + case WIRELESS_MODE_B: + offset = -7; + break; + case WIRELESS_MODE_G: + case WIRELESS_MODE_N_24G: + offset = -8; + break; + default: + offset = -8; + break; + } + + if ((power_indbm - offset) > 0) + txpwridx = (u8) ((power_indbm - offset) * 2); + else + txpwridx = 0; + + if (txpwridx > MAX_TXPWR_IDX_NMODE_92S) + txpwridx = MAX_TXPWR_IDX_NMODE_92S; + + return txpwridx; +} + +static long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u8 txpwridx) +{ + long offset; + long pwrout_dbm; + + switch (wirelessmode) { + case WIRELESS_MODE_B: + offset = -7; + break; + case WIRELESS_MODE_G: + case WIRELESS_MODE_N_24G: + offset = -8; + break; + default: + offset = -8; + break; + } + pwrout_dbm = txpwridx / 2 + offset; + return pwrout_dbm; +} + +void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + enum io_type iotype; + + if (!is_hal_stop(rtlhal)) { + switch (operation) { + case SCAN_OPT_BACKUP: + iotype = IO_CMD_PAUSE_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_IO_CMD, + (u8 *)&iotype); + + break; + case SCAN_OPT_RESTORE: + iotype = IO_CMD_RESUME_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_IO_CMD, + (u8 *)&iotype); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Unknown Scan Backup operation.\n")); + break; + } + } +} + +void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 reg_bw_opmode; + u8 reg_prsr_rsc; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + ("Switch to %s bandwidth\n", + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : "40MHz")) + + if (is_hal_stop(rtlhal)) + return; + + reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); + reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + reg_bw_opmode |= BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + break; + + case HT_CHANNEL_WIDTH_20_40: + reg_bw_opmode &= ~BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + + reg_prsr_rsc = + (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); + break; + + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); + break; + } + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, + (mac->cur_40_prime_sc >> 1)); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); + rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), + (mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); + break; + } + rtl92c_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); +} + +void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_bw = rtlphy->current_chan_bw; + + if (rtlphy->set_bwmode_inprogress) + return; + rtlphy->set_bwmode_inprogress = true; + if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) + rtl92c_phy_set_bw_mode_callback(hw); + else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("FALSE driver sleep or unload\n")); + rtlphy->set_bwmode_inprogress = false; + rtlphy->current_chan_bw = tmp_bw; + } +} + +void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 delay; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + ("switch to channel%d\n", rtlphy->current_channel)); + if (is_hal_stop(rtlhal)) + return; + do { + if (!rtlphy->sw_chnl_inprogress) + break; + if (!_rtl92c_phy_sw_chnl_step_by_step + (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage, + &rtlphy->sw_chnl_step, &delay)) { + if (delay > 0) + mdelay(delay); + else + continue; + } else + rtlphy->sw_chnl_inprogress = false; + break; + } while (true); + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); +} + +u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlphy->sw_chnl_inprogress) + return 0; + if (rtlphy->set_bwmode_inprogress) + return 0; + RT_ASSERT((rtlphy->current_channel <= 14), + ("WIRELESS_MODE_G but channel>14")); + rtlphy->sw_chnl_inprogress = true; + rtlphy->sw_chnl_stage = 0; + rtlphy->sw_chnl_step = 0; + if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtl92c_phy_sw_chnl_callback(hw); + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + ("sw_chnl_inprogress false schdule workitem\n")); + rtlphy->sw_chnl_inprogress = false; + } else { + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + ("sw_chnl_inprogress false driver sleep or" + " unload\n")); + rtlphy->sw_chnl_inprogress = false; + } + return 1; +} + +static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; + u32 precommoncmdcnt; + struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; + u32 postcommoncmdcnt; + struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; + u32 rfdependcmdcnt; + struct swchnlcmd *currentcmd = NULL; + u8 rfpath; + u8 num_total_rfpath = rtlphy->num_total_rfpath; + + precommoncmdcnt = 0; + _rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, + CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); + _rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); + + postcommoncmdcnt = 0; + + _rtl92c_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, + MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); + + rfdependcmdcnt = 0; + + RT_ASSERT((channel >= 1 && channel <= 14), + ("illegal channel for Zebra: %d\n", channel)); + + _rtl92c_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, + RF_CHNLBW, channel, 10); + + _rtl92c_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, + 0); + + do { + switch (*stage) { + case 0: + currentcmd = &precommoncmd[*step]; + break; + case 1: + currentcmd = &rfdependcmd[*step]; + break; + case 2: + currentcmd = &postcommoncmd[*step]; + break; + } + + if (currentcmd->cmdid == CMDID_END) { + if ((*stage) == 2) { + return true; + } else { + (*stage)++; + (*step) = 0; + continue; + } + } + + switch (currentcmd->cmdid) { + case CMDID_SET_TXPOWEROWER_LEVEL: + rtl92c_phy_set_txpower_level(hw, channel); + break; + case CMDID_WRITEPORT_ULONG: + rtl_write_dword(rtlpriv, currentcmd->para1, + currentcmd->para2); + break; + case CMDID_WRITEPORT_USHORT: + rtl_write_word(rtlpriv, currentcmd->para1, + (u16) currentcmd->para2); + break; + case CMDID_WRITEPORT_UCHAR: + rtl_write_byte(rtlpriv, currentcmd->para1, + (u8) currentcmd->para2); + break; + case CMDID_RF_WRITEREG: + for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { + rtlphy->rfreg_chnlval[rfpath] = + ((rtlphy->rfreg_chnlval[rfpath] & + 0xfffffc00) | currentcmd->para2); + + rtl_set_rfreg(hw, (enum radio_path)rfpath, + currentcmd->para1, + RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[rfpath]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + + break; + } while (true); + + (*delay) = currentcmd->msdelay; + (*step)++; + return false; +} + +static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, + enum swchnlcmd_id cmdid, + u32 para1, u32 para2, u32 msdelay) +{ + struct swchnlcmd *pcmd; + + if (cmdtable == NULL) { + RT_ASSERT(false, ("cmdtable cannot be NULL.\n")); + return false; + } + + if (cmdtableidx >= cmdtablesz) + return false; + + pcmd = cmdtable + cmdtableidx; + pcmd->cmdid = cmdid; + pcmd->para1 = para1; + pcmd->para2 = para2; + pcmd->msdelay = msdelay; + return true; +} + +bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath) +{ + return true; +} + +static u8 _rtl92c_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb) +{ + u32 reg_eac, reg_e94, reg_e9c, reg_ea4; + u8 result = 0x00; + + rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f); + rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f); + rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102); + rtl_set_bbreg(hw, 0xe3c, MASKDWORD, + config_pathb ? 0x28160202 : 0x28160502); + + if (config_pathb) { + rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22); + rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22); + rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102); + rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160202); + } + + rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x001028d1); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); + reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); + reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && + (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else + return result; + + if (!(reg_eac & BIT(27)) && + (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_eac & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + return result; +} + +static u8 _rtl92c_phy_path_b_iqk(struct ieee80211_hw *hw) +{ + u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; + u8 result = 0x00; + + rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002); + rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000); + mdelay(IQK_DELAY_TIME); + reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); + reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); + reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); + reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); + if (!(reg_eac & BIT(31)) && + (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && + (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else + return result; + + if (!(reg_eac & BIT(30)) && + (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + return result; +} + +static void _rtl92c_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, + bool b_iqk_ok, long result[][8], + u8 final_candidate, bool btxonly) +{ + u32 oldval_0, x, tx0_a, reg; + long y, tx0_c; + + if (final_candidate == 0xFF) + return; + else if (b_iqk_ok) { + oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD) >> 22) & 0x3FF; + x = result[final_candidate][0]; + if ((x & 0x00000200) != 0) + x = x | 0xFFFFFC00; + tx0_a = (x * oldval_0) >> 8; + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31), + ((x * oldval_0 >> 7) & 0x1)); + y = result[final_candidate][1]; + if ((y & 0x00000200) != 0) + y = y | 0xFFFFFC00; + tx0_c = (y * oldval_0) >> 8; + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, + ((tx0_c & 0x3C0) >> 6)); + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000, + (tx0_c & 0x3F)); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29), + ((y * oldval_0 >> 7) & 0x1)); + if (btxonly) + return; + reg = result[final_candidate][2]; + rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg); + reg = result[final_candidate][3] & 0x3F; + rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg); + reg = (result[final_candidate][3] >> 6) & 0xF; + rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); + } +} + +static void _rtl92c_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw, + bool b_iqk_ok, long result[][8], + u8 final_candidate, bool btxonly) +{ + u32 oldval_1, x, tx1_a, reg; + long y, tx1_c; + + if (final_candidate == 0xFF) + return; + else if (b_iqk_ok) { + oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, + MASKDWORD) >> 22) & 0x3FF; + x = result[final_candidate][4]; + if ((x & 0x00000200) != 0) + x = x | 0xFFFFFC00; + tx1_a = (x * oldval_1) >> 8; + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x3FF, tx1_a); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(27), + ((x * oldval_1 >> 7) & 0x1)); + y = result[final_candidate][5]; + if ((y & 0x00000200) != 0) + y = y | 0xFFFFFC00; + tx1_c = (y * oldval_1) >> 8; + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000, + ((tx1_c & 0x3C0) >> 6)); + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000, + (tx1_c & 0x3F)); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(25), + ((y * oldval_1 >> 7) & 0x1)); + if (btxonly) + return; + reg = result[final_candidate][6]; + rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg); + reg = result[final_candidate][7] & 0x3F; + rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg); + reg = (result[final_candidate][7] >> 6) & 0xF; + rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, reg); + } +} + +static void _rtl92c_phy_save_adda_registers(struct ieee80211_hw *hw, + u32 *addareg, u32 *addabackup, + u32 registernum) +{ + u32 i; + + for (i = 0; i < registernum; i++) + addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD); +} + +static void _rtl92c_phy_save_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) + macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); + macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); +} + +static void _rtl92c_phy_reload_adda_registers(struct ieee80211_hw *hw, + u32 *addareg, u32 *addabackup, + u32 regiesternum) +{ + u32 i; + + for (i = 0; i < regiesternum; i++) + rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]); +} + +static void _rtl92c_phy_reload_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) + rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]); + rtl_write_dword(rtlpriv, macreg[i], macbackup[i]); +} + +static void _rtl92c_phy_path_adda_on(struct ieee80211_hw *hw, + u32 *addareg, bool is_patha_on, bool is2t) +{ + u32 pathOn; + u32 i; + + pathOn = is_patha_on ? 0x04db25a4 : 0x0b1b25a4; + if (false == is2t) { + pathOn = 0x0bdb25a0; + rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0); + } else { + rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathOn); + } + + for (i = 1; i < IQK_ADDA_REG_NUM; i++) + rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathOn); +} + +static void _rtl92c_phy_mac_setting_calibration(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + rtl_write_byte(rtlpriv, macreg[0], 0x3F); + + for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) + rtl_write_byte(rtlpriv, macreg[i], + (u8) (macbackup[i] & (~BIT(3)))); + rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5)))); +} + +static void _rtl92c_phy_path_a_standby(struct ieee80211_hw *hw) +{ + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0); + rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); +} + +static void _rtl92c_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode) +{ + u32 mode; + + mode = pi_mode ? 0x01000100 : 0x01000000; + rtl_set_bbreg(hw, 0x820, MASKDWORD, mode); + rtl_set_bbreg(hw, 0x828, MASKDWORD, mode); +} + +static bool _rtl92c_phy_simularity_compare(struct ieee80211_hw *hw, + long result[][8], u8 c1, u8 c2) +{ + u32 i, j, diff, simularity_bitmap, bound; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + u8 final_candidate[2] = { 0xFF, 0xFF }; + bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version); + + if (is2t) + bound = 8; + else + bound = 4; + + simularity_bitmap = 0; + + for (i = 0; i < bound; i++) { + diff = (result[c1][i] > result[c2][i]) ? + (result[c1][i] - result[c2][i]) : + (result[c2][i] - result[c1][i]); + + if (diff > MAX_TOLERANCE) { + if ((i == 2 || i == 6) && !simularity_bitmap) { + if (result[c1][i] + result[c1][i + 1] == 0) + final_candidate[(i / 4)] = c2; + else if (result[c2][i] + result[c2][i + 1] == 0) + final_candidate[(i / 4)] = c1; + else + simularity_bitmap = simularity_bitmap | + (1 << i); + } else + simularity_bitmap = + simularity_bitmap | (1 << i); + } + } + + if (simularity_bitmap == 0) { + for (i = 0; i < (bound / 4); i++) { + if (final_candidate[i] != 0xFF) { + for (j = i * 4; j < (i + 1) * 4 - 2; j++) + result[3][j] = + result[final_candidate[i]][j]; + bresult = false; + } + } + return bresult; + } else if (!(simularity_bitmap & 0x0F)) { + for (i = 0; i < 4; i++) + result[3][i] = result[c1][i]; + return false; + } else if (!(simularity_bitmap & 0xF0) && is2t) { + for (i = 4; i < 8; i++) + result[3][i] = result[c1][i]; + return false; + } else { + return false; + } + +} + +static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, + long result[][8], u8 t, bool is2t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 i; + u8 patha_ok, pathb_ok; + u32 adda_reg[IQK_ADDA_REG_NUM] = { + 0x85c, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xeec + }; + + u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { + 0x522, 0x550, 0x551, 0x040 + }; + + const u32 retrycount = 2; + + u32 bbvalue; + + if (t == 0) { + bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD); + + _rtl92c_phy_save_adda_registers(hw, adda_reg, + rtlphy->adda_backup, 16); + _rtl92c_phy_save_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + } + _rtl92c_phy_path_adda_on(hw, adda_reg, true, is2t); + if (t == 0) { + rtlphy->b_rfpi_enable = (u8) rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER1, + BIT(8)); + } + if (!rtlphy->b_rfpi_enable) + _rtl92c_phy_pi_mode_switch(hw, true); + if (t == 0) { + rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD); + rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD); + rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD); + } + rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); + rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); + rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); + if (is2t) { + rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); + rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000); + } + _rtl92c_phy_mac_setting_calibration(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x00080000); + if (is2t) + rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x00080000); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); + rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800); + for (i = 0; i < retrycount; i++) { + patha_ok = _rtl92c_phy_path_a_iqk(hw, is2t); + if (patha_ok == 0x03) { + result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & + 0x3FF0000) >> 16; + break; + } else if (i == (retrycount - 1) && patha_ok == 0x01) + result[t][0] = (rtl_get_bbreg(hw, 0xe94, + MASKDWORD) & 0x3FF0000) >> + 16; + result[t][1] = + (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16; + + } + + if (is2t) { + _rtl92c_phy_path_a_standby(hw); + _rtl92c_phy_path_adda_on(hw, adda_reg, false, is2t); + for (i = 0; i < retrycount; i++) { + pathb_ok = _rtl92c_phy_path_b_iqk(hw); + if (pathb_ok == 0x03) { + result[t][4] = (rtl_get_bbreg(hw, + 0xeb4, + MASKDWORD) & + 0x3FF0000) >> 16; + result[t][5] = + (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][6] = + (rtl_get_bbreg(hw, 0xec4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][7] = + (rtl_get_bbreg(hw, 0xecc, MASKDWORD) & + 0x3FF0000) >> 16; + break; + } else if (i == (retrycount - 1) && pathb_ok == 0x01) { + result[t][4] = (rtl_get_bbreg(hw, + 0xeb4, + MASKDWORD) & + 0x3FF0000) >> 16; + } + result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & + 0x3FF0000) >> 16; + } + } + rtl_set_bbreg(hw, 0xc04, MASKDWORD, rtlphy->reg_c04); + rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874); + rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); + rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); + if (is2t) + rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); + if (t != 0) { + if (!rtlphy->b_rfpi_enable) + _rtl92c_phy_pi_mode_switch(hw, false); + _rtl92c_phy_reload_adda_registers(hw, adda_reg, + rtlphy->adda_backup, 16); + _rtl92c_phy_reload_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + } +} + +static void _rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) +{ + u8 tmpreg; + u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + tmpreg = rtl_read_byte(rtlpriv, 0xd03); + + if ((tmpreg & 0x70) != 0) + rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); + else + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + + if ((tmpreg & 0x70) != 0) { + rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); + + if (is2t) + rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, + MASK12BITS); + + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, + (rf_a_mode & 0x8FFFF) | 0x10000); + + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, + (rf_b_mode & 0x8FFFF) | 0x10000); + } + lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); + + rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000); + + mdelay(100); + + if ((tmpreg & 0x70) != 0) { + rtl_write_byte(rtlpriv, 0xd03, tmpreg); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); + + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, + rf_b_mode); + } else { + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + } +} + +static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, + char delta, bool is2t) +{ + /* This routine is deliberately dummied out for later fixes */ +#if 0 + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + u32 reg_d[PATH_NUM]; + u32 tmpreg, index, offset, path, i, pathbound = PATH_NUM, apkbound; + + u32 bb_backup[APK_BB_REG_NUM]; + u32 bb_reg[APK_BB_REG_NUM] = { + 0x904, 0xc04, 0x800, 0xc08, 0x874 + }; + u32 bb_ap_mode[APK_BB_REG_NUM] = { + 0x00000020, 0x00a05430, 0x02040000, + 0x000800e4, 0x00204000 + }; + u32 bb_normal_ap_mode[APK_BB_REG_NUM] = { + 0x00000020, 0x00a05430, 0x02040000, + 0x000800e4, 0x22204000 + }; + + u32 afe_backup[APK_AFE_REG_NUM]; + u32 afe_reg[APK_AFE_REG_NUM] = { + 0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, + 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c, + 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, + 0xeec + }; + + u32 mac_backup[IQK_MAC_REG_NUM]; + u32 mac_reg[IQK_MAC_REG_NUM] = { + 0x522, 0x550, 0x551, 0x040 + }; + + u32 apk_rf_init_value[PATH_NUM][APK_BB_REG_NUM] = { + {0x0852c, 0x1852c, 0x5852c, 0x1852c, 0x5852c}, + {0x2852e, 0x0852e, 0x3852e, 0x0852e, 0x0852e} + }; + + u32 apk_normal_rf_init_value[PATH_NUM][APK_BB_REG_NUM] = { + {0x0852c, 0x0a52c, 0x3a52c, 0x5a52c, 0x5a52c}, + {0x0852c, 0x0a52c, 0x5a52c, 0x5a52c, 0x5a52c} + }; + + u32 apk_rf_value_0[PATH_NUM][APK_BB_REG_NUM] = { + {0x52019, 0x52014, 0x52013, 0x5200f, 0x5208d}, + {0x5201a, 0x52019, 0x52016, 0x52033, 0x52050} + }; + + u32 apk_normal_rf_value_0[PATH_NUM][APK_BB_REG_NUM] = { + {0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a}, + {0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a} + }; + + u32 afe_on_off[PATH_NUM] = { + 0x04db25a4, 0x0b1b25a4 + }; + + u32 apk_offset[PATH_NUM] = { 0xb68, 0xb6c }; + + u32 apk_normal_offset[PATH_NUM] = { 0xb28, 0xb98 }; + + u32 apk_value[PATH_NUM] = { 0x92fc0000, 0x12fc0000 }; + + u32 apk_normal_value[PATH_NUM] = { 0x92680000, 0x12680000 }; + + const char apk_delta_mapping[APK_BB_REG_NUM][13] = { + {-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6}, + {-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6}, + {-6, -4, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6}, + {-1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6}, + {-11, -9, -7, -5, -3, -1, 0, 0, 0, 0, 0, 0, 0} + }; + + const u32 apk_normal_setting_value_1[13] = { + 0x01017018, 0xf7ed8f84, 0x1b1a1816, 0x2522201e, 0x322e2b28, + 0x433f3a36, 0x5b544e49, 0x7b726a62, 0xa69a8f84, 0xdfcfc0b3, + 0x12680000, 0x00880000, 0x00880000 + }; + + const u32 apk_normal_setting_value_2[16] = { + 0x01c7021d, 0x01670183, 0x01000123, 0x00bf00e2, 0x008d00a3, + 0x0068007b, 0x004d0059, 0x003a0042, 0x002b0031, 0x001f0025, + 0x0017001b, 0x00110014, 0x000c000f, 0x0009000b, 0x00070008, + 0x00050006 + }; + + const u32 apk_result[PATH_NUM][APK_BB_REG_NUM]; + + long bb_offset, delta_v, delta_offset; + + if (!is2t) + pathbound = 1; + + for (index = 0; index < PATH_NUM; index++) { + apk_offset[index] = apk_normal_offset[index]; + apk_value[index] = apk_normal_value[index]; + afe_on_off[index] = 0x6fdb25a4; + } + + for (index = 0; index < APK_BB_REG_NUM; index++) { + for (path = 0; path < pathbound; path++) { + apk_rf_init_value[path][index] = + apk_normal_rf_init_value[path][index]; + apk_rf_value_0[path][index] = + apk_normal_rf_value_0[path][index]; + } + bb_ap_mode[index] = bb_normal_ap_mode[index]; + + apkbound = 6; + } + + for (index = 0; index < APK_BB_REG_NUM; index++) { + if (index == 0) + continue; + bb_backup[index] = rtl_get_bbreg(hw, bb_reg[index], MASKDWORD); + } + + _rtl92c_phy_save_mac_registers(hw, mac_reg, mac_backup); + + _rtl92c_phy_save_adda_registers(hw, afe_reg, afe_backup, 16); + + for (path = 0; path < pathbound; path++) { + if (path == RF90_PATH_A) { + offset = 0xb00; + for (index = 0; index < 11; index++) { + rtl_set_bbreg(hw, offset, MASKDWORD, + apk_normal_setting_value_1 + [index]); + + offset += 0x04; + } + + rtl_set_bbreg(hw, 0xb98, MASKDWORD, 0x12680000); + + offset = 0xb68; + for (; index < 13; index++) { + rtl_set_bbreg(hw, offset, MASKDWORD, + apk_normal_setting_value_1 + [index]); + + offset += 0x04; + } + + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x40000000); + + offset = 0xb00; + for (index = 0; index < 16; index++) { + rtl_set_bbreg(hw, offset, MASKDWORD, + apk_normal_setting_value_2 + [index]); + + offset += 0x04; + } + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000); + } else if (path == RF90_PATH_B) { + offset = 0xb70; + for (index = 0; index < 10; index++) { + rtl_set_bbreg(hw, offset, MASKDWORD, + apk_normal_setting_value_1 + [index]); + + offset += 0x04; + } + rtl_set_bbreg(hw, 0xb28, MASKDWORD, 0x12680000); + rtl_set_bbreg(hw, 0xb98, MASKDWORD, 0x12680000); + + offset = 0xb68; + index = 11; + for (; index < 13; index++) { + rtl_set_bbreg(hw, offset, MASKDWORD, + apk_normal_setting_value_1 + [index]); + + offset += 0x04; + } + + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x40000000); + + offset = 0xb60; + for (index = 0; index < 16; index++) { + rtl_set_bbreg(hw, offset, MASKDWORD, + apk_normal_setting_value_2 + [index]); + + offset += 0x04; + } + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000); + } + + reg_d[path] = rtl_get_rfreg(hw, (enum radio_path)path, + 0xd, MASKDWORD); + + for (index = 0; index < APK_AFE_REG_NUM; index++) + rtl_set_bbreg(hw, afe_reg[index], MASKDWORD, + afe_on_off[path]); + + if (path == RF90_PATH_A) { + for (index = 0; index < APK_BB_REG_NUM; index++) { + if (index == 0) + continue; + rtl_set_bbreg(hw, bb_reg[index], MASKDWORD, + bb_ap_mode[index]); + } + } + + _rtl92c_phy_mac_setting_calibration(hw, mac_reg, mac_backup); + + if (path == 0) { + rtl_set_rfreg(hw, RF90_PATH_B, 0x0, MASKDWORD, 0x10000); + } else { + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASKDWORD, + 0x10000); + rtl_set_rfreg(hw, RF90_PATH_A, 0x10, MASKDWORD, + 0x1000f); + rtl_set_rfreg(hw, RF90_PATH_A, 0x11, MASKDWORD, + 0x20103); + } + + delta_offset = ((delta + 14) / 2); + if (delta_offset < 0) + delta_offset = 0; + else if (delta_offset > 12) + delta_offset = 12; + + for (index = 0; index < APK_BB_REG_NUM; index++) { + if (index != 1) + continue; + + tmpreg = apk_rf_init_value[path][index]; + + if (!rtlefuse->b_apk_thermalmeterignore) { + bb_offset = (tmpreg & 0xF0000) >> 16; + + if (!(tmpreg & BIT(15))) + bb_offset = -bb_offset; + + delta_v = + apk_delta_mapping[index][delta_offset]; + + bb_offset += delta_v; + + if (bb_offset < 0) { + tmpreg = tmpreg & (~BIT(15)); + bb_offset = -bb_offset; + } else { + tmpreg = tmpreg | BIT(15); + } + + tmpreg = + (tmpreg & 0xFFF0FFFF) | (bb_offset << 16); + } + + rtl_set_rfreg(hw, (enum radio_path)path, 0xc, + MASKDWORD, 0x8992e); + rtl_set_rfreg(hw, (enum radio_path)path, 0x0, + MASKDWORD, apk_rf_value_0[path][index]); + rtl_set_rfreg(hw, (enum radio_path)path, 0xd, + MASKDWORD, tmpreg); + + i = 0; + do { + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80000000); + rtl_set_bbreg(hw, apk_offset[path], + MASKDWORD, apk_value[0]); + RTPRINT(rtlpriv, FINIT, INIT_IQK, + ("PHY_APCalibrate() offset 0x%x " + "value 0x%x\n", + apk_offset[path], + rtl_get_bbreg(hw, apk_offset[path], + MASKDWORD))); + + mdelay(3); + + rtl_set_bbreg(hw, apk_offset[path], + MASKDWORD, apk_value[1]); + RTPRINT(rtlpriv, FINIT, INIT_IQK, + ("PHY_APCalibrate() offset 0x%x " + "value 0x%x\n", + apk_offset[path], + rtl_get_bbreg(hw, apk_offset[path], + MASKDWORD))); + + mdelay(20); + + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000); + + if (path == RF90_PATH_A) + tmpreg = rtl_get_bbreg(hw, 0xbd8, + 0x03E00000); + else + tmpreg = rtl_get_bbreg(hw, 0xbd8, + 0xF8000000); + + RTPRINT(rtlpriv, FINIT, INIT_IQK, + ("PHY_APCalibrate() offset " + "0xbd8[25:21] %x\n", tmpreg)); + + i++; + + } while (tmpreg > apkbound && i < 4); + + apk_result[path][index] = tmpreg; + } + } + + _rtl92c_phy_reload_mac_registers(hw, mac_reg, mac_backup); + + for (index = 0; index < APK_BB_REG_NUM; index++) { + if (index == 0) + continue; + rtl_set_bbreg(hw, bb_reg[index], MASKDWORD, bb_backup[index]); + } + + _rtl92c_phy_reload_adda_registers(hw, afe_reg, afe_backup, 16); + + for (path = 0; path < pathbound; path++) { + rtl_set_rfreg(hw, (enum radio_path)path, 0xd, + MASKDWORD, reg_d[path]); + + if (path == RF90_PATH_B) { + rtl_set_rfreg(hw, RF90_PATH_A, 0x10, MASKDWORD, + 0x1000f); + rtl_set_rfreg(hw, RF90_PATH_A, 0x11, MASKDWORD, + 0x20101); + } + + if (apk_result[path][1] > 6) + apk_result[path][1] = 6; + } + + for (path = 0; path < pathbound; path++) { + rtl_set_rfreg(hw, (enum radio_path)path, 0x3, MASKDWORD, + ((apk_result[path][1] << 15) | + (apk_result[path][1] << 10) | + (apk_result[path][1] << 5) | + apk_result[path][1])); + + if (path == RF90_PATH_A) + rtl_set_rfreg(hw, (enum radio_path)path, 0x4, MASKDWORD, + ((apk_result[path][1] << 15) | + (apk_result[path][1] << 10) | + (0x00 << 5) | 0x05)); + else + rtl_set_rfreg(hw, (enum radio_path)path, 0x4, MASKDWORD, + ((apk_result[path][1] << 15) | + (apk_result[path][1] << 10) | + (0x02 << 5) | 0x05)); + + rtl_set_rfreg(hw, (enum radio_path)path, 0xe, MASKDWORD, + ((0x08 << 15) | (0x08 << 10) | (0x08 << 5) | + 0x08)); + + } + + rtlphy->b_apk_done = true; +#endif +} + +static void _rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, + bool bmain, bool is2t) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (is_hal_stop(rtlhal)) { + rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01); + rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); + } + if (is2t) { + if (bmain) + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(6), 0x1); + else + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(6), 0x2); + } else { + if (bmain) + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x2); + else + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1); + + } +} + +#undef IQK_ADDA_REG_NUM +#undef IQK_DELAY_TIME + +void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + long result[4][8]; + u8 i, final_candidate; + bool b_patha_ok, b_pathb_ok; + long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, + reg_ecc, reg_tmp = 0; + bool is12simular, is13simular, is23simular; + bool b_start_conttx = false, b_singletone = false; + u32 iqk_bb_reg[10] = { + ROFDM0_XARXIQIMBALANCE, + ROFDM0_XBRXIQIMBALANCE, + ROFDM0_ECCATHRESHOLD, + ROFDM0_AGCRSSITABLE, + ROFDM0_XATXIQIMBALANCE, + ROFDM0_XBTXIQIMBALANCE, + ROFDM0_XCTXIQIMBALANCE, + ROFDM0_XCTXAFE, + ROFDM0_XDTXAFE, + ROFDM0_RXIQEXTANTA + }; + + if (b_recovery) { + _rtl92c_phy_reload_adda_registers(hw, + iqk_bb_reg, + rtlphy->iqk_bb_backup, 10); + return; + } + if (b_start_conttx || b_singletone) + return; + for (i = 0; i < 8; i++) { + result[0][i] = 0; + result[1][i] = 0; + result[2][i] = 0; + result[3][i] = 0; + } + final_candidate = 0xff; + b_patha_ok = false; + b_pathb_ok = false; + is12simular = false; + is23simular = false; + is13simular = false; + for (i = 0; i < 3; i++) { + if (IS_92C_SERIAL(rtlhal->version)) + _rtl92c_phy_iq_calibrate(hw, result, i, true); + else + _rtl92c_phy_iq_calibrate(hw, result, i, false); + if (i == 1) { + is12simular = _rtl92c_phy_simularity_compare(hw, + result, 0, + 1); + if (is12simular) { + final_candidate = 0; + break; + } + } + if (i == 2) { + is13simular = _rtl92c_phy_simularity_compare(hw, + result, 0, + 2); + if (is13simular) { + final_candidate = 0; + break; + } + is23simular = _rtl92c_phy_simularity_compare(hw, + result, 1, + 2); + if (is23simular) + final_candidate = 1; + else { + for (i = 0; i < 8; i++) + reg_tmp += result[3][i]; + + if (reg_tmp != 0) + final_candidate = 3; + else + final_candidate = 0xFF; + } + } + } + for (i = 0; i < 4; i++) { + reg_e94 = result[i][0]; + reg_e9c = result[i][1]; + reg_ea4 = result[i][2]; + reg_eac = result[i][3]; + reg_eb4 = result[i][4]; + reg_ebc = result[i][5]; + reg_ec4 = result[i][6]; + reg_ecc = result[i][7]; + } + if (final_candidate != 0xff) { + rtlphy->reg_e94 = reg_e94 = result[final_candidate][0]; + rtlphy->reg_e9c = reg_e9c = result[final_candidate][1]; + reg_ea4 = result[final_candidate][2]; + reg_eac = result[final_candidate][3]; + rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4]; + rtlphy->reg_ebc = reg_ebc = result[final_candidate][5]; + reg_ec4 = result[final_candidate][6]; + reg_ecc = result[final_candidate][7]; + b_patha_ok = b_pathb_ok = true; + } else { + rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; + rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0; + } + if (reg_e94 != 0) /*&&(reg_ea4 != 0) */ + _rtl92c_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result, + final_candidate, + (reg_ea4 == 0)); + if (IS_92C_SERIAL(rtlhal->version)) { + if (reg_eb4 != 0) /*&&(reg_ec4 != 0) */ + _rtl92c_phy_path_b_fill_iqk_matrix(hw, b_pathb_ok, + result, + final_candidate, + (reg_ec4 == 0)); + } + _rtl92c_phy_save_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, 10); +} + +void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool b_start_conttx = false, b_singletone = false; + + if (b_start_conttx || b_singletone) + return; + if (IS_92C_SERIAL(rtlhal->version)) + _rtl92c_phy_lc_calibrate(hw, true); + else + _rtl92c_phy_lc_calibrate(hw, false); +} + +void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlphy->b_apk_done) + return; + if (IS_92C_SERIAL(rtlhal->version)) + _rtl92c_phy_ap_calibrate(hw, delta, true); + else + _rtl92c_phy_ap_calibrate(hw, delta, false); +} + +void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (IS_92C_SERIAL(rtlhal->version)) + _rtl92c_phy_set_rfpath_switch(hw, bmain, true); + else + _rtl92c_phy_set_rfpath_switch(hw, bmain, false); +} + +bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + bool b_postprocessing = false; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + ("-->IO Cmd(%#x), set_io_inprogress(%d)\n", + iotype, rtlphy->set_io_inprogress)); + do { + switch (iotype) { + case IO_CMD_RESUME_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + ("[IO CMD] Resume DM after scan.\n")); + b_postprocessing = true; + break; + case IO_CMD_PAUSE_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + ("[IO CMD] Pause DM before scan.\n")); + b_postprocessing = true; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + } while (false); + if (b_postprocessing && !rtlphy->set_io_inprogress) { + rtlphy->set_io_inprogress = true; + rtlphy->current_io_type = iotype; + } else { + return false; + } + rtl92c_phy_set_io(hw); + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, ("<--IO Type(%#x)\n", iotype)); + return true; +} + +void rtl92c_phy_set_io(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + ("--->Cmd(%#x), set_io_inprogress(%d)\n", + rtlphy->current_io_type, rtlphy->set_io_inprogress)); + switch (rtlphy->current_io_type) { + case IO_CMD_RESUME_DM_BY_SCAN: + dm_digtable.cur_igvalue = rtlphy->initgain_backup.xaagccore1; + rtl92c_dm_write_dig(hw); + rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); + break; + case IO_CMD_PAUSE_DM_BY_SCAN: + rtlphy->initgain_backup.xaagccore1 = dm_digtable.cur_igvalue; + dm_digtable.cur_igvalue = 0x17; + rtl92c_dm_write_dig(hw); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + rtlphy->set_io_inprogress = false; + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + ("<---(%#x)\n", rtlphy->current_io_type)); +} + +void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); +} + +static void _rtl92ce_phy_set_rf_sleep(struct ieee80211_hw *hw) +{ + u32 u4b_tmp; + u8 delay = 5; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + while (u4b_tmp != 0 && delay > 0) { + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + delay--; + } + if (delay == 0) { + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + ("Switch RF timeout !!!.\n")); + return; + } + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); +} + +static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = true; + u8 i, queue_id; + struct rtl8192_tx_ring *ring = NULL; + + ppsc->set_rfpowerstate_inprogress = true; + switch (rfpwr_state) { + case ERFON:{ + if ((ppsc->rfpwr_state == ERFOFF) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { + bool rtstatus; + u32 InitializeCount = 0; + do { + InitializeCount++; + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + ("IPS Set eRf nic enable\n")); + rtstatus = rtl_ps_enable_nic(hw); + } while ((rtstatus != true) + && (InitializeCount < 10)); + RT_CLEAR_PS_LEVEL(ppsc, + RT_RF_OFF_LEVL_HALT_NIC); + } else { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + ("Set ERFON sleeped:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc-> + last_sleep_jiffies))); + ppsc->last_awake_jiffies = jiffies; + rtl92ce_phy_set_rf_on(hw); + } + if (mac->link_state == MAC80211_LINKED) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } + break; + } + case ERFOFF:{ + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (skb_queue_len(&ring->queue) == 0 || + queue_id == BEACON_QUEUE) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("eRf Off/Sleep: %d times " + "TcbBusyQueue[%d] " + "=%d before doze!\n", (i + 1), + queue_id, + skb_queue_len(&ring->queue))); + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("\nERFOFF: %d times " + "TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue))); + break; + } + } + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + ("IPS Set eRf nic disable\n")); + rtl_ps_disable_nic(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } else { + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_POWER_OFF); + } + } + break; + } + case ERFSLEEP:{ + if (ppsc->rfpwr_state == ERFOFF) + break; + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (skb_queue_len(&ring->queue) == 0) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("eRf Off/Sleep: %d times " + "TcbBusyQueue[%d] =%d before " + "doze!\n", (i + 1), queue_id, + skb_queue_len(&ring->queue))); + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("\n ERFSLEEP: %d times " + "TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue))); + break; + } + } + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + ("Set ERFSLEEP awaked:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc->last_awake_jiffies))); + ppsc->last_sleep_jiffies = jiffies; + _rtl92ce_phy_set_rf_sleep(hw); + break; + } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + bresult = false; + break; + } + if (bresult) + ppsc->rfpwr_state = rfpwr_state; + ppsc->set_rfpowerstate_inprogress = false; + return bresult; +} + +bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = false; + + if (rfpwr_state == ppsc->rfpwr_state) + return bresult; + bresult = _rtl92ce_phy_set_rf_power_state(hw, rfpwr_state); + return bresult; +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h new file mode 100644 index 000000000000..ca4daee6e9a8 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h @@ -0,0 +1,237 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92C_PHY_H__ +#define __RTL92C_PHY_H__ + +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +#define MAX_DOZE_WAITING_TIMES_9x 64 + +#define RT_CANNOT_IO(hw) false +#define HIGHPOWER_RADIOA_ARRAYLEN 22 + +#define MAX_TOLERANCE 5 +#define IQK_DELAY_TIME 1 + +#define APK_BB_REG_NUM 5 +#define APK_AFE_REG_NUM 16 +#define APK_CURVE_REG_NUM 4 +#define PATH_NUM 2 + +#define LOOP_LIMIT 5 +#define MAX_STALL_TIME 50 +#define AntennaDiversityValue 0x80 +#define MAX_TXPWR_IDX_NMODE_92S 63 +#define Reset_Cnt_Limit 3 + +#define IQK_ADDA_REG_NUM 16 +#define IQK_MAC_REG_NUM 4 + +#define RF90_PATH_MAX 2 +#define CHANNEL_MAX_NUMBER 14 +#define CHANNEL_GROUP_MAX 3 + +#define CT_OFFSET_MAC_ADDR 0X16 + +#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A +#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 +#define CT_OFFSET_HT402S_TX_PWR_IDX_DIF 0x66 +#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 +#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C + +#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F +#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 + +#define CT_OFFSET_CHANNEL_PLAH 0x75 +#define CT_OFFSET_THERMAL_METER 0x78 +#define CT_OFFSET_RF_OPTION 0x79 +#define CT_OFFSET_VERSION 0x7E +#define CT_OFFSET_CUSTOMER_ID 0x7F + +#define RTL92C_MAX_PATH_NUM 2 +#define CHANNEL_MAX_NUMBER 14 +#define CHANNEL_GROUP_MAX 3 + +enum swchnlcmd_id { + CMDID_END, + CMDID_SET_TXPOWEROWER_LEVEL, + CMDID_BBREGWRITE10, + CMDID_WRITEPORT_ULONG, + CMDID_WRITEPORT_USHORT, + CMDID_WRITEPORT_UCHAR, + CMDID_RF_WRITEREG, +}; + +struct swchnlcmd { + enum swchnlcmd_id cmdid; + u32 para1; + u32 para2; + u32 msdelay; +}; + +enum hw90_block_e { + HW90_BLOCK_MAC = 0, + HW90_BLOCK_PHY0 = 1, + HW90_BLOCK_PHY1 = 2, + HW90_BLOCK_RF = 3, + HW90_BLOCK_MAXIMUM = 4, +}; + +enum baseband_config_type { + BASEBAND_CONFIG_PHY_REG = 0, + BASEBAND_CONFIG_AGC_TAB = 1, +}; + +enum ra_offset_area { + RA_OFFSET_LEGACY_OFDM1, + RA_OFFSET_LEGACY_OFDM2, + RA_OFFSET_HT_OFDM1, + RA_OFFSET_HT_OFDM2, + RA_OFFSET_HT_OFDM3, + RA_OFFSET_HT_OFDM4, + RA_OFFSET_HT_CCK, +}; + +enum antenna_path { + ANTENNA_NONE, + ANTENNA_D, + ANTENNA_C, + ANTENNA_CD, + ANTENNA_B, + ANTENNA_BD, + ANTENNA_BC, + ANTENNA_BCD, + ANTENNA_A, + ANTENNA_AD, + ANTENNA_AC, + ANTENNA_ACD, + ANTENNA_AB, + ANTENNA_ABD, + ANTENNA_ABC, + ANTENNA_ABCD +}; + +struct r_antenna_select_ofdm { + u32 r_tx_antenna:4; + u32 r_ant_l:4; + u32 r_ant_non_ht:4; + u32 r_ant_ht1:4; + u32 r_ant_ht2:4; + u32 r_ant_ht_s1:4; + u32 r_ant_non_ht_s1:4; + u32 ofdm_txsc:2; + u32 reserved:2; +}; + +struct r_antenna_select_cck { + u8 r_cckrx_enable_2:2; + u8 r_cckrx_enable:2; + u8 r_ccktx_enable:4; +}; + +struct efuse_contents { + u8 mac_addr[ETH_ALEN]; + u8 cck_tx_power_idx[6]; + u8 ht40_1s_tx_power_idx[6]; + u8 ht40_2s_tx_power_idx_diff[3]; + u8 ht20_tx_power_idx_diff[3]; + u8 ofdm_tx_power_idx_diff[3]; + u8 ht40_max_power_offset[3]; + u8 ht20_max_power_offset[3]; + u8 channel_plan; + u8 thermal_meter; + u8 rf_option[5]; + u8 version; + u8 oem_id; + u8 regulatory; +}; + +struct tx_power_struct { + u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 legacy_ht_txpowerdiff; + u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 pwrgroup_cnt; + u32 mcs_original_offset[4][16]; +}; + +extern u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask); +extern void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, u32 data); +extern u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask); +extern void rtl92c_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask, u32 data); +extern bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); +extern bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); +extern bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); +extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +extern void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +extern void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, + long *powerlevel); +extern void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +extern bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, + long power_indbm); +extern void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, + u8 operation); +extern void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw); +extern void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type); +extern void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); +extern u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); +extern void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); +extern void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, + u16 beaconinterval); +void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); +void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); +void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); +bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +extern bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, + u32 rfpath); +bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); +extern bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); +void rtl92c_phy_config_bb_external_pa(struct ieee80211_hw *hw); +void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw); +bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); +void rtl92c_phy_set_io(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h new file mode 100644 index 000000000000..875d51465225 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h @@ -0,0 +1,2065 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92C_REG_H__ +#define __RTL92C_REG_H__ + +#define REG_SYS_ISO_CTRL 0x0000 +#define REG_SYS_FUNC_EN 0x0002 +#define REG_APS_FSMCO 0x0004 +#define REG_SYS_CLKR 0x0008 +#define REG_9346CR 0x000A +#define REG_EE_VPD 0x000C +#define REG_AFE_MISC 0x0010 +#define REG_SPS0_CTRL 0x0011 +#define REG_SPS_OCP_CFG 0x0018 +#define REG_RSV_CTRL 0x001C +#define REG_RF_CTRL 0x001F +#define REG_LDOA15_CTRL 0x0020 +#define REG_LDOV12D_CTRL 0x0021 +#define REG_LDOHCI12_CTRL 0x0022 +#define REG_LPLDO_CTRL 0x0023 +#define REG_AFE_XTAL_CTRL 0x0024 +#define REG_AFE_PLL_CTRL 0x0028 +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define REG_PWR_DATA 0x0038 +#define REG_CAL_TIMER 0x003C +#define REG_ACLK_MON 0x003E +#define REG_GPIO_MUXCFG 0x0040 +#define REG_GPIO_IO_SEL 0x0042 +#define REG_MAC_PINMUX_CFG 0x0043 +#define REG_GPIO_PIN_CTRL 0x0044 +#define REG_GPIO_INTM 0x0048 +#define REG_LEDCFG0 0x004C +#define REG_LEDCFG1 0x004D +#define REG_LEDCFG2 0x004E +#define REG_LEDCFG3 0x004F +#define REG_FSIMR 0x0050 +#define REG_FSISR 0x0054 + +#define REG_MCUFWDL 0x0080 + +#define REG_HMEBOX_EXT_0 0x0088 +#define REG_HMEBOX_EXT_1 0x008A +#define REG_HMEBOX_EXT_2 0x008C +#define REG_HMEBOX_EXT_3 0x008E + +#define REG_BIST_SCAN 0x00D0 +#define REG_BIST_RPT 0x00D4 +#define REG_BIST_ROM_RPT 0x00D8 +#define REG_USB_SIE_INTF 0x00E0 +#define REG_PCIE_MIO_INTF 0x00E4 +#define REG_PCIE_MIO_INTD 0x00E8 +#define REG_HPON_FSM 0x00EC +#define REG_SYS_CFG 0x00F0 + +#define REG_CR 0x0100 +#define REG_PBP 0x0104 +#define REG_TRXDMA_CTRL 0x010C +#define REG_TRXFF_BNDY 0x0114 +#define REG_TRXFF_STATUS 0x0118 +#define REG_RXFF_PTR 0x011C +#define REG_HIMR 0x0120 +#define REG_HISR 0x0124 +#define REG_HIMRE 0x0128 +#define REG_HISRE 0x012C +#define REG_CPWM 0x012F +#define REG_FWIMR 0x0130 +#define REG_FWISR 0x0134 +#define REG_PKTBUF_DBG_CTRL 0x0140 +#define REG_PKTBUF_DBG_DATA_L 0x0144 +#define REG_PKTBUF_DBG_DATA_H 0x0148 + +#define REG_TC0_CTRL 0x0150 +#define REG_TC1_CTRL 0x0154 +#define REG_TC2_CTRL 0x0158 +#define REG_TC3_CTRL 0x015C +#define REG_TC4_CTRL 0x0160 +#define REG_TCUNIT_BASE 0x0164 +#define REG_MBIST_START 0x0174 +#define REG_MBIST_DONE 0x0178 +#define REG_MBIST_FAIL 0x017C +#define REG_C2HEVT_MSG_NORMAL 0x01A0 +#define REG_C2HEVT_MSG_TEST 0x01B8 +#define REG_C2HEVT_CLEAR 0x01BF +#define REG_MCUTST_1 0x01c0 +#define REG_FMETHR 0x01C8 +#define REG_HMETFR 0x01CC +#define REG_HMEBOX_0 0x01D0 +#define REG_HMEBOX_1 0x01D4 +#define REG_HMEBOX_2 0x01D8 +#define REG_HMEBOX_3 0x01DC + +#define REG_LLT_INIT 0x01E0 +#define REG_BB_ACCEESS_CTRL 0x01E8 +#define REG_BB_ACCESS_DATA 0x01EC + +#define REG_RQPN 0x0200 +#define REG_FIFOPAGE 0x0204 +#define REG_TDECTRL 0x0208 +#define REG_TXDMA_OFFSET_CHK 0x020C +#define REG_TXDMA_STATUS 0x0210 +#define REG_RQPN_NPQ 0x0214 + +#define REG_RXDMA_AGG_PG_TH 0x0280 +#define REG_RXPKT_NUM 0x0284 +#define REG_RXDMA_STATUS 0x0288 + +#define REG_PCIE_CTRL_REG 0x0300 +#define REG_INT_MIG 0x0304 +#define REG_BCNQ_DESA 0x0308 +#define REG_HQ_DESA 0x0310 +#define REG_MGQ_DESA 0x0318 +#define REG_VOQ_DESA 0x0320 +#define REG_VIQ_DESA 0x0328 +#define REG_BEQ_DESA 0x0330 +#define REG_BKQ_DESA 0x0338 +#define REG_RX_DESA 0x0340 +#define REG_DBI 0x0348 +#define REG_MDIO 0x0354 +#define REG_DBG_SEL 0x0360 +#define REG_PCIE_HRPWM 0x0361 +#define REG_PCIE_HCPWM 0x0363 +#define REG_UART_CTRL 0x0364 +#define REG_UART_TX_DESA 0x0370 +#define REG_UART_RX_DESA 0x0378 + +#define REG_HDAQ_DESA_NODEF 0x0000 +#define REG_CMDQ_DESA_NODEF 0x0000 + +#define REG_VOQ_INFORMATION 0x0400 +#define REG_VIQ_INFORMATION 0x0404 +#define REG_BEQ_INFORMATION 0x0408 +#define REG_BKQ_INFORMATION 0x040C +#define REG_MGQ_INFORMATION 0x0410 +#define REG_HGQ_INFORMATION 0x0414 +#define REG_BCNQ_INFORMATION 0x0418 + +#define REG_CPU_MGQ_INFORMATION 0x041C +#define REG_FWHW_TXQ_CTRL 0x0420 +#define REG_HWSEQ_CTRL 0x0423 +#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 +#define REG_TXPKTBUF_MGQ_BDNY 0x0425 +#define REG_MULTI_BCNQ_EN 0x0426 +#define REG_MULTI_BCNQ_OFFSET 0x0427 +#define REG_SPEC_SIFS 0x0428 +#define REG_RL 0x042A +#define REG_DARFRC 0x0430 +#define REG_RARFRC 0x0438 +#define REG_RRSR 0x0440 +#define REG_ARFR0 0x0444 +#define REG_ARFR1 0x0448 +#define REG_ARFR2 0x044C +#define REG_ARFR3 0x0450 +#define REG_AGGLEN_LMT 0x0458 +#define REG_AMPDU_MIN_SPACE 0x045C +#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D +#define REG_FAST_EDCA_CTRL 0x0460 +#define REG_RD_RESP_PKT_TH 0x0463 +#define REG_INIRTS_RATE_SEL 0x0480 +#define REG_INIDATA_RATE_SEL 0x0484 +#define REG_POWER_STATUS 0x04A4 +#define REG_POWER_STAGE1 0x04B4 +#define REG_POWER_STAGE2 0x04B8 +#define REG_PKT_LIFE_TIME 0x04C0 +#define REG_STBC_SETTING 0x04C4 +#define REG_PROT_MODE_CTRL 0x04C8 +#define REG_BAR_MODE_CTRL 0x04CC +#define REG_RA_TRY_RATE_AGG_LMT 0x04CF +#define REG_NQOS_SEQ 0x04DC +#define REG_QOS_SEQ 0x04DE +#define REG_NEED_CPU_HANDLE 0x04E0 +#define REG_PKT_LOSE_RPT 0x04E1 +#define REG_PTCL_ERR_STATUS 0x04E2 +#define REG_DUMMY 0x04FC + +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050C +#define REG_BCNTCFG 0x0510 +#define REG_PIFS 0x0512 +#define REG_RDG_PIFS 0x0513 +#define REG_SIFS_CTX 0x0514 +#define REG_SIFS_TRX 0x0516 +#define REG_AGGR_BREAK_TIME 0x051A +#define REG_SLOT 0x051B +#define REG_TX_PTCL_CTRL 0x0520 +#define REG_TXPAUSE 0x0522 +#define REG_DIS_TXREQ_CLR 0x0523 +#define REG_RD_CTRL 0x0524 +#define REG_TBTT_PROHIBIT 0x0540 +#define REG_RD_NAV_NXT 0x0544 +#define REG_NAV_PROT_LEN 0x0546 +#define REG_BCN_CTRL 0x0550 +#define REG_USTIME_TSF 0x0551 +#define REG_MBID_NUM 0x0552 +#define REG_DUAL_TSF_RST 0x0553 +#define REG_BCN_INTERVAL 0x0554 +#define REG_MBSSID_BCN_SPACE 0x0554 +#define REG_DRVERLYINT 0x0558 +#define REG_BCNDMATIM 0x0559 +#define REG_ATIMWND 0x055A +#define REG_BCN_MAX_ERR 0x055D +#define REG_RXTSF_OFFSET_CCK 0x055E +#define REG_RXTSF_OFFSET_OFDM 0x055F +#define REG_TSFTR 0x0560 +#define REG_INIT_TSFTR 0x0564 +#define REG_PSTIMER 0x0580 +#define REG_TIMER0 0x0584 +#define REG_TIMER1 0x0588 +#define REG_ACMHWCTRL 0x05C0 +#define REG_ACMRSTCTRL 0x05C1 +#define REG_ACMAVG 0x05C2 +#define REG_VO_ADMTIME 0x05C4 +#define REG_VI_ADMTIME 0x05C6 +#define REG_BE_ADMTIME 0x05C8 +#define REG_EDCA_RANDOM_GEN 0x05CC +#define REG_SCH_TXCMD 0x05D0 + +#define REG_APSD_CTRL 0x0600 +#define REG_BWOPMODE 0x0603 +#define REG_TCR 0x0604 +#define REG_RCR 0x0608 +#define REG_RX_PKT_LIMIT 0x060C +#define REG_RX_DLK_TIME 0x060D +#define REG_RX_DRVINFO_SZ 0x060F + +#define REG_MACID 0x0610 +#define REG_BSSID 0x0618 +#define REG_MAR 0x0620 +#define REG_MBIDCAMCFG 0x0628 + +#define REG_USTIME_EDCA 0x0638 +#define REG_MAC_SPEC_SIFS 0x063A +#define REG_RESP_SIFS_CCK 0x063C +#define REG_RESP_SIFS_OFDM 0x063E +#define REG_ACKTO 0x0640 +#define REG_CTS2TO 0x0641 +#define REG_EIFS 0x0642 + +#define REG_NAV_CTRL 0x0650 +#define REG_BACAMCMD 0x0654 +#define REG_BACAMCONTENT 0x0658 +#define REG_LBDLY 0x0660 +#define REG_FWDLY 0x0661 +#define REG_RXERR_RPT 0x0664 +#define REG_WMAC_TRXPTCL_CTL 0x0668 + +#define REG_CAMCMD 0x0670 +#define REG_CAMWRITE 0x0674 +#define REG_CAMREAD 0x0678 +#define REG_CAMDBG 0x067C +#define REG_SECCFG 0x0680 + +#define REG_WOW_CTRL 0x0690 +#define REG_PSSTATUS 0x0691 +#define REG_PS_RX_INFO 0x0692 +#define REG_LPNAV_CTRL 0x0694 +#define REG_WKFMCAM_CMD 0x0698 +#define REG_WKFMCAM_RWD 0x069C +#define REG_RXFLTMAP0 0x06A0 +#define REG_RXFLTMAP1 0x06A2 +#define REG_RXFLTMAP2 0x06A4 +#define REG_BCN_PSR_RPT 0x06A8 +#define REG_CALB32K_CTRL 0x06AC +#define REG_PKT_MON_CTRL 0x06B4 +#define REG_BT_COEX_TABLE 0x06C0 +#define REG_WMAC_RESP_TXINFO 0x06D8 + +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_TEST_USB_TXQS 0xFE48 +#define REG_TEST_SIE_VID 0xFE60 +#define REG_TEST_SIE_PID 0xFE62 +#define REG_TEST_SIE_OPTIONAL 0xFE64 +#define REG_TEST_SIE_CHIRP_K 0xFE65 +#define REG_TEST_SIE_PHY 0xFE66 +#define REG_TEST_SIE_MAC_ADDR 0xFE70 +#define REG_TEST_SIE_STRING 0xFE80 + +#define REG_NORMAL_SIE_VID 0xFE60 +#define REG_NORMAL_SIE_PID 0xFE62 +#define REG_NORMAL_SIE_OPTIONAL 0xFE64 +#define REG_NORMAL_SIE_EP 0xFE65 +#define REG_NORMAL_SIE_PHY 0xFE68 +#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 +#define REG_NORMAL_SIE_STRING 0xFE80 + +#define CR9346 REG_9346CR +#define MSR (REG_CR + 2) +#define ISR REG_HISR +#define TSFR REG_TSFTR + +#define MACIDR0 REG_MACID +#define MACIDR4 (REG_MACID + 4) + +#define PBP REG_PBP + +#define IDR0 MACIDR0 +#define IDR4 MACIDR4 + +#define UNUSED_REGISTER 0x1BF +#define DCAM UNUSED_REGISTER +#define PSR UNUSED_REGISTER +#define BBADDR UNUSED_REGISTER +#define PHYDATAR UNUSED_REGISTER + +#define INVALID_BBRF_VALUE 0x12345678 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define CMDEEPROM_EN BIT(5) +#define CMDEEPROM_SEL BIT(4) +#define CMD9346CR_9356SEL BIT(4) +#define AUTOLOAD_EEPROM (CMDEEPROM_EN|CMDEEPROM_SEL) +#define AUTOLOAD_EFUSE CMDEEPROM_EN + +#define GPIOSEL_GPIO 0 +#define GPIOSEL_ENBT BIT(5) + +#define GPIO_IN REG_GPIO_PIN_CTRL +#define GPIO_OUT (REG_GPIO_PIN_CTRL+1) +#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) +#define GPIO_MOD (REG_GPIO_PIN_CTRL+3) + +#define MSR_NOLINK 0x00 +#define MSR_ADHOC 0x01 +#define MSR_INFRA 0x02 +#define MSR_AP 0x03 + +#define RRSR_RSC_OFFSET 21 +#define RRSR_SHORT_OFFSET 23 +#define RRSR_RSC_BW_40M 0x600000 +#define RRSR_RSC_UPSUBCHNL 0x400000 +#define RRSR_RSC_LOWSUBCHNL 0x200000 +#define RRSR_SHORT 0x800000 +#define RRSR_1M BIT(0) +#define RRSR_2M BIT(1) +#define RRSR_5_5M BIT(2) +#define RRSR_11M BIT(3) +#define RRSR_6M BIT(4) +#define RRSR_9M BIT(5) +#define RRSR_12M BIT(6) +#define RRSR_18M BIT(7) +#define RRSR_24M BIT(8) +#define RRSR_36M BIT(9) +#define RRSR_48M BIT(10) +#define RRSR_54M BIT(11) +#define RRSR_MCS0 BIT(12) +#define RRSR_MCS1 BIT(13) +#define RRSR_MCS2 BIT(14) +#define RRSR_MCS3 BIT(15) +#define RRSR_MCS4 BIT(16) +#define RRSR_MCS5 BIT(17) +#define RRSR_MCS6 BIT(18) +#define RRSR_MCS7 BIT(19) +#define BRSR_ACKSHORTPMB BIT(23) + +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 + +#define RATE_1M BIT(0) +#define RATE_2M BIT(1) +#define RATE_5_5M BIT(2) +#define RATE_11M BIT(3) +#define RATE_6M BIT(4) +#define RATE_9M BIT(5) +#define RATE_12M BIT(6) +#define RATE_18M BIT(7) +#define RATE_24M BIT(8) +#define RATE_36M BIT(9) +#define RATE_48M BIT(10) +#define RATE_54M BIT(11) +#define RATE_MCS0 BIT(12) +#define RATE_MCS1 BIT(13) +#define RATE_MCS2 BIT(14) +#define RATE_MCS3 BIT(15) +#define RATE_MCS4 BIT(16) +#define RATE_MCS5 BIT(17) +#define RATE_MCS6 BIT(18) +#define RATE_MCS7 BIT(19) +#define RATE_MCS8 BIT(20) +#define RATE_MCS9 BIT(21) +#define RATE_MCS10 BIT(22) +#define RATE_MCS11 BIT(23) +#define RATE_MCS12 BIT(24) +#define RATE_MCS13 BIT(25) +#define RATE_MCS14 BIT(26) +#define RATE_MCS15 BIT(27) + +#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) +#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M \ + | RATR_24M | RATR_36M | RATR_48M | RATR_54M) +#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \ + RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \ + RATR_MCS6 | RATR_MCS7) +#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \ + RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \ + RATR_MCS14 | RATR_MCS15) + +#define BW_OPMODE_20MHZ BIT(2) +#define BW_OPMODE_5G BIT(1) +#define BW_OPMODE_11J BIT(0) + +#define CAM_VALID BIT(15) +#define CAM_NOTVALID 0x0000 +#define CAM_USEDK BIT(5) + +#define CAM_NONE 0x0 +#define CAM_WEP40 0x01 +#define CAM_TKIP 0x02 +#define CAM_AES 0x04 +#define CAM_WEP104 0x05 + +#define TOTAL_CAM_ENTRY 32 +#define HALF_CAM_ENTRY 16 + +#define CAM_WRITE BIT(16) +#define CAM_READ 0x00000000 +#define CAM_POLLINIG BIT(31) + +#define SCR_USEDK 0x01 +#define SCR_TXSEC_ENABLE 0x02 +#define SCR_RXSEC_ENABLE 0x04 + +#define WOW_PMEN BIT(0) +#define WOW_WOMEN BIT(1) +#define WOW_MAGIC BIT(2) +#define WOW_UWF BIT(3) + +#define IMR8190_DISABLED 0x0 +#define IMR_BCNDMAINT6 BIT(31) +#define IMR_BCNDMAINT5 BIT(30) +#define IMR_BCNDMAINT4 BIT(29) +#define IMR_BCNDMAINT3 BIT(28) +#define IMR_BCNDMAINT2 BIT(27) +#define IMR_BCNDMAINT1 BIT(26) +#define IMR_BCNDOK8 BIT(25) +#define IMR_BCNDOK7 BIT(24) +#define IMR_BCNDOK6 BIT(23) +#define IMR_BCNDOK5 BIT(22) +#define IMR_BCNDOK4 BIT(21) +#define IMR_BCNDOK3 BIT(20) +#define IMR_BCNDOK2 BIT(19) +#define IMR_BCNDOK1 BIT(18) +#define IMR_TIMEOUT2 BIT(17) +#define IMR_TIMEOUT1 BIT(16) +#define IMR_TXFOVW BIT(15) +#define IMR_PSTIMEOUT BIT(14) +#define IMR_BCNINT BIT(13) +#define IMR_RXFOVW BIT(12) +#define IMR_RDU BIT(11) +#define IMR_ATIMEND BIT(10) +#define IMR_BDOK BIT(9) +#define IMR_HIGHDOK BIT(8) +#define IMR_TBDOK BIT(7) +#define IMR_MGNTDOK BIT(6) +#define IMR_TBDER BIT(5) +#define IMR_BKDOK BIT(4) +#define IMR_BEDOK BIT(3) +#define IMR_VIDOK BIT(2) +#define IMR_VODOK BIT(1) +#define IMR_ROK BIT(0) + +#define IMR_TXERR BIT(11) +#define IMR_RXERR BIT(10) +#define IMR_C2HCMD BIT(9) +#define IMR_CPWM BIT(8) +#define IMR_OCPINT BIT(1) +#define IMR_WLANOFF BIT(0) + +#define HWSET_MAX_SIZE 128 + +#define EEPROM_DEFAULT_TSSI 0x0 +#define EEPROM_DEFAULT_TXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_BOARDTYPE 0x02 +#define EEPROM_DEFAULT_TXPOWER 0x1010 +#define EEPROM_DEFAULT_HT2T_TXPWR 0x10 + +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 +#define EEPROM_DEFAULT_THERMALMETER 0x12 +#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 +#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 +#define EEPROM_DEFAULT_HT20_DIFF 2 +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 +#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 +#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 + +#define RF_OPTION1 0x79 +#define RF_OPTION2 0x7A +#define RF_OPTION3 0x7B +#define RF_OPTION4 0x7C + +#define EEPROM_DEFAULT_PID 0x1234 +#define EEPROM_DEFAULT_VID 0x5678 +#define EEPROM_DEFAULT_CUSTOMERID 0xAB +#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD +#define EEPROM_DEFAULT_VERSION 0 + +#define EEPROM_CHANNEL_PLAN_FCC 0x0 +#define EEPROM_CHANNEL_PLAN_IC 0x1 +#define EEPROM_CHANNEL_PLAN_ETSI 0x2 +#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 +#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 +#define EEPROM_CHANNEL_PLAN_MKK 0x5 +#define EEPROM_CHANNEL_PLAN_MKK1 0x6 +#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 +#define EEPROM_CHANNEL_PLAN_TELEC 0x8 +#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 +#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA +#define EEPROM_CHANNEL_PLAN_NCC 0xB +#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 + +#define EEPROM_CID_DEFAULT 0x0 +#define EEPROM_CID_TOSHIBA 0x4 +#define EEPROM_CID_CCX 0x10 +#define EEPROM_CID_QMI 0x0D +#define EEPROM_CID_WHQL 0xFE + +#define RTL8192_EEPROM_ID 0x8129 + +#define RTL8190_EEPROM_ID 0x8129 +#define EEPROM_HPON 0x02 +#define EEPROM_CLK 0x06 +#define EEPROM_TESTR 0x08 + +#define EEPROM_VID 0x0A +#define EEPROM_DID 0x0C +#define EEPROM_SVID 0x0E +#define EEPROM_SMID 0x10 + +#define EEPROM_MAC_ADDR 0x16 + +#define EEPROM_CCK_TX_PWR_INX 0x5A +#define EEPROM_HT40_1S_TX_PWR_INX 0x60 +#define EEPROM_HT40_2S_TX_PWR_INX_DIFF 0x66 +#define EEPROM_HT20_TX_PWR_INX_DIFF 0x69 +#define EEPROM_OFDM_TX_PWR_INX_DIFF 0x6C +#define EEPROM_HT40_MAX_PWR_OFFSET 0x6F +#define EEPROM_HT20_MAX_PWR_OFFSET 0x72 + +#define EEPROM_TSSI_A 0x76 +#define EEPROM_TSSI_B 0x77 +#define EEPROM_THERMAL_METER 0x78 +#define EEPROM_XTAL_K 0x78 +#define EEPROM_RF_OPT1 0x79 +#define EEPROM_RF_OPT2 0x7A +#define EEPROM_RF_OPT3 0x7B +#define EEPROM_RF_OPT4 0x7C +#define EEPROM_CHANNEL_PLAN 0x7D +#define EEPROM_VERSION 0x7E +#define EEPROM_CUSTOMER_ID 0x7F + +#define EEPROM_PWRDIFF 0x54 + +#define EEPROM_TXPOWERCCK 0x5A +#define EEPROM_TXPOWERHT40_1S 0x60 +#define EEPROM_TXPOWERHT40_2SDIFF 0x66 +#define EEPROM_TXPOWERHT20DIFF 0x69 +#define EEPROM_TXPOWER_OFDMDIFF 0x6C + +#define EEPROM_TXPWR_GROUP 0x6F + +#define EEPROM_TSSI_A 0x76 +#define EEPROM_TSSI_B 0x77 +#define EEPROM_THERMAL_METER 0x78 + +#define EEPROM_CHANNELPLAN 0x75 + +#define RF_OPTION1 0x79 +#define RF_OPTION2 0x7A +#define RF_OPTION3 0x7B +#define RF_OPTION4 0x7C + +#define STOPBECON BIT(6) +#define STOPHIGHT BIT(5) +#define STOPMGT BIT(4) +#define STOPVO BIT(3) +#define STOPVI BIT(2) +#define STOPBE BIT(1) +#define STOPBK BIT(0) + +#define RCR_APPFCS BIT(31) +#define RCR_APP_MIC BIT(30) +#define RCR_APP_ICV BIT(29) +#define RCR_APP_PHYST_RXFF BIT(28) +#define RCR_APP_BA_SSN BIT(27) +#define RCR_ENMBID BIT(24) +#define RCR_LSIGEN BIT(23) +#define RCR_MFBEN BIT(22) +#define RCR_HTC_LOC_CTRL BIT(14) +#define RCR_AMF BIT(13) +#define RCR_ACF BIT(12) +#define RCR_ADF BIT(11) +#define RCR_AICV BIT(9) +#define RCR_ACRC32 BIT(8) +#define RCR_CBSSID_BCN BIT(7) +#define RCR_CBSSID_DATA BIT(6) +#define RCR_CBSSID RCR_CBSSID_DATA +#define RCR_APWRMGT BIT(5) +#define RCR_ADD3 BIT(4) +#define RCR_AB BIT(3) +#define RCR_AM BIT(2) +#define RCR_APM BIT(1) +#define RCR_AAP BIT(0) +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 + +#define RSV_CTRL 0x001C +#define RD_CTRL 0x0524 + +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_USB_VID 0xFE60 +#define REG_USB_PID 0xFE62 +#define REG_USB_OPTIONAL 0xFE64 +#define REG_USB_CHIRP_K 0xFE65 +#define REG_USB_PHY 0xFE66 +#define REG_USB_MAC_ADDR 0xFE70 +#define REG_USB_HRPWM 0xFE58 +#define REG_USB_HCPWM 0xFE57 + +#define SW18_FPWM BIT(3) + +#define ISO_MD2PP BIT(0) +#define ISO_UA2USB BIT(1) +#define ISO_UD2CORE BIT(2) +#define ISO_PA2PCIE BIT(3) +#define ISO_PD2CORE BIT(4) +#define ISO_IP2MAC BIT(5) +#define ISO_DIOP BIT(6) +#define ISO_DIOE BIT(7) +#define ISO_EB2CORE BIT(8) +#define ISO_DIOR BIT(9) + +#define PWC_EV25V BIT(14) +#define PWC_EV12V BIT(15) + +#define FEN_BBRSTB BIT(0) +#define FEN_BB_GLB_RSTn BIT(1) +#define FEN_USBA BIT(2) +#define FEN_UPLL BIT(3) +#define FEN_USBD BIT(4) +#define FEN_DIO_PCIE BIT(5) +#define FEN_PCIEA BIT(6) +#define FEN_PPLL BIT(7) +#define FEN_PCIED BIT(8) +#define FEN_DIOE BIT(9) +#define FEN_CPUEN BIT(10) +#define FEN_DCORE BIT(11) +#define FEN_ELDR BIT(12) +#define FEN_DIO_RF BIT(13) +#define FEN_HWPDN BIT(14) +#define FEN_MREGEN BIT(15) + +#define PFM_LDALL BIT(0) +#define PFM_ALDN BIT(1) +#define PFM_LDKP BIT(2) +#define PFM_WOWL BIT(3) +#define EnPDN BIT(4) +#define PDN_PL BIT(5) +#define APFM_ONMAC BIT(8) +#define APFM_OFF BIT(9) +#define APFM_RSM BIT(10) +#define AFSM_HSUS BIT(11) +#define AFSM_PCIE BIT(12) +#define APDM_MAC BIT(13) +#define APDM_HOST BIT(14) +#define APDM_HPDN BIT(15) +#define RDY_MACON BIT(16) +#define SUS_HOST BIT(17) +#define ROP_ALD BIT(20) +#define ROP_PWR BIT(21) +#define ROP_SPS BIT(22) +#define SOP_MRST BIT(25) +#define SOP_FUSE BIT(26) +#define SOP_ABG BIT(27) +#define SOP_AMB BIT(28) +#define SOP_RCK BIT(29) +#define SOP_A8M BIT(30) +#define XOP_BTCK BIT(31) + +#define ANAD16V_EN BIT(0) +#define ANA8M BIT(1) +#define MACSLP BIT(4) +#define LOADER_CLK_EN BIT(5) +#define _80M_SSC_DIS BIT(7) +#define _80M_SSC_EN_HO BIT(8) +#define PHY_SSC_RSTB BIT(9) +#define SEC_CLK_EN BIT(10) +#define MAC_CLK_EN BIT(11) +#define SYS_CLK_EN BIT(12) +#define RING_CLK_EN BIT(13) + +#define BOOT_FROM_EEPROM BIT(4) +#define EEPROM_EN BIT(5) + +#define AFE_BGEN BIT(0) +#define AFE_MBEN BIT(1) +#define MAC_ID_EN BIT(7) + +#define WLOCK_ALL BIT(0) +#define WLOCK_00 BIT(1) +#define WLOCK_04 BIT(2) +#define WLOCK_08 BIT(3) +#define WLOCK_40 BIT(4) +#define R_DIS_PRST_0 BIT(5) +#define R_DIS_PRST_1 BIT(6) +#define LOCK_ALL_EN BIT(7) + +#define RF_EN BIT(0) +#define RF_RSTB BIT(1) +#define RF_SDMRSTB BIT(2) + +#define LDA15_EN BIT(0) +#define LDA15_STBY BIT(1) +#define LDA15_OBUF BIT(2) +#define LDA15_REG_VOS BIT(3) +#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) + +#define LDV12_EN BIT(0) +#define LDV12_SDBY BIT(1) +#define LPLDO_HSM BIT(2) +#define LPLDO_LSM_DIS BIT(3) +#define _LDV12_VADJ(x) (((x) & 0xF) << 4) + +#define XTAL_EN BIT(0) +#define XTAL_BSEL BIT(1) +#define _XTAL_BOSC(x) (((x) & 0x3) << 2) +#define _XTAL_CADJ(x) (((x) & 0xF) << 4) +#define XTAL_GATE_USB BIT(8) +#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) +#define XTAL_GATE_AFE BIT(11) +#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) +#define XTAL_RF_GATE BIT(14) +#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) +#define XTAL_GATE_DIG BIT(17) +#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) +#define XTAL_BT_GATE BIT(20) +#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) +#define _XTAL_GPIO(x) (((x) & 0x7) << 23) + +#define CKDLY_AFE BIT(26) +#define CKDLY_USB BIT(27) +#define CKDLY_DIG BIT(28) +#define CKDLY_BT BIT(29) + +#define APLL_EN BIT(0) +#define APLL_320_EN BIT(1) +#define APLL_FREF_SEL BIT(2) +#define APLL_EDGE_SEL BIT(3) +#define APLL_WDOGB BIT(4) +#define APLL_LPFEN BIT(5) + +#define APLL_REF_CLK_13MHZ 0x1 +#define APLL_REF_CLK_19_2MHZ 0x2 +#define APLL_REF_CLK_20MHZ 0x3 +#define APLL_REF_CLK_25MHZ 0x4 +#define APLL_REF_CLK_26MHZ 0x5 +#define APLL_REF_CLK_38_4MHZ 0x6 +#define APLL_REF_CLK_40MHZ 0x7 + +#define APLL_320EN BIT(14) +#define APLL_80EN BIT(15) +#define APLL_1MEN BIT(24) + +#define ALD_EN BIT(18) +#define EF_PD BIT(19) +#define EF_FLAG BIT(31) + +#define EF_TRPT BIT(7) +#define LDOE25_EN BIT(31) + +#define RSM_EN BIT(0) +#define Timer_EN BIT(4) + +#define TRSW0EN BIT(2) +#define TRSW1EN BIT(3) +#define EROM_EN BIT(4) +#define EnBT BIT(5) +#define EnUart BIT(8) +#define Uart_910 BIT(9) +#define EnPMAC BIT(10) +#define SIC_SWRST BIT(11) +#define EnSIC BIT(12) +#define SIC_23 BIT(13) +#define EnHDP BIT(14) +#define SIC_LBK BIT(15) + +#define LED0PL BIT(4) +#define LED1PL BIT(12) +#define LED0DIS BIT(7) + +#define MCUFWDL_EN BIT(0) +#define MCUFWDL_RDY BIT(1) +#define FWDL_ChkSum_rpt BIT(2) +#define MACINI_RDY BIT(3) +#define BBINI_RDY BIT(4) +#define RFINI_RDY BIT(5) +#define WINTINI_RDY BIT(6) +#define CPRST BIT(23) + +#define XCLK_VLD BIT(0) +#define ACLK_VLD BIT(1) +#define UCLK_VLD BIT(2) +#define PCLK_VLD BIT(3) +#define PCIRSTB BIT(4) +#define V15_VLD BIT(5) +#define TRP_B15V_EN BIT(7) +#define SIC_IDLE BIT(8) +#define BD_MAC2 BIT(9) +#define BD_MAC1 BIT(10) +#define IC_MACPHY_MODE BIT(11) +#define PAD_HWPD_IDN BIT(22) +#define TRP_VAUX_EN BIT(23) +#define TRP_BT_EN BIT(24) +#define BD_PKG_SEL BIT(25) +#define BD_HCI_SEL BIT(26) +#define TYPE_ID BIT(27) + +#define CHIP_VER_RTL_MASK 0xF000 +#define CHIP_VER_RTL_SHIFT 12 + +#define REG_LBMODE (REG_CR + 3) + +#define HCI_TXDMA_EN BIT(0) +#define HCI_RXDMA_EN BIT(1) +#define TXDMA_EN BIT(2) +#define RXDMA_EN BIT(3) +#define PROTOCOL_EN BIT(4) +#define SCHEDULE_EN BIT(5) +#define MACTXEN BIT(6) +#define MACRXEN BIT(7) +#define ENSWBCN BIT(8) +#define ENSEC BIT(9) + +#define _NETTYPE(x) (((x) & 0x3) << 16) +#define MASK_NETTYPE 0x30000 +#define NT_NO_LINK 0x0 +#define NT_LINK_AD_HOC 0x1 +#define NT_LINK_AP 0x2 +#define NT_AS_AP 0x3 + +#define _LBMODE(x) (((x) & 0xF) << 24) +#define MASK_LBMODE 0xF000000 +#define LOOPBACK_NORMAL 0x0 +#define LOOPBACK_IMMEDIATELY 0xB +#define LOOPBACK_MAC_DELAY 0x3 +#define LOOPBACK_PHY 0x1 +#define LOOPBACK_DMA 0x7 + +#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) +#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) +#define _PSRX_MASK 0xF +#define _PSTX_MASK 0xF0 +#define _PSRX(x) (x) +#define _PSTX(x) ((x) << 4) + +#define PBP_64 0x0 +#define PBP_128 0x1 +#define PBP_256 0x2 +#define PBP_512 0x3 +#define PBP_1024 0x4 + +#define RXDMA_ARBBW_EN BIT(0) +#define RXSHFT_EN BIT(1) +#define RXDMA_AGG_EN BIT(2) +#define QS_VO_QUEUE BIT(8) +#define QS_VI_QUEUE BIT(9) +#define QS_BE_QUEUE BIT(10) +#define QS_BK_QUEUE BIT(11) +#define QS_MANAGER_QUEUE BIT(12) +#define QS_HIGH_QUEUE BIT(13) + +#define HQSEL_VOQ BIT(0) +#define HQSEL_VIQ BIT(1) +#define HQSEL_BEQ BIT(2) +#define HQSEL_BKQ BIT(3) +#define HQSEL_MGTQ BIT(4) +#define HQSEL_HIQ BIT(5) + +#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) +#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) +#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) +#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) +#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) +#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) + +#define QUEUE_LOW 1 +#define QUEUE_NORMAL 2 +#define QUEUE_HIGH 3 + +#define _LLT_NO_ACTIVE 0x0 +#define _LLT_WRITE_ACCESS 0x1 +#define _LLT_READ_ACCESS 0x2 + +#define _LLT_INIT_DATA(x) ((x) & 0xFF) +#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) +#define _LLT_OP(x) (((x) & 0x3) << 30) +#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) + +#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) +#define BB_WRITE_EN BIT(30) +#define BB_READ_EN BIT(31) + +#define _HPQ(x) ((x) & 0xFF) +#define _LPQ(x) (((x) & 0xFF) << 8) +#define _PUBQ(x) (((x) & 0xFF) << 16) +#define _NPQ(x) ((x) & 0xFF) + +#define HPQ_PUBLIC_DIS BIT(24) +#define LPQ_PUBLIC_DIS BIT(25) +#define LD_RQPN BIT(31) + +#define BCN_VALID BIT(16) +#define BCN_HEAD(x) (((x) & 0xFF) << 8) +#define BCN_HEAD_MASK 0xFF00 + +#define BLK_DESC_NUM_SHIFT 4 +#define BLK_DESC_NUM_MASK 0xF + +#define DROP_DATA_EN BIT(9) + +#define EN_AMPDU_RTY_NEW BIT(7) + +#define _INIRTSMCS_SEL(x) ((x) & 0x3F) + +#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) +#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) + +#define RATE_REG_BITMAP_ALL 0xFFFFF + +#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) + +#define _RRSR_RSC(x) (((x) & 0x3) << 21) +#define RRSR_RSC_RESERVED 0x0 +#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 +#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 +#define RRSR_RSC_DUPLICATE_MODE 0x3 + +#define USE_SHORT_G1 BIT(20) + +#define _AGGLMT_MCS0(x) ((x) & 0xF) +#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) +#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) +#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) +#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) +#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) +#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) +#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) + +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_LONG_SHIFT 0 + +#define _DARF_RC1(x) ((x) & 0x1F) +#define _DARF_RC2(x) (((x) & 0x1F) << 8) +#define _DARF_RC3(x) (((x) & 0x1F) << 16) +#define _DARF_RC4(x) (((x) & 0x1F) << 24) +#define _DARF_RC5(x) ((x) & 0x1F) +#define _DARF_RC6(x) (((x) & 0x1F) << 8) +#define _DARF_RC7(x) (((x) & 0x1F) << 16) +#define _DARF_RC8(x) (((x) & 0x1F) << 24) + +#define _RARF_RC1(x) ((x) & 0x1F) +#define _RARF_RC2(x) (((x) & 0x1F) << 8) +#define _RARF_RC3(x) (((x) & 0x1F) << 16) +#define _RARF_RC4(x) (((x) & 0x1F) << 24) +#define _RARF_RC5(x) ((x) & 0x1F) +#define _RARF_RC6(x) (((x) & 0x1F) << 8) +#define _RARF_RC7(x) (((x) & 0x1F) << 16) +#define _RARF_RC8(x) (((x) & 0x1F) << 24) + +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 +#define AC_PARAM_ECW_MAX_OFFSET 12 +#define AC_PARAM_ECW_MIN_OFFSET 8 +#define AC_PARAM_AIFS_OFFSET 0 + +#define _AIFS(x) (x) +#define _ECW_MAX_MIN(x) ((x) << 8) +#define _TXOP_LIMIT(x) ((x) << 16) + +#define _BCNIFS(x) ((x) & 0xFF) +#define _BCNECW(x) ((((x) & 0xF)) << 8) + +#define _LRL(x) ((x) & 0x3F) +#define _SRL(x) (((x) & 0x3F) << 8) + +#define _SIFS_CCK_CTX(x) ((x) & 0xFF) +#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8); + +#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) +#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8); + +#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) + +#define DIS_EDCA_CNT_DWN BIT(11) + +#define EN_MBSSID BIT(1) +#define EN_TXBCN_RPT BIT(2) +#define EN_BCN_FUNCTION BIT(3) + +#define TSFTR_RST BIT(0) +#define TSFTR1_RST BIT(1) + +#define STOP_BCNQ BIT(6) + +#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) +#define DIS_TSF_UDT0_TEST_CHIP BIT(5) + +#define AcmHw_HwEn BIT(0) +#define AcmHw_BeqEn BIT(1) +#define AcmHw_ViqEn BIT(2) +#define AcmHw_VoqEn BIT(3) +#define AcmHw_BeqStatus BIT(4) +#define AcmHw_ViqStatus BIT(5) +#define AcmHw_VoqStatus BIT(6) + +#define APSDOFF BIT(6) +#define APSDOFF_STATUS BIT(7) + +#define BW_20MHZ BIT(2) + +#define RATE_BITMAP_ALL 0xFFFFF + +#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 + +#define TSFRST BIT(0) +#define DIS_GCLK BIT(1) +#define PAD_SEL BIT(2) +#define PWR_ST BIT(6) +#define PWRBIT_OW_EN BIT(7) +#define ACRC BIT(8) +#define CFENDFORM BIT(9) +#define ICV BIT(10) + +#define AAP BIT(0) +#define APM BIT(1) +#define AM BIT(2) +#define AB BIT(3) +#define ADD3 BIT(4) +#define APWRMGT BIT(5) +#define CBSSID BIT(6) +#define CBSSID_DATA BIT(6) +#define CBSSID_BCN BIT(7) +#define ACRC32 BIT(8) +#define AICV BIT(9) +#define ADF BIT(11) +#define ACF BIT(12) +#define AMF BIT(13) +#define HTC_LOC_CTRL BIT(14) +#define UC_DATA_EN BIT(16) +#define BM_DATA_EN BIT(17) +#define MFBEN BIT(22) +#define LSIGEN BIT(23) +#define EnMBID BIT(24) +#define APP_BASSN BIT(27) +#define APP_PHYSTS BIT(28) +#define APP_ICV BIT(29) +#define APP_MIC BIT(30) +#define APP_FCS BIT(31) + +#define _MIN_SPACE(x) ((x) & 0x7) +#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) + +#define RXERR_TYPE_OFDM_PPDU 0 +#define RXERR_TYPE_OFDM_FALSE_ALARM 1 +#define RXERR_TYPE_OFDM_MPDU_OK 2 +#define RXERR_TYPE_OFDM_MPDU_FAIL 3 +#define RXERR_TYPE_CCK_PPDU 4 +#define RXERR_TYPE_CCK_FALSE_ALARM 5 +#define RXERR_TYPE_CCK_MPDU_OK 6 +#define RXERR_TYPE_CCK_MPDU_FAIL 7 +#define RXERR_TYPE_HT_PPDU 8 +#define RXERR_TYPE_HT_FALSE_ALARM 9 +#define RXERR_TYPE_HT_MPDU_TOTAL 10 +#define RXERR_TYPE_HT_MPDU_OK 11 +#define RXERR_TYPE_HT_MPDU_FAIL 12 +#define RXERR_TYPE_RX_FULL_DROP 15 + +#define RXERR_COUNTER_MASK 0xFFFFF +#define RXERR_RPT_RST BIT(27) +#define _RXERR_RPT_SEL(type) ((type) << 28) + +#define SCR_TxUseDK BIT(0) +#define SCR_RxUseDK BIT(1) +#define SCR_TxEncEnable BIT(2) +#define SCR_RxDecEnable BIT(3) +#define SCR_SKByA2 BIT(4) +#define SCR_NoSKMC BIT(5) +#define SCR_TXBCUSEDK BIT(6) +#define SCR_RXBCUSEDK BIT(7) + +#define USB_IS_HIGH_SPEED 0 +#define USB_IS_FULL_SPEED 1 +#define USB_SPEED_MASK BIT(5) + +#define USB_NORMAL_SIE_EP_MASK 0xF +#define USB_NORMAL_SIE_EP_SHIFT 4 + +#define USB_TEST_EP_MASK 0x30 +#define USB_TEST_EP_SHIFT 4 + +#define USB_AGG_EN BIT(3) + +#define MAC_ADDR_LEN 6 +#define LAST_ENTRY_OF_TX_PKT_BUFFER 255 + +#define POLLING_LLT_THRESHOLD 20 +#define POLLING_READY_TIMEOUT_COUNT 1000 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) +#define EPROM_CMD_CONFIG 0x3 +#define EPROM_CMD_LOAD 1 + +#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE + +#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) + +#define RPMAC_RESET 0x100 +#define RPMAC_TXSTART 0x104 +#define RPMAC_TXLEGACYSIG 0x108 +#define RPMAC_TXHTSIG1 0x10c +#define RPMAC_TXHTSIG2 0x110 +#define RPMAC_PHYDEBUG 0x114 +#define RPMAC_TXPACKETNUM 0x118 +#define RPMAC_TXIDLE 0x11c +#define RPMAC_TXMACHEADER0 0x120 +#define RPMAC_TXMACHEADER1 0x124 +#define RPMAC_TXMACHEADER2 0x128 +#define RPMAC_TXMACHEADER3 0x12c +#define RPMAC_TXMACHEADER4 0x130 +#define RPMAC_TXMACHEADER5 0x134 +#define RPMAC_TXDADATYPE 0x138 +#define RPMAC_TXRANDOMSEED 0x13c +#define RPMAC_CCKPLCPPREAMBLE 0x140 +#define RPMAC_CCKPLCPHEADER 0x144 +#define RPMAC_CCKCRC16 0x148 +#define RPMAC_OFDMRXCRC32OK 0x170 +#define RPMAC_OFDMRXCRC32Er 0x174 +#define RPMAC_OFDMRXPARITYER 0x178 +#define RPMAC_OFDMRXCRC8ER 0x17c +#define RPMAC_CCKCRXRC16ER 0x180 +#define RPMAC_CCKCRXRC32ER 0x184 +#define RPMAC_CCKCRXRC32OK 0x188 +#define RPMAC_TXSTATUS 0x18c + +#define RFPGA0_RFMOD 0x800 + +#define RFPGA0_TXINFO 0x804 +#define RFPGA0_PSDFUNCTION 0x808 + +#define RFPGA0_TXGAINSTAGE 0x80c + +#define RFPGA0_RFTIMING1 0x810 +#define RFPGA0_RFTIMING2 0x814 + +#define RFPGA0_XA_HSSIPARAMETER1 0x820 +#define RFPGA0_XA_HSSIPARAMETER2 0x824 +#define RFPGA0_XB_HSSIPARAMETER1 0x828 +#define RFPGA0_XB_HSSIPARAMETER2 0x82c + +#define RFPGA0_XA_LSSIPARAMETER 0x840 +#define RFPGA0_XB_LSSIPARAMETER 0x844 + +#define RFPGA0_RFWAKEUPPARAMETER 0x850 +#define RFPGA0_RFSLEEPUPPARAMETER 0x854 + +#define RFPGA0_XAB_SWITCHCONTROL 0x858 +#define RFPGA0_XCD_SWITCHCONTROL 0x85c + +#define RFPGA0_XA_RFINTERFACEOE 0x860 +#define RFPGA0_XB_RFINTERFACEOE 0x864 + +#define RFPGA0_XAB_RFINTERFACESW 0x870 +#define RFPGA0_XCD_RFINTERFACESW 0x874 + +#define rFPGA0_XAB_RFPARAMETER 0x878 +#define rFPGA0_XCD_RFPARAMETER 0x87c + +#define RFPGA0_ANALOGPARAMETER1 0x880 +#define RFPGA0_ANALOGPARAMETER2 0x884 +#define RFPGA0_ANALOGPARAMETER3 0x888 +#define RFPGA0_ANALOGPARAMETER4 0x88c + +#define RFPGA0_XA_LSSIREADBACK 0x8a0 +#define RFPGA0_XB_LSSIREADBACK 0x8a4 +#define RFPGA0_XC_LSSIREADBACK 0x8a8 +#define RFPGA0_XD_LSSIREADBACK 0x8ac + +#define RFPGA0_PSDREPORT 0x8b4 +#define TRANSCEIVEA_HSPI_READBACK 0x8b8 +#define TRANSCEIVEB_HSPI_READBACK 0x8bc +#define RFPGA0_XAB_RFINTERFACERB 0x8e0 +#define RFPGA0_XCD_RFINTERFACERB 0x8e4 + +#define RFPGA1_RFMOD 0x900 + +#define RFPGA1_TXBLOCK 0x904 +#define RFPGA1_DEBUGSELECT 0x908 +#define RFPGA1_TXINFO 0x90c + +#define RCCK0_SYSTEM 0xa00 + +#define RCCK0_AFESETTING 0xa04 +#define RCCK0_CCA 0xa08 + +#define RCCK0_RXAGC1 0xa0c +#define RCCK0_RXAGC2 0xa10 + +#define RCCK0_RXHP 0xa14 + +#define RCCK0_DSPPARAMETER1 0xa18 +#define RCCK0_DSPPARAMETER2 0xa1c + +#define RCCK0_TXFILTER1 0xa20 +#define RCCK0_TXFILTER2 0xa24 +#define RCCK0_DEBUGPORT 0xa28 +#define RCCK0_FALSEALARMREPORT 0xa2c +#define RCCK0_TRSSIREPORT 0xa50 +#define RCCK0_RXREPORT 0xa54 +#define RCCK0_FACOUNTERLOWER 0xa5c +#define RCCK0_FACOUNTERUPPER 0xa58 + +#define ROFDM0_LSTF 0xc00 + +#define ROFDM0_TRXPATHENABLE 0xc04 +#define ROFDM0_TRMUXPAR 0xc08 +#define ROFDM0_TRSWISOLATION 0xc0c + +#define ROFDM0_XARXAFE 0xc10 +#define ROFDM0_XARXIQIMBALANCE 0xc14 +#define ROFDM0_XBRXAFE 0xc18 +#define ROFDM0_XBRXIQIMBALANCE 0xc1c +#define ROFDM0_XCRXAFE 0xc20 +#define ROFDM0_XCRXIQIMBANLANCE 0xc24 +#define ROFDM0_XDRXAFE 0xc28 +#define ROFDM0_XDRXIQIMBALANCE 0xc2c + +#define ROFDM0_RXDETECTOR1 0xc30 +#define ROFDM0_RXDETECTOR2 0xc34 +#define ROFDM0_RXDETECTOR3 0xc38 +#define ROFDM0_RXDETECTOR4 0xc3c + +#define ROFDM0_RXDSP 0xc40 +#define ROFDM0_CFOANDDAGC 0xc44 +#define ROFDM0_CCADROPTHRESHOLD 0xc48 +#define ROFDM0_ECCATHRESHOLD 0xc4c + +#define ROFDM0_XAAGCCORE1 0xc50 +#define ROFDM0_XAAGCCORE2 0xc54 +#define ROFDM0_XBAGCCORE1 0xc58 +#define ROFDM0_XBAGCCORE2 0xc5c +#define ROFDM0_XCAGCCORE1 0xc60 +#define ROFDM0_XCAGCCORE2 0xc64 +#define ROFDM0_XDAGCCORE1 0xc68 +#define ROFDM0_XDAGCCORE2 0xc6c + +#define ROFDM0_AGCPARAMETER1 0xc70 +#define ROFDM0_AGCPARAMETER2 0xc74 +#define ROFDM0_AGCRSSITABLE 0xc78 +#define ROFDM0_HTSTFAGC 0xc7c + +#define ROFDM0_XATXIQIMBALANCE 0xc80 +#define ROFDM0_XATXAFE 0xc84 +#define ROFDM0_XBTXIQIMBALANCE 0xc88 +#define ROFDM0_XBTXAFE 0xc8c +#define ROFDM0_XCTXIQIMBALANCE 0xc90 +#define ROFDM0_XCTXAFE 0xc94 +#define ROFDM0_XDTXIQIMBALANCE 0xc98 +#define ROFDM0_XDTXAFE 0xc9c + +#define ROFDM0_RXIQEXTANTA 0xca0 + +#define ROFDM0_RXHPPARAMETER 0xce0 +#define ROFDM0_TXPSEUDONOISEWGT 0xce4 +#define ROFDM0_FRAMESYNC 0xcf0 +#define ROFDM0_DFSREPORT 0xcf4 +#define ROFDM0_TXCOEFF1 0xca4 +#define ROFDM0_TXCOEFF2 0xca8 +#define ROFDM0_TXCOEFF3 0xcac +#define ROFDM0_TXCOEFF4 0xcb0 +#define ROFDM0_TXCOEFF5 0xcb4 +#define ROFDM0_TXCOEFF6 0xcb8 + +#define ROFDM1_LSTF 0xd00 +#define ROFDM1_TRXPATHENABLE 0xd04 + +#define ROFDM1_CF0 0xd08 +#define ROFDM1_CSI1 0xd10 +#define ROFDM1_SBD 0xd14 +#define ROFDM1_CSI2 0xd18 +#define ROFDM1_CFOTRACKING 0xd2c +#define ROFDM1_TRXMESAURE1 0xd34 +#define ROFDM1_INTFDET 0xd3c +#define ROFDM1_PSEUDONOISESTATEAB 0xd50 +#define ROFDM1_PSEUDONOISESTATECD 0xd54 +#define ROFDM1_RXPSEUDONOISEWGT 0xd58 + +#define ROFDM_PHYCOUNTER1 0xda0 +#define ROFDM_PHYCOUNTER2 0xda4 +#define ROFDM_PHYCOUNTER3 0xda8 + +#define ROFDM_SHORTCFOAB 0xdac +#define ROFDM_SHORTCFOCD 0xdb0 +#define ROFDM_LONGCFOAB 0xdb4 +#define ROFDM_LONGCFOCD 0xdb8 +#define ROFDM_TAILCF0AB 0xdbc +#define ROFDM_TAILCF0CD 0xdc0 +#define ROFDM_PWMEASURE1 0xdc4 +#define ROFDM_PWMEASURE2 0xdc8 +#define ROFDM_BWREPORT 0xdcc +#define ROFDM_AGCREPORT 0xdd0 +#define ROFDM_RXSNR 0xdd4 +#define ROFDM_RXEVMCSI 0xdd8 +#define ROFDM_SIGREPORT 0xddc + +#define RTXAGC_A_RATE18_06 0xe00 +#define RTXAGC_A_RATE54_24 0xe04 +#define RTXAGC_A_CCK1_MCS32 0xe08 +#define RTXAGC_A_MCS03_MCS00 0xe10 +#define RTXAGC_A_MCS07_MCS04 0xe14 +#define RTXAGC_A_MCS11_MCS08 0xe18 +#define RTXAGC_A_MCS15_MCS12 0xe1c + +#define RTXAGC_B_RATE18_06 0x830 +#define RTXAGC_B_RATE54_24 0x834 +#define RTXAGC_B_CCK1_55_MCS32 0x838 +#define RTXAGC_B_MCS03_MCS00 0x83c +#define RTXAGC_B_MCS07_MCS04 0x848 +#define RTXAGC_B_MCS11_MCS08 0x84c +#define RTXAGC_B_MCS15_MCS12 0x868 +#define RTXAGC_B_CCK11_A_CCK2_11 0x86c + +#define RZEBRA1_HSSIENABLE 0x0 +#define RZEBRA1_TRXENABLE1 0x1 +#define RZEBRA1_TRXENABLE2 0x2 +#define RZEBRA1_AGC 0x4 +#define RZEBRA1_CHARGEPUMP 0x5 +#define RZEBRA1_CHANNEL 0x7 + +#define RZEBRA1_TXGAIN 0x8 +#define RZEBRA1_TXLPF 0x9 +#define RZEBRA1_RXLPF 0xb +#define RZEBRA1_RXHPFCORNER 0xc + +#define RGLOBALCTRL 0 +#define RRTL8256_TXLPF 19 +#define RRTL8256_RXLPF 11 +#define RRTL8258_TXLPF 0x11 +#define RRTL8258_RXLPF 0x13 +#define RRTL8258_RSSILPF 0xa + +#define RF_AC 0x00 + +#define RF_IQADJ_G1 0x01 +#define RF_IQADJ_G2 0x02 +#define RF_POW_TRSW 0x05 + +#define RF_GAIN_RX 0x06 +#define RF_GAIN_TX 0x07 + +#define RF_TXM_IDAC 0x08 +#define RF_BS_IQGEN 0x0F + +#define RF_MODE1 0x10 +#define RF_MODE2 0x11 + +#define RF_RX_AGC_HP 0x12 +#define RF_TX_AGC 0x13 +#define RF_BIAS 0x14 +#define RF_IPA 0x15 +#define RF_POW_ABILITY 0x17 +#define RF_MODE_AG 0x18 +#define RRFCHANNEL 0x18 +#define RF_CHNLBW 0x18 +#define RF_TOP 0x19 + +#define RF_RX_G1 0x1A +#define RF_RX_G2 0x1B + +#define RF_RX_BB2 0x1C +#define RF_RX_BB1 0x1D + +#define RF_RCK1 0x1E +#define RF_RCK2 0x1F + +#define RF_TX_G1 0x20 +#define RF_TX_G2 0x21 +#define RF_TX_G3 0x22 + +#define RF_TX_BB1 0x23 +#define RF_T_METER 0x24 + +#define RF_SYN_G1 0x25 +#define RF_SYN_G2 0x26 +#define RF_SYN_G3 0x27 +#define RF_SYN_G4 0x28 +#define RF_SYN_G5 0x29 +#define RF_SYN_G6 0x2A +#define RF_SYN_G7 0x2B +#define RF_SYN_G8 0x2C + +#define RF_RCK_OS 0x30 +#define RF_TXPA_G1 0x31 +#define RF_TXPA_G2 0x32 +#define RF_TXPA_G3 0x33 + +#define BBBRESETB 0x100 +#define BGLOBALRESETB 0x200 +#define BOFDMTXSTART 0x4 +#define BCCKTXSTART 0x8 +#define BCRC32DEBUG 0x100 +#define BPMACLOOPBACK 0x10 +#define BTXLSIG 0xffffff +#define BOFDMTXRATE 0xf +#define BOFDMTXRESERVED 0x10 +#define BOFDMTXLENGTH 0x1ffe0 +#define BOFDMTXPARITY 0x20000 +#define BTXHTSIG1 0xffffff +#define BTXHTMCSRATE 0x7f +#define BTXHTBW 0x80 +#define BTXHTLENGTH 0xffff00 +#define BTXHTSIG2 0xffffff +#define BTXHTSMOOTHING 0x1 +#define BTXHTSOUNDING 0x2 +#define BTXHTRESERVED 0x4 +#define BTXHTAGGREATION 0x8 +#define BTXHTSTBC 0x30 +#define BTXHTADVANCECODING 0x40 +#define BTXHTSHORTGI 0x80 +#define BTXHTNUMBERHT_LT F 0x300 +#define BTXHTCRC8 0x3fc00 +#define BCOUNTERRESET 0x10000 +#define BNUMOFOFDMTX 0xffff +#define BNUMOFCCKTX 0xffff0000 +#define BTXIDLEINTERVAL 0xffff +#define BOFDMSERVICE 0xffff0000 +#define BTXMACHEADER 0xffffffff +#define BTXDATAINIT 0xff +#define BTXHTMODE 0x100 +#define BTXDATATYPE 0x30000 +#define BTXRANDOMSEED 0xffffffff +#define BCCKTXPREAMBLE 0x1 +#define BCCKTXSFD 0xffff0000 +#define BCCKTXSIG 0xff +#define BCCKTXSERVICE 0xff00 +#define BCCKLENGTHEXT 0x8000 +#define BCCKTXLENGHT 0xffff0000 +#define BCCKTXCRC16 0xffff +#define BCCKTXSTATUS 0x1 +#define BOFDMTXSTATUS 0x2 +#define IS_BB_REG_OFFSET_92S(_Offset) \ + ((_Offset >= 0x800) && (_Offset <= 0xfff)) + +#define BRFMOD 0x1 +#define BJAPANMODE 0x2 +#define BCCKTXSC 0x30 +#define BCCKEN 0x1000000 +#define BOFDMEN 0x2000000 + +#define BOFDMRXADCPHASE 0x10000 +#define BOFDMTXDACPHASE 0x40000 +#define BXATXAGC 0x3f + +#define BXBTXAGC 0xf00 +#define BXCTXAGC 0xf000 +#define BXDTXAGC 0xf0000 + +#define BPASTART 0xf0000000 +#define BTRSTART 0x00f00000 +#define BRFSTART 0x0000f000 +#define BBBSTART 0x000000f0 +#define BBBCCKSTART 0x0000000f +#define BPAEND 0xf +#define BTREND 0x0f000000 +#define BRFEND 0x000f0000 +#define BCCAMASK 0x000000f0 +#define BR2RCCAMASK 0x00000f00 +#define BHSSI_R2TDELAY 0xf8000000 +#define BHSSI_T2RDELAY 0xf80000 +#define BCONTXHSSI 0x400 +#define BIGFROMCCK 0x200 +#define BAGCADDRESS 0x3f +#define BRXHPTX 0x7000 +#define BRXHP2RX 0x38000 +#define BRXHPCCKINI 0xc0000 +#define BAGCTXCODE 0xc00000 +#define BAGCRXCODE 0x300000 + +#define B3WIREDATALENGTH 0x800 +#define B3WIREADDREAALENGTH 0x400 + +#define B3WIRERFPOWERDOWN 0x1 +#define B5GPAPEPOLARITY 0x40000000 +#define B2GPAPEPOLARITY 0x80000000 +#define BRFSW_TXDEFAULTANT 0x3 +#define BRFSW_TXOPTIONANT 0x30 +#define BRFSW_RXDEFAULTANT 0x300 +#define BRFSW_RXOPTIONANT 0x3000 +#define BRFSI_3WIREDATA 0x1 +#define BRFSI_3WIRECLOCK 0x2 +#define BRFSI_3WIRELOAD 0x4 +#define BRFSI_3WIRERW 0x8 +#define BRFSI_3WIRE 0xf + +#define BRFSI_RFENV 0x10 + +#define BRFSI_TRSW 0x20 +#define BRFSI_TRSWB 0x40 +#define BRFSI_ANTSW 0x100 +#define BRFSI_ANTSWB 0x200 +#define BRFSI_PAPE 0x400 +#define BRFSI_PAPE5G 0x800 +#define BBANDSELECT 0x1 +#define BHTSIG2_GI 0x80 +#define BHTSIG2_SMOOTHING 0x01 +#define BHTSIG2_SOUNDING 0x02 +#define BHTSIG2_AGGREATON 0x08 +#define BHTSIG2_STBC 0x30 +#define BHTSIG2_ADVCODING 0x40 +#define BHTSIG2_NUMOFHTLTF 0x300 +#define BHTSIG2_CRC8 0x3fc +#define BHTSIG1_MCS 0x7f +#define BHTSIG1_BANDWIDTH 0x80 +#define BHTSIG1_HTLENGTH 0xffff +#define BLSIG_RATE 0xf +#define BLSIG_RESERVED 0x10 +#define BLSIG_LENGTH 0x1fffe +#define BLSIG_PARITY 0x20 +#define BCCKRXPHASE 0x4 + +#define BLSSIREADADDRESS 0x7f800000 +#define BLSSIREADEDGE 0x80000000 + +#define BLSSIREADBACKDATA 0xfffff + +#define BLSSIREADOKFLAG 0x1000 +#define BCCKSAMPLERATE 0x8 +#define BREGULATOR0STANDBY 0x1 +#define BREGULATORPLLSTANDBY 0x2 +#define BREGULATOR1STANDBY 0x4 +#define BPLLPOWERUP 0x8 +#define BDPLLPOWERUP 0x10 +#define BDA10POWERUP 0x20 +#define BAD7POWERUP 0x200 +#define BDA6POWERUP 0x2000 +#define BXTALPOWERUP 0x4000 +#define B40MDCLKPOWERUP 0x8000 +#define BDA6DEBUGMODE 0x20000 +#define BDA6SWING 0x380000 + +#define BADCLKPHASE 0x4000000 +#define B80MCLKDELAY 0x18000000 +#define BAFEWATCHDOGENABLE 0x20000000 + +#define BXTALCAP01 0xc0000000 +#define BXTALCAP23 0x3 +#define BXTALCAP92X 0x0f000000 +#define BXTALCAP 0x0f000000 + +#define BINTDIFCLKENABLE 0x400 +#define BEXTSIGCLKENABLE 0x800 +#define BBANDGAP_MBIAS_POWERUP 0x10000 +#define BAD11SH_GAIN 0xc0000 +#define BAD11NPUT_RANGE 0x700000 +#define BAD110P_CURRENT 0x3800000 +#define BLPATH_LOOPBACK 0x4000000 +#define BQPATH_LOOPBACK 0x8000000 +#define BAFE_LOOPBACK 0x10000000 +#define BDA10_SWING 0x7e0 +#define BDA10_REVERSE 0x800 +#define BDA_CLK_SOURCE 0x1000 +#define BDA7INPUT_RANGE 0x6000 +#define BDA7_GAIN 0x38000 +#define BDA7OUTPUT_CM_MODE 0x40000 +#define BDA7INPUT_CM_MODE 0x380000 +#define BDA7CURRENT 0xc00000 +#define BREGULATOR_ADJUST 0x7000000 +#define BAD11POWERUP_ATTX 0x1 +#define BDA10PS_ATTX 0x10 +#define BAD11POWERUP_ATRX 0x100 +#define BDA10PS_ATRX 0x1000 +#define BCCKRX_AGC_FORMAT 0x200 +#define BPSDFFT_SAMPLE_POINT 0xc000 +#define BPSD_AVERAGE_NUM 0x3000 +#define BIQPATH_CONTROL 0xc00 +#define BPSD_FREQ 0x3ff +#define BPSD_ANTENNA_PATH 0x30 +#define BPSD_IQ_SWITCH 0x40 +#define BPSD_RX_TRIGGER 0x400000 +#define BPSD_TX_TRIGGER 0x80000000 +#define BPSD_SINE_TONE_SCALE 0x7f000000 +#define BPSD_REPORT 0xffff + +#define BOFDM_TXSC 0x30000000 +#define BCCK_TXON 0x1 +#define BOFDM_TXON 0x2 +#define BDEBUG_PAGE 0xfff +#define BDEBUG_ITEM 0xff +#define BANTL 0x10 +#define BANT_NONHT 0x100 +#define BANT_HT1 0x1000 +#define BANT_HT2 0x10000 +#define BANT_HT1S1 0x100000 +#define BANT_NONHTS1 0x1000000 + +#define BCCK_BBMODE 0x3 +#define BCCK_TXPOWERSAVING 0x80 +#define BCCK_RXPOWERSAVING 0x40 + +#define BCCK_SIDEBAND 0x10 + +#define BCCK_SCRAMBLE 0x8 +#define BCCK_ANTDIVERSITY 0x8000 +#define BCCK_CARRIER_RECOVERY 0x4000 +#define BCCK_TXRATE 0x3000 +#define BCCK_DCCANCEL 0x0800 +#define BCCK_ISICANCEL 0x0400 +#define BCCK_MATCH_FILTER 0x0200 +#define BCCK_EQUALIZER 0x0100 +#define BCCK_PREAMBLE_DETECT 0x800000 +#define BCCK_FAST_FALSECCA 0x400000 +#define BCCK_CH_ESTSTART 0x300000 +#define BCCK_CCA_COUNT 0x080000 +#define BCCK_CS_LIM 0x070000 +#define BCCK_BIST_MODE 0x80000000 +#define BCCK_CCAMASK 0x40000000 +#define BCCK_TX_DAC_PHASE 0x4 +#define BCCK_RX_ADC_PHASE 0x20000000 +#define BCCKR_CP_MODE 0x0100 +#define BCCK_TXDC_OFFSET 0xf0 +#define BCCK_RXDC_OFFSET 0xf +#define BCCK_CCA_MODE 0xc000 +#define BCCK_FALSECS_LIM 0x3f00 +#define BCCK_CS_RATIO 0xc00000 +#define BCCK_CORGBIT_SEL 0x300000 +#define BCCK_PD_LIM 0x0f0000 +#define BCCK_NEWCCA 0x80000000 +#define BCCK_RXHP_OF_IG 0x8000 +#define BCCK_RXIG 0x7f00 +#define BCCK_LNA_POLARITY 0x800000 +#define BCCK_RX1ST_BAIN 0x7f0000 +#define BCCK_RF_EXTEND 0x20000000 +#define BCCK_RXAGC_SATLEVEL 0x1f000000 +#define BCCK_RXAGC_SATCOUNT 0xe0 +#define bCCKRxRFSettle 0x1f +#define BCCK_FIXED_RXAGC 0x8000 +#define BCCK_ANTENNA_POLARITY 0x2000 +#define BCCK_TXFILTER_TYPE 0x0c00 +#define BCCK_RXAGC_REPORTTYPE 0x0300 +#define BCCK_RXDAGC_EN 0x80000000 +#define BCCK_RXDAGC_PERIOD 0x20000000 +#define BCCK_RXDAGC_SATLEVEL 0x1f000000 +#define BCCK_TIMING_RECOVERY 0x800000 +#define BCCK_TXC0 0x3f0000 +#define BCCK_TXC1 0x3f000000 +#define BCCK_TXC2 0x3f +#define BCCK_TXC3 0x3f00 +#define BCCK_TXC4 0x3f0000 +#define BCCK_TXC5 0x3f000000 +#define BCCK_TXC6 0x3f +#define BCCK_TXC7 0x3f00 +#define BCCK_DEBUGPORT 0xff0000 +#define BCCK_DAC_DEBUG 0x0f000000 +#define BCCK_FALSEALARM_ENABLE 0x8000 +#define BCCK_FALSEALARM_READ 0x4000 +#define BCCK_TRSSI 0x7f +#define BCCK_RXAGC_REPORT 0xfe +#define BCCK_RXREPORT_ANTSEL 0x80000000 +#define BCCK_RXREPORT_MFOFF 0x40000000 +#define BCCK_RXREPORT_SQLOSS 0x20000000 +#define BCCK_RXREPORT_PKTLOSS 0x10000000 +#define BCCK_RXREPORT_LOCKEDBIT 0x08000000 +#define BCCK_RXREPORT_RATEERROR 0x04000000 +#define BCCK_RXREPORT_RXRATE 0x03000000 +#define BCCK_RXFA_COUNTER_LOWER 0xff +#define BCCK_RXFA_COUNTER_UPPER 0xff000000 +#define BCCK_RXHPAGC_START 0xe000 +#define BCCK_RXHPAGC_FINAL 0x1c00 +#define BCCK_RXFALSEALARM_ENABLE 0x8000 +#define BCCK_FACOUNTER_FREEZE 0x4000 +#define BCCK_TXPATH_SEL 0x10000000 +#define BCCK_DEFAULT_RXPATH 0xc000000 +#define BCCK_OPTION_RXPATH 0x3000000 + +#define BNUM_OFSTF 0x3 +#define BSHIFT_L 0xc0 +#define BGI_TH 0xc +#define BRXPATH_A 0x1 +#define BRXPATH_B 0x2 +#define BRXPATH_C 0x4 +#define BRXPATH_D 0x8 +#define BTXPATH_A 0x1 +#define BTXPATH_B 0x2 +#define BTXPATH_C 0x4 +#define BTXPATH_D 0x8 +#define BTRSSI_FREQ 0x200 +#define BADC_BACKOFF 0x3000 +#define BDFIR_BACKOFF 0xc000 +#define BTRSSI_LATCH_PHASE 0x10000 +#define BRX_LDC_OFFSET 0xff +#define BRX_QDC_OFFSET 0xff00 +#define BRX_DFIR_MODE 0x1800000 +#define BRX_DCNF_TYPE 0xe000000 +#define BRXIQIMB_A 0x3ff +#define BRXIQIMB_B 0xfc00 +#define BRXIQIMB_C 0x3f0000 +#define BRXIQIMB_D 0xffc00000 +#define BDC_DC_NOTCH 0x60000 +#define BRXNB_NOTCH 0x1f000000 +#define BPD_TH 0xf +#define BPD_TH_OPT2 0xc000 +#define BPWED_TH 0x700 +#define BIFMF_WIN_L 0x800 +#define BPD_OPTION 0x1000 +#define BMF_WIN_L 0xe000 +#define BBW_SEARCH_L 0x30000 +#define BWIN_ENH_L 0xc0000 +#define BBW_TH 0x700000 +#define BED_TH2 0x3800000 +#define BBW_OPTION 0x4000000 +#define BRADIO_TH 0x18000000 +#define BWINDOW_L 0xe0000000 +#define BSBD_OPTION 0x1 +#define BFRAME_TH 0x1c +#define BFS_OPTION 0x60 +#define BDC_SLOPE_CHECK 0x80 +#define BFGUARD_COUNTER_DC_L 0xe00 +#define BFRAME_WEIGHT_SHORT 0x7000 +#define BSUB_TUNE 0xe00000 +#define BFRAME_DC_LENGTH 0xe000000 +#define BSBD_START_OFFSET 0x30000000 +#define BFRAME_TH_2 0x7 +#define BFRAME_GI2_TH 0x38 +#define BGI2_SYNC_EN 0x40 +#define BSARCH_SHORT_EARLY 0x300 +#define BSARCH_SHORT_LATE 0xc00 +#define BSARCH_GI2_LATE 0x70000 +#define BCFOANTSUM 0x1 +#define BCFOACC 0x2 +#define BCFOSTARTOFFSET 0xc +#define BCFOLOOPBACK 0x70 +#define BCFOSUMWEIGHT 0x80 +#define BDAGCENABLE 0x10000 +#define BTXIQIMB_A 0x3ff +#define BTXIQIMB_b 0xfc00 +#define BTXIQIMB_C 0x3f0000 +#define BTXIQIMB_D 0xffc00000 +#define BTXIDCOFFSET 0xff +#define BTXIQDCOFFSET 0xff00 +#define BTXDFIRMODE 0x10000 +#define BTXPESUDO_NOISEON 0x4000000 +#define BTXPESUDO_NOISE_A 0xff +#define BTXPESUDO_NOISE_B 0xff00 +#define BTXPESUDO_NOISE_C 0xff0000 +#define BTXPESUDO_NOISE_D 0xff000000 +#define BCCA_DROPOPTION 0x20000 +#define BCCA_DROPTHRES 0xfff00000 +#define BEDCCA_H 0xf +#define BEDCCA_L 0xf0 +#define BLAMBDA_ED 0x300 +#define BRX_INITIALGAIN 0x7f +#define BRX_ANTDIV_EN 0x80 +#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 +#define BRX_HIGHPOWER_FLOW 0x8000 +#define BRX_AGC_FREEZE_THRES 0xc0000 +#define BRX_FREEZESTEP_AGC1 0x300000 +#define BRX_FREEZESTEP_AGC2 0xc00000 +#define BRX_FREEZESTEP_AGC3 0x3000000 +#define BRX_FREEZESTEP_AGC0 0xc000000 +#define BRXRSSI_CMP_EN 0x10000000 +#define BRXQUICK_AGCEN 0x20000000 +#define BRXAGC_FREEZE_THRES_MODE 0x40000000 +#define BRX_OVERFLOW_CHECKTYPE 0x80000000 +#define BRX_AGCSHIFT 0x7f +#define BTRSW_TRI_ONLY 0x80 +#define BPOWER_THRES 0x300 +#define BRXAGC_EN 0x1 +#define BRXAGC_TOGETHER_EN 0x2 +#define BRXAGC_MIN 0x4 +#define BRXHP_INI 0x7 +#define BRXHP_TRLNA 0x70 +#define BRXHP_RSSI 0x700 +#define BRXHP_BBP1 0x7000 +#define BRXHP_BBP2 0x70000 +#define BRXHP_BBP3 0x700000 +#define BRSSI_H 0x7f0000 +#define BRSSI_GEN 0x7f000000 +#define BRXSETTLE_TRSW 0x7 +#define BRXSETTLE_LNA 0x38 +#define BRXSETTLE_RSSI 0x1c0 +#define BRXSETTLE_BBP 0xe00 +#define BRXSETTLE_RXHP 0x7000 +#define BRXSETTLE_ANTSW_RSSI 0x38000 +#define BRXSETTLE_ANTSW 0xc0000 +#define BRXPROCESS_TIME_DAGC 0x300000 +#define BRXSETTLE_HSSI 0x400000 +#define BRXPROCESS_TIME_BBPPW 0x800000 +#define BRXANTENNA_POWER_SHIFT 0x3000000 +#define BRSSI_TABLE_SELECT 0xc000000 +#define BRXHP_FINAL 0x7000000 +#define BRXHPSETTLE_BBP 0x7 +#define BRXHTSETTLE_HSSI 0x8 +#define BRXHTSETTLE_RXHP 0x70 +#define BRXHTSETTLE_BBPPW 0x80 +#define BRXHTSETTLE_IDLE 0x300 +#define BRXHTSETTLE_RESERVED 0x1c00 +#define BRXHT_RXHP_EN 0x8000 +#define BRXAGC_FREEZE_THRES 0x30000 +#define BRXAGC_TOGETHEREN 0x40000 +#define BRXHTAGC_MIN 0x80000 +#define BRXHTAGC_EN 0x100000 +#define BRXHTDAGC_EN 0x200000 +#define BRXHT_RXHP_BBP 0x1c00000 +#define BRXHT_RXHP_FINAL 0xe0000000 +#define BRXPW_RADIO_TH 0x3 +#define BRXPW_RADIO_EN 0x4 +#define BRXMF_HOLD 0x3800 +#define BRXPD_DELAY_TH1 0x38 +#define BRXPD_DELAY_TH2 0x1c0 +#define BRXPD_DC_COUNT_MAX 0x600 +#define BRXPD_DELAY_TH 0x8000 +#define BRXPROCESS_DELAY 0xf0000 +#define BRXSEARCHRANGE_GI2_EARLY 0x700000 +#define BRXFRAME_FUARD_COUNTER_L 0x3800000 +#define BRXSGI_GUARD_L 0xc000000 +#define BRXSGI_SEARCH_L 0x30000000 +#define BRXSGI_TH 0xc0000000 +#define BDFSCNT0 0xff +#define BDFSCNT1 0xff00 +#define BDFSFLAG 0xf0000 +#define BMF_WEIGHT_SUM 0x300000 +#define BMINIDX_TH 0x7f000000 +#define BDAFORMAT 0x40000 +#define BTXCH_EMU_ENABLE 0x01000000 +#define BTRSW_ISOLATION_A 0x7f +#define BTRSW_ISOLATION_B 0x7f00 +#define BTRSW_ISOLATION_C 0x7f0000 +#define BTRSW_ISOLATION_D 0x7f000000 +#define BEXT_LNA_GAIN 0x7c00 + +#define BSTBC_EN 0x4 +#define BANTENNA_MAPPING 0x10 +#define BNSS 0x20 +#define BCFO_ANTSUM_ID 0x200 +#define BPHY_COUNTER_RESET 0x8000000 +#define BCFO_REPORT_GET 0x4000000 +#define BOFDM_CONTINUE_TX 0x10000000 +#define BOFDM_SINGLE_CARRIER 0x20000000 +#define BOFDM_SINGLE_TONE 0x40000000 +#define BHT_DETECT 0x100 +#define BCFOEN 0x10000 +#define BCFOVALUE 0xfff00000 +#define BSIGTONE_RE 0x3f +#define BSIGTONE_IM 0x7f00 +#define BCOUNTER_CCA 0xffff +#define BCOUNTER_PARITYFAIL 0xffff0000 +#define BCOUNTER_RATEILLEGAL 0xffff +#define BCOUNTER_CRC8FAIL 0xffff0000 +#define BCOUNTER_MCSNOSUPPORT 0xffff +#define BCOUNTER_FASTSYNC 0xffff +#define BSHORTCFO 0xfff +#define BSHORTCFOT_LENGTH 12 +#define BSHORTCFOF_LENGTH 11 +#define BLONGCFO 0x7ff +#define BLONGCFOT_LENGTH 11 +#define BLONGCFOF_LENGTH 11 +#define BTAILCFO 0x1fff +#define BTAILCFOT_LENGTH 13 +#define BTAILCFOF_LENGTH 12 +#define BNOISE_EN_PWDB 0xffff +#define BCC_POWER_DB 0xffff0000 +#define BMOISE_PWDB 0xffff +#define BPOWERMEAST_LENGTH 10 +#define BPOWERMEASF_LENGTH 3 +#define BRX_HT_BW 0x1 +#define BRXSC 0x6 +#define BRX_HT 0x8 +#define BNB_INTF_DET_ON 0x1 +#define BINTF_WIN_LEN_CFG 0x30 +#define BNB_INTF_TH_CFG 0x1c0 +#define BRFGAIN 0x3f +#define BTABLESEL 0x40 +#define BTRSW 0x80 +#define BRXSNR_A 0xff +#define BRXSNR_B 0xff00 +#define BRXSNR_C 0xff0000 +#define BRXSNR_D 0xff000000 +#define BSNR_EVMT_LENGTH 8 +#define BSNR_EVMF_LENGTH 1 +#define BCSI1ST 0xff +#define BCSI2ND 0xff00 +#define BRXEVM1ST 0xff0000 +#define BRXEVM2ND 0xff000000 +#define BSIGEVM 0xff +#define BPWDB 0xff00 +#define BSGIEN 0x10000 + +#define BSFACTOR_QMA1 0xf +#define BSFACTOR_QMA2 0xf0 +#define BSFACTOR_QMA3 0xf00 +#define BSFACTOR_QMA4 0xf000 +#define BSFACTOR_QMA5 0xf0000 +#define BSFACTOR_QMA6 0xf0000 +#define BSFACTOR_QMA7 0xf00000 +#define BSFACTOR_QMA8 0xf000000 +#define BSFACTOR_QMA9 0xf0000000 +#define BCSI_SCHEME 0x100000 + +#define BNOISE_LVL_TOP_SET 0x3 +#define BCHSMOOTH 0x4 +#define BCHSMOOTH_CFG1 0x38 +#define BCHSMOOTH_CFG2 0x1c0 +#define BCHSMOOTH_CFG3 0xe00 +#define BCHSMOOTH_CFG4 0x7000 +#define BMRCMODE 0x800000 +#define BTHEVMCFG 0x7000000 + +#define BLOOP_FIT_TYPE 0x1 +#define BUPD_CFO 0x40 +#define BUPD_CFO_OFFDATA 0x80 +#define BADV_UPD_CFO 0x100 +#define BADV_TIME_CTRL 0x800 +#define BUPD_CLKO 0x1000 +#define BFC 0x6000 +#define BTRACKING_MODE 0x8000 +#define BPHCMP_ENABLE 0x10000 +#define BUPD_CLKO_LTF 0x20000 +#define BCOM_CH_CFO 0x40000 +#define BCSI_ESTI_MODE 0x80000 +#define BADV_UPD_EQZ 0x100000 +#define BUCHCFG 0x7000000 +#define BUPDEQZ 0x8000000 + +#define BRX_PESUDO_NOISE_ON 0x20000000 +#define BRX_PESUDO_NOISE_A 0xff +#define BRX_PESUDO_NOISE_B 0xff00 +#define BRX_PESUDO_NOISE_C 0xff0000 +#define BRX_PESUDO_NOISE_D 0xff000000 +#define BRX_PESUDO_NOISESTATE_A 0xffff +#define BRX_PESUDO_NOISESTATE_B 0xffff0000 +#define BRX_PESUDO_NOISESTATE_C 0xffff +#define BRX_PESUDO_NOISESTATE_D 0xffff0000 + +#define BZEBRA1_HSSIENABLE 0x8 +#define BZEBRA1_TRXCONTROL 0xc00 +#define BZEBRA1_TRXGAINSETTING 0x07f +#define BZEBRA1_RXCOUNTER 0xc00 +#define BZEBRA1_TXCHANGEPUMP 0x38 +#define BZEBRA1_RXCHANGEPUMP 0x7 +#define BZEBRA1_CHANNEL_NUM 0xf80 +#define BZEBRA1_TXLPFBW 0x400 +#define BZEBRA1_RXLPFBW 0x600 + +#define BRTL8256REG_MODE_CTRL1 0x100 +#define BRTL8256REG_MODE_CTRL0 0x40 +#define BRTL8256REG_TXLPFBW 0x18 +#define BRTL8256REG_RXLPFBW 0x600 + +#define BRTL8258_TXLPFBW 0xc +#define BRTL8258_RXLPFBW 0xc00 +#define BRTL8258_RSSILPFBW 0xc0 + +#define BBYTE0 0x1 +#define BBYTE1 0x2 +#define BBYTE2 0x4 +#define BBYTE3 0x8 +#define BWORD0 0x3 +#define BWORD1 0xc +#define BWORD 0xf + +#define MASKBYTE0 0xff +#define MASKBYTE1 0xff00 +#define MASKBYTE2 0xff0000 +#define MASKBYTE3 0xff000000 +#define MASKHWORD 0xffff0000 +#define MASKLWORD 0x0000ffff +#define MASKDWORD 0xffffffff +#define MASK12BITS 0xfff +#define MASKH4BITS 0xf0000000 +#define MASKOFDM_D 0xffc00000 +#define MASKCCK 0x3f3f3f3f + +#define MASK4BITS 0x0f +#define MASK20BITS 0xfffff +#define RFREG_OFFSET_MASK 0xfffff + +#define BENABLE 0x1 +#define BDISABLE 0x0 + +#define LEFT_ANTENNA 0x0 +#define RIGHT_ANTENNA 0x1 + +#define TCHECK_TXSTATUS 500 +#define TUPDATE_RXCOUNTER 100 + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c new file mode 100644 index 000000000000..ffd8e04c4028 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c @@ -0,0 +1,523 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "../wifi.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" + +static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw); + +void rtl92c_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff) | 0x0400); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + case HT_CHANNEL_WIDTH_20_40: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff)); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("unknown bandwidth: %#X\n", bandwidth)); + break; + } +} + +void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 tx_agc[2] = {0, 0}, tmpval; + bool turbo_scanoff = false; + u8 idx1, idx2; + u8 *ptr; + + if (rtlefuse->eeprom_regulatory != 0) + turbo_scanoff = true; + + if (mac->act_scanning == true) { + tx_agc[RF90_PATH_A] = 0x3f3f3f3f; + tx_agc[RF90_PATH_B] = 0x3f3f3f3f; + + if (turbo_scanoff) { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + } + } else { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + + if (rtlefuse->eeprom_regulatory == 0) { + tmpval = + (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + + (rtlphy->mcs_txpwrlevel_origoffset[0][7] << + 8); + tx_agc[RF90_PATH_A] += tmpval; + + tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + + (rtlphy->mcs_txpwrlevel_origoffset[0][15] << + 24); + tx_agc[RF90_PATH_B] += tmpval; + } + } + + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + ptr = (u8 *) (&(tx_agc[idx1])); + for (idx2 = 0; idx2 < 4; idx2++) { + if (*ptr > RF6052_MAX_TX_PWR) + *ptr = RF6052_MAX_TX_PWR; + ptr++; + } + } + + tmpval = tx_agc[RF90_PATH_A] & 0xff; + rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_A_CCK1_MCS32)); + + tmpval = tx_agc[RF90_PATH_A] >> 8; + + if (mac->mode == WIRELESS_MODE_B) + tmpval = tmpval & 0xff00ffff; + + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_B_CCK11_A_CCK2_11)); + + tmpval = tx_agc[RF90_PATH_B] >> 24; + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_B_CCK11_A_CCK2_11)); + + tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; + rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_B_CCK1_55_MCS32)); +} + +static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel, + u32 *ofdmbase, u32 *mcsbase) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 powerBase0, powerBase1; + u8 legacy_pwrdiff, ht20_pwrdiff; + u8 i, powerlevel[2]; + + for (i = 0; i < 2; i++) { + powerlevel[i] = ppowerlevel[i]; + legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; + powerBase0 = powerlevel[i] + legacy_pwrdiff; + + powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | + (powerBase0 << 8) | powerBase0; + *(ofdmbase + i) = powerBase0; + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + (" [OFDM power base index rf(%c) = 0x%x]\n", + ((i == 0) ? 'A' : 'B'), *(ofdmbase + i))); + } + + for (i = 0; i < 2; i++) { + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { + ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1]; + powerlevel[i] += ht20_pwrdiff; + } + powerBase1 = powerlevel[i]; + powerBase1 = (powerBase1 << 24) | + (powerBase1 << 16) | (powerBase1 << 8) | powerBase1; + + *(mcsbase + i) = powerBase1; + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + (" [MCS power base index rf(%c) = 0x%x]\n", + ((i == 0) ? 'A' : 'B'), *(mcsbase + i))); + } +} + +static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, + u8 channel, u8 index, + u32 *powerBase0, + u32 *powerBase1, + u32 *p_outwriteval) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 i, chnlgroup, pwr_diff_limit[4]; + u32 writeVal, customer_limit, rf; + + for (rf = 0; rf < 2; rf++) { + switch (rtlefuse->eeprom_regulatory) { + case 0: + chnlgroup = 0; + + writeVal = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index + + (rf ? 8 : 0)] + + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("RTK better performance, " + "writeVal(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeVal)); + break; + case 1: + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + writeVal = ((index < 2) ? powerBase0[rf] : + powerBase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("Realtek regulatory, 40MHz, " + "writeVal(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeVal)); + } else { + if (rtlphy->pwrgroup_cnt == 1) + chnlgroup = 0; + if (rtlphy->pwrgroup_cnt >= 3) { + if (channel <= 3) + chnlgroup = 0; + else if (channel >= 4 && channel <= 9) + chnlgroup = 1; + else if (channel > 9) + chnlgroup = 2; + if (rtlphy->pwrgroup_cnt == 4) + chnlgroup++; + } + + writeVal = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] + [index + (rf ? 8 : 0)] + ((index < 2) ? + powerBase0[rf] : + powerBase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("Realtek regulatory, 20MHz, " + "writeVal(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeVal)); + } + break; + case 2: + writeVal = + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("Better regulatory, " + "writeVal(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeVal)); + break; + case 3: + chnlgroup = 0; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("customer's limit, 40MHz " + "rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), + rtlefuse->pwrgroup_ht40[rf][channel - + 1])); + } else { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("customer's limit, 20MHz " + "rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), + rtlefuse->pwrgroup_ht20[rf][channel - + 1])); + } + for (i = 0; i < 4; i++) { + pwr_diff_limit[i] = + (u8) ((rtlphy->mcs_txpwrlevel_origoffset + [chnlgroup][index + + (rf ? 8 : 0)] & (0x7f << (i * 8))) >> + (i * 8)); + + if (rtlphy->current_chan_bw == + HT_CHANNEL_WIDTH_20_40) { + if (pwr_diff_limit[i] > + rtlefuse-> + pwrgroup_ht40[rf][channel - 1]) + pwr_diff_limit[i] = + rtlefuse->pwrgroup_ht40[rf] + [channel - 1]; + } else { + if (pwr_diff_limit[i] > + rtlefuse-> + pwrgroup_ht20[rf][channel - 1]) + pwr_diff_limit[i] = + rtlefuse->pwrgroup_ht20[rf] + [channel - 1]; + } + } + + customer_limit = (pwr_diff_limit[3] << 24) | + (pwr_diff_limit[2] << 16) | + (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("Customer's limit rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), customer_limit)); + + writeVal = customer_limit + + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("Customer, writeVal rf(%c)= 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeVal)); + break; + default: + chnlgroup = 0; + writeVal = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] + [index + (rf ? 8 : 0)] + + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("RTK better performance, writeVal " + "rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeVal)); + break; + } + + if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) + writeVal = writeVal - 0x06060606; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_BT2) + writeVal = writeVal - 0x0c0c0c0c; + *(p_outwriteval + rf) = writeVal; + } +} + +static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, + u8 index, u32 *pValue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + u16 regoffset_a[6] = { + RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, + RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, + RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 + }; + u16 regoffset_b[6] = { + RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, + RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, + RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 + }; + u8 i, rf, pwr_val[4]; + u32 writeVal; + u16 regoffset; + + for (rf = 0; rf < 2; rf++) { + writeVal = pValue[rf]; + for (i = 0; i < 4; i++) { + pwr_val[i] = (u8) ((writeVal & (0x7f << + (i * 8))) >> (i * 8)); + + if (pwr_val[i] > RF6052_MAX_TX_PWR) + pwr_val[i] = RF6052_MAX_TX_PWR; + } + writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) | + (pwr_val[1] << 8) | pwr_val[0]; + + if (rf == 0) + regoffset = regoffset_a[index]; + else + regoffset = regoffset_b[index]; + rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + ("Set 0x%x = %08x\n", regoffset, writeVal)); + + if (((get_rf_type(rtlphy) == RF_2T2R) && + (regoffset == RTXAGC_A_MCS15_MCS12 || + regoffset == RTXAGC_B_MCS15_MCS12)) || + ((get_rf_type(rtlphy) != RF_2T2R) && + (regoffset == RTXAGC_A_MCS07_MCS04 || + regoffset == RTXAGC_B_MCS07_MCS04))) { + + writeVal = pwr_val[3]; + if (regoffset == RTXAGC_A_MCS15_MCS12 || + regoffset == RTXAGC_A_MCS07_MCS04) + regoffset = 0xc90; + if (regoffset == RTXAGC_B_MCS15_MCS12 || + regoffset == RTXAGC_B_MCS07_MCS04) + regoffset = 0xc98; + + for (i = 0; i < 3; i++) { + writeVal = (writeVal > 6) ? (writeVal - 6) : 0; + rtl_write_byte(rtlpriv, (u32) (regoffset + i), + (u8) writeVal); + } + } + } +} + +void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel) +{ + u32 writeVal[2], powerBase0[2], powerBase1[2]; + u8 index; + + rtl92c_phy_get_power_base(hw, ppowerlevel, + channel, &powerBase0[0], &powerBase1[0]); + + for (index = 0; index < 6; index++) { + _rtl92c_get_txpower_writeval_by_regulatory(hw, + channel, index, + &powerBase0[0], + &powerBase1[0], + &writeVal[0]); + + _rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]); + } +} + +bool rtl92c_phy_rf6052_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + if (rtlphy->rf_type == RF_1T1R) + rtlphy->num_total_rfpath = 1; + else + rtlphy->num_total_rfpath = 2; + + return _rtl92c_phy_rf6052_config_parafile(hw); +} + +static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 u4_regvalue; + u8 rfpath; + bool rtstatus; + struct bb_reg_def *pphyreg; + + for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { + + pphyreg = &rtlphy->phyreg_def[rfpath]; + + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV); + break; + case RF90_PATH_B: + case RF90_PATH_D: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16); + break; + } + + rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, + B3WIREADDREAALENGTH, 0x0); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); + udelay(1); + + switch (rfpath) { + case RF90_PATH_A: + rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, + (enum radio_path) rfpath); + break; + case RF90_PATH_B: + rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, + (enum radio_path) rfpath); + break; + case RF90_PATH_C: + break; + case RF90_PATH_D: + break; + } + + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV, u4_regvalue); + break; + case RF90_PATH_B: + case RF90_PATH_D: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16, u4_regvalue); + break; + } + + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Radio[%d] Fail!!", rfpath)); + return false; + } + + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("<---\n")); + return rtstatus; +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h new file mode 100644 index 000000000000..d3014f99bb7b --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92C_RF_H__ +#define __RTL92C_RF_H__ + +#define RF6052_MAX_TX_PWR 0x3F +#define RF6052_MAX_REG 0x3F +#define RF6052_MAX_PATH 2 + +extern void rtl92c_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, + u8 bandwidth); +extern void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); +extern bool rtl92c_phy_rf6052_config(struct ieee80211_hw *hw); +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c new file mode 100644 index 000000000000..b366e8862929 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -0,0 +1,282 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include <linux/vmalloc.h> + +#include "../wifi.h" +#include "../core.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "hw.h" +#include "sw.h" +#include "trx.h" +#include "led.h" + +int rtl92c_init_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtlpriv->dm.b_dm_initialgain_enable = 1; + rtlpriv->dm.dm_flag = 0; + rtlpriv->dm.b_disable_framebursting = 0;; + rtlpriv->dm.thermalvalue = 0; + rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13); + + rtlpci->receive_config = (RCR_APPFCS | + RCR_AMF | + RCR_ADF | + RCR_APP_MIC | + RCR_APP_ICV | + RCR_AICV | + RCR_ACRC32 | + RCR_AB | + RCR_AM | + RCR_APM | + RCR_APP_PHYST_RXFF | RCR_HTC_LOC_CTRL | 0); + + rtlpci->irq_mask[0] = + (u32) (IMR_ROK | + IMR_VODOK | + IMR_VIDOK | + IMR_BEDOK | + IMR_BKDOK | + IMR_MGNTDOK | + IMR_HIGHDOK | IMR_BDOK | IMR_RDU | IMR_RXFOVW | 0); + + rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD | 0); + + rtlpriv->rtlhal.pfirmware = (u8 *) vmalloc(0x4000); + if (!rtlpriv->rtlhal.pfirmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Can't alloc buffer for fw.\n")); + return 1; + } + + return 0; +} + +void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->rtlhal.pfirmware) { + vfree(rtlpriv->rtlhal.pfirmware); + rtlpriv->rtlhal.pfirmware = NULL; + } +} + +static struct rtl_hal_ops rtl8192ce_hal_ops = { + .init_sw_vars = rtl92c_init_sw_vars, + .deinit_sw_vars = rtl92c_deinit_sw_vars, + .read_eeprom_info = rtl92ce_read_eeprom_info, + .interrupt_recognized = rtl92ce_interrupt_recognized, + .hw_init = rtl92ce_hw_init, + .hw_disable = rtl92ce_card_disable, + .enable_interrupt = rtl92ce_enable_interrupt, + .disable_interrupt = rtl92ce_disable_interrupt, + .set_network_type = rtl92ce_set_network_type, + .set_qos = rtl92ce_set_qos, + .set_bcn_reg = rtl92ce_set_beacon_related_registers, + .set_bcn_intv = rtl92ce_set_beacon_interval, + .update_interrupt_mask = rtl92ce_update_interrupt_mask, + .get_hw_reg = rtl92ce_get_hw_reg, + .set_hw_reg = rtl92ce_set_hw_reg, + .update_rate_table = rtl92ce_update_hal_rate_table, + .update_rate_mask = rtl92ce_update_hal_rate_mask, + .fill_tx_desc = rtl92ce_tx_fill_desc, + .fill_tx_cmddesc = rtl92ce_tx_fill_cmddesc, + .query_rx_desc = rtl92ce_rx_query_desc, + .set_channel_access = rtl92ce_update_channel_access_setting, + .radio_onoff_checking = rtl92ce_gpio_radio_on_off_checking, + .set_bw_mode = rtl92c_phy_set_bw_mode, + .switch_channel = rtl92c_phy_sw_chnl, + .dm_watchdog = rtl92c_dm_watchdog, + .scan_operation_backup = rtl92c_phy_scan_operation_backup, + .set_rf_power_state = rtl92c_phy_set_rf_power_state, + .led_control = rtl92ce_led_control, + .set_desc = rtl92ce_set_desc, + .get_desc = rtl92ce_get_desc, + .tx_polling = rtl92ce_tx_polling, + .enable_hw_sec = rtl92ce_enable_hw_security_config, + .set_key = rtl92ce_set_key, + .init_sw_leds = rtl92ce_init_sw_leds, + .deinit_sw_leds = rtl92ce_deinit_sw_leds, + .get_bbreg = rtl92c_phy_query_bb_reg, + .set_bbreg = rtl92c_phy_set_bb_reg, + .get_rfreg = rtl92c_phy_query_rf_reg, + .set_rfreg = rtl92c_phy_set_rf_reg, +}; + +static struct rtl_mod_params rtl92ce_mod_params = { + .sw_crypto = 0, +}; + +static struct rtl_hal_cfg rtl92ce_hal_cfg = { + .name = "rtl92c_pci", + .fw_name = "rtlwifi/rtl8192cfw.bin", + .ops = &rtl8192ce_hal_ops, + .mod_params = &rtl92ce_mod_params, + + .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, + .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, + .maps[SYS_CLK] = REG_SYS_CLKR, + .maps[MAC_RCR_AM] = AM, + .maps[MAC_RCR_AB] = AB, + .maps[MAC_RCR_ACRC32] = ACRC32, + .maps[MAC_RCR_ACF] = ACF, + .maps[MAC_RCR_AAP] = AAP, + + .maps[EFUSE_TEST] = REG_EFUSE_TEST, + .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_CLK] = 0, + .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_PWC_EV12V] = PWC_EV12V, + .maps[EFUSE_FEN_ELDR] = FEN_ELDR, + .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, + .maps[EFUSE_ANA8M] = EFUSE_ANA8M, + .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, + + .maps[RWCAM] = REG_CAMCMD, + .maps[WCAMI] = REG_CAMWRITE, + .maps[RCAMO] = REG_CAMREAD, + .maps[CAMDBG] = REG_CAMDBG, + .maps[SECR] = REG_SECCFG, + .maps[SEC_CAM_NONE] = CAM_NONE, + .maps[SEC_CAM_WEP40] = CAM_WEP40, + .maps[SEC_CAM_TKIP] = CAM_TKIP, + .maps[SEC_CAM_AES] = CAM_AES, + .maps[SEC_CAM_WEP104] = CAM_WEP104, + + .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, + .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, + .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, + .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, + .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, + .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, + .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, + .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, + .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, + .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, + .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, + .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, + .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, + .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, + .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, + .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, + + .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, + .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, + .maps[RTL_IMR_BcnInt] = IMR_BCNINT, + .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, + .maps[RTL_IMR_RDU] = IMR_RDU, + .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, + .maps[RTL_IMR_BDOK] = IMR_BDOK, + .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, + .maps[RTL_IMR_TBDER] = IMR_TBDER, + .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, + .maps[RTL_IMR_TBDOK] = IMR_TBDOK, + .maps[RTL_IMR_BKDOK] = IMR_BKDOK, + .maps[RTL_IMR_BEDOK] = IMR_BEDOK, + .maps[RTL_IMR_VIDOK] = IMR_VIDOK, + .maps[RTL_IMR_VODOK] = IMR_VODOK, + .maps[RTL_IMR_ROK] = IMR_ROK, + .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), + + .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, +}; + +static struct pci_device_id rtl92ce_pci_ids[] __devinitdata = { + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8191, rtl92ce_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8178, rtl92ce_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8177, rtl92ce_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8176, rtl92ce_hal_cfg)}, + {}, +}; + +MODULE_DEVICE_TABLE(pci, rtl92ce_pci_ids); + +MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>"); +MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>"); +MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n PCI wireless"); +MODULE_FIRMWARE("rtlwifi/rtl8192cfw.bin"); + +module_param_named(swenc, rtl92ce_mod_params.sw_crypto, bool, 0444); +MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); + +static struct pci_driver rtl92ce_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl92ce_pci_ids, + .probe = rtl_pci_probe, + .remove = rtl_pci_disconnect, + +#ifdef CONFIG_PM + .suspend = rtl_pci_suspend, + .resume = rtl_pci_resume, +#endif + +}; + +static int __init rtl92ce_module_init(void) +{ + int ret; + + ret = pci_register_driver(&rtl92ce_driver); + if (ret) + RT_ASSERT(false, (": No device found\n")); + + return ret; +} + +static void __exit rtl92ce_module_exit(void) +{ + pci_unregister_driver(&rtl92ce_driver); +} + +module_init(rtl92ce_module_init); +module_exit(rtl92ce_module_exit); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h new file mode 100644 index 000000000000..de1198c38d4e --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92CE_SW_H__ +#define __RTL92CE_SW_H__ + +int rtl92c_init_sw_vars(struct ieee80211_hw *hw); +void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw); +void rtl92c_init_var_map(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/table.c b/drivers/net/wireless/rtlwifi/rtl8192ce/table.c new file mode 100644 index 000000000000..ba938b91aa6f --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/table.c @@ -0,0 +1,1224 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "table.h" + + +u32 RTL8192CEPHY_REG_2TARRAY[PHY_REG_2TARRAY_LENGTH] = { + 0x024, 0x0011800f, + 0x028, 0x00ffdb83, + 0x800, 0x80040002, + 0x804, 0x00000003, + 0x808, 0x0000fc00, + 0x80c, 0x0000000a, + 0x810, 0x10005388, + 0x814, 0x020c3d10, + 0x818, 0x02200385, + 0x81c, 0x00000000, + 0x820, 0x01000100, + 0x824, 0x00390004, + 0x828, 0x01000100, + 0x82c, 0x00390004, + 0x830, 0x27272727, + 0x834, 0x27272727, + 0x838, 0x27272727, + 0x83c, 0x27272727, + 0x840, 0x00010000, + 0x844, 0x00010000, + 0x848, 0x27272727, + 0x84c, 0x27272727, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x569a569a, + 0x85c, 0x0c1b25a4, + 0x860, 0x66e60230, + 0x864, 0x061f0130, + 0x868, 0x27272727, + 0x86c, 0x2b2b2b27, + 0x870, 0x07000700, + 0x874, 0x22184000, + 0x878, 0x08080808, + 0x87c, 0x00000000, + 0x880, 0xc0083070, + 0x884, 0x000004d5, + 0x888, 0x00000000, + 0x88c, 0xcc0000c0, + 0x890, 0x00000800, + 0x894, 0xfffffffe, + 0x898, 0x40302010, + 0x89c, 0x00706050, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90c, 0x81121313, + 0xa00, 0x00d047c8, + 0xa04, 0x80ff000c, + 0xa08, 0x8c838300, + 0xa0c, 0x2e68120f, + 0xa10, 0x9500bb78, + 0xa14, 0x11144028, + 0xa18, 0x00881117, + 0xa1c, 0x89140f00, + 0xa20, 0x1a1b0000, + 0xa24, 0x090e1317, + 0xa28, 0x00000204, + 0xa2c, 0x00d30000, + 0xa70, 0x101fbf00, + 0xa74, 0x00000007, + 0xc00, 0x48071d40, + 0xc04, 0x03a05633, + 0xc08, 0x000000e4, + 0xc0c, 0x6c6c6c6c, + 0xc10, 0x08800000, + 0xc14, 0x40000100, + 0xc18, 0x08800000, + 0xc1c, 0x40000100, + 0xc20, 0x00000000, + 0xc24, 0x00000000, + 0xc28, 0x00000000, + 0xc2c, 0x00000000, + 0xc30, 0x69e9ac44, + 0xc34, 0x469652cf, + 0xc38, 0x49795994, + 0xc3c, 0x0a97971c, + 0xc40, 0x1f7c403f, + 0xc44, 0x000100b7, + 0xc48, 0xec020107, + 0xc4c, 0x007f037f, + 0xc50, 0x69543420, + 0xc54, 0x43bc0094, + 0xc58, 0x69543420, + 0xc5c, 0x433c0094, + 0xc60, 0x00000000, + 0xc64, 0x5116848b, + 0xc68, 0x47c00bff, + 0xc6c, 0x00000036, + 0xc70, 0x2c7f000d, + 0xc74, 0x018610db, + 0xc78, 0x0000001f, + 0xc7c, 0x00b91612, + 0xc80, 0x40000100, + 0xc84, 0x20f60000, + 0xc88, 0x40000100, + 0xc8c, 0x20200000, + 0xc90, 0x00121820, + 0xc94, 0x00000000, + 0xc98, 0x00121820, + 0xc9c, 0x00007f7f, + 0xca0, 0x00000000, + 0xca4, 0x00000080, + 0xca8, 0x00000000, + 0xcac, 0x00000000, + 0xcb0, 0x00000000, + 0xcb4, 0x00000000, + 0xcb8, 0x00000000, + 0xcbc, 0x28000000, + 0xcc0, 0x00000000, + 0xcc4, 0x00000000, + 0xcc8, 0x00000000, + 0xccc, 0x00000000, + 0xcd0, 0x00000000, + 0xcd4, 0x00000000, + 0xcd8, 0x64b22427, + 0xcdc, 0x00766932, + 0xce0, 0x00222222, + 0xce4, 0x00000000, + 0xce8, 0x37644302, + 0xcec, 0x2f97d40c, + 0xd00, 0x00080740, + 0xd04, 0x00020403, + 0xd08, 0x0000907f, + 0xd0c, 0x20010201, + 0xd10, 0xa0633333, + 0xd14, 0x3333bc43, + 0xd18, 0x7a8f5b6b, + 0xd2c, 0xcc979975, + 0xd30, 0x00000000, + 0xd34, 0x80608000, + 0xd38, 0x00000000, + 0xd3c, 0x00027293, + 0xd40, 0x00000000, + 0xd44, 0x00000000, + 0xd48, 0x00000000, + 0xd4c, 0x00000000, + 0xd50, 0x6437140a, + 0xd54, 0x00000000, + 0xd58, 0x00000000, + 0xd5c, 0x30032064, + 0xd60, 0x4653de68, + 0xd64, 0x04518a3c, + 0xd68, 0x00002101, + 0xd6c, 0x2a201c16, + 0xd70, 0x1812362e, + 0xd74, 0x322c2220, + 0xd78, 0x000e3c24, + 0xe00, 0x2a2a2a2a, + 0xe04, 0x2a2a2a2a, + 0xe08, 0x03902a2a, + 0xe10, 0x2a2a2a2a, + 0xe14, 0x2a2a2a2a, + 0xe18, 0x2a2a2a2a, + 0xe1c, 0x2a2a2a2a, + 0xe28, 0x00000000, + 0xe30, 0x1000dc1f, + 0xe34, 0x10008c1f, + 0xe38, 0x02140102, + 0xe3c, 0x681604c2, + 0xe40, 0x01007c00, + 0xe44, 0x01004800, + 0xe48, 0xfb000000, + 0xe4c, 0x000028d1, + 0xe50, 0x1000dc1f, + 0xe54, 0x10008c1f, + 0xe58, 0x02140102, + 0xe5c, 0x28160d05, + 0xe60, 0x00000010, + 0xe68, 0x001b25a4, + 0xe6c, 0x63db25a4, + 0xe70, 0x63db25a4, + 0xe74, 0x0c1b25a4, + 0xe78, 0x0c1b25a4, + 0xe7c, 0x0c1b25a4, + 0xe80, 0x0c1b25a4, + 0xe84, 0x63db25a4, + 0xe88, 0x0c1b25a4, + 0xe8c, 0x63db25a4, + 0xed0, 0x63db25a4, + 0xed4, 0x63db25a4, + 0xed8, 0x63db25a4, + 0xedc, 0x001b25a4, + 0xee0, 0x001b25a4, + 0xeec, 0x6fdb25a4, + 0xf14, 0x00000003, + 0xf4c, 0x00000000, + 0xf00, 0x00000300, +}; + +u32 RTL8192CEPHY_REG_1TARRAY[PHY_REG_1TARRAY_LENGTH] = { + 0x024, 0x0011800f, + 0x028, 0x00ffdb83, + 0x800, 0x80040000, + 0x804, 0x00000001, + 0x808, 0x0000fc00, + 0x80c, 0x0000000a, + 0x810, 0x10005388, + 0x814, 0x020c3d10, + 0x818, 0x02200385, + 0x81c, 0x00000000, + 0x820, 0x01000100, + 0x824, 0x00390004, + 0x828, 0x00000000, + 0x82c, 0x00000000, + 0x830, 0x00000000, + 0x834, 0x00000000, + 0x838, 0x00000000, + 0x83c, 0x00000000, + 0x840, 0x00010000, + 0x844, 0x00000000, + 0x848, 0x00000000, + 0x84c, 0x00000000, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x569a569a, + 0x85c, 0x001b25a4, + 0x860, 0x66e60230, + 0x864, 0x061f0130, + 0x868, 0x00000000, + 0x86c, 0x32323200, + 0x870, 0x07000700, + 0x874, 0x22004000, + 0x878, 0x00000808, + 0x87c, 0x00000000, + 0x880, 0xc0083070, + 0x884, 0x000004d5, + 0x888, 0x00000000, + 0x88c, 0xccc000c0, + 0x890, 0x00000800, + 0x894, 0xfffffffe, + 0x898, 0x40302010, + 0x89c, 0x00706050, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90c, 0x81121111, + 0xa00, 0x00d047c8, + 0xa04, 0x80ff000c, + 0xa08, 0x8c838300, + 0xa0c, 0x2e68120f, + 0xa10, 0x9500bb78, + 0xa14, 0x11144028, + 0xa18, 0x00881117, + 0xa1c, 0x89140f00, + 0xa20, 0x1a1b0000, + 0xa24, 0x090e1317, + 0xa28, 0x00000204, + 0xa2c, 0x00d30000, + 0xa70, 0x101fbf00, + 0xa74, 0x00000007, + 0xc00, 0x48071d40, + 0xc04, 0x03a05611, + 0xc08, 0x000000e4, + 0xc0c, 0x6c6c6c6c, + 0xc10, 0x08800000, + 0xc14, 0x40000100, + 0xc18, 0x08800000, + 0xc1c, 0x40000100, + 0xc20, 0x00000000, + 0xc24, 0x00000000, + 0xc28, 0x00000000, + 0xc2c, 0x00000000, + 0xc30, 0x69e9ac44, + 0xc34, 0x469652cf, + 0xc38, 0x49795994, + 0xc3c, 0x0a97971c, + 0xc40, 0x1f7c403f, + 0xc44, 0x000100b7, + 0xc48, 0xec020107, + 0xc4c, 0x007f037f, + 0xc50, 0x69543420, + 0xc54, 0x43bc0094, + 0xc58, 0x69543420, + 0xc5c, 0x433c0094, + 0xc60, 0x00000000, + 0xc64, 0x5116848b, + 0xc68, 0x47c00bff, + 0xc6c, 0x00000036, + 0xc70, 0x2c7f000d, + 0xc74, 0x018610db, + 0xc78, 0x0000001f, + 0xc7c, 0x00b91612, + 0xc80, 0x40000100, + 0xc84, 0x20f60000, + 0xc88, 0x40000100, + 0xc8c, 0x20200000, + 0xc90, 0x00121820, + 0xc94, 0x00000000, + 0xc98, 0x00121820, + 0xc9c, 0x00007f7f, + 0xca0, 0x00000000, + 0xca4, 0x00000080, + 0xca8, 0x00000000, + 0xcac, 0x00000000, + 0xcb0, 0x00000000, + 0xcb4, 0x00000000, + 0xcb8, 0x00000000, + 0xcbc, 0x28000000, + 0xcc0, 0x00000000, + 0xcc4, 0x00000000, + 0xcc8, 0x00000000, + 0xccc, 0x00000000, + 0xcd0, 0x00000000, + 0xcd4, 0x00000000, + 0xcd8, 0x64b22427, + 0xcdc, 0x00766932, + 0xce0, 0x00222222, + 0xce4, 0x00000000, + 0xce8, 0x37644302, + 0xcec, 0x2f97d40c, + 0xd00, 0x00080740, + 0xd04, 0x00020401, + 0xd08, 0x0000907f, + 0xd0c, 0x20010201, + 0xd10, 0xa0633333, + 0xd14, 0x3333bc43, + 0xd18, 0x7a8f5b6b, + 0xd2c, 0xcc979975, + 0xd30, 0x00000000, + 0xd34, 0x80608000, + 0xd38, 0x00000000, + 0xd3c, 0x00027293, + 0xd40, 0x00000000, + 0xd44, 0x00000000, + 0xd48, 0x00000000, + 0xd4c, 0x00000000, + 0xd50, 0x6437140a, + 0xd54, 0x00000000, + 0xd58, 0x00000000, + 0xd5c, 0x30032064, + 0xd60, 0x4653de68, + 0xd64, 0x04518a3c, + 0xd68, 0x00002101, + 0xd6c, 0x2a201c16, + 0xd70, 0x1812362e, + 0xd74, 0x322c2220, + 0xd78, 0x000e3c24, + 0xe00, 0x2a2a2a2a, + 0xe04, 0x2a2a2a2a, + 0xe08, 0x03902a2a, + 0xe10, 0x2a2a2a2a, + 0xe14, 0x2a2a2a2a, + 0xe18, 0x2a2a2a2a, + 0xe1c, 0x2a2a2a2a, + 0xe28, 0x00000000, + 0xe30, 0x1000dc1f, + 0xe34, 0x10008c1f, + 0xe38, 0x02140102, + 0xe3c, 0x681604c2, + 0xe40, 0x01007c00, + 0xe44, 0x01004800, + 0xe48, 0xfb000000, + 0xe4c, 0x000028d1, + 0xe50, 0x1000dc1f, + 0xe54, 0x10008c1f, + 0xe58, 0x02140102, + 0xe5c, 0x28160d05, + 0xe60, 0x00000010, + 0xe68, 0x001b25a4, + 0xe6c, 0x631b25a0, + 0xe70, 0x631b25a0, + 0xe74, 0x081b25a0, + 0xe78, 0x081b25a0, + 0xe7c, 0x081b25a0, + 0xe80, 0x081b25a0, + 0xe84, 0x631b25a0, + 0xe88, 0x081b25a0, + 0xe8c, 0x631b25a0, + 0xed0, 0x631b25a0, + 0xed4, 0x631b25a0, + 0xed8, 0x631b25a0, + 0xedc, 0x001b25a0, + 0xee0, 0x001b25a0, + 0xeec, 0x6b1b25a0, + 0xf14, 0x00000003, + 0xf4c, 0x00000000, + 0xf00, 0x00000300, +}; + +u32 RTL8192CEPHY_REG_ARRAY_PG[PHY_REG_ARRAY_PGLENGTH] = { + 0xe00, 0xffffffff, 0x0a0c0c0c, + 0xe04, 0xffffffff, 0x02040608, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x0a0c0d0e, + 0xe14, 0xffffffff, 0x02040608, + 0xe18, 0xffffffff, 0x0a0c0d0e, + 0xe1c, 0xffffffff, 0x02040608, + 0x830, 0xffffffff, 0x0a0c0c0c, + 0x834, 0xffffffff, 0x02040608, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x0a0c0d0e, + 0x848, 0xffffffff, 0x02040608, + 0x84c, 0xffffffff, 0x0a0c0d0e, + 0x868, 0xffffffff, 0x02040608, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x06060606, + 0xe14, 0xffffffff, 0x00020406, + 0xe18, 0xffffffff, 0x06060606, + 0xe1c, 0xffffffff, 0x00020406, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x06060606, + 0x848, 0xffffffff, 0x00020406, + 0x84c, 0xffffffff, 0x06060606, + 0x868, 0xffffffff, 0x00020406, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, +}; + +u32 RTL8192CERADIOA_2TARRAY[RADIOA_2TARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00031284, + 0x002, 0x00098000, + 0x003, 0x00018c63, + 0x004, 0x000210e7, + 0x009, 0x0002044f, + 0x00a, 0x0001adb0, + 0x00b, 0x00054867, + 0x00c, 0x0008992e, + 0x00d, 0x0000e52c, + 0x00e, 0x00039ce7, + 0x00f, 0x00000451, + 0x019, 0x00000000, + 0x01a, 0x00010255, + 0x01b, 0x00060a00, + 0x01c, 0x000fc378, + 0x01d, 0x000a1250, + 0x01e, 0x0004445f, + 0x01f, 0x00080001, + 0x020, 0x0000b614, + 0x021, 0x0006c000, + 0x022, 0x00000000, + 0x023, 0x00001558, + 0x024, 0x00000060, + 0x025, 0x00000483, + 0x026, 0x0004f000, + 0x027, 0x000ec7d9, + 0x028, 0x000977c0, + 0x029, 0x00004783, + 0x02a, 0x00000001, + 0x02b, 0x00021334, + 0x02a, 0x00000000, + 0x02b, 0x00000054, + 0x02a, 0x00000001, + 0x02b, 0x00000808, + 0x02b, 0x00053333, + 0x02c, 0x0000000c, + 0x02a, 0x00000002, + 0x02b, 0x00000808, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000003, + 0x02b, 0x00000808, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000004, + 0x02b, 0x00000808, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000005, + 0x02b, 0x00000808, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x00000006, + 0x02b, 0x00000709, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000007, + 0x02b, 0x00000709, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000008, + 0x02b, 0x0000060a, + 0x02b, 0x0004b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000009, + 0x02b, 0x0000060a, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000a, + 0x02b, 0x0000060a, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000b, + 0x02b, 0x0000060a, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000c, + 0x02b, 0x0000060a, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000d, + 0x02b, 0x0000060a, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000e, + 0x02b, 0x0000050b, + 0x02b, 0x00066666, + 0x02c, 0x0000001a, + 0x02a, 0x000e0000, + 0x010, 0x0004000f, + 0x011, 0x000e31fc, + 0x010, 0x0006000f, + 0x011, 0x000ff9f8, + 0x010, 0x0002000f, + 0x011, 0x000203f9, + 0x010, 0x0003000f, + 0x011, 0x000ff500, + 0x010, 0x00000000, + 0x011, 0x00000000, + 0x010, 0x0008000f, + 0x011, 0x0003f100, + 0x010, 0x0009000f, + 0x011, 0x00023100, + 0x012, 0x00032000, + 0x012, 0x00071000, + 0x012, 0x000b0000, + 0x012, 0x000fc000, + 0x013, 0x000287af, + 0x013, 0x000244b7, + 0x013, 0x000204ab, + 0x013, 0x0001c49f, + 0x013, 0x00018493, + 0x013, 0x00014297, + 0x013, 0x00010295, + 0x013, 0x0000c298, + 0x013, 0x0000819c, + 0x013, 0x000040a8, + 0x013, 0x0000001c, + 0x014, 0x0001944c, + 0x014, 0x00059444, + 0x014, 0x0009944c, + 0x014, 0x000d9444, + 0x015, 0x0000f424, + 0x015, 0x0004f424, + 0x015, 0x0008f424, + 0x015, 0x000cf424, + 0x016, 0x000e0330, + 0x016, 0x000a0330, + 0x016, 0x00060330, + 0x016, 0x00020330, + 0x000, 0x00010159, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01f, 0x00080003, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01e, 0x00044457, + 0x01f, 0x00080000, + 0x000, 0x00030159, +}; + +u32 RTL8192CE_RADIOB_2TARRAY[RADIOB_2TARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00031284, + 0x002, 0x00098000, + 0x003, 0x00018c63, + 0x004, 0x000210e7, + 0x009, 0x0002044f, + 0x00a, 0x0001adb0, + 0x00b, 0x00054867, + 0x00c, 0x0008992e, + 0x00d, 0x0000e52c, + 0x00e, 0x00039ce7, + 0x00f, 0x00000451, + 0x012, 0x00032000, + 0x012, 0x00071000, + 0x012, 0x000b0000, + 0x012, 0x000fc000, + 0x013, 0x000287af, + 0x013, 0x000244b7, + 0x013, 0x000204ab, + 0x013, 0x0001c49f, + 0x013, 0x00018493, + 0x013, 0x00014297, + 0x013, 0x00010295, + 0x013, 0x0000c298, + 0x013, 0x0000819c, + 0x013, 0x000040a8, + 0x013, 0x0000001c, + 0x014, 0x0001944c, + 0x014, 0x00059444, + 0x014, 0x0009944c, + 0x014, 0x000d9444, + 0x015, 0x0000f424, + 0x015, 0x0004f424, + 0x015, 0x0008f424, + 0x015, 0x000cf424, + 0x016, 0x000e0330, + 0x016, 0x000a0330, + 0x016, 0x00060330, + 0x016, 0x00020330, +}; + +u32 RTL8192CE_RADIOA_1TARRAY[RADIOA_1TARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00031284, + 0x002, 0x00098000, + 0x003, 0x00018c63, + 0x004, 0x000210e7, + 0x009, 0x0002044f, + 0x00a, 0x0001adb0, + 0x00b, 0x00054867, + 0x00c, 0x0008992e, + 0x00d, 0x0000e52c, + 0x00e, 0x00039ce7, + 0x00f, 0x00000451, + 0x019, 0x00000000, + 0x01a, 0x00010255, + 0x01b, 0x00060a00, + 0x01c, 0x000fc378, + 0x01d, 0x000a1250, + 0x01e, 0x0004445f, + 0x01f, 0x00080001, + 0x020, 0x0000b614, + 0x021, 0x0006c000, + 0x022, 0x00000000, + 0x023, 0x00001558, + 0x024, 0x00000060, + 0x025, 0x00000483, + 0x026, 0x0004f000, + 0x027, 0x000ec7d9, + 0x028, 0x000977c0, + 0x029, 0x00004783, + 0x02a, 0x00000001, + 0x02b, 0x00021334, + 0x02a, 0x00000000, + 0x02b, 0x00000054, + 0x02a, 0x00000001, + 0x02b, 0x00000808, + 0x02b, 0x00053333, + 0x02c, 0x0000000c, + 0x02a, 0x00000002, + 0x02b, 0x00000808, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000003, + 0x02b, 0x00000808, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000004, + 0x02b, 0x00000808, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000005, + 0x02b, 0x00000808, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x00000006, + 0x02b, 0x00000709, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000007, + 0x02b, 0x00000709, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000008, + 0x02b, 0x0000060a, + 0x02b, 0x0004b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000009, + 0x02b, 0x0000060a, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000a, + 0x02b, 0x0000060a, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000b, + 0x02b, 0x0000060a, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000c, + 0x02b, 0x0000060a, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000d, + 0x02b, 0x0000060a, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000e, + 0x02b, 0x0000050b, + 0x02b, 0x00066666, + 0x02c, 0x0000001a, + 0x02a, 0x000e0000, + 0x010, 0x0004000f, + 0x011, 0x000e31fc, + 0x010, 0x0006000f, + 0x011, 0x000ff9f8, + 0x010, 0x0002000f, + 0x011, 0x000203f9, + 0x010, 0x0003000f, + 0x011, 0x000ff500, + 0x010, 0x00000000, + 0x011, 0x00000000, + 0x010, 0x0008000f, + 0x011, 0x0003f100, + 0x010, 0x0009000f, + 0x011, 0x00023100, + 0x012, 0x00032000, + 0x012, 0x00071000, + 0x012, 0x000b0000, + 0x012, 0x000fc000, + 0x013, 0x000287af, + 0x013, 0x000244b7, + 0x013, 0x000204ab, + 0x013, 0x0001c49f, + 0x013, 0x00018493, + 0x013, 0x00014297, + 0x013, 0x00010295, + 0x013, 0x0000c298, + 0x013, 0x0000819c, + 0x013, 0x000040a8, + 0x013, 0x0000001c, + 0x014, 0x0001944c, + 0x014, 0x00059444, + 0x014, 0x0009944c, + 0x014, 0x000d9444, + 0x015, 0x0000f424, + 0x015, 0x0004f424, + 0x015, 0x0008f424, + 0x015, 0x000cf424, + 0x016, 0x000e0330, + 0x016, 0x000a0330, + 0x016, 0x00060330, + 0x016, 0x00020330, + 0x000, 0x00010159, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01f, 0x00080003, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01e, 0x00044457, + 0x01f, 0x00080000, + 0x000, 0x00030159, +}; + +u32 RTL8192CE_RADIOB_1TARRAY[RADIOB_1TARRAYLENGTH] = { + 0x0, +}; + +u32 RTL8192CEMAC_2T_ARRAY[MAC_2T_ARRAYLENGTH] = { + 0x420, 0x00000080, + 0x423, 0x00000000, + 0x430, 0x00000000, + 0x431, 0x00000000, + 0x432, 0x00000000, + 0x433, 0x00000001, + 0x434, 0x00000004, + 0x435, 0x00000005, + 0x436, 0x00000006, + 0x437, 0x00000007, + 0x438, 0x00000000, + 0x439, 0x00000000, + 0x43a, 0x00000000, + 0x43b, 0x00000001, + 0x43c, 0x00000004, + 0x43d, 0x00000005, + 0x43e, 0x00000006, + 0x43f, 0x00000007, + 0x440, 0x0000005d, + 0x441, 0x00000001, + 0x442, 0x00000000, + 0x444, 0x00000015, + 0x445, 0x000000f0, + 0x446, 0x0000000f, + 0x447, 0x00000000, + 0x458, 0x00000041, + 0x459, 0x000000a8, + 0x45a, 0x00000072, + 0x45b, 0x000000b9, + 0x460, 0x00000088, + 0x461, 0x00000088, + 0x462, 0x00000006, + 0x463, 0x00000003, + 0x4c8, 0x00000004, + 0x4c9, 0x00000008, + 0x4cc, 0x00000002, + 0x4cd, 0x00000028, + 0x4ce, 0x00000001, + 0x500, 0x00000026, + 0x501, 0x000000a2, + 0x502, 0x0000002f, + 0x503, 0x00000000, + 0x504, 0x00000028, + 0x505, 0x000000a3, + 0x506, 0x0000005e, + 0x507, 0x00000000, + 0x508, 0x0000002b, + 0x509, 0x000000a4, + 0x50a, 0x0000005e, + 0x50b, 0x00000000, + 0x50c, 0x0000004f, + 0x50d, 0x000000a4, + 0x50e, 0x00000000, + 0x50f, 0x00000000, + 0x512, 0x0000001c, + 0x514, 0x0000000a, + 0x515, 0x00000010, + 0x516, 0x0000000a, + 0x517, 0x00000010, + 0x51a, 0x00000016, + 0x524, 0x0000000f, + 0x525, 0x0000004f, + 0x546, 0x00000020, + 0x547, 0x00000000, + 0x559, 0x00000002, + 0x55a, 0x00000002, + 0x55d, 0x000000ff, + 0x605, 0x00000030, + 0x608, 0x0000000e, + 0x609, 0x0000002a, + 0x652, 0x00000020, + 0x63c, 0x0000000a, + 0x63d, 0x0000000a, + 0x700, 0x00000021, + 0x701, 0x00000043, + 0x702, 0x00000065, + 0x703, 0x00000087, + 0x708, 0x00000021, + 0x709, 0x00000043, + 0x70a, 0x00000065, + 0x70b, 0x00000087, +}; + +u32 RTL8192CEAGCTAB_2TARRAY[AGCTAB_2TARRAYLENGTH] = { + 0xc78, 0x7b000001, + 0xc78, 0x7b010001, + 0xc78, 0x7b020001, + 0xc78, 0x7b030001, + 0xc78, 0x7b040001, + 0xc78, 0x7b050001, + 0xc78, 0x7a060001, + 0xc78, 0x79070001, + 0xc78, 0x78080001, + 0xc78, 0x77090001, + 0xc78, 0x760a0001, + 0xc78, 0x750b0001, + 0xc78, 0x740c0001, + 0xc78, 0x730d0001, + 0xc78, 0x720e0001, + 0xc78, 0x710f0001, + 0xc78, 0x70100001, + 0xc78, 0x6f110001, + 0xc78, 0x6e120001, + 0xc78, 0x6d130001, + 0xc78, 0x6c140001, + 0xc78, 0x6b150001, + 0xc78, 0x6a160001, + 0xc78, 0x69170001, + 0xc78, 0x68180001, + 0xc78, 0x67190001, + 0xc78, 0x661a0001, + 0xc78, 0x651b0001, + 0xc78, 0x641c0001, + 0xc78, 0x631d0001, + 0xc78, 0x621e0001, + 0xc78, 0x611f0001, + 0xc78, 0x60200001, + 0xc78, 0x49210001, + 0xc78, 0x48220001, + 0xc78, 0x47230001, + 0xc78, 0x46240001, + 0xc78, 0x45250001, + 0xc78, 0x44260001, + 0xc78, 0x43270001, + 0xc78, 0x42280001, + 0xc78, 0x41290001, + 0xc78, 0x402a0001, + 0xc78, 0x262b0001, + 0xc78, 0x252c0001, + 0xc78, 0x242d0001, + 0xc78, 0x232e0001, + 0xc78, 0x222f0001, + 0xc78, 0x21300001, + 0xc78, 0x20310001, + 0xc78, 0x06320001, + 0xc78, 0x05330001, + 0xc78, 0x04340001, + 0xc78, 0x03350001, + 0xc78, 0x02360001, + 0xc78, 0x01370001, + 0xc78, 0x00380001, + 0xc78, 0x00390001, + 0xc78, 0x003a0001, + 0xc78, 0x003b0001, + 0xc78, 0x003c0001, + 0xc78, 0x003d0001, + 0xc78, 0x003e0001, + 0xc78, 0x003f0001, + 0xc78, 0x7b400001, + 0xc78, 0x7b410001, + 0xc78, 0x7b420001, + 0xc78, 0x7b430001, + 0xc78, 0x7b440001, + 0xc78, 0x7b450001, + 0xc78, 0x7a460001, + 0xc78, 0x79470001, + 0xc78, 0x78480001, + 0xc78, 0x77490001, + 0xc78, 0x764a0001, + 0xc78, 0x754b0001, + 0xc78, 0x744c0001, + 0xc78, 0x734d0001, + 0xc78, 0x724e0001, + 0xc78, 0x714f0001, + 0xc78, 0x70500001, + 0xc78, 0x6f510001, + 0xc78, 0x6e520001, + 0xc78, 0x6d530001, + 0xc78, 0x6c540001, + 0xc78, 0x6b550001, + 0xc78, 0x6a560001, + 0xc78, 0x69570001, + 0xc78, 0x68580001, + 0xc78, 0x67590001, + 0xc78, 0x665a0001, + 0xc78, 0x655b0001, + 0xc78, 0x645c0001, + 0xc78, 0x635d0001, + 0xc78, 0x625e0001, + 0xc78, 0x615f0001, + 0xc78, 0x60600001, + 0xc78, 0x49610001, + 0xc78, 0x48620001, + 0xc78, 0x47630001, + 0xc78, 0x46640001, + 0xc78, 0x45650001, + 0xc78, 0x44660001, + 0xc78, 0x43670001, + 0xc78, 0x42680001, + 0xc78, 0x41690001, + 0xc78, 0x406a0001, + 0xc78, 0x266b0001, + 0xc78, 0x256c0001, + 0xc78, 0x246d0001, + 0xc78, 0x236e0001, + 0xc78, 0x226f0001, + 0xc78, 0x21700001, + 0xc78, 0x20710001, + 0xc78, 0x06720001, + 0xc78, 0x05730001, + 0xc78, 0x04740001, + 0xc78, 0x03750001, + 0xc78, 0x02760001, + 0xc78, 0x01770001, + 0xc78, 0x00780001, + 0xc78, 0x00790001, + 0xc78, 0x007a0001, + 0xc78, 0x007b0001, + 0xc78, 0x007c0001, + 0xc78, 0x007d0001, + 0xc78, 0x007e0001, + 0xc78, 0x007f0001, + 0xc78, 0x3800001e, + 0xc78, 0x3801001e, + 0xc78, 0x3802001e, + 0xc78, 0x3803001e, + 0xc78, 0x3804001e, + 0xc78, 0x3805001e, + 0xc78, 0x3806001e, + 0xc78, 0x3807001e, + 0xc78, 0x3808001e, + 0xc78, 0x3c09001e, + 0xc78, 0x3e0a001e, + 0xc78, 0x400b001e, + 0xc78, 0x440c001e, + 0xc78, 0x480d001e, + 0xc78, 0x4c0e001e, + 0xc78, 0x500f001e, + 0xc78, 0x5210001e, + 0xc78, 0x5611001e, + 0xc78, 0x5a12001e, + 0xc78, 0x5e13001e, + 0xc78, 0x6014001e, + 0xc78, 0x6015001e, + 0xc78, 0x6016001e, + 0xc78, 0x6217001e, + 0xc78, 0x6218001e, + 0xc78, 0x6219001e, + 0xc78, 0x621a001e, + 0xc78, 0x621b001e, + 0xc78, 0x621c001e, + 0xc78, 0x621d001e, + 0xc78, 0x621e001e, + 0xc78, 0x621f001e, +}; + +u32 RTL8192CEAGCTAB_1TARRAY[AGCTAB_1TARRAYLENGTH] = { + 0xc78, 0x7b000001, + 0xc78, 0x7b010001, + 0xc78, 0x7b020001, + 0xc78, 0x7b030001, + 0xc78, 0x7b040001, + 0xc78, 0x7b050001, + 0xc78, 0x7a060001, + 0xc78, 0x79070001, + 0xc78, 0x78080001, + 0xc78, 0x77090001, + 0xc78, 0x760a0001, + 0xc78, 0x750b0001, + 0xc78, 0x740c0001, + 0xc78, 0x730d0001, + 0xc78, 0x720e0001, + 0xc78, 0x710f0001, + 0xc78, 0x70100001, + 0xc78, 0x6f110001, + 0xc78, 0x6e120001, + 0xc78, 0x6d130001, + 0xc78, 0x6c140001, + 0xc78, 0x6b150001, + 0xc78, 0x6a160001, + 0xc78, 0x69170001, + 0xc78, 0x68180001, + 0xc78, 0x67190001, + 0xc78, 0x661a0001, + 0xc78, 0x651b0001, + 0xc78, 0x641c0001, + 0xc78, 0x631d0001, + 0xc78, 0x621e0001, + 0xc78, 0x611f0001, + 0xc78, 0x60200001, + 0xc78, 0x49210001, + 0xc78, 0x48220001, + 0xc78, 0x47230001, + 0xc78, 0x46240001, + 0xc78, 0x45250001, + 0xc78, 0x44260001, + 0xc78, 0x43270001, + 0xc78, 0x42280001, + 0xc78, 0x41290001, + 0xc78, 0x402a0001, + 0xc78, 0x262b0001, + 0xc78, 0x252c0001, + 0xc78, 0x242d0001, + 0xc78, 0x232e0001, + 0xc78, 0x222f0001, + 0xc78, 0x21300001, + 0xc78, 0x20310001, + 0xc78, 0x06320001, + 0xc78, 0x05330001, + 0xc78, 0x04340001, + 0xc78, 0x03350001, + 0xc78, 0x02360001, + 0xc78, 0x01370001, + 0xc78, 0x00380001, + 0xc78, 0x00390001, + 0xc78, 0x003a0001, + 0xc78, 0x003b0001, + 0xc78, 0x003c0001, + 0xc78, 0x003d0001, + 0xc78, 0x003e0001, + 0xc78, 0x003f0001, + 0xc78, 0x7b400001, + 0xc78, 0x7b410001, + 0xc78, 0x7b420001, + 0xc78, 0x7b430001, + 0xc78, 0x7b440001, + 0xc78, 0x7b450001, + 0xc78, 0x7a460001, + 0xc78, 0x79470001, + 0xc78, 0x78480001, + 0xc78, 0x77490001, + 0xc78, 0x764a0001, + 0xc78, 0x754b0001, + 0xc78, 0x744c0001, + 0xc78, 0x734d0001, + 0xc78, 0x724e0001, + 0xc78, 0x714f0001, + 0xc78, 0x70500001, + 0xc78, 0x6f510001, + 0xc78, 0x6e520001, + 0xc78, 0x6d530001, + 0xc78, 0x6c540001, + 0xc78, 0x6b550001, + 0xc78, 0x6a560001, + 0xc78, 0x69570001, + 0xc78, 0x68580001, + 0xc78, 0x67590001, + 0xc78, 0x665a0001, + 0xc78, 0x655b0001, + 0xc78, 0x645c0001, + 0xc78, 0x635d0001, + 0xc78, 0x625e0001, + 0xc78, 0x615f0001, + 0xc78, 0x60600001, + 0xc78, 0x49610001, + 0xc78, 0x48620001, + 0xc78, 0x47630001, + 0xc78, 0x46640001, + 0xc78, 0x45650001, + 0xc78, 0x44660001, + 0xc78, 0x43670001, + 0xc78, 0x42680001, + 0xc78, 0x41690001, + 0xc78, 0x406a0001, + 0xc78, 0x266b0001, + 0xc78, 0x256c0001, + 0xc78, 0x246d0001, + 0xc78, 0x236e0001, + 0xc78, 0x226f0001, + 0xc78, 0x21700001, + 0xc78, 0x20710001, + 0xc78, 0x06720001, + 0xc78, 0x05730001, + 0xc78, 0x04740001, + 0xc78, 0x03750001, + 0xc78, 0x02760001, + 0xc78, 0x01770001, + 0xc78, 0x00780001, + 0xc78, 0x00790001, + 0xc78, 0x007a0001, + 0xc78, 0x007b0001, + 0xc78, 0x007c0001, + 0xc78, 0x007d0001, + 0xc78, 0x007e0001, + 0xc78, 0x007f0001, + 0xc78, 0x3800001e, + 0xc78, 0x3801001e, + 0xc78, 0x3802001e, + 0xc78, 0x3803001e, + 0xc78, 0x3804001e, + 0xc78, 0x3805001e, + 0xc78, 0x3806001e, + 0xc78, 0x3807001e, + 0xc78, 0x3808001e, + 0xc78, 0x3c09001e, + 0xc78, 0x3e0a001e, + 0xc78, 0x400b001e, + 0xc78, 0x440c001e, + 0xc78, 0x480d001e, + 0xc78, 0x4c0e001e, + 0xc78, 0x500f001e, + 0xc78, 0x5210001e, + 0xc78, 0x5611001e, + 0xc78, 0x5a12001e, + 0xc78, 0x5e13001e, + 0xc78, 0x6014001e, + 0xc78, 0x6015001e, + 0xc78, 0x6016001e, + 0xc78, 0x6217001e, + 0xc78, 0x6218001e, + 0xc78, 0x6219001e, + 0xc78, 0x621a001e, + 0xc78, 0x621b001e, + 0xc78, 0x621c001e, + 0xc78, 0x621d001e, + 0xc78, 0x621e001e, + 0xc78, 0x621f001e, +}; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/table.h b/drivers/net/wireless/rtlwifi/rtl8192ce/table.h new file mode 100644 index 000000000000..3a6e8b6aeee0 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/table.h @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92CE_TABLE__H_ +#define __RTL92CE_TABLE__H_ + +#include <linux/types.h> + +#define PHY_REG_2TARRAY_LENGTH 374 +extern u32 RTL8192CEPHY_REG_2TARRAY[PHY_REG_2TARRAY_LENGTH]; +#define PHY_REG_1TARRAY_LENGTH 374 +extern u32 RTL8192CEPHY_REG_1TARRAY[PHY_REG_1TARRAY_LENGTH]; +#define PHY_REG_ARRAY_PGLENGTH 192 +extern u32 RTL8192CEPHY_REG_ARRAY_PG[PHY_REG_ARRAY_PGLENGTH]; +#define RADIOA_2TARRAYLENGTH 282 +extern u32 RTL8192CERADIOA_2TARRAY[RADIOA_2TARRAYLENGTH]; +#define RADIOB_2TARRAYLENGTH 78 +extern u32 RTL8192CE_RADIOB_2TARRAY[RADIOB_2TARRAYLENGTH]; +#define RADIOA_1TARRAYLENGTH 282 +extern u32 RTL8192CE_RADIOA_1TARRAY[RADIOA_1TARRAYLENGTH]; +#define RADIOB_1TARRAYLENGTH 1 +extern u32 RTL8192CE_RADIOB_1TARRAY[RADIOB_1TARRAYLENGTH]; +#define MAC_2T_ARRAYLENGTH 162 +extern u32 RTL8192CEMAC_2T_ARRAY[MAC_2T_ARRAYLENGTH]; +#define AGCTAB_2TARRAYLENGTH 320 +extern u32 RTL8192CEAGCTAB_2TARRAY[AGCTAB_2TARRAYLENGTH]; +#define AGCTAB_1TARRAYLENGTH 320 +extern u32 RTL8192CEAGCTAB_1TARRAY[AGCTAB_1TARRAYLENGTH]; + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c new file mode 100644 index 000000000000..bf5852f2d634 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -0,0 +1,1031 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "trx.h" +#include "led.h" + +static enum rtl_desc_qsel _rtl92ce_map_hwqueue_to_fwqueue(u16 fc, + unsigned int + skb_queue) +{ + enum rtl_desc_qsel qsel; + + if (unlikely(ieee80211_is_beacon(fc))) { + qsel = QSLT_BEACON; + return qsel; + } + + if (ieee80211_is_mgmt(fc)) { + qsel = QSLT_MGNT; + return qsel; + } + + switch (skb_queue) { + case VO_QUEUE: + qsel = QSLT_VO; + break; + case VI_QUEUE: + qsel = QSLT_VI; + break; + case BE_QUEUE: + qsel = QSLT_BE; + break; + case BK_QUEUE: + qsel = QSLT_BK; + break; + default: + qsel = QSLT_BE; + RT_ASSERT(false, ("BE queue, skb_queue:%d," + " set qsel = 0x%X\n", skb_queue, QSLT_BE)); + break; + } + return qsel; +} + +static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) +{ + int rate_idx; + + if (first_ampdu) { + if (false == isht) { + switch (desc_rate) { + case DESC92C_RATE1M: + rate_idx = 0; + break; + case DESC92C_RATE2M: + rate_idx = 1; + break; + case DESC92C_RATE5_5M: + rate_idx = 2; + break; + case DESC92C_RATE11M: + rate_idx = 3; + break; + case DESC92C_RATE6M: + rate_idx = 4; + break; + case DESC92C_RATE9M: + rate_idx = 5; + break; + case DESC92C_RATE12M: + rate_idx = 6; + break; + case DESC92C_RATE18M: + rate_idx = 7; + break; + case DESC92C_RATE24M: + rate_idx = 8; + break; + case DESC92C_RATE36M: + rate_idx = 9; + break; + case DESC92C_RATE48M: + rate_idx = 10; + break; + case DESC92C_RATE54M: + rate_idx = 11; + break; + default: + rate_idx = 0; + break; + } + } else { + rate_idx = 11; + } + + return rate_idx; + } + + switch (desc_rate) { + case DESC92C_RATE1M: + rate_idx = 0; + break; + case DESC92C_RATE2M: + rate_idx = 1; + break; + case DESC92C_RATE5_5M: + rate_idx = 2; + break; + case DESC92C_RATE11M: + rate_idx = 3; + break; + case DESC92C_RATE6M: + rate_idx = 4; + break; + case DESC92C_RATE9M: + rate_idx = 5; + break; + case DESC92C_RATE12M: + rate_idx = 6; + break; + case DESC92C_RATE18M: + rate_idx = 7; + break; + case DESC92C_RATE24M: + rate_idx = 8; + break; + case DESC92C_RATE36M: + rate_idx = 9; + break; + case DESC92C_RATE48M: + rate_idx = 10; + break; + case DESC92C_RATE54M: + rate_idx = 11; + break; + default: + rate_idx = 11; + break; + } + return rate_idx; +} + +static u8 _rtl92c_query_rxpwrpercentage(char antpower) +{ + if ((antpower <= -100) || (antpower >= 20)) + return 0; + else if (antpower >= 0) + return 100; + else + return 100 + antpower; +} + +static u8 _rtl92c_evm_db_to_percentage(char value) +{ + char ret_val; + ret_val = value; + + if (ret_val >= 0) + ret_val = 0; + + if (ret_val <= -33) + ret_val = -33; + + ret_val = 0 - ret_val; + ret_val *= 3; + + if (ret_val == 99) + ret_val = 100; + + return ret_val; +} + +static long _rtl92ce_translate_todbm(struct ieee80211_hw *hw, + u8 signal_strength_index) +{ + long signal_power; + + signal_power = (long)((signal_strength_index + 1) >> 1); + signal_power -= 95; + return signal_power; +} + +static long _rtl92ce_signal_scale_mapping(struct ieee80211_hw *hw, + long currsig) +{ + long retsig; + + if (currsig >= 61 && currsig <= 100) + retsig = 90 + ((currsig - 60) / 4); + else if (currsig >= 41 && currsig <= 60) + retsig = 78 + ((currsig - 40) / 2); + else if (currsig >= 31 && currsig <= 40) + retsig = 66 + (currsig - 30); + else if (currsig >= 21 && currsig <= 30) + retsig = 54 + (currsig - 20); + else if (currsig >= 5 && currsig <= 20) + retsig = 42 + (((currsig - 5) * 2) / 3); + else if (currsig == 4) + retsig = 36; + else if (currsig == 3) + retsig = 27; + else if (currsig == 2) + retsig = 18; + else if (currsig == 1) + retsig = 9; + else + retsig = currsig; + + return retsig; +} + +static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, + struct rtl_stats *pstats, + struct rx_desc_92c *pdesc, + struct rx_fwinfo_92c *p_drvinfo, + bool bpacket_match_bssid, + bool bpacket_toself, + bool b_packet_beacon) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct phy_sts_cck_8192s_t *cck_buf; + s8 rx_pwr_all, rx_pwr[4]; + u8 rf_rx_num, evm, pwdb_all; + u8 i, max_spatial_stream; + u32 rssi, total_rssi; + bool is_cck_rate; + + is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); + pstats->b_packet_matchbssid = bpacket_match_bssid; + pstats->b_packet_toself = bpacket_toself; + pstats->b_is_cck = is_cck_rate; + pstats->b_packet_beacon = b_packet_beacon; + pstats->b_is_cck = is_cck_rate; + pstats->rx_mimo_signalquality[0] = -1; + pstats->rx_mimo_signalquality[1] = -1; + + if (is_cck_rate) { + u8 report, cck_highpwr; + cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; + + cck_highpwr = (u8) rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + BIT(9)); + if (!cck_highpwr) { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = cck_buf->cck_agc_rpt & 0xc0; + report = report >> 6; + switch (report) { + case 0x3: + rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); + break; + case 0x2: + rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); + break; + case 0x1: + rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); + break; + case 0x0: + rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); + break; + } + } else { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = p_drvinfo->cfosho[0] & 0x60; + report = report >> 5; + switch (report) { + case 0x3: + rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x2: + rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x1: + rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x0: + rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1); + break; + } + } + + pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); + pstats->rx_pwdb_all = pwdb_all; + pstats->recvsignalpower = rx_pwr_all; + + if (bpacket_match_bssid) { + u8 sq; + if (pstats->rx_pwdb_all > 40) + sq = 100; + else { + sq = cck_buf->sq_rpt; + if (sq > 64) + sq = 0; + else if (sq < 20) + sq = 100; + else + sq = ((64 - sq) * 100) / 44; + } + + pstats->signalquality = sq; + pstats->rx_mimo_signalquality[0] = sq; + pstats->rx_mimo_signalquality[1] = -1; + } + } else { + rtlpriv->dm.brfpath_rxenable[0] = + rtlpriv->dm.brfpath_rxenable[1] = true; + for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { + if (rtlpriv->dm.brfpath_rxenable[i]) + rf_rx_num++; + + rx_pwr[i] = + ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110; + rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += rssi; + rtlpriv->stats.rx_snr_db[i] = + (long)(p_drvinfo->rxsnr[i] / 2); + + if (bpacket_match_bssid) + pstats->rx_mimo_signalstrength[i] = (u8) rssi; + } + + rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; + pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); + pstats->rx_pwdb_all = pwdb_all; + pstats->rxpower = rx_pwr_all; + pstats->recvsignalpower = rx_pwr_all; + + if (pdesc->rxht && pdesc->rxmcs >= DESC92C_RATEMCS8 && + pdesc->rxmcs <= DESC92C_RATEMCS15) + max_spatial_stream = 2; + else + max_spatial_stream = 1; + + for (i = 0; i < max_spatial_stream; i++) { + evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]); + + if (bpacket_match_bssid) { + if (i == 0) + pstats->signalquality = + (u8) (evm & 0xff); + pstats->rx_mimo_signalquality[i] = + (u8) (evm & 0xff); + } + } + } + + if (is_cck_rate) + pstats->signalstrength = + (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all)); + else if (rf_rx_num != 0) + pstats->signalstrength = + (u8) (_rtl92ce_signal_scale_mapping + (hw, total_rssi /= rf_rx_num)); +} + +static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u8 rfpath; + u32 last_rssi, tmpval; + + if (pstats->b_packet_toself || pstats->b_packet_beacon) { + rtlpriv->stats.rssi_calculate_cnt++; + + if (rtlpriv->stats.ui_rssi.total_num++ >= + PHY_RSSI_SLID_WIN_MAX) { + rtlpriv->stats.ui_rssi.total_num = + PHY_RSSI_SLID_WIN_MAX; + last_rssi = + rtlpriv->stats.ui_rssi.elements[rtlpriv-> + stats.ui_rssi.index]; + rtlpriv->stats.ui_rssi.total_val -= last_rssi; + } + + rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; + rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi. + index++] = + pstats->signalstrength; + + if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) + rtlpriv->stats.ui_rssi.index = 0; + + tmpval = rtlpriv->stats.ui_rssi.total_val / + rtlpriv->stats.ui_rssi.total_num; + rtlpriv->stats.signal_strength = + _rtl92ce_translate_todbm(hw, (u8) tmpval); + pstats->rssi = rtlpriv->stats.signal_strength; + } + + if (!pstats->b_is_cck && pstats->b_packet_toself) { + for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; + rfpath++) { + + if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath)) + continue; + + if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { + rtlpriv->stats.rx_rssi_percentage[rfpath] = + pstats->rx_mimo_signalstrength[rfpath]; + + } + + if (pstats->rx_mimo_signalstrength[rfpath] > + rtlpriv->stats.rx_rssi_percentage[rfpath]) { + rtlpriv->stats.rx_rssi_percentage[rfpath] = + ((rtlpriv->stats. + rx_rssi_percentage[rfpath] * + (RX_SMOOTH_FACTOR - 1)) + + (pstats->rx_mimo_signalstrength[rfpath])) / + (RX_SMOOTH_FACTOR); + + rtlpriv->stats.rx_rssi_percentage[rfpath] = + rtlpriv->stats.rx_rssi_percentage[rfpath] + + 1; + } else { + rtlpriv->stats.rx_rssi_percentage[rfpath] = + ((rtlpriv->stats. + rx_rssi_percentage[rfpath] * + (RX_SMOOTH_FACTOR - 1)) + + (pstats->rx_mimo_signalstrength[rfpath])) / + (RX_SMOOTH_FACTOR); + } + + } + } +} + +static void _rtl92ce_update_rxsignalstatistics(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int weighting; + + if (rtlpriv->stats.recv_signal_power == 0) + rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; + + if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) + weighting = 5; + + else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) + weighting = (-5); + + rtlpriv->stats.recv_signal_power = + (rtlpriv->stats.recv_signal_power * 5 + + pstats->recvsignalpower + weighting) / 6; +} + +static void _rtl92ce_process_pwdb(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undecorated_smoothed_pwdb; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + return; + } else { + undecorated_smoothed_pwdb = + rtlpriv->dm.undecorated_smoothed_pwdb; + } + + if (pstats->b_packet_toself || pstats->b_packet_beacon) { + if (undecorated_smoothed_pwdb < 0) + undecorated_smoothed_pwdb = pstats->rx_pwdb_all; + + if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) { + undecorated_smoothed_pwdb = + (((undecorated_smoothed_pwdb) * + (RX_SMOOTH_FACTOR - 1)) + + (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); + + undecorated_smoothed_pwdb = undecorated_smoothed_pwdb + + 1; + } else { + undecorated_smoothed_pwdb = + (((undecorated_smoothed_pwdb) * + (RX_SMOOTH_FACTOR - 1)) + + (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); + } + + rtlpriv->dm.undecorated_smoothed_pwdb = + undecorated_smoothed_pwdb; + _rtl92ce_update_rxsignalstatistics(hw, pstats); + } +} + +static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 last_evm, n_spatialstream, tmpval; + + if (pstats->signalquality != 0) { + if (pstats->b_packet_toself || pstats->b_packet_beacon) { + + if (rtlpriv->stats.ui_link_quality.total_num++ >= + PHY_LINKQUALITY_SLID_WIN_MAX) { + rtlpriv->stats.ui_link_quality.total_num = + PHY_LINKQUALITY_SLID_WIN_MAX; + last_evm = + rtlpriv->stats. + ui_link_quality.elements[rtlpriv-> + stats.ui_link_quality. + index]; + rtlpriv->stats.ui_link_quality.total_val -= + last_evm; + } + + rtlpriv->stats.ui_link_quality.total_val += + pstats->signalquality; + rtlpriv->stats.ui_link_quality.elements[rtlpriv->stats. + ui_link_quality. + index++] = + pstats->signalquality; + + if (rtlpriv->stats.ui_link_quality.index >= + PHY_LINKQUALITY_SLID_WIN_MAX) + rtlpriv->stats.ui_link_quality.index = 0; + + tmpval = rtlpriv->stats.ui_link_quality.total_val / + rtlpriv->stats.ui_link_quality.total_num; + rtlpriv->stats.signal_quality = tmpval; + + rtlpriv->stats.last_sigstrength_inpercent = tmpval; + + for (n_spatialstream = 0; n_spatialstream < 2; + n_spatialstream++) { + if (pstats-> + rx_mimo_signalquality[n_spatialstream] != + -1) { + if (rtlpriv->stats. + rx_evm_percentage[n_spatialstream] + == 0) { + rtlpriv->stats. + rx_evm_percentage + [n_spatialstream] = + pstats->rx_mimo_signalquality + [n_spatialstream]; + } + + rtlpriv->stats. + rx_evm_percentage[n_spatialstream] = + ((rtlpriv-> + stats.rx_evm_percentage + [n_spatialstream] * + (RX_SMOOTH_FACTOR - 1)) + + (pstats-> + rx_mimo_signalquality + [n_spatialstream] * 1)) / + (RX_SMOOTH_FACTOR); + } + } + } + } else { + ; + } +} + +static void _rtl92ce_process_phyinfo(struct ieee80211_hw *hw, + u8 *buffer, + struct rtl_stats *pcurrent_stats) +{ + + if (!pcurrent_stats->b_packet_matchbssid && + !pcurrent_stats->b_packet_beacon) + return; + + _rtl92ce_process_ui_rssi(hw, pcurrent_stats); + _rtl92ce_process_pwdb(hw, pcurrent_stats); + _rtl92ce_process_ui_link_quality(hw, pcurrent_stats); +} + +static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct rtl_stats *pstats, + struct rx_desc_92c *pdesc, + struct rx_fwinfo_92c *p_drvinfo) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + struct ieee80211_hdr *hdr; + u8 *tmp_buf; + u8 *praddr; + u8 *psaddr; + u16 fc, type; + bool b_packet_matchbssid, b_packet_toself, b_packet_beacon; + + tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; + + hdr = (struct ieee80211_hdr *)tmp_buf; + fc = le16_to_cpu(hdr->frame_control); + type = WLAN_FC_GET_TYPE(fc); + praddr = hdr->addr1; + psaddr = hdr->addr2; + + b_packet_matchbssid = + ((IEEE80211_FTYPE_CTL != type) && + (!compare_ether_addr(mac->bssid, + (fc & IEEE80211_FCTL_TODS) ? + hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? + hdr->addr2 : hdr->addr3)) && + (!pstats->b_hwerror) && (!pstats->b_crc) && (!pstats->b_icv)); + + b_packet_toself = b_packet_matchbssid && + (!compare_ether_addr(praddr, rtlefuse->dev_addr)); + + if (ieee80211_is_beacon(fc)) + b_packet_beacon = true; + + _rtl92ce_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, + b_packet_matchbssid, b_packet_toself, + b_packet_beacon); + + _rtl92ce_process_phyinfo(hw, tmp_buf, pstats); +} + +bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, + u8 *p_desc, struct sk_buff *skb) +{ + struct rx_fwinfo_92c *p_drvinfo; + struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; + + u32 phystatus = GET_RX_DESC_PHYST(pdesc); + stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); + stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * + RX_DRV_INFO_SIZE_UNIT; + stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); + stats->b_icv = (u16) GET_RX_DESC_ICV(pdesc); + stats->b_crc = (u16) GET_RX_DESC_CRC32(pdesc); + stats->b_hwerror = (stats->b_crc | stats->b_icv); + stats->decrypted = !GET_RX_DESC_SWDEC(pdesc); + stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc); + stats->b_shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); + stats->b_isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); + stats->b_isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) + && (GET_RX_DESC_FAGGR(pdesc) == 1)); + stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); + stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); + + rx_status->freq = hw->conf.channel->center_freq; + rx_status->band = hw->conf.channel->band; + + if (GET_RX_DESC_CRC32(pdesc)) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (!GET_RX_DESC_SWDEC(pdesc)) + rx_status->flag |= RX_FLAG_DECRYPTED; + + if (GET_RX_DESC_BW(pdesc)) + rx_status->flag |= RX_FLAG_40MHZ; + + if (GET_RX_DESC_RXHT(pdesc)) + rx_status->flag |= RX_FLAG_HT; + + rx_status->flag |= RX_FLAG_TSFT; + + if (stats->decrypted) + rx_status->flag |= RX_FLAG_DECRYPTED; + + rx_status->rate_idx = _rtl92ce_rate_mapping((bool) + GET_RX_DESC_RXHT(pdesc), + (u8) + GET_RX_DESC_RXMCS(pdesc), + (bool) + GET_RX_DESC_PAGGR(pdesc)); + + rx_status->mactime = GET_RX_DESC_TSFL(pdesc); + if (phystatus == true) { + p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + + stats->rx_bufshift); + + _rtl92ce_translate_rx_signal_stuff(hw, + skb, stats, pdesc, + p_drvinfo); + } + + /*rx_status->qual = stats->signal; */ + rx_status->signal = stats->rssi + 10; + /*rx_status->noise = -stats->noise; */ + + return true; +} + +void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + struct ieee80211_tx_info *info, struct sk_buff *skb, + unsigned int queue_index) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool b_defaultadapter = true; + + struct ieee80211_sta *sta = ieee80211_find_sta(mac->vif, mac->bssid); + + u8 *pdesc = (u8 *) pdesc_tx; + struct rtl_tcb_desc tcb_desc; + u8 *qc = ieee80211_get_qos_ctl(hdr); + u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + u16 seq_number; + u16 fc = le16_to_cpu(hdr->frame_control); + u8 rate_flag = info->control.rates[0].flags; + + enum rtl_desc_qsel fw_qsel = + _rtl92ce_map_hwqueue_to_fwqueue(le16_to_cpu(hdr->frame_control), + queue_index); + + bool b_firstseg = ((hdr->seq_ctrl & + cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); + + bool b_lastseg = ((hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); + + dma_addr_t mapping = pci_map_single(rtlpci->pdev, + skb->data, skb->len, + PCI_DMA_TODEVICE); + + seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; + + rtl_get_tcb_desc(hw, info, skb, &tcb_desc); + + CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c)); + + if (b_firstseg) { + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + + SET_TX_DESC_TX_RATE(pdesc, tcb_desc.hw_rate); + + if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble) + SET_TX_DESC_DATA_SHORTGI(pdesc, 1); + + if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && + info->flags & IEEE80211_TX_CTL_AMPDU) { + SET_TX_DESC_AGG_BREAK(pdesc, 1); + SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); + } + SET_TX_DESC_SEQ(pdesc, seq_number); + + SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc.b_rts_enable && + !tcb_desc. + b_cts_enable) ? 1 : 0)); + SET_TX_DESC_HW_RTS_ENABLE(pdesc, + ((tcb_desc.b_rts_enable + || tcb_desc.b_cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc.b_cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc.b_rts_stbc) ? 1 : 0)); + + SET_TX_DESC_RTS_RATE(pdesc, tcb_desc.rts_rate); + SET_TX_DESC_RTS_BW(pdesc, 0); + SET_TX_DESC_RTS_SC(pdesc, tcb_desc.rts_sc); + SET_TX_DESC_RTS_SHORT(pdesc, + ((tcb_desc.rts_rate <= DESC92C_RATE54M) ? + (tcb_desc.b_rts_use_shortpreamble ? 1 : 0) + : (tcb_desc.b_rts_use_shortgi ? 1 : 0))); + + if (mac->bw_40) { + if (tcb_desc.b_packet_bw) { + SET_TX_DESC_DATA_BW(pdesc, 1); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + + if (rate_flag & IEEE80211_TX_RC_DUP_DATA) { + SET_TX_DESC_TX_SUB_CARRIER(pdesc, + mac->cur_40_prime_sc); + } + } + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); + } + + SET_TX_DESC_LINIP(pdesc, 0); + SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); + + if (sta) { + u8 ampdu_density = sta->ht_cap.ampdu_density; + SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); + } + + if (info->control.hw_key) { + struct ieee80211_key_conf *keyconf = + info->control.hw_key; + + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x1); + break; + case WLAN_CIPHER_SUITE_CCMP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x3); + break; + default: + SET_TX_DESC_SEC_TYPE(pdesc, 0x0); + break; + + } + } + + SET_TX_DESC_PKT_ID(pdesc, 0); + SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); + + SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); + SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); + SET_TX_DESC_DISABLE_FB(pdesc, 0); + SET_TX_DESC_USE_RATE(pdesc, tcb_desc.use_driver_rate ? 1 : 0); + + if (ieee80211_is_data_qos(fc)) { + if (mac->rdg_en) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + ("Enable RDG function.\n")); + SET_TX_DESC_RDG_ENABLE(pdesc, 1); + SET_TX_DESC_HTC(pdesc, 1); + } + } + } + + SET_TX_DESC_FIRST_SEG(pdesc, (b_firstseg ? 1 : 0)); + SET_TX_DESC_LAST_SEG(pdesc, (b_lastseg ? 1 : 0)); + + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); + + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); + + if (rtlpriv->dm.b_useramask) { + SET_TX_DESC_RATE_ID(pdesc, tcb_desc.ratr_index); + SET_TX_DESC_MACID(pdesc, tcb_desc.mac_id); + } else { + SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc.ratr_index); + SET_TX_DESC_MACID(pdesc, tcb_desc.ratr_index); + } + + if ((!ieee80211_is_data_qos(fc)) && ppsc->b_leisure_ps && + ppsc->b_fwctrl_lps) { + SET_TX_DESC_HWSEQ_EN(pdesc, 1); + SET_TX_DESC_PKT_ID(pdesc, 8); + + if (!b_defaultadapter) + SET_TX_DESC_QOS(pdesc, 1); + } + + SET_TX_DESC_MORE_FRAG(pdesc, (b_lastseg ? 0 : 1)); + + if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { + SET_TX_DESC_BMC(pdesc, 1); + } + + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n")); +} + +void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, + u8 *pdesc, bool b_firstseg, + bool b_lastseg, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 fw_queue = QSLT_BEACON; + + dma_addr_t mapping = pci_map_single(rtlpci->pdev, + skb->data, skb->len, + PCI_DMA_TODEVICE); + + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + u16 fc = le16_to_cpu(hdr->frame_control); + + CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); + + if (b_firstseg) + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + + SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); + + SET_TX_DESC_SEQ(pdesc, 0); + + SET_TX_DESC_LINIP(pdesc, 0); + + SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); + + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len)); + + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); + + SET_TX_DESC_RATE_ID(pdesc, 7); + SET_TX_DESC_MACID(pdesc, 0); + + SET_TX_DESC_OWN(pdesc, 1); + + SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len)); + + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_OFFSET(pdesc, 0x20); + + SET_TX_DESC_USE_RATE(pdesc, 1); + + if (!ieee80211_is_data_qos(fc)) { + SET_TX_DESC_HWSEQ_EN(pdesc, 1); + SET_TX_DESC_PKT_ID(pdesc, 8); + } + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C Tx Cmd Content\n", + pdesc, TX_DESC_SIZE); +} + +void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val) +{ + if (istx == true) { + switch (desc_name) { + case HW_DESC_OWN: + SET_TX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_TX_NEXTDESC_ADDR: + SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); + break; + default: + RT_ASSERT(false, ("ERR txdesc :%d" + " not process\n", desc_name)); + break; + } + } else { + switch (desc_name) { + case HW_DESC_RXOWN: + SET_RX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_RXBUFF_ADDR: + SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val); + break; + case HW_DESC_RXPKT_LEN: + SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val); + break; + case HW_DESC_RXERO: + SET_RX_DESC_EOR(pdesc, 1); + break; + default: + RT_ASSERT(false, ("ERR rxdesc :%d " + "not process\n", desc_name)); + break; + } + } +} + +u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name) +{ + u32 ret = 0; + + if (istx == true) { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_TX_DESC_OWN(p_desc); + break; + case HW_DESC_TXBUFF_ADDR: + ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc); + break; + default: + RT_ASSERT(false, ("ERR txdesc :%d " + "not process\n", desc_name)); + break; + } + } else { + struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_RX_DESC_OWN(pdesc); + break; + case HW_DESC_RXPKT_LEN: + ret = GET_RX_DESC_PKT_LEN(pdesc); + break; + default: + RT_ASSERT(false, ("ERR rxdesc :%d " + "not process\n", desc_name)); + break; + } + } + return ret; +} + +void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (hw_queue == BEACON_QUEUE) { + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); + } else { + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, + BIT(0) << (hw_queue)); + } +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h new file mode 100644 index 000000000000..53d0e0a5af5c --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h @@ -0,0 +1,714 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92CE_TRX_H__ +#define __RTL92CE_TRX_H__ + +#define TX_DESC_SIZE 64 +#define TX_DESC_AGGR_SUBFRAME_SIZE 32 + +#define RX_DESC_SIZE 32 +#define RX_DRV_INFO_SIZE_UNIT 8 + +#define TX_DESC_NEXT_DESC_OFFSET 40 +#define USB_HWDESC_HEADER_LEN 32 +#define CRCLENGTH 4 + +#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) +#define SET_TX_DESC_OFFSET(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) +#define SET_TX_DESC_BMC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) +#define SET_TX_DESC_HTC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) +#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) +#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) +#define SET_TX_DESC_LINIP(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) +#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) +#define SET_TX_DESC_GF(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) +#define SET_TX_DESC_OWN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + +#define GET_TX_DESC_PKT_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 0, 16) +#define GET_TX_DESC_OFFSET(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 16, 8) +#define GET_TX_DESC_BMC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 24, 1) +#define GET_TX_DESC_HTC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 25, 1) +#define GET_TX_DESC_LAST_SEG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 26, 1) +#define GET_TX_DESC_FIRST_SEG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 27, 1) +#define GET_TX_DESC_LINIP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 28, 1) +#define GET_TX_DESC_NO_ACM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 29, 1) +#define GET_TX_DESC_GF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 30, 1) +#define GET_TX_DESC_OWN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 31, 1) + +#define SET_TX_DESC_MACID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 5, __val) +#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 5, 1, __val) +#define SET_TX_DESC_BK(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 6, 1, __val) +#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 7, 1, __val) +#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) +#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) +#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) +#define SET_TX_DESC_PIFS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) +#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val) +#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val) +#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) +#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) +#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val) + +#define GET_TX_DESC_MACID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 0, 5) +#define GET_TX_DESC_AGG_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 5, 1) +#define GET_TX_DESC_AGG_BREAK(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 6, 1) +#define GET_TX_DESC_RDG_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 7, 1) +#define GET_TX_DESC_QUEUE_SEL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 8, 5) +#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) +#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) +#define GET_TX_DESC_PIFS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) +#define GET_TX_DESC_RATE_ID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) +#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) +#define GET_TX_DESC_EN_DESC_ID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) +#define GET_TX_DESC_SEC_TYPE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 22, 2) +#define GET_TX_DESC_PKT_OFFSET(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 24, 8) + +#define SET_TX_DESC_RTS_RC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val) +#define SET_TX_DESC_DATA_RC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val) +#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val) +#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) +#define SET_TX_DESC_RAW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) +#define SET_TX_DESC_CCX(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) +#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) +#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val) +#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val) +#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val) +#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val) +#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val) + +#define GET_TX_DESC_RTS_RC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 0, 6) +#define GET_TX_DESC_DATA_RC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 6, 6) +#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 14, 2) +#define GET_TX_DESC_MORE_FRAG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 17, 1) +#define GET_TX_DESC_RAW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 18, 1) +#define GET_TX_DESC_CCX(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 19, 1) +#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 20, 3) +#define GET_TX_DESC_ANTSEL_A(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 24, 1) +#define GET_TX_DESC_ANTSEL_B(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 25, 1) +#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 26, 2) +#define GET_TX_DESC_TX_ANTL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 28, 2) +#define GET_TX_DESC_TX_ANT_HT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 30, 2) + +#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val) +#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val) +#define SET_TX_DESC_SEQ(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val) +#define SET_TX_DESC_PKT_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 4, __val) + +#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 0, 8) +#define GET_TX_DESC_TAIL_PAGE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 8, 8) +#define GET_TX_DESC_SEQ(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 16, 12) +#define GET_TX_DESC_PKT_ID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 28, 4) + +#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val) +#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val) +#define SET_TX_DESC_QOS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val) +#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val) +#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val) +#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val) +#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val) +#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val) +#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val) +#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val) +#define SET_TX_DESC_PORT_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val) +#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val) +#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val) +#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val) +#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val) +#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val) +#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val) +#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val) +#define SET_TX_DESC_RTS_BW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val) +#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val) +#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val) + +#define GET_TX_DESC_RTS_RATE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 0, 5) +#define GET_TX_DESC_AP_DCFE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 5, 1) +#define GET_TX_DESC_QOS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 6, 1) +#define GET_TX_DESC_HWSEQ_EN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 7, 1) +#define GET_TX_DESC_USE_RATE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 8, 1) +#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 9, 1) +#define GET_TX_DESC_DISABLE_FB(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 10, 1) +#define GET_TX_DESC_CTS2SELF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 11, 1) +#define GET_TX_DESC_RTS_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 12, 1) +#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 13, 1) +#define GET_TX_DESC_PORT_ID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 14, 1) +#define GET_TX_DESC_WAIT_DCTS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 18, 1) +#define GET_TX_DESC_CTS2AP_EN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 19, 1) +#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 20, 2) +#define GET_TX_DESC_TX_STBC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 22, 2) +#define GET_TX_DESC_DATA_SHORT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 24, 1) +#define GET_TX_DESC_DATA_BW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 25, 1) +#define GET_TX_DESC_RTS_SHORT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 26, 1) +#define GET_TX_DESC_RTS_BW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 27, 1) +#define GET_TX_DESC_RTS_SC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 28, 2) +#define GET_TX_DESC_RTS_STBC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 30, 2) + +#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val) +#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val) +#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) +#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val) +#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) +#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val) +#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val) +#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val) + +#define GET_TX_DESC_TX_RATE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 0, 6) +#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 6, 1) +#define GET_TX_DESC_CCX_TAG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 7, 1) +#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 8, 5) +#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 13, 4) +#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 17, 1) +#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 18, 6) +#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 24, 8) + +#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val) +#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val) +#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val) +#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val) +#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val) +#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val) +#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val) +#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 28, 4, __val) + +#define GET_TX_DESC_TXAGC_A(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 0, 5) +#define GET_TX_DESC_TXAGC_B(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 5, 5) +#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 10, 1) +#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 11, 5) +#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 16, 4) +#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 20, 4) +#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 24, 4) +#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 28, 4) + +#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) +#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 4, __val) +#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 20, 4, __val) +#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val) +#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 28, 4, __val) + +#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 0, 16) +#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 16, 4) +#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 20, 4) +#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 24, 4) +#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 28, 4) + +#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val) +#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val) + +#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+32, 0, 32) +#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+36, 0, 32) + +#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) +#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val) + +#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+40, 0, 32) +#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+44, 0, 32) + +#define GET_RX_DESC_PKT_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 0, 14) +#define GET_RX_DESC_CRC32(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 14, 1) +#define GET_RX_DESC_ICV(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 15, 1) +#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 16, 4) +#define GET_RX_DESC_SECURITY(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 20, 3) +#define GET_RX_DESC_QOS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 23, 1) +#define GET_RX_DESC_SHIFT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 24, 2) +#define GET_RX_DESC_PHYST(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 26, 1) +#define GET_RX_DESC_SWDEC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 27, 1) +#define GET_RX_DESC_LS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 28, 1) +#define GET_RX_DESC_FS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 29, 1) +#define GET_RX_DESC_EOR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 30, 1) +#define GET_RX_DESC_OWN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 31, 1) + +#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) +#define SET_RX_DESC_EOR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) +#define SET_RX_DESC_OWN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + +#define GET_RX_DESC_MACID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 0, 5) +#define GET_RX_DESC_TID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 5, 4) +#define GET_RX_DESC_HWRSVD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 9, 5) +#define GET_RX_DESC_PAGGR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) +#define GET_RX_DESC_FAGGR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) +#define GET_RX_DESC_A1_FIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) +#define GET_RX_DESC_A2_FIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 20, 4) +#define GET_RX_DESC_PAM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) +#define GET_RX_DESC_PWR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) +#define GET_RX_DESC_MD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) +#define GET_RX_DESC_MF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) +#define GET_RX_DESC_TYPE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) +#define GET_RX_DESC_MC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) +#define GET_RX_DESC_BC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) +#define GET_RX_DESC_SEQ(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) +#define GET_RX_DESC_FRAG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) +#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 16, 14) +#define GET_RX_DESC_NEXT_IND(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 30, 1) +#define GET_RX_DESC_RSVD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 31, 1) + +#define GET_RX_DESC_RXMCS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 0, 6) +#define GET_RX_DESC_RXHT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 6, 1) +#define GET_RX_DESC_SPLCP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 8, 1) +#define GET_RX_DESC_BW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 9, 1) +#define GET_RX_DESC_HTC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) +#define GET_RX_DESC_HWPC_ERR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 14, 1) +#define GET_RX_DESC_HWPC_IND(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 15, 1) +#define GET_RX_DESC_IV0(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 16, 16) + +#define GET_RX_DESC_IV1(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 0, 32) +#define GET_RX_DESC_TSFL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) + +#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) +#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) + +#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) +#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) + +#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ +do { \ + if (_size > TX_DESC_NEXT_DESC_OFFSET) \ + memset((void *)__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ + else \ + memset((void *)__pdesc, 0, _size); \ +} while (0); + +#define RX_HAL_IS_CCK_RATE(_pdesc)\ + (_pdesc->rxmcs == DESC92C_RATE1M || \ + _pdesc->rxmcs == DESC92C_RATE2M || \ + _pdesc->rxmcs == DESC92C_RATE5_5M || \ + _pdesc->rxmcs == DESC92C_RATE11M) + +struct rx_fwinfo_92c { + u8 gain_trsw[4]; + u8 pwdb_all; + u8 cfosho[4]; + u8 cfotail[4]; + char rxevm[2]; + char rxsnr[4]; + u8 pdsnr[2]; + u8 csi_current[2]; + u8 csi_target[2]; + u8 sigevm; + u8 max_ex_pwr; + u8 ex_intf_flag:1; + u8 sgi_en:1; + u8 rxsc:2; + u8 reserve:4; +} __packed; + +struct tx_desc_92c { + u32 pktsize:16; + u32 offset:8; + u32 bmc:1; + u32 htc:1; + u32 lastseg:1; + u32 firstseg:1; + u32 linip:1; + u32 noacm:1; + u32 gf:1; + u32 own:1; + + u32 macid:5; + u32 agg_en:1; + u32 bk:1; + u32 rdg_en:1; + u32 queuesel:5; + u32 rd_nav_ext:1; + u32 lsig_txop_en:1; + u32 pifs:1; + u32 rateid:4; + u32 nav_usehdr:1; + u32 en_descid:1; + u32 sectype:2; + u32 pktoffset:8; + + u32 rts_rc:6; + u32 data_rc:6; + u32 rsvd0:2; + u32 bar_retryht:2; + u32 rsvd1:1; + u32 morefrag:1; + u32 raw:1; + u32 ccx:1; + u32 ampdudensity:3; + u32 rsvd2:1; + u32 ant_sela:1; + u32 ant_selb:1; + u32 txant_cck:2; + u32 txant_l:2; + u32 txant_ht:2; + + u32 nextheadpage:8; + u32 tailpage:8; + u32 seq:12; + u32 pktid:4; + + u32 rtsrate:5; + u32 apdcfe:1; + u32 qos:1; + u32 hwseq_enable:1; + u32 userrate:1; + u32 dis_rtsfb:1; + u32 dis_datafb:1; + u32 cts2self:1; + u32 rts_en:1; + u32 hwrts_en:1; + u32 portid:1; + u32 rsvd3:3; + u32 waitdcts:1; + u32 cts2ap_en:1; + u32 txsc:2; + u32 stbc:2; + u32 txshort:1; + u32 txbw:1; + u32 rtsshort:1; + u32 rtsbw:1; + u32 rtssc:2; + u32 rtsstbc:2; + + u32 txrate:6; + u32 shortgi:1; + u32 ccxt:1; + u32 txrate_fb_lmt:5; + u32 rtsrate_fb_lmt:4; + u32 retrylmt_en:1; + u32 txretrylmt:6; + u32 usb_txaggnum:8; + + u32 txagca:5; + u32 txagcb:5; + u32 usemaxlen:1; + u32 maxaggnum:5; + u32 mcsg1maxlen:4; + u32 mcsg2maxlen:4; + u32 mcsg3maxlen:4; + u32 mcs7sgimaxlen:4; + + u32 txbuffersize:16; + u32 mcsg4maxlen:4; + u32 mcsg5maxlen:4; + u32 mcsg6maxlen:4; + u32 mcsg15sgimaxlen:4; + + u32 txbuffaddr; + u32 txbufferaddr64; + u32 nextdescaddress; + u32 nextdescaddress64; + + u32 reserve_pass_pcie_mm_limit[4]; +} __packed; + +struct rx_desc_92c { + u32 length:14; + u32 crc32:1; + u32 icverror:1; + u32 drv_infosize:4; + u32 security:3; + u32 qos:1; + u32 shift:2; + u32 phystatus:1; + u32 swdec:1; + u32 lastseg:1; + u32 firstseg:1; + u32 eor:1; + u32 own:1; + + u32 macid:5; + u32 tid:4; + u32 hwrsvd:5; + u32 paggr:1; + u32 faggr:1; + u32 a1_fit:4; + u32 a2_fit:4; + u32 pam:1; + u32 pwr:1; + u32 moredata:1; + u32 morefrag:1; + u32 type:2; + u32 mc:1; + u32 bc:1; + + u32 seq:12; + u32 frag:4; + u32 nextpktlen:14; + u32 nextind:1; + u32 rsvd:1; + + u32 rxmcs:6; + u32 rxht:1; + u32 amsdu:1; + u32 splcp:1; + u32 bandwidth:1; + u32 htc:1; + u32 tcpchk_rpt:1; + u32 ipcchk_rpt:1; + u32 tcpchk_valid:1; + u32 hwpcerr:1; + u32 hwpcind:1; + u32 iv0:16; + + u32 iv1; + + u32 tsfl; + + u32 bufferaddress; + u32 bufferaddress64; + +} __packed; + +void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, + u8 *pdesc, struct ieee80211_tx_info *info, + struct sk_buff *skb, unsigned int qsel); +bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb); +void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val); +u32 rtl92ce_get_desc(u8 *pdesc, bool istx, u8 desc_name); +void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue); +void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + bool b_firstseg, bool b_lastseg, + struct sk_buff *skb); +#endif diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h new file mode 100644 index 000000000000..d44d79613d2d --- /dev/null +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -0,0 +1,1532 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL_WIFI_H__ +#define __RTL_WIFI_H__ + +#include <linux/sched.h> +#include <linux/firmware.h> +#include <linux/version.h> +#include <linux/etherdevice.h> +#include <net/mac80211.h> +#include "debug.h" + +#define RF_CHANGE_BY_INIT 0 +#define RF_CHANGE_BY_IPS BIT(28) +#define RF_CHANGE_BY_PS BIT(29) +#define RF_CHANGE_BY_HW BIT(30) +#define RF_CHANGE_BY_SW BIT(31) + +#define IQK_ADDA_REG_NUM 16 +#define IQK_MAC_REG_NUM 4 + +#define MAX_KEY_LEN 61 +#define KEY_BUF_SIZE 5 + +/* QoS related. */ +/*aci: 0x00 Best Effort*/ +/*aci: 0x01 Background*/ +/*aci: 0x10 Video*/ +/*aci: 0x11 Voice*/ +/*Max: define total number.*/ +#define AC0_BE 0 +#define AC1_BK 1 +#define AC2_VI 2 +#define AC3_VO 3 +#define AC_MAX 4 +#define QOS_QUEUE_NUM 4 +#define RTL_MAC80211_NUM_QUEUE 5 + +#define QBSS_LOAD_SIZE 5 +#define MAX_WMMELE_LENGTH 64 + +/*slot time for 11g. */ +#define RTL_SLOT_TIME_9 9 +#define RTL_SLOT_TIME_20 20 + +/*related with tcp/ip. */ +/*if_ehther.h*/ +#define ETH_P_PAE 0x888E /*Port Access Entity (IEEE 802.1X) */ +#define ETH_P_IP 0x0800 /*Internet Protocol packet */ +#define ETH_P_ARP 0x0806 /*Address Resolution packet */ +#define SNAP_SIZE 6 +#define PROTOC_TYPE_SIZE 2 + +/*related with 802.11 frame*/ +#define MAC80211_3ADDR_LEN 24 +#define MAC80211_4ADDR_LEN 30 + +enum intf_type { + INTF_PCI = 0, + INTF_USB = 1, +}; + +enum radio_path { + RF90_PATH_A = 0, + RF90_PATH_B = 1, + RF90_PATH_C = 2, + RF90_PATH_D = 3, +}; + +enum rt_eeprom_type { + EEPROM_93C46, + EEPROM_93C56, + EEPROM_BOOT_EFUSE, +}; + +enum rtl_status { + RTL_STATUS_INTERFACE_START = 0, +}; + +enum hardware_type { + HARDWARE_TYPE_RTL8192E, + HARDWARE_TYPE_RTL8192U, + HARDWARE_TYPE_RTL8192SE, + HARDWARE_TYPE_RTL8192SU, + HARDWARE_TYPE_RTL8192CE, + HARDWARE_TYPE_RTL8192CU, + HARDWARE_TYPE_RTL8192DE, + HARDWARE_TYPE_RTL8192DU, + + /*keep it last*/ + HARDWARE_TYPE_NUM +}; + +enum scan_operation_backup_opt { + SCAN_OPT_BACKUP = 0, + SCAN_OPT_RESTORE, + SCAN_OPT_MAX +}; + +/*RF state.*/ +enum rf_pwrstate { + ERFON, + ERFSLEEP, + ERFOFF +}; + +struct bb_reg_def { + u32 rfintfs; + u32 rfintfi; + u32 rfintfo; + u32 rfintfe; + u32 rf3wire_offset; + u32 rflssi_select; + u32 rftxgain_stage; + u32 rfhssi_para1; + u32 rfhssi_para2; + u32 rfswitch_control; + u32 rfagc_control1; + u32 rfagc_control2; + u32 rfrxiq_imbalance; + u32 rfrx_afe; + u32 rftxiq_imbalance; + u32 rftx_afe; + u32 rflssi_readback; + u32 rflssi_readbackpi; +}; + +enum io_type { + IO_CMD_PAUSE_DM_BY_SCAN = 0, + IO_CMD_RESUME_DM_BY_SCAN = 1, +}; + +enum hw_variables { + HW_VAR_ETHER_ADDR, + HW_VAR_MULTICAST_REG, + HW_VAR_BASIC_RATE, + HW_VAR_BSSID, + HW_VAR_MEDIA_STATUS, + HW_VAR_SECURITY_CONF, + HW_VAR_BEACON_INTERVAL, + HW_VAR_ATIM_WINDOW, + HW_VAR_LISTEN_INTERVAL, + HW_VAR_CS_COUNTER, + HW_VAR_DEFAULTKEY0, + HW_VAR_DEFAULTKEY1, + HW_VAR_DEFAULTKEY2, + HW_VAR_DEFAULTKEY3, + HW_VAR_SIFS, + HW_VAR_DIFS, + HW_VAR_EIFS, + HW_VAR_SLOT_TIME, + HW_VAR_ACK_PREAMBLE, + HW_VAR_CW_CONFIG, + HW_VAR_CW_VALUES, + HW_VAR_RATE_FALLBACK_CONTROL, + HW_VAR_CONTENTION_WINDOW, + HW_VAR_RETRY_COUNT, + HW_VAR_TR_SWITCH, + HW_VAR_COMMAND, + HW_VAR_WPA_CONFIG, + HW_VAR_AMPDU_MIN_SPACE, + HW_VAR_SHORTGI_DENSITY, + HW_VAR_AMPDU_FACTOR, + HW_VAR_MCS_RATE_AVAILABLE, + HW_VAR_AC_PARAM, + HW_VAR_ACM_CTRL, + HW_VAR_DIS_Req_Qsize, + HW_VAR_CCX_CHNL_LOAD, + HW_VAR_CCX_NOISE_HISTOGRAM, + HW_VAR_CCX_CLM_NHM, + HW_VAR_TxOPLimit, + HW_VAR_TURBO_MODE, + HW_VAR_RF_STATE, + HW_VAR_RF_OFF_BY_HW, + HW_VAR_BUS_SPEED, + HW_VAR_SET_DEV_POWER, + + HW_VAR_RCR, + HW_VAR_RATR_0, + HW_VAR_RRSR, + HW_VAR_CPU_RST, + HW_VAR_CECHK_BSSID, + HW_VAR_LBK_MODE, + HW_VAR_AES_11N_FIX, + HW_VAR_USB_RX_AGGR, + HW_VAR_USER_CONTROL_TURBO_MODE, + HW_VAR_RETRY_LIMIT, + HW_VAR_INIT_TX_RATE, + HW_VAR_TX_RATE_REG, + HW_VAR_EFUSE_USAGE, + HW_VAR_EFUSE_BYTES, + HW_VAR_AUTOLOAD_STATUS, + HW_VAR_RF_2R_DISABLE, + HW_VAR_SET_RPWM, + HW_VAR_H2C_FW_PWRMODE, + HW_VAR_H2C_FW_JOINBSSRPT, + HW_VAR_FW_PSMODE_STATUS, + HW_VAR_1X1_RECV_COMBINE, + HW_VAR_STOP_SEND_BEACON, + HW_VAR_TSF_TIMER, + HW_VAR_IO_CMD, + + HW_VAR_RF_RECOVERY, + HW_VAR_H2C_FW_UPDATE_GTK, + HW_VAR_WF_MASK, + HW_VAR_WF_CRC, + HW_VAR_WF_IS_MAC_ADDR, + HW_VAR_H2C_FW_OFFLOAD, + HW_VAR_RESET_WFCRC, + + HW_VAR_HANDLE_FW_C2H, + HW_VAR_DL_FW_RSVD_PAGE, + HW_VAR_AID, + HW_VAR_HW_SEQ_ENABLE, + HW_VAR_CORRECT_TSF, + HW_VAR_BCN_VALID, + HW_VAR_FWLPS_RF_ON, + HW_VAR_DUAL_TSF_RST, + HW_VAR_SWITCH_EPHY_WoWLAN, + HW_VAR_INT_MIGRATION, + HW_VAR_INT_AC, + HW_VAR_RF_TIMING, + + HW_VAR_MRC, + + HW_VAR_MGT_FILTER, + HW_VAR_CTRL_FILTER, + HW_VAR_DATA_FILTER, +}; + +enum _RT_MEDIA_STATUS { + RT_MEDIA_DISCONNECT = 0, + RT_MEDIA_CONNECT = 1 +}; + +enum rt_oem_id { + RT_CID_DEFAULT = 0, + RT_CID_8187_ALPHA0 = 1, + RT_CID_8187_SERCOMM_PS = 2, + RT_CID_8187_HW_LED = 3, + RT_CID_8187_NETGEAR = 4, + RT_CID_WHQL = 5, + RT_CID_819x_CAMEO = 6, + RT_CID_819x_RUNTOP = 7, + RT_CID_819x_Senao = 8, + RT_CID_TOSHIBA = 9, + RT_CID_819x_Netcore = 10, + RT_CID_Nettronix = 11, + RT_CID_DLINK = 12, + RT_CID_PRONET = 13, + RT_CID_COREGA = 14, + RT_CID_819x_ALPHA = 15, + RT_CID_819x_Sitecom = 16, + RT_CID_CCX = 17, + RT_CID_819x_Lenovo = 18, + RT_CID_819x_QMI = 19, + RT_CID_819x_Edimax_Belkin = 20, + RT_CID_819x_Sercomm_Belkin = 21, + RT_CID_819x_CAMEO1 = 22, + RT_CID_819x_MSI = 23, + RT_CID_819x_Acer = 24, + RT_CID_819x_HP = 27, + RT_CID_819x_CLEVO = 28, + RT_CID_819x_Arcadyan_Belkin = 29, + RT_CID_819x_SAMSUNG = 30, + RT_CID_819x_WNC_COREGA = 31, + RT_CID_819x_Foxcoon = 32, + RT_CID_819x_DELL = 33, +}; + +enum hw_descs { + HW_DESC_OWN, + HW_DESC_RXOWN, + HW_DESC_TX_NEXTDESC_ADDR, + HW_DESC_TXBUFF_ADDR, + HW_DESC_RXBUFF_ADDR, + HW_DESC_RXPKT_LEN, + HW_DESC_RXERO, +}; + +enum prime_sc { + PRIME_CHNL_OFFSET_DONT_CARE = 0, + PRIME_CHNL_OFFSET_LOWER = 1, + PRIME_CHNL_OFFSET_UPPER = 2, +}; + +enum rf_type { + RF_1T1R = 0, + RF_1T2R = 1, + RF_2T2R = 2, +}; + +enum ht_channel_width { + HT_CHANNEL_WIDTH_20 = 0, + HT_CHANNEL_WIDTH_20_40 = 1, +}; + +/* Ref: 802.11i sepc D10.0 7.3.2.25.1 +Cipher Suites Encryption Algorithms */ +enum rt_enc_alg { + NO_ENCRYPTION = 0, + WEP40_ENCRYPTION = 1, + TKIP_ENCRYPTION = 2, + RSERVED_ENCRYPTION = 3, + AESCCMP_ENCRYPTION = 4, + WEP104_ENCRYPTION = 5, +}; + +enum rtl_hal_state { + _HAL_STATE_STOP = 0, + _HAL_STATE_START = 1, +}; + +enum rtl_var_map { + /*reg map */ + SYS_ISO_CTRL = 0, + SYS_FUNC_EN, + SYS_CLK, + MAC_RCR_AM, + MAC_RCR_AB, + MAC_RCR_ACRC32, + MAC_RCR_ACF, + MAC_RCR_AAP, + + /*efuse map */ + EFUSE_TEST, + EFUSE_CTRL, + EFUSE_CLK, + EFUSE_CLK_CTRL, + EFUSE_PWC_EV12V, + EFUSE_FEN_ELDR, + EFUSE_LOADER_CLK_EN, + EFUSE_ANA8M, + EFUSE_HWSET_MAX_SIZE, + + /*CAM map */ + RWCAM, + WCAMI, + RCAMO, + CAMDBG, + SECR, + SEC_CAM_NONE, + SEC_CAM_WEP40, + SEC_CAM_TKIP, + SEC_CAM_AES, + SEC_CAM_WEP104, + + /*IMR map */ + RTL_IMR_BCNDMAINT6, /*Beacon DMA Interrupt 6 */ + RTL_IMR_BCNDMAINT5, /*Beacon DMA Interrupt 5 */ + RTL_IMR_BCNDMAINT4, /*Beacon DMA Interrupt 4 */ + RTL_IMR_BCNDMAINT3, /*Beacon DMA Interrupt 3 */ + RTL_IMR_BCNDMAINT2, /*Beacon DMA Interrupt 2 */ + RTL_IMR_BCNDMAINT1, /*Beacon DMA Interrupt 1 */ + RTL_IMR_BCNDOK8, /*Beacon Queue DMA OK Interrup 8 */ + RTL_IMR_BCNDOK7, /*Beacon Queue DMA OK Interrup 7 */ + RTL_IMR_BCNDOK6, /*Beacon Queue DMA OK Interrup 6 */ + RTL_IMR_BCNDOK5, /*Beacon Queue DMA OK Interrup 5 */ + RTL_IMR_BCNDOK4, /*Beacon Queue DMA OK Interrup 4 */ + RTL_IMR_BCNDOK3, /*Beacon Queue DMA OK Interrup 3 */ + RTL_IMR_BCNDOK2, /*Beacon Queue DMA OK Interrup 2 */ + RTL_IMR_BCNDOK1, /*Beacon Queue DMA OK Interrup 1 */ + RTL_IMR_TIMEOUT2, /*Timeout interrupt 2 */ + RTL_IMR_TIMEOUT1, /*Timeout interrupt 1 */ + RTL_IMR_TXFOVW, /*Transmit FIFO Overflow */ + RTL_IMR_PSTIMEOUT, /*Power save time out interrupt */ + RTL_IMR_BcnInt, /*Beacon DMA Interrupt 0 */ + RTL_IMR_RXFOVW, /*Receive FIFO Overflow */ + RTL_IMR_RDU, /*Receive Descriptor Unavailable */ + RTL_IMR_ATIMEND, /*For 92C,ATIM Window End Interrupt */ + RTL_IMR_BDOK, /*Beacon Queue DMA OK Interrup */ + RTL_IMR_HIGHDOK, /*High Queue DMA OK Interrupt */ + RTL_IMR_TBDOK, /*Transmit Beacon OK interrup */ + RTL_IMR_MGNTDOK, /*Management Queue DMA OK Interrupt */ + RTL_IMR_TBDER, /*For 92C,Transmit Beacon Error Interrupt */ + RTL_IMR_BKDOK, /*AC_BK DMA OK Interrupt */ + RTL_IMR_BEDOK, /*AC_BE DMA OK Interrupt */ + RTL_IMR_VIDOK, /*AC_VI DMA OK Interrupt */ + RTL_IMR_VODOK, /*AC_VO DMA Interrupt */ + RTL_IMR_ROK, /*Receive DMA OK Interrupt */ + RTL_IBSS_INT_MASKS, /*(RTL_IMR_BcnInt|RTL_IMR_TBDOK|RTL_IMR_TBDER)*/ + + /*CCK Rates, TxHT = 0 */ + RTL_RC_CCK_RATE1M, + RTL_RC_CCK_RATE2M, + RTL_RC_CCK_RATE5_5M, + RTL_RC_CCK_RATE11M, + + /*OFDM Rates, TxHT = 0 */ + RTL_RC_OFDM_RATE6M, + RTL_RC_OFDM_RATE9M, + RTL_RC_OFDM_RATE12M, + RTL_RC_OFDM_RATE18M, + RTL_RC_OFDM_RATE24M, + RTL_RC_OFDM_RATE36M, + RTL_RC_OFDM_RATE48M, + RTL_RC_OFDM_RATE54M, + + RTL_RC_HT_RATEMCS7, + RTL_RC_HT_RATEMCS15, + + /*keep it last */ + RTL_VAR_MAP_MAX, +}; + +/*Firmware PS mode for control LPS.*/ +enum _fw_ps_mode { + FW_PS_ACTIVE_MODE = 0, + FW_PS_MIN_MODE = 1, + FW_PS_MAX_MODE = 2, + FW_PS_DTIM_MODE = 3, + FW_PS_VOIP_MODE = 4, + FW_PS_UAPSD_WMM_MODE = 5, + FW_PS_UAPSD_MODE = 6, + FW_PS_IBSS_MODE = 7, + FW_PS_WWLAN_MODE = 8, + FW_PS_PM_Radio_Off = 9, + FW_PS_PM_Card_Disable = 10, +}; + +enum rt_psmode { + EACTIVE, /*Active/Continuous access. */ + EMAXPS, /*Max power save mode. */ + EFASTPS, /*Fast power save mode. */ + EAUTOPS, /*Auto power save mode. */ +}; + +/*LED related.*/ +enum led_ctl_mode { + LED_CTL_POWER_ON = 1, + LED_CTL_LINK = 2, + LED_CTL_NO_LINK = 3, + LED_CTL_TX = 4, + LED_CTL_RX = 5, + LED_CTL_SITE_SURVEY = 6, + LED_CTL_POWER_OFF = 7, + LED_CTL_START_TO_LINK = 8, + LED_CTL_START_WPS = 9, + LED_CTL_STOP_WPS = 10, +}; + +enum rtl_led_pin { + LED_PIN_GPIO0, + LED_PIN_LED0, + LED_PIN_LED1, + LED_PIN_LED2 +}; + +/*QoS related.*/ +/*acm implementation method.*/ +enum acm_method { + eAcmWay0_SwAndHw = 0, + eAcmWay1_HW = 1, + eAcmWay2_SW = 2, +}; + +/*aci/aifsn Field. +Ref: WMM spec 2.2.2: WME Parameter Element, p.12.*/ +union aci_aifsn { + u8 char_data; + + struct { + u8 aifsn:4; + u8 acm:1; + u8 aci:2; + u8 reserved:1; + } f; /* Field */ +}; + +/*mlme related.*/ +enum wireless_mode { + WIRELESS_MODE_UNKNOWN = 0x00, + WIRELESS_MODE_A = 0x01, + WIRELESS_MODE_B = 0x02, + WIRELESS_MODE_G = 0x04, + WIRELESS_MODE_AUTO = 0x08, + WIRELESS_MODE_N_24G = 0x10, + WIRELESS_MODE_N_5G = 0x20 +}; + +enum ratr_table_mode { + RATR_INX_WIRELESS_NGB = 0, + RATR_INX_WIRELESS_NG = 1, + RATR_INX_WIRELESS_NB = 2, + RATR_INX_WIRELESS_N = 3, + RATR_INX_WIRELESS_GB = 4, + RATR_INX_WIRELESS_G = 5, + RATR_INX_WIRELESS_B = 6, + RATR_INX_WIRELESS_MC = 7, + RATR_INX_WIRELESS_A = 8, +}; + +enum rtl_link_state { + MAC80211_NOLINK = 0, + MAC80211_LINKING = 1, + MAC80211_LINKED = 2, + MAC80211_LINKED_SCANNING = 3, +}; + +enum act_category { + ACT_CAT_QOS = 1, + ACT_CAT_DLS = 2, + ACT_CAT_BA = 3, + ACT_CAT_HT = 7, + ACT_CAT_WMM = 17, +}; + +enum ba_action { + ACT_ADDBAREQ = 0, + ACT_ADDBARSP = 1, + ACT_DELBA = 2, +}; + +struct octet_string { + u8 *octet; + u16 length; +}; + +struct rtl_hdr_3addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 payload[0]; +} __packed; + +struct rtl_info_element { + u8 id; + u8 len; + u8 data[0]; +} __packed; + +struct rtl_probe_rsp { + struct rtl_hdr_3addr header; + u32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + /*SSID, supported rates, FH params, DS params, + CF params, IBSS params, TIM (if beacon), RSN */ + struct rtl_info_element info_element[0]; +} __packed; + +/*LED related.*/ +/*ledpin Identify how to implement this SW led.*/ +struct rtl_led { + void *hw; + enum rtl_led_pin ledpin; + bool b_ledon; +}; + +struct rtl_led_ctl { + bool bled_opendrain; + struct rtl_led sw_led0; + struct rtl_led sw_led1; +}; + +struct rtl_qos_parameters { + __le16 cw_min; + __le16 cw_max; + u8 aifs; + u8 flag; + __le16 tx_op; +} __packed; + +struct rt_smooth_data { + u32 elements[100]; /*array to store values */ + u32 index; /*index to current array to store */ + u32 total_num; /*num of valid elements */ + u32 total_val; /*sum of valid elements */ +}; + +struct false_alarm_statistics { + u32 cnt_parity_fail; + u32 cnt_rate_illegal; + u32 cnt_crc8_fail; + u32 cnt_mcs_fail; + u32 cnt_ofdm_fail; + u32 cnt_cck_fail; + u32 cnt_all; +}; + +struct init_gain { + u8 xaagccore1; + u8 xbagccore1; + u8 xcagccore1; + u8 xdagccore1; + u8 cca; + +}; + +struct wireless_stats { + unsigned long txbytesunicast; + unsigned long txbytesmulticast; + unsigned long txbytesbroadcast; + unsigned long rxbytesunicast; + + long rx_snr_db[4]; + /*Correct smoothed ss in Dbm, only used + in driver to report real power now. */ + long recv_signal_power; + long signal_quality; + long last_sigstrength_inpercent; + + u32 rssi_calculate_cnt; + + /*Transformed, in dbm. Beautified signal + strength for UI, not correct. */ + long signal_strength; + + u8 rx_rssi_percentage[4]; + u8 rx_evm_percentage[2]; + + struct rt_smooth_data ui_rssi; + struct rt_smooth_data ui_link_quality; +}; + +struct rate_adaptive { + u8 rate_adaptive_disabled; + u8 ratr_state; + u16 reserve; + + u32 high_rssi_thresh_for_ra; + u32 high2low_rssi_thresh_for_ra; + u8 low2high_rssi_thresh_for_ra40m; + u32 low_rssi_thresh_for_ra40M; + u8 low2high_rssi_thresh_for_ra20m; + u32 low_rssi_thresh_for_ra20M; + u32 upper_rssi_threshold_ratr; + u32 middleupper_rssi_threshold_ratr; + u32 middle_rssi_threshold_ratr; + u32 middlelow_rssi_threshold_ratr; + u32 low_rssi_threshold_ratr; + u32 ultralow_rssi_threshold_ratr; + u32 low_rssi_threshold_ratr_40m; + u32 low_rssi_threshold_ratr_20m; + u8 ping_rssi_enable; + u32 ping_rssi_ratr; + u32 ping_rssi_thresh_for_ra; + u32 last_ratr; + u8 pre_ratr_state; +}; + +struct regd_pair_mapping { + u16 reg_dmnenum; + u16 reg_5ghz_ctl; + u16 reg_2ghz_ctl; +}; + +struct rtl_regulatory { + char alpha2[2]; + u16 country_code; + u16 max_power_level; + u32 tp_scale; + u16 current_rd; + u16 current_rd_ext; + int16_t power_limit; + struct regd_pair_mapping *regpair; +}; + +struct rtl_rfkill { + bool rfkill_state; /*0 is off, 1 is on */ +}; + +struct rtl_phy { + struct bb_reg_def phyreg_def[4]; /*Radio A/B/C/D */ + struct init_gain initgain_backup; + enum io_type current_io_type; + + u8 rf_mode; + u8 rf_type; + u8 current_chan_bw; + u8 set_bwmode_inprogress; + u8 sw_chnl_inprogress; + u8 sw_chnl_stage; + u8 sw_chnl_step; + u8 current_channel; + u8 h2c_box_num; + u8 set_io_inprogress; + + /*record for power tracking*/ + s32 reg_e94; + s32 reg_e9c; + s32 reg_ea4; + s32 reg_eac; + s32 reg_eb4; + s32 reg_ebc; + s32 reg_ec4; + s32 reg_ecc; + u8 rfpienable; + u8 reserve_0; + u16 reserve_1; + u32 reg_c04, reg_c08, reg_874; + u32 adda_backup[16]; + u32 iqk_mac_backup[IQK_MAC_REG_NUM]; + u32 iqk_bb_backup[10]; + + bool b_rfpi_enable; + + u8 pwrgroup_cnt; + u8 bcck_high_power; + /* 3 groups of pwr diff by rates*/ + u32 mcs_txpwrlevel_origoffset[4][16]; + u8 default_initialgain[4]; + + /*the current Tx power level*/ + u8 cur_cck_txpwridx; + u8 cur_ofdm24g_txpwridx; + + u32 rfreg_chnlval[2]; + bool b_apk_done; + + /*fsync*/ + u8 framesync; + u32 framesync_c34; + + u8 num_total_rfpath; +}; + +#define MAX_TID_COUNT 9 +#define RTL_AGG_OFF 0 +#define RTL_AGG_ON 1 +#define RTL_AGG_EMPTYING_HW_QUEUE_ADDBA 2 +#define RTL_AGG_EMPTYING_HW_QUEUE_DELBA 3 + +struct rtl_ht_agg { + u16 txq_id; + u16 wait_for_ba; + u16 start_idx; + u64 bitmap; + u32 rate_n_flags; + u8 agg_state; +}; + +struct rtl_tid_data { + u16 seq_number; + struct rtl_ht_agg agg; +}; + +struct rtl_priv; +struct rtl_io { + struct device *dev; + + /*PCI MEM map */ + unsigned long pci_mem_end; /*shared mem end */ + unsigned long pci_mem_start; /*shared mem start */ + + /*PCI IO map */ + unsigned long pci_base_addr; /*device I/O address */ + + void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val); + void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val); + void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val); + + u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr); + u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr); + u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr); + +}; + +struct rtl_mac { + u8 mac_addr[ETH_ALEN]; + u8 mac80211_registered; + u8 beacon_enabled; + + u32 tx_ss_num; + u32 rx_ss_num; + + struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; + struct ieee80211_hw *hw; + struct ieee80211_vif *vif; + enum nl80211_iftype opmode; + + /*Probe Beacon management */ + struct rtl_tid_data tids[MAX_TID_COUNT]; + enum rtl_link_state link_state; + + int n_channels; + int n_bitrates; + + /*filters */ + u32 rx_conf; + u16 rx_mgt_filter; + u16 rx_ctrl_filter; + u16 rx_data_filter; + + bool act_scanning; + u8 cnt_after_linked; + + /*RDG*/ bool rdg_en; + + /*AP*/ u8 bssid[6]; + u8 mcs[16]; /*16 bytes mcs for HT rates.*/ + u32 basic_rates; /*b/g rates*/ + u8 ht_enable; + u8 sgi_40; + u8 sgi_20; + u8 bw_40; + u8 mode; /*wireless mode*/ + u8 slot_time; + u8 short_preamble; + u8 use_cts_protect; + u8 cur_40_prime_sc; + u8 cur_40_prime_sc_bk; + u64 tsf; + u8 retry_short; + u8 retry_long; + u16 assoc_id; + + /*IBSS*/ int beacon_interval; + + /*AMPDU*/ u8 min_space_cfg; /*For Min spacing configurations */ + u8 max_mss_density; + u8 current_ampdu_factor; + u8 current_ampdu_density; + + /*QOS & EDCA */ + struct ieee80211_tx_queue_params edca_param[RTL_MAC80211_NUM_QUEUE]; + struct rtl_qos_parameters ac[AC_MAX]; +}; + +struct rtl_hal { + struct ieee80211_hw *hw; + + enum intf_type interface; + u16 hw_type; /*92c or 92d or 92s and so on */ + u8 oem_id; + u8 version; /*version of chip */ + u8 state; /*stop 0, start 1 */ + + /*firmware */ + u8 *pfirmware; + bool b_h2c_setinprogress; + u8 last_hmeboxnum; + bool bfw_ready; + /*Reserve page start offset except beacon in TxQ. */ + u8 fw_rsvdpage_startoffset; +}; + +struct rtl_security { + /*default 0 */ + bool use_sw_sec; + + bool being_setkey; + bool use_defaultkey; + /*Encryption Algorithm for Unicast Packet */ + enum rt_enc_alg pairwise_enc_algorithm; + /*Encryption Algorithm for Brocast/Multicast */ + enum rt_enc_alg group_enc_algorithm; + + /*local Key buffer, indx 0 is for + pairwise key 1-4 is for agoup key. */ + u8 key_buf[KEY_BUF_SIZE][MAX_KEY_LEN]; + u8 key_len[KEY_BUF_SIZE]; + + /*The pointer of Pairwise Key, + it always points to KeyBuf[4] */ + u8 *pairwise_key; +}; + +struct rtl_dm { + /*PHY status for DM */ + long entry_min_undecoratedsmoothed_pwdb; + long undecorated_smoothed_pwdb; /*out dm */ + long entry_max_undecoratedsmoothed_pwdb; + bool b_dm_initialgain_enable; + bool bdynamic_txpower_enable; + bool bcurrent_turbo_edca; + bool bis_any_nonbepkts; /*out dm */ + bool bis_cur_rdlstate; + bool btxpower_trackingInit; + bool b_disable_framebursting; + bool b_cck_inch14; + bool btxpower_tracking; + bool b_useramask; + bool brfpath_rxenable[4]; + + u8 thermalvalue_iqk; + u8 thermalvalue_lck; + u8 thermalvalue; + u8 last_dtp_lvl; + u8 dynamic_txhighpower_lvl; /*Tx high power level */ + u8 dm_flag; /*Indicate if each dynamic mechanism's status. */ + u8 dm_type; + u8 txpower_track_control; + + char ofdm_index[2]; + char cck_index; +}; + +#define EFUSE_MAX_LOGICAL_SIZE 128 + +struct rtl_efuse { + bool bautoLoad_ok; + bool bootfromefuse; + u16 max_physical_size; + u8 contents[EFUSE_MAX_LOGICAL_SIZE]; + + u8 efuse_map[2][EFUSE_MAX_LOGICAL_SIZE]; + u16 efuse_usedbytes; + u8 efuse_usedpercentage; + + u8 autoload_failflag; + + short epromtype; + u16 eeprom_vid; + u16 eeprom_did; + u16 eeprom_svid; + u16 eeprom_smid; + u8 eeprom_oemid; + u16 eeprom_channelplan; + u8 eeprom_version; + + u8 dev_addr[6]; + + bool b_txpwr_fromeprom; + u8 eeprom_tssi[2]; + u8 eeprom_pwrlimit_ht20[3]; + u8 eeprom_pwrlimit_ht40[3]; + u8 eeprom_chnlarea_txpwr_cck[2][3]; + u8 eeprom_chnlarea_txpwr_ht40_1s[2][3]; + u8 eeprom_chnlarea_txpwr_ht40_2sdiif[2][3]; + u8 txpwrlevel_cck[2][14]; + u8 txpwrlevel_ht40_1s[2][14]; /*For HT 40MHZ pwr */ + u8 txpwrlevel_ht40_2s[2][14]; /*For HT 40MHZ pwr */ + + /*For power group */ + u8 pwrgroup_ht20[2][14]; + u8 pwrgroup_ht40[2][14]; + + char txpwr_ht20diff[2][14]; /*HT 20<->40 Pwr diff */ + u8 txpwr_legacyhtdiff[2][14]; /*For HT<->legacy pwr diff */ + + u8 eeprom_regulatory; + u8 eeprom_thermalmeter; + /*ThermalMeter, index 0 for RFIC0, and 1 for RFIC1 */ + u8 thermalmeter[2]; + + u8 legacy_ht_txpowerdiff; /*Legacy to HT rate power diff */ + bool b_apk_thermalmeterignore; +}; + +struct rtl_ps_ctl { + bool set_rfpowerstate_inprogress; + bool b_in_powersavemode; + bool rfchange_inprogress; + bool b_swrf_processing; + bool b_hwradiooff; + + u32 last_sleep_jiffies; + u32 last_awake_jiffies; + u32 last_delaylps_stamp_jiffies; + + /* + * just for PCIE ASPM + * If it supports ASPM, Offset[560h] = 0x40, + * otherwise Offset[560h] = 0x00. + * */ + bool b_support_aspm; + bool b_support_backdoor; + + /*for LPS */ + enum rt_psmode dot11_psmode; /*Power save mode configured. */ + bool b_leisure_ps; + bool b_fwctrl_lps; + u8 fwctrl_psmode; + /*For Fw control LPS mode */ + u8 b_reg_fwctrl_lps; + /*Record Fw PS mode status. */ + bool b_fw_current_inpsmode; + u8 reg_max_lps_awakeintvl; + bool report_linked; + + /*for IPS */ + bool b_inactiveps; + + u32 rfoff_reason; + + /*RF OFF Level */ + u32 cur_ps_level; + u32 reg_rfps_level; + + /*just for PCIE ASPM */ + u8 const_amdpci_aspm; + + enum rf_pwrstate inactive_pwrstate; + enum rf_pwrstate rfpwr_state; /*cur power state */ +}; + +struct rtl_stats { + u32 mac_time[2]; + s8 rssi; + u8 signal; + u8 noise; + u16 rate; /*in 100 kbps */ + u8 received_channel; + u8 control; + u8 mask; + u8 freq; + u16 len; + u64 tsf; + u32 beacon_time; + u8 nic_type; + u16 length; + u8 signalquality; /*in 0-100 index. */ + /* + * Real power in dBm for this packet, + * no beautification and aggregation. + * */ + s32 recvsignalpower; + s8 rxpower; /*in dBm Translate from PWdB */ + u8 signalstrength; /*in 0-100 index. */ + u16 b_hwerror:1; + u16 b_crc:1; + u16 b_icv:1; + u16 b_shortpreamble:1; + u16 antenna:1; + u16 decrypted:1; + u16 wakeup:1; + u32 timestamp_low; + u32 timestamp_high; + + u8 rx_drvinfo_size; + u8 rx_bufshift; + bool b_isampdu; + bool rx_is40Mhzpacket; + u32 rx_pwdb_all; + u8 rx_mimo_signalstrength[4]; /*in 0~100 index */ + s8 rx_mimo_signalquality[2]; + bool b_packet_matchbssid; + bool b_is_cck; + bool b_packet_toself; + bool b_packet_beacon; /*for rssi */ + char cck_adc_pwdb[4]; /*for rx path selection */ +}; + +struct rt_link_detect { + u32 num_tx_in4period[4]; + u32 num_rx_in4period[4]; + + u32 num_tx_inperiod; + u32 num_rx_inperiod; + + bool b_busytraffic; + bool b_higher_busytraffic; + bool b_higher_busyrxtraffic; +}; + +struct rtl_tcb_desc { + u8 b_packet_bw:1; + u8 b_multicast:1; + u8 b_broadcast:1; + + u8 b_rts_stbc:1; + u8 b_rts_enable:1; + u8 b_cts_enable:1; + u8 b_rts_use_shortpreamble:1; + u8 b_rts_use_shortgi:1; + u8 rts_sc:1; + u8 b_rts_bw:1; + u8 rts_rate; + + u8 use_shortgi:1; + u8 use_shortpreamble:1; + u8 use_driver_rate:1; + u8 disable_ratefallback:1; + + u8 ratr_index; + u8 mac_id; + u8 hw_rate; +}; + +struct rtl_hal_ops { + int (*init_sw_vars) (struct ieee80211_hw *hw); + void (*deinit_sw_vars) (struct ieee80211_hw *hw); + void (*read_eeprom_info) (struct ieee80211_hw *hw); + void (*interrupt_recognized) (struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb); + int (*hw_init) (struct ieee80211_hw *hw); + void (*hw_disable) (struct ieee80211_hw *hw); + void (*enable_interrupt) (struct ieee80211_hw *hw); + void (*disable_interrupt) (struct ieee80211_hw *hw); + int (*set_network_type) (struct ieee80211_hw *hw, + enum nl80211_iftype type); + void (*set_bw_mode) (struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type); + u8(*switch_channel) (struct ieee80211_hw *hw); + void (*set_qos) (struct ieee80211_hw *hw, int aci); + void (*set_bcn_reg) (struct ieee80211_hw *hw); + void (*set_bcn_intv) (struct ieee80211_hw *hw); + void (*update_interrupt_mask) (struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr); + void (*get_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); + void (*set_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); + void (*update_rate_table) (struct ieee80211_hw *hw); + void (*update_rate_mask) (struct ieee80211_hw *hw, u8 rssi_level); + void (*fill_tx_desc) (struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + struct ieee80211_tx_info *info, + struct sk_buff *skb, unsigned int queue_index); + void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc, + bool b_firstseg, bool b_lastseg, + struct sk_buff *skb); + bool(*query_rx_desc) (struct ieee80211_hw *hw, + struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb); + void (*set_channel_access) (struct ieee80211_hw *hw); + bool(*radio_onoff_checking) (struct ieee80211_hw *hw, u8 *valid); + void (*dm_watchdog) (struct ieee80211_hw *hw); + void (*scan_operation_backup) (struct ieee80211_hw *hw, u8 operation); + bool(*set_rf_power_state) (struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); + void (*led_control) (struct ieee80211_hw *hw, + enum led_ctl_mode ledaction); + void (*set_desc) (u8 *pdesc, bool istx, u8 desc_name, u8 *val); + u32(*get_desc) (u8 *pdesc, bool istx, u8 desc_name); + void (*tx_polling) (struct ieee80211_hw *hw, unsigned int hw_queue); + void (*enable_hw_sec) (struct ieee80211_hw *hw); + void (*set_key) (struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all); + void (*init_sw_leds) (struct ieee80211_hw *hw); + void (*deinit_sw_leds) (struct ieee80211_hw *hw); + u32(*get_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); + void (*set_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, + u32 data); + u32(*get_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask); + void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data); +}; + +struct rtl_intf_ops { + /*com */ + int (*adapter_start) (struct ieee80211_hw *hw); + void (*adapter_stop) (struct ieee80211_hw *hw); + + int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb); + int (*reset_trx_ring) (struct ieee80211_hw *hw); + + /*pci */ + void (*disable_aspm) (struct ieee80211_hw *hw); + void (*enable_aspm) (struct ieee80211_hw *hw); + + /*usb */ +}; + +struct rtl_mod_params { + /* default: 0 = using hardware encryption */ + int sw_crypto; +}; + +struct rtl_hal_cfg { + char *name; + char *fw_name; + struct rtl_hal_ops *ops; + struct rtl_mod_params *mod_params; + + /*this map used for some registers or vars + defined int HAL but used in MAIN */ + u32 maps[RTL_VAR_MAP_MAX]; + +}; + +struct rtl_locks { + /* mutex */ + struct mutex conf_mutex; + + /*spin lock */ + spinlock_t ips_lock; + spinlock_t irq_th_lock; + spinlock_t h2c_lock; + spinlock_t rf_ps_lock; + spinlock_t rf_lock; + spinlock_t lps_lock; +}; + +struct rtl_works { + struct ieee80211_hw *hw; + + /*timer */ + struct timer_list watchdog_timer; + + /*task */ + struct tasklet_struct irq_tasklet; + struct tasklet_struct irq_prepare_bcn_tasklet; + + /*work queue */ + struct workqueue_struct *rtl_wq; + struct delayed_work watchdog_wq; + struct delayed_work ips_nic_off_wq; +}; + +struct rtl_debug { + u32 dbgp_type[DBGP_TYPE_MAX]; + u32 global_debuglevel; + u64 global_debugcomponents; +}; + +struct rtl_priv { + struct rtl_locks locks; + struct rtl_works works; + struct rtl_mac mac80211; + struct rtl_hal rtlhal; + struct rtl_regulatory regd; + struct rtl_rfkill rfkill; + struct rtl_io io; + struct rtl_phy phy; + struct rtl_dm dm; + struct rtl_security sec; + struct rtl_efuse efuse; + + struct rtl_ps_ctl psc; + struct rate_adaptive ra; + struct wireless_stats stats; + struct rt_link_detect link_info; + struct false_alarm_statistics falsealm_cnt; + + struct rtl_rate_priv *rate_priv; + + struct rtl_debug dbg; + + /* + *hal_cfg : for diff cards + *intf_ops : for diff interrface usb/pcie + */ + struct rtl_hal_cfg *cfg; + struct rtl_intf_ops *intf_ops; + + /*this var will be set by set_bit, + and was used to indicate status of + interface or hardware */ + unsigned long status; + + /*This must be the last item so + that it points to the data allocated + beyond this structure like: + rtl_pci_priv or rtl_usb_priv */ + u8 priv[0]; +}; + +#define rtl_priv(hw) (((struct rtl_priv *)(hw)->priv)) +#define rtl_mac(rtlpriv) (&((rtlpriv)->mac80211)) +#define rtl_hal(rtlpriv) (&((rtlpriv)->rtlhal)) +#define rtl_efuse(rtlpriv) (&((rtlpriv)->efuse)) +#define rtl_psc(rtlpriv) (&((rtlpriv)->psc)) + +/**************************************** + mem access macro define start + Call endian free function when + 1. Read/write packet content. + 2. Before write integer to IO. + 3. After read integer from IO. +****************************************/ +/* Convert little data endian to host */ +#define EF1BYTE(_val) \ + ((u8)(_val)) +#define EF2BYTE(_val) \ + (le16_to_cpu(_val)) +#define EF4BYTE(_val) \ + (le32_to_cpu(_val)) + +/* Read data from memory */ +#define READEF1BYTE(_ptr) \ + EF1BYTE(*((u8 *)(_ptr))) +#define READEF2BYTE(_ptr) \ + EF2BYTE(*((u16 *)(_ptr))) +#define READEF4BYTE(_ptr) \ + EF4BYTE(*((u32 *)(_ptr))) + +/* Write data to memory */ +#define WRITEEF1BYTE(_ptr, _val) \ + (*((u8 *)(_ptr))) = EF1BYTE(_val) +#define WRITEEF2BYTE(_ptr, _val) \ + (*((u16 *)(_ptr))) = EF2BYTE(_val) +#define WRITEEF4BYTE(_ptr, _val) \ + (*((u32 *)(_ptr))) = EF4BYTE(_val) + +/*Example: +BIT_LEN_MASK_32(0) => 0x00000000 +BIT_LEN_MASK_32(1) => 0x00000001 +BIT_LEN_MASK_32(2) => 0x00000003 +BIT_LEN_MASK_32(32) => 0xFFFFFFFF*/ +#define BIT_LEN_MASK_32(__bitlen) \ + (0xFFFFFFFF >> (32 - (__bitlen))) +#define BIT_LEN_MASK_16(__bitlen) \ + (0xFFFF >> (16 - (__bitlen))) +#define BIT_LEN_MASK_8(__bitlen) \ + (0xFF >> (8 - (__bitlen))) + +/*Example: +BIT_OFFSET_LEN_MASK_32(0, 2) => 0x00000003 +BIT_OFFSET_LEN_MASK_32(16, 2) => 0x00030000*/ +#define BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen) \ + (BIT_LEN_MASK_32(__bitlen) << (__bitoffset)) +#define BIT_OFFSET_LEN_MASK_16(__bitoffset, __bitlen) \ + (BIT_LEN_MASK_16(__bitlen) << (__bitoffset)) +#define BIT_OFFSET_LEN_MASK_8(__bitoffset, __bitlen) \ + (BIT_LEN_MASK_8(__bitlen) << (__bitoffset)) + +/*Description: +Return 4-byte value in host byte ordering from +4-byte pointer in little-endian system.*/ +#define LE_P4BYTE_TO_HOST_4BYTE(__pstart) \ + (EF4BYTE(*((u32 *)(__pstart)))) +#define LE_P2BYTE_TO_HOST_2BYTE(__pstart) \ + (EF2BYTE(*((u16 *)(__pstart)))) +#define LE_P1BYTE_TO_HOST_1BYTE(__pstart) \ + (EF1BYTE(*((u8 *)(__pstart)))) + +/*Description: +Translate subfield (continuous bits in little-endian) of 4-byte +value to host byte ordering.*/ +#define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + (LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset)) & \ + BIT_LEN_MASK_32(__bitlen) \ + ) +#define LE_BITS_TO_2BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + (LE_P2BYTE_TO_HOST_2BYTE(__pstart) >> (__bitoffset)) & \ + BIT_LEN_MASK_16(__bitlen) \ + ) +#define LE_BITS_TO_1BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + (LE_P1BYTE_TO_HOST_1BYTE(__pstart) >> (__bitoffset)) & \ + BIT_LEN_MASK_8(__bitlen) \ + ) + +/*Description: +Mask subfield (continuous bits in little-endian) of 4-byte value +and return the result in 4-byte value in host byte ordering.*/ +#define LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + LE_P4BYTE_TO_HOST_4BYTE(__pstart) & \ + (~BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen)) \ + ) +#define LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + LE_P2BYTE_TO_HOST_2BYTE(__pstart) & \ + (~BIT_OFFSET_LEN_MASK_16(__bitoffset, __bitlen)) \ + ) +#define LE_BITS_CLEARED_TO_1BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + LE_P1BYTE_TO_HOST_1BYTE(__pstart) & \ + (~BIT_OFFSET_LEN_MASK_8(__bitoffset, __bitlen)) \ + ) + +/*Description: +Set subfield of little-endian 4-byte value to specified value. */ +#define SET_BITS_TO_LE_4BYTE(__pstart, __bitoffset, __bitlen, __val) \ + *((u32 *)(__pstart)) = EF4BYTE \ + ( \ + LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) | \ + ((((u32)__val) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset)) \ + ); +#define SET_BITS_TO_LE_2BYTE(__pstart, __bitoffset, __bitlen, __val) \ + *((u16 *)(__pstart)) = EF2BYTE \ + ( \ + LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \ + ((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset)) \ + ); +#define SET_BITS_TO_LE_1BYTE(__pstart, __bitoffset, __bitlen, __val) \ + *((u8 *)(__pstart)) = EF1BYTE \ + ( \ + LE_BITS_CLEARED_TO_1BYTE(__pstart, __bitoffset, __bitlen) | \ + ((((u8)__val) & BIT_LEN_MASK_8(__bitlen)) << (__bitoffset)) \ + ); + +/**************************************** + mem access macro define end +****************************************/ + +#define packet_get_type(_packet) (EF1BYTE((_packet).octet[0]) & 0xFC) +#define RTL_WATCH_DOG_TIME 2000 +#define MSECS(t) msecs_to_jiffies(t) +#define WLAN_FC_GET_VERS(fc) ((fc) & IEEE80211_FCTL_VERS) +#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE) +#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE) +#define WLAN_FC_MORE_DATA(fc) ((fc) & IEEE80211_FCTL_MOREDATA) +#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) +#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) +#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) + +#define RT_RF_OFF_LEVL_ASPM BIT(0) /*PCI ASPM */ +#define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /*PCI clock request */ +#define RT_RF_OFF_LEVL_PCI_D3 BIT(2) /*PCI D3 mode */ +/*NIC halt, re-initialize hw parameters*/ +#define RT_RF_OFF_LEVL_HALT_NIC BIT(3) +#define RT_RF_OFF_LEVL_FREE_FW BIT(4) /*FW free, re-download the FW */ +#define RT_RF_OFF_LEVL_FW_32K BIT(5) /*FW in 32k */ +/*Always enable ASPM and Clock Req in initialization.*/ +#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT(6) +/*When LPS is on, disable 2R if no packet is received or transmittd.*/ +#define RT_RF_LPS_DISALBE_2R BIT(30) +#define RT_RF_LPS_LEVEL_ASPM BIT(31) /*LPS with ASPM */ +#define RT_IN_PS_LEVEL(ppsc, _ps_flg) \ + ((ppsc->cur_ps_level & _ps_flg) ? true : false) +#define RT_CLEAR_PS_LEVEL(ppsc, _ps_flg) \ + (ppsc->cur_ps_level &= (~(_ps_flg))) +#define RT_SET_PS_LEVEL(ppsc, _ps_flg) \ + (ppsc->cur_ps_level |= _ps_flg) + +#define container_of_dwork_rtl(x, y, z) \ + container_of(container_of(x, struct delayed_work, work), y, z) + +#define FILL_OCTET_STRING(_os, _octet, _len) \ + (_os).octet = (u8 *)(_octet); \ + (_os).length = (_len); + +#define CP_MACADDR(des, src) \ + ((des)[0] = (src)[0], (des)[1] = (src)[1],\ + (des)[2] = (src)[2], (des)[3] = (src)[3],\ + (des)[4] = (src)[4], (des)[5] = (src)[5]) + +static inline u8 rtl_read_byte(struct rtl_priv *rtlpriv, u32 addr) +{ + return rtlpriv->io.read8_sync(rtlpriv, addr); +} + +static inline u16 rtl_read_word(struct rtl_priv *rtlpriv, u32 addr) +{ + return rtlpriv->io.read16_sync(rtlpriv, addr); +} + +static inline u32 rtl_read_dword(struct rtl_priv *rtlpriv, u32 addr) +{ + return rtlpriv->io.read32_sync(rtlpriv, addr); +} + +static inline void rtl_write_byte(struct rtl_priv *rtlpriv, u32 addr, u8 val8) +{ + rtlpriv->io.write8_async(rtlpriv, addr, val8); +} + +static inline void rtl_write_word(struct rtl_priv *rtlpriv, u32 addr, u16 val16) +{ + rtlpriv->io.write16_async(rtlpriv, addr, val16); +} + +static inline void rtl_write_dword(struct rtl_priv *rtlpriv, + u32 addr, u32 val32) +{ + rtlpriv->io.write32_async(rtlpriv, addr, val32); +} + +static inline u32 rtl_get_bbreg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask) +{ + return ((struct rtl_priv *)(hw)->priv)->cfg->ops->get_bbreg(hw, + regaddr, + bitmask); +} + +static inline void rtl_set_bbreg(struct ieee80211_hw *hw, u32 regaddr, + u32 bitmask, u32 data) +{ + ((struct rtl_priv *)(hw)->priv)->cfg->ops->set_bbreg(hw, + regaddr, bitmask, + data); + +} + +static inline u32 rtl_get_rfreg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask) +{ + return ((struct rtl_priv *)(hw)->priv)->cfg->ops->get_rfreg(hw, + rfpath, + regaddr, + bitmask); +} + +static inline void rtl_set_rfreg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask, u32 data) +{ + ((struct rtl_priv *)(hw)->priv)->cfg->ops->set_rfreg(hw, + rfpath, regaddr, + bitmask, data); +} + +static inline bool is_hal_stop(struct rtl_hal *rtlhal) +{ + return (_HAL_STATE_STOP == rtlhal->state); +} + +static inline void set_hal_start(struct rtl_hal *rtlhal) +{ + rtlhal->state = _HAL_STATE_START; +} + +static inline void set_hal_stop(struct rtl_hal *rtlhal) +{ + rtlhal->state = _HAL_STATE_STOP; +} + +static inline u8 get_rf_type(struct rtl_phy *rtlphy) +{ + return rtlphy->rf_type; +} + +#endif diff --git a/drivers/net/wireless/wl1251/boot.c b/drivers/net/wireless/wl1251/boot.c index 61572dfa1f60..d729daf8e841 100644 --- a/drivers/net/wireless/wl1251/boot.c +++ b/drivers/net/wireless/wl1251/boot.c @@ -19,7 +19,6 @@ * */ -#include <linux/gpio.h> #include <linux/slab.h> #include "reg.h" diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c index 7a8762553cdc..012e1a4016fe 100644 --- a/drivers/net/wireless/wl1251/main.c +++ b/drivers/net/wireless/wl1251/main.c @@ -52,14 +52,14 @@ void wl1251_disable_interrupts(struct wl1251 *wl) wl->if_ops->disable_irq(wl); } -static void wl1251_power_off(struct wl1251 *wl) +static int wl1251_power_off(struct wl1251 *wl) { - wl->set_power(false); + return wl->if_ops->power(wl, false); } -static void wl1251_power_on(struct wl1251 *wl) +static int wl1251_power_on(struct wl1251 *wl) { - wl->set_power(true); + return wl->if_ops->power(wl, true); } static int wl1251_fetch_firmware(struct wl1251 *wl) @@ -152,9 +152,12 @@ static void wl1251_fw_wakeup(struct wl1251 *wl) static int wl1251_chip_wakeup(struct wl1251 *wl) { - int ret = 0; + int ret; + + ret = wl1251_power_on(wl); + if (ret < 0) + return ret; - wl1251_power_on(wl); msleep(WL1251_POWER_ON_SLEEP); wl->if_ops->reset(wl); diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c index 74ba9ced5393..d550b5e68d3c 100644 --- a/drivers/net/wireless/wl1251/sdio.c +++ b/drivers/net/wireless/wl1251/sdio.c @@ -26,6 +26,7 @@ #include <linux/platform_device.h> #include <linux/wl12xx.h> #include <linux/irq.h> +#include <linux/pm_runtime.h> #include "wl1251.h" @@ -42,8 +43,6 @@ struct wl1251_sdio { u32 elp_val; }; -static struct wl12xx_platform_data *wl12xx_board_data; - static struct sdio_func *wl_to_func(struct wl1251 *wl) { struct wl1251_sdio *wl_sdio = wl->if_priv; @@ -171,8 +170,42 @@ static void wl1251_disable_line_irq(struct wl1251 *wl) return disable_irq(wl->irq); } -static void wl1251_sdio_set_power(bool enable) +static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable) { + struct sdio_func *func = wl_to_func(wl); + int ret; + + if (enable) { + /* + * Power is controlled by runtime PM, but we still call board + * callback in case it wants to do any additional setup, + * for example enabling clock buffer for the module. + */ + if (wl->set_power) + wl->set_power(true); + + ret = pm_runtime_get_sync(&func->dev); + if (ret < 0) + goto out; + + sdio_claim_host(func); + sdio_enable_func(func); + sdio_release_host(func); + } else { + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); + + ret = pm_runtime_put_sync(&func->dev); + if (ret < 0) + goto out; + + if (wl->set_power) + wl->set_power(false); + } + +out: + return ret; } static struct wl1251_if_operations wl1251_sdio_ops = { @@ -181,30 +214,7 @@ static struct wl1251_if_operations wl1251_sdio_ops = { .write_elp = wl1251_sdio_write_elp, .read_elp = wl1251_sdio_read_elp, .reset = wl1251_sdio_reset, -}; - -static int wl1251_platform_probe(struct platform_device *pdev) -{ - if (pdev->id != -1) { - wl1251_error("can only handle single device"); - return -ENODEV; - } - - wl12xx_board_data = pdev->dev.platform_data; - return 0; -} - -/* - * Dummy platform_driver for passing platform_data to this driver, - * until we have a way to pass this through SDIO subsystem or - * some other way. - */ -static struct platform_driver wl1251_platform_driver = { - .driver = { - .name = "wl1251_data", - .owner = THIS_MODULE, - }, - .probe = wl1251_platform_probe, + .power = wl1251_sdio_set_power, }; static int wl1251_sdio_probe(struct sdio_func *func, @@ -214,6 +224,7 @@ static int wl1251_sdio_probe(struct sdio_func *func, struct wl1251 *wl; struct ieee80211_hw *hw; struct wl1251_sdio *wl_sdio; + const struct wl12xx_platform_data *wl12xx_board_data; hw = wl1251_alloc_hw(); if (IS_ERR(hw)) @@ -239,9 +250,9 @@ static int wl1251_sdio_probe(struct sdio_func *func, wl_sdio->func = func; wl->if_priv = wl_sdio; wl->if_ops = &wl1251_sdio_ops; - wl->set_power = wl1251_sdio_set_power; - if (wl12xx_board_data != NULL) { + wl12xx_board_data = wl12xx_get_platform_data(); + if (!IS_ERR(wl12xx_board_data)) { wl->set_power = wl12xx_board_data->set_power; wl->irq = wl12xx_board_data->irq; wl->use_eeprom = wl12xx_board_data->use_eeprom; @@ -273,6 +284,10 @@ static int wl1251_sdio_probe(struct sdio_func *func, goto out_free_irq; sdio_set_drvdata(func, wl); + + /* Tell PM core that we don't need the card to be powered now */ + pm_runtime_put_noidle(&func->dev); + return ret; out_free_irq: @@ -294,6 +309,9 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func) struct wl1251 *wl = sdio_get_drvdata(func); struct wl1251_sdio *wl_sdio = wl->if_priv; + /* Undo decrement done above in wl1251_probe */ + pm_runtime_get_noresume(&func->dev); + if (wl->irq) free_irq(wl->irq, wl); kfree(wl_sdio); @@ -305,23 +323,37 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func) sdio_release_host(func); } +static int wl1251_suspend(struct device *dev) +{ + /* + * Tell MMC/SDIO core it's OK to power down the card + * (if it isn't already), but not to remove it completely. + */ + return 0; +} + +static int wl1251_resume(struct device *dev) +{ + return 0; +} + +static const struct dev_pm_ops wl1251_sdio_pm_ops = { + .suspend = wl1251_suspend, + .resume = wl1251_resume, +}; + static struct sdio_driver wl1251_sdio_driver = { .name = "wl1251_sdio", .id_table = wl1251_devices, .probe = wl1251_sdio_probe, .remove = __devexit_p(wl1251_sdio_remove), + .drv.pm = &wl1251_sdio_pm_ops, }; static int __init wl1251_sdio_init(void) { int err; - err = platform_driver_register(&wl1251_platform_driver); - if (err) { - wl1251_error("failed to register platform driver: %d", err); - return err; - } - err = sdio_register_driver(&wl1251_sdio_driver); if (err) wl1251_error("failed to register sdio driver: %d", err); @@ -331,7 +363,6 @@ static int __init wl1251_sdio_init(void) static void __exit wl1251_sdio_exit(void) { sdio_unregister_driver(&wl1251_sdio_driver); - platform_driver_unregister(&wl1251_platform_driver); wl1251_notice("unloaded"); } diff --git a/drivers/net/wireless/wl1251/spi.c b/drivers/net/wireless/wl1251/spi.c index 88fa8e69d0d1..ac872b38960f 100644 --- a/drivers/net/wireless/wl1251/spi.c +++ b/drivers/net/wireless/wl1251/spi.c @@ -215,12 +215,21 @@ static void wl1251_spi_disable_irq(struct wl1251 *wl) return disable_irq(wl->irq); } +static int wl1251_spi_set_power(struct wl1251 *wl, bool enable) +{ + if (wl->set_power) + wl->set_power(enable); + + return 0; +} + static const struct wl1251_if_operations wl1251_spi_ops = { .read = wl1251_spi_read, .write = wl1251_spi_write, .reset = wl1251_spi_reset_wake, .enable_irq = wl1251_spi_enable_irq, .disable_irq = wl1251_spi_disable_irq, + .power = wl1251_spi_set_power, }; static int __devinit wl1251_spi_probe(struct spi_device *spi) diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h index e113d4c1fb35..13fbeeccf609 100644 --- a/drivers/net/wireless/wl1251/wl1251.h +++ b/drivers/net/wireless/wl1251/wl1251.h @@ -256,6 +256,7 @@ struct wl1251_if_operations { void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len); void (*read_elp)(struct wl1251 *wl, int addr, u32 *val); void (*write_elp)(struct wl1251 *wl, int addr, u32 val); + int (*power)(struct wl1251 *wl, bool enable); void (*reset)(struct wl1251 *wl); void (*enable_irq)(struct wl1251 *wl); void (*disable_irq)(struct wl1251 *wl); diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index b447559f1db5..0e65bce457d6 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig @@ -1,46 +1,68 @@ -menuconfig WL12XX +menuconfig WL12XX_MENU tristate "TI wl12xx driver support" depends on MAC80211 && EXPERIMENTAL ---help--- - This will enable TI wl12xx driver support. The drivers make - use of the mac80211 stack. + This will enable TI wl12xx driver support for the following chips: + wl1271 and wl1273. + The drivers make use of the mac80211 stack. -config WL1271 - tristate "TI wl1271 support" - depends on WL12XX && GENERIC_HARDIRQS +config WL12XX + tristate "TI wl12xx support" + depends on WL12XX_MENU && GENERIC_HARDIRQS depends on INET select FW_LOADER select CRC7 ---help--- - This module adds support for wireless adapters based on the - TI wl1271 chipset. + This module adds support for wireless adapters based on TI wl1271 and + TI wl1273 chipsets. This module does *not* include support for wl1251. + For wl1251 support, use the separate homonymous driver instead. - If you choose to build a module, it'll be called wl1271. Say N if + If you choose to build a module, it will be called wl12xx. Say N if unsure. -config WL1271_SPI - tristate "TI wl1271 SPI support" - depends on WL1271 && SPI_MASTER +config WL12XX_HT + bool "TI wl12xx 802.11 HT support (EXPERIMENTAL)" + depends on WL12XX && EXPERIMENTAL + default n + ---help--- + This will enable 802.11 HT support in the wl12xx module. + + That configuration is temporary due to the code incomplete and + still in testing process. + +config WL12XX_SPI + tristate "TI wl12xx SPI support" + depends on WL12XX && SPI_MASTER ---help--- This module adds support for the SPI interface of adapters using - TI wl1271 chipset. Select this if your platform is using + TI wl12xx chipsets. Select this if your platform is using the SPI bus. - If you choose to build a module, it'll be called wl1251_spi. + If you choose to build a module, it'll be called wl12xx_spi. Say N if unsure. -config WL1271_SDIO - tristate "TI wl1271 SDIO support" - depends on WL1271 && MMC +config WL12XX_SDIO + tristate "TI wl12xx SDIO support" + depends on WL12XX && MMC ---help--- This module adds support for the SDIO interface of adapters using - TI wl1271 chipset. Select this if your platform is using + TI wl12xx chipsets. Select this if your platform is using the SDIO bus. - If you choose to build a module, it'll be called - wl1271_sdio. Say N if unsure. + If you choose to build a module, it'll be called wl12xx_sdio. + Say N if unsure. + +config WL12XX_SDIO_TEST + tristate "TI wl12xx SDIO testing support" + depends on WL12XX && MMC + default n + ---help--- + This module adds support for the SDIO bus testing with the + TI wl12xx chipsets. You probably don't want this unless you are + testing a new hardware platform. Select this if you want to test the + SDIO bus which is connected to the wl12xx chip. config WL12XX_PLATFORM_DATA bool - depends on WL1271_SDIO != n + depends on WL12XX_SDIO != n || WL1251_SDIO != n default y diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index 3a807444b2af..521c0414e52e 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile @@ -1,12 +1,16 @@ -wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ - wl1271_event.o wl1271_tx.o wl1271_rx.o \ - wl1271_ps.o wl1271_acx.o wl1271_boot.o \ - wl1271_init.o wl1271_debugfs.o wl1271_scan.o - -wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o -obj-$(CONFIG_WL1271) += wl1271.o -obj-$(CONFIG_WL1271_SPI) += wl1271_spi.o -obj-$(CONFIG_WL1271_SDIO) += wl1271_sdio.o +wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ + boot.o init.o debugfs.o scan.o + +wl12xx_spi-objs = spi.o +wl12xx_sdio-objs = sdio.o +wl12xx_sdio_test-objs = sdio_test.o + +wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o +obj-$(CONFIG_WL12XX) += wl12xx.o +obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o +obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o + +obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o # small builtin driver bit obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/acx.c index 618993405262..cc4068d2b4a8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -21,7 +21,7 @@ * */ -#include "wl1271_acx.h" +#include "acx.h" #include <linux/module.h> #include <linux/platform_device.h> @@ -29,10 +29,10 @@ #include <linux/spi/spi.h> #include <linux/slab.h> -#include "wl1271.h" +#include "wl12xx.h" #include "wl12xx_80211.h" -#include "wl1271_reg.h" -#include "wl1271_ps.h" +#include "reg.h" +#include "ps.h" int wl1271_acx_wake_up_conditions(struct wl1271 *wl) { @@ -862,7 +862,7 @@ out: return ret; } -int wl1271_acx_frag_threshold(struct wl1271 *wl) +int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold) { struct acx_frag_threshold *acx; int ret = 0; @@ -876,7 +876,7 @@ int wl1271_acx_frag_threshold(struct wl1271 *wl) goto out; } - acx->frag_threshold = cpu_to_le16(wl->conf.tx.frag_threshold); + acx->frag_threshold = cpu_to_le16(frag_threshold); ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx)); if (ret < 0) { wl1271_warning("Setting of frag threshold failed: %d", ret); @@ -1041,7 +1041,7 @@ out: return ret; } -int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address) +int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address) { struct wl1271_acx_arp_filter *acx; int ret; @@ -1057,7 +1057,7 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address) acx->version = ACX_IPV4_VERSION; acx->enable = enable; - if (enable == true) + if (enable) memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE); ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER, @@ -1226,6 +1226,89 @@ out: return ret; } +int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, + struct ieee80211_sta_ht_cap *ht_cap, + bool allow_ht_operation) +{ + struct wl1271_acx_ht_capabilities *acx; + u8 mac_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + int ret = 0; + + wl1271_debug(DEBUG_ACX, "acx ht capabilities setting"); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) { + ret = -ENOMEM; + goto out; + } + + /* Allow HT Operation ? */ + if (allow_ht_operation) { + acx->ht_capabilites = + WL1271_ACX_FW_CAP_HT_OPERATION; + if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD) + acx->ht_capabilites |= + WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT; + if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20) + acx->ht_capabilites |= + WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS; + if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT) + acx->ht_capabilites |= + WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION; + + /* get data from A-MPDU parameters field */ + acx->ampdu_max_length = ht_cap->ampdu_factor; + acx->ampdu_min_spacing = ht_cap->ampdu_density; + + memcpy(acx->mac_address, mac_address, ETH_ALEN); + } else { /* HT operations are not allowed */ + acx->ht_capabilites = 0; + } + + ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx ht capabilities setting failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} + +int wl1271_acx_set_ht_information(struct wl1271 *wl, + u16 ht_operation_mode) +{ + struct wl1271_acx_ht_information *acx; + int ret = 0; + + wl1271_debug(DEBUG_ACX, "acx ht information setting"); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) { + ret = -ENOMEM; + goto out; + } + + acx->ht_protection = + (u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION); + acx->rifs_mode = 0; + acx->gf_protection = 0; + acx->ht_tx_burst_limit = 0; + acx->dual_cts_protection = 0; + + ret = wl1271_cmd_configure(wl, ACX_HT_BSS_OPERATION, acx, sizeof(*acx)); + + if (ret < 0) { + wl1271_warning("acx ht information setting failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} + int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) { struct wl1271_acx_fw_tsf_information *tsf_info; diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/acx.h index ebb341d36e8c..9cbc3f40c8dd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -22,11 +22,11 @@ * */ -#ifndef __WL1271_ACX_H__ -#define __WL1271_ACX_H__ +#ifndef __ACX_H__ +#define __ACX_H__ -#include "wl1271.h" -#include "wl1271_cmd.h" +#include "wl12xx.h" +#include "cmd.h" /************************************************************************* @@ -61,7 +61,8 @@ WL1271_ACX_INTR_HW_AVAILABLE | \ WL1271_ACX_INTR_DATA) -#define WL1271_INTR_MASK (WL1271_ACX_INTR_EVENT_A | \ +#define WL1271_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \ + WL1271_ACX_INTR_EVENT_A | \ WL1271_ACX_INTR_EVENT_B | \ WL1271_ACX_INTR_HW_AVAILABLE | \ WL1271_ACX_INTR_DATA) @@ -867,10 +868,15 @@ struct wl1271_acx_bet_enable { #define ACX_IPV4_VERSION 4 #define ACX_IPV6_VERSION 6 #define ACX_IPV4_ADDR_SIZE 4 + +/* bitmap of enabled arp_filter features */ +#define ACX_ARP_FILTER_ARP_FILTERING BIT(0) +#define ACX_ARP_FILTER_AUTO_ARP BIT(1) + struct wl1271_acx_arp_filter { struct acx_header header; u8 version; /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */ - u8 enable; /* 1 to enable ARP filtering, 0 to disable */ + u8 enable; /* bitmap of enabled ARP filtering features */ u8 padding[2]; u8 address[16]; /* The configured device IP address - all ARP requests directed to this IP address will pass @@ -964,6 +970,87 @@ struct wl1271_acx_rssi_snr_avg_weights { u8 snr_data; }; +/* + * ACX_PEER_HT_CAP + * Configure HT capabilities - declare the capabilities of the peer + * we are connected to. + */ +struct wl1271_acx_ht_capabilities { + struct acx_header header; + + /* + * bit 0 - Allow HT Operation + * bit 1 - Allow Greenfield format in TX + * bit 2 - Allow Short GI in TX + * bit 3 - Allow L-SIG TXOP Protection in TX + * bit 4 - Allow HT Control fields in TX. + * Note, driver will still leave space for HT control in packets + * regardless of the value of this field. FW will be responsible + * to drop the HT field from any frame when this Bit set to 0. + * bit 5 - Allow RD initiation in TXOP. FW is allowed to initate RD. + * Exact policy setting for this feature is TBD. + * Note, this bit can only be set to 1 if bit 3 is set to 1. + */ + __le32 ht_capabilites; + + /* + * Indicates to which peer these capabilities apply. + * For infrastructure use ff:ff:ff:ff:ff:ff that indicates relevance + * for all peers. + * Only valid for IBSS/DLS operation. + */ + u8 mac_address[ETH_ALEN]; + + /* + * This the maximum A-MPDU length supported by the AP. The FW may not + * exceed this length when sending A-MPDUs + */ + u8 ampdu_max_length; + + /* This is the minimal spacing required when sending A-MPDUs to the AP*/ + u8 ampdu_min_spacing; +} __packed; + +/* HT Capabilites Fw Bit Mask Mapping */ +#define WL1271_ACX_FW_CAP_HT_OPERATION BIT(0) +#define WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT BIT(1) +#define WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS BIT(2) +#define WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION BIT(3) +#define WL1271_ACX_FW_CAP_HT_CONTROL_FIELDS BIT(4) +#define WL1271_ACX_FW_CAP_RD_INITIATION BIT(5) + + +/* + * ACX_HT_BSS_OPERATION + * Configure HT capabilities - AP rules for behavior in the BSS. + */ +struct wl1271_acx_ht_information { + struct acx_header header; + + /* Values: 0 - RIFS not allowed, 1 - RIFS allowed */ + u8 rifs_mode; + + /* Values: 0 - 3 like in spec */ + u8 ht_protection; + + /* Values: 0 - GF protection not required, 1 - GF protection required */ + u8 gf_protection; + + /*Values: 0 - TX Burst limit not required, 1 - TX Burst Limit required*/ + u8 ht_tx_burst_limit; + + /* + * Values: 0 - Dual CTS protection not required, + * 1 - Dual CTS Protection required + * Note: When this value is set to 1 FW will protect all TXOP with RTS + * frame and will not use CTS-to-self regardless of the value of the + * ACX_CTS_PROTECTION information element + */ + u8 dual_cts_protection; + + u8 padding[3]; +} __packed; + struct wl1271_acx_fw_tsf_information { struct acx_header header; @@ -1079,20 +1166,25 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, u8 tsid, u8 ps_scheme, u8 ack_policy, u32 apsd_conf0, u32 apsd_conf1); -int wl1271_acx_frag_threshold(struct wl1271 *wl); +int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold); int wl1271_acx_tx_config_options(struct wl1271 *wl); int wl1271_acx_mem_cfg(struct wl1271 *wl); int wl1271_acx_init_mem_config(struct wl1271 *wl); int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); int wl1271_acx_smart_reflex(struct wl1271 *wl); int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); -int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address); +int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address); int wl1271_acx_pm_config(struct wl1271 *wl); int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, s16 thold, u8 hyst); int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); +int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, + struct ieee80211_sta_ht_cap *ht_cap, + bool allow_ht_operation); +int wl1271_acx_set_ht_information(struct wl1271 *wl, + u16 ht_operation_mode); int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); #endif /* __WL1271_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/boot.c index b91021242098..4df04f84d7f1 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -21,14 +21,13 @@ * */ -#include <linux/gpio.h> #include <linux/slab.h> -#include "wl1271_acx.h" -#include "wl1271_reg.h" -#include "wl1271_boot.h" -#include "wl1271_io.h" -#include "wl1271_event.h" +#include "acx.h" +#include "reg.h" +#include "boot.h" +#include "io.h" +#include "event.h" static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { [PART_DOWN] = { @@ -467,24 +466,24 @@ static void wl1271_boot_hw_version(struct wl1271 *wl) wl->hw_pg_ver = (s8)fuse; } -int wl1271_boot(struct wl1271 *wl) +/* uploads NVS and firmware */ +int wl1271_load_firmware(struct wl1271 *wl) { int ret = 0; u32 tmp, clk, pause; - int ref_clock = wl->ref_clock; wl1271_boot_hw_version(wl); - if (ref_clock == 0 || ref_clock == 2 || ref_clock == 4) + if (wl->ref_clock == 0 || wl->ref_clock == 2 || wl->ref_clock == 4) /* ref clk: 19.2/38.4/38.4-XTAL */ clk = 0x3; - else if (ref_clock == 1 || ref_clock == 3) + else if (wl->ref_clock == 1 || wl->ref_clock == 3) /* ref clk: 26/52 */ clk = 0x5; else return -EINVAL; - if (ref_clock != 0) { + if (wl->ref_clock != 0) { u16 val; /* Set clock type (open drain) */ val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); @@ -529,8 +528,7 @@ int wl1271_boot(struct wl1271 *wl) wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); - /* 2 */ - clk |= (ref_clock << 1) << 4; + clk |= (wl->ref_clock << 1) << 4; wl1271_write32(wl, DRPW_SCRATCH_START, clk); wl1271_set_partition(wl, &part_table[PART_WORK]); @@ -574,6 +572,20 @@ int wl1271_boot(struct wl1271 *wl) if (ret < 0) goto out; +out: + return ret; +} +EXPORT_SYMBOL_GPL(wl1271_load_firmware); + +int wl1271_boot(struct wl1271 *wl) +{ + int ret; + + /* upload NVS and firmware */ + ret = wl1271_load_firmware(wl); + if (ret) + return ret; + /* 10.5 start firmware */ ret = wl1271_boot_run_firmware(wl); if (ret < 0) diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/boot.h index f73b0b15a280..d67dcffa31eb 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.h +++ b/drivers/net/wireless/wl12xx/boot.h @@ -24,9 +24,10 @@ #ifndef __BOOT_H__ #define __BOOT_H__ -#include "wl1271.h" +#include "wl12xx.h" int wl1271_boot(struct wl1271 *wl); +int wl1271_load_firmware(struct wl1271 *wl); #define WL1271_NO_SUBBANDS 8 #define WL1271_NO_POWER_LEVELS 4 diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 5d3e8485ea4e..0106628aa5a2 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -29,13 +29,13 @@ #include <linux/ieee80211.h> #include <linux/slab.h> -#include "wl1271.h" -#include "wl1271_reg.h" -#include "wl1271_io.h" -#include "wl1271_acx.h" +#include "wl12xx.h" +#include "reg.h" +#include "io.h" +#include "acx.h" #include "wl12xx_80211.h" -#include "wl1271_cmd.h" -#include "wl1271_event.h" +#include "cmd.h" +#include "event.h" #define WL1271_CMD_FAST_POLL_COUNT 50 @@ -611,6 +611,75 @@ out: return ret; } +struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, + struct sk_buff *skb) +{ + int ret; + + if (!skb) + skb = ieee80211_ap_probereq_get(wl->hw, wl->vif); + if (!skb) + goto out; + + wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); + + if (wl->band == IEEE80211_BAND_2GHZ) + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, + skb->data, skb->len, 0, + wl->conf.tx.basic_rate); + else + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, + skb->data, skb->len, 0, + wl->conf.tx.basic_rate_5); + + if (ret < 0) + wl1271_error("Unable to set ap probe request template."); + +out: + return skb; +} + +int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr) +{ + int ret; + struct wl12xx_arp_rsp_template tmpl; + struct ieee80211_hdr_3addr *hdr; + struct arphdr *arp_hdr; + + memset(&tmpl, 0, sizeof(tmpl)); + + /* mac80211 header */ + hdr = &tmpl.hdr; + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | + IEEE80211_STYPE_DATA | + IEEE80211_FCTL_TODS); + memcpy(hdr->addr1, wl->vif->bss_conf.bssid, ETH_ALEN); + memcpy(hdr->addr2, wl->vif->addr, ETH_ALEN); + memset(hdr->addr3, 0xff, ETH_ALEN); + + /* llc layer */ + memcpy(tmpl.llc_hdr, rfc1042_header, sizeof(rfc1042_header)); + tmpl.llc_type = htons(ETH_P_ARP); + + /* arp header */ + arp_hdr = &tmpl.arp_hdr; + arp_hdr->ar_hrd = htons(ARPHRD_ETHER); + arp_hdr->ar_pro = htons(ETH_P_IP); + arp_hdr->ar_hln = ETH_ALEN; + arp_hdr->ar_pln = 4; + arp_hdr->ar_op = htons(ARPOP_REPLY); + + /* arp payload */ + memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN); + tmpl.sender_ip = ip_addr; + + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, + &tmpl, sizeof(tmpl), 0, + wl->basic_rate); + + return ret; +} + int wl1271_build_qos_null_data(struct wl1271 *wl) { struct ieee80211_qos_hdr template; diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/cmd.h index a0caf4fc37b1..2a1d9db7ceb8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -22,10 +22,10 @@ * */ -#ifndef __WL1271_CMD_H__ -#define __WL1271_CMD_H__ +#ifndef __CMD_H__ +#define __CMD_H__ -#include "wl1271.h" +#include "wl12xx.h" struct acx_header; @@ -49,6 +49,9 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); int wl1271_cmd_build_probe_req(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u8 band); +struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, + struct sk_buff *skb); +int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr); int wl1271_build_qos_null_data(struct wl1271 *wl); int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); @@ -122,6 +125,7 @@ enum cmd_templ { CMD_TEMPL_CTS, /* * For CTS-to-self (FastCTS) mechanism * for BT/WLAN coexistence (SoftGemini). */ + CMD_TEMPL_ARP_RSP, CMD_TEMPL_MAX = 0xff }; @@ -327,9 +331,6 @@ enum wl1271_channel_tune_bands { #define WL1271_PD_REFERENCE_POINT_BAND_B_G 0 -#define TEST_CMD_P2G_CAL 0x02 -#define TEST_CMD_CHANNEL_TUNE 0x0d -#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d #define TEST_CMD_INI_FILE_RADIO_PARAM 0x19 #define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E #define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26 @@ -375,51 +376,6 @@ struct wl1271_ext_radio_parms_cmd { u8 padding[3]; } __packed; -struct wl1271_cmd_cal_channel_tune { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - u8 band; - u8 channel; - - __le16 radio_status; -} __packed; - -struct wl1271_cmd_cal_update_ref_point { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - __le32 ref_power; - __le32 ref_detector; - u8 sub_band; - u8 padding[3]; -} __packed; - -#define MAX_TLV_LENGTH 400 -#define MAX_NVS_VERSION_LENGTH 12 - -#define WL1271_CAL_P2G_BAND_B_G BIT(0) - -struct wl1271_cmd_cal_p2g { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - __le16 len; - u8 buf[MAX_TLV_LENGTH]; - u8 type; - u8 padding; - - __le16 radio_status; - u8 nvs_version[MAX_NVS_VERSION_LENGTH]; - - u8 sub_band_mask; - u8 padding2; -} __packed; - - /* * There are three types of disconnections: * diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/conf.h index 5f78a6cb1433..a16b3616e430 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -21,8 +21,8 @@ * */ -#ifndef __WL1271_CONF_H__ -#define __WL1271_CONF_H__ +#ifndef __CONF_H__ +#define __CONF_H__ enum { CONF_HW_BIT_RATE_1MBPS = BIT(0), diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c new file mode 100644 index 000000000000..ec6077760157 --- /dev/null +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -0,0 +1,480 @@ +/* + * This file is part of wl1271 + * + * Copyright (C) 2009 Nokia Corporation + * + * Contact: Luciano Coelho <luciano.coelho@nokia.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "debugfs.h" + +#include <linux/skbuff.h> +#include <linux/slab.h> + +#include "wl12xx.h" +#include "acx.h" +#include "ps.h" +#include "io.h" + +/* ms */ +#define WL1271_DEBUGFS_STATS_LIFETIME 1000 + +/* debugfs macros idea from mac80211 */ +#define DEBUGFS_FORMAT_BUFFER_SIZE 100 +static int wl1271_format_buffer(char __user *userbuf, size_t count, + loff_t *ppos, char *fmt, ...) +{ + va_list args; + char buf[DEBUGFS_FORMAT_BUFFER_SIZE]; + int res; + + va_start(args, fmt); + res = vscnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + return simple_read_from_buffer(userbuf, count, ppos, buf, res); +} + +#define DEBUGFS_READONLY_FILE(name, fmt, value...) \ +static ssize_t name## _read(struct file *file, char __user *userbuf, \ + size_t count, loff_t *ppos) \ +{ \ + struct wl1271 *wl = file->private_data; \ + return wl1271_format_buffer(userbuf, count, ppos, \ + fmt "\n", ##value); \ +} \ + \ +static const struct file_operations name## _ops = { \ + .read = name## _read, \ + .open = wl1271_open_file_generic, \ + .llseek = generic_file_llseek, \ +}; + +#define DEBUGFS_ADD(name, parent) \ + entry = debugfs_create_file(#name, 0400, parent, \ + wl, &name## _ops); \ + if (!entry || IS_ERR(entry)) \ + goto err; \ + +#define DEBUGFS_FWSTATS_FILE(sub, name, fmt) \ +static ssize_t sub## _ ##name## _read(struct file *file, \ + char __user *userbuf, \ + size_t count, loff_t *ppos) \ +{ \ + struct wl1271 *wl = file->private_data; \ + \ + wl1271_debugfs_update_stats(wl); \ + \ + return wl1271_format_buffer(userbuf, count, ppos, fmt "\n", \ + wl->stats.fw_stats->sub.name); \ +} \ + \ +static const struct file_operations sub## _ ##name## _ops = { \ + .read = sub## _ ##name## _read, \ + .open = wl1271_open_file_generic, \ + .llseek = generic_file_llseek, \ +}; + +#define DEBUGFS_FWSTATS_ADD(sub, name) \ + DEBUGFS_ADD(sub## _ ##name, stats) + +static void wl1271_debugfs_update_stats(struct wl1271 *wl) +{ + int ret; + + mutex_lock(&wl->mutex); + + ret = wl1271_ps_elp_wakeup(wl, false); + if (ret < 0) + goto out; + + if (wl->state == WL1271_STATE_ON && + time_after(jiffies, wl->stats.fw_stats_update + + msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) { + wl1271_acx_statistics(wl, wl->stats.fw_stats); + wl->stats.fw_stats_update = jiffies; + } + + wl1271_ps_elp_sleep(wl); + +out: + mutex_unlock(&wl->mutex); +} + +static int wl1271_open_file_generic(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, "%u"); + +DEBUGFS_FWSTATS_FILE(rx, out_of_mem, "%u"); +DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, "%u"); +DEBUGFS_FWSTATS_FILE(rx, hw_stuck, "%u"); +DEBUGFS_FWSTATS_FILE(rx, dropped, "%u"); +DEBUGFS_FWSTATS_FILE(rx, fcs_err, "%u"); +DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, "%u"); +DEBUGFS_FWSTATS_FILE(rx, path_reset, "%u"); +DEBUGFS_FWSTATS_FILE(rx, reset_counter, "%u"); + +DEBUGFS_FWSTATS_FILE(dma, rx_requested, "%u"); +DEBUGFS_FWSTATS_FILE(dma, rx_errors, "%u"); +DEBUGFS_FWSTATS_FILE(dma, tx_requested, "%u"); +DEBUGFS_FWSTATS_FILE(dma, tx_errors, "%u"); + +DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, "%u"); +DEBUGFS_FWSTATS_FILE(isr, fiqs, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_headers, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_rdys, "%u"); +DEBUGFS_FWSTATS_FILE(isr, irqs, "%u"); +DEBUGFS_FWSTATS_FILE(isr, tx_procs, "%u"); +DEBUGFS_FWSTATS_FILE(isr, decrypt_done, "%u"); +DEBUGFS_FWSTATS_FILE(isr, dma0_done, "%u"); +DEBUGFS_FWSTATS_FILE(isr, dma1_done, "%u"); +DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, "%u"); +DEBUGFS_FWSTATS_FILE(isr, commands, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_procs, "%u"); +DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, "%u"); +DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, "%u"); +DEBUGFS_FWSTATS_FILE(isr, pci_pm, "%u"); +DEBUGFS_FWSTATS_FILE(isr, wakeups, "%u"); +DEBUGFS_FWSTATS_FILE(isr, low_rssi, "%u"); + +DEBUGFS_FWSTATS_FILE(wep, addr_key_count, "%u"); +DEBUGFS_FWSTATS_FILE(wep, default_key_count, "%u"); +/* skipping wep.reserved */ +DEBUGFS_FWSTATS_FILE(wep, key_not_found, "%u"); +DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, "%u"); +DEBUGFS_FWSTATS_FILE(wep, packets, "%u"); +DEBUGFS_FWSTATS_FILE(wep, interrupt, "%u"); + +DEBUGFS_FWSTATS_FILE(pwr, ps_enter, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, elp_enter, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, power_save_off, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, enable_ps, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, disable_ps, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, "%u"); +/* skipping cont_miss_bcns_spread for now */ +DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, "%u"); + +DEBUGFS_FWSTATS_FILE(mic, rx_pkts, "%u"); +DEBUGFS_FWSTATS_FILE(mic, calc_failure, "%u"); + +DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, "%u"); +DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, "%u"); +DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, "%u"); +DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, "%u"); +DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, "%u"); +DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, "%u"); + +DEBUGFS_FWSTATS_FILE(event, heart_beat, "%u"); +DEBUGFS_FWSTATS_FILE(event, calibration, "%u"); +DEBUGFS_FWSTATS_FILE(event, rx_mismatch, "%u"); +DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, "%u"); +DEBUGFS_FWSTATS_FILE(event, rx_pool, "%u"); +DEBUGFS_FWSTATS_FILE(event, oom_late, "%u"); +DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, "%u"); +DEBUGFS_FWSTATS_FILE(event, tx_stuck, "%u"); + +DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, "%u"); +DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, "%u"); +DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, "%u"); + +DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, "%u"); + +DEBUGFS_READONLY_FILE(retry_count, "%u", wl->stats.retry_count); +DEBUGFS_READONLY_FILE(excessive_retries, "%u", + wl->stats.excessive_retries); + +static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + u32 queue_len; + char buf[20]; + int res; + + queue_len = wl->tx_queue_count; + + res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); + return simple_read_from_buffer(userbuf, count, ppos, buf, res); +} + +static const struct file_operations tx_queue_len_ops = { + .read = tx_queue_len_read, + .open = wl1271_open_file_generic, + .llseek = default_llseek, +}; + +static ssize_t gpio_power_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + bool state = test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); + + int res; + char buf[10]; + + res = scnprintf(buf, sizeof(buf), "%d\n", state); + + return simple_read_from_buffer(user_buf, count, ppos, buf, res); +} + +static ssize_t gpio_power_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + char buf[10]; + size_t len; + unsigned long value; + int ret; + + mutex_lock(&wl->mutex); + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) { + ret = -EFAULT; + goto out; + } + buf[len] = '\0'; + + ret = strict_strtoul(buf, 0, &value); + if (ret < 0) { + wl1271_warning("illegal value in gpio_power"); + goto out; + } + + if (value) + wl1271_power_on(wl); + else + wl1271_power_off(wl); + +out: + mutex_unlock(&wl->mutex); + return count; +} + +static const struct file_operations gpio_power_ops = { + .read = gpio_power_read, + .write = gpio_power_write, + .open = wl1271_open_file_generic, + .llseek = default_llseek, +}; + +static int wl1271_debugfs_add_files(struct wl1271 *wl) +{ + int ret = 0; + struct dentry *entry, *stats; + + stats = debugfs_create_dir("fw-statistics", wl->rootdir); + if (!stats || IS_ERR(stats)) { + entry = stats; + goto err; + } + + DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); + + DEBUGFS_FWSTATS_ADD(rx, out_of_mem); + DEBUGFS_FWSTATS_ADD(rx, hdr_overflow); + DEBUGFS_FWSTATS_ADD(rx, hw_stuck); + DEBUGFS_FWSTATS_ADD(rx, dropped); + DEBUGFS_FWSTATS_ADD(rx, fcs_err); + DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig); + DEBUGFS_FWSTATS_ADD(rx, path_reset); + DEBUGFS_FWSTATS_ADD(rx, reset_counter); + + DEBUGFS_FWSTATS_ADD(dma, rx_requested); + DEBUGFS_FWSTATS_ADD(dma, rx_errors); + DEBUGFS_FWSTATS_ADD(dma, tx_requested); + DEBUGFS_FWSTATS_ADD(dma, tx_errors); + + DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt); + DEBUGFS_FWSTATS_ADD(isr, fiqs); + DEBUGFS_FWSTATS_ADD(isr, rx_headers); + DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow); + DEBUGFS_FWSTATS_ADD(isr, rx_rdys); + DEBUGFS_FWSTATS_ADD(isr, irqs); + DEBUGFS_FWSTATS_ADD(isr, tx_procs); + DEBUGFS_FWSTATS_ADD(isr, decrypt_done); + DEBUGFS_FWSTATS_ADD(isr, dma0_done); + DEBUGFS_FWSTATS_ADD(isr, dma1_done); + DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete); + DEBUGFS_FWSTATS_ADD(isr, commands); + DEBUGFS_FWSTATS_ADD(isr, rx_procs); + DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes); + DEBUGFS_FWSTATS_ADD(isr, host_acknowledges); + DEBUGFS_FWSTATS_ADD(isr, pci_pm); + DEBUGFS_FWSTATS_ADD(isr, wakeups); + DEBUGFS_FWSTATS_ADD(isr, low_rssi); + + DEBUGFS_FWSTATS_ADD(wep, addr_key_count); + DEBUGFS_FWSTATS_ADD(wep, default_key_count); + /* skipping wep.reserved */ + DEBUGFS_FWSTATS_ADD(wep, key_not_found); + DEBUGFS_FWSTATS_ADD(wep, decrypt_fail); + DEBUGFS_FWSTATS_ADD(wep, packets); + DEBUGFS_FWSTATS_ADD(wep, interrupt); + + DEBUGFS_FWSTATS_ADD(pwr, ps_enter); + DEBUGFS_FWSTATS_ADD(pwr, elp_enter); + DEBUGFS_FWSTATS_ADD(pwr, missing_bcns); + DEBUGFS_FWSTATS_ADD(pwr, wake_on_host); + DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp); + DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps); + DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps); + DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons); + DEBUGFS_FWSTATS_ADD(pwr, power_save_off); + DEBUGFS_FWSTATS_ADD(pwr, enable_ps); + DEBUGFS_FWSTATS_ADD(pwr, disable_ps); + DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps); + /* skipping cont_miss_bcns_spread for now */ + DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons); + + DEBUGFS_FWSTATS_ADD(mic, rx_pkts); + DEBUGFS_FWSTATS_ADD(mic, calc_failure); + + DEBUGFS_FWSTATS_ADD(aes, encrypt_fail); + DEBUGFS_FWSTATS_ADD(aes, decrypt_fail); + DEBUGFS_FWSTATS_ADD(aes, encrypt_packets); + DEBUGFS_FWSTATS_ADD(aes, decrypt_packets); + DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt); + DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt); + + DEBUGFS_FWSTATS_ADD(event, heart_beat); + DEBUGFS_FWSTATS_ADD(event, calibration); + DEBUGFS_FWSTATS_ADD(event, rx_mismatch); + DEBUGFS_FWSTATS_ADD(event, rx_mem_empty); + DEBUGFS_FWSTATS_ADD(event, rx_pool); + DEBUGFS_FWSTATS_ADD(event, oom_late); + DEBUGFS_FWSTATS_ADD(event, phy_transmit_error); + DEBUGFS_FWSTATS_ADD(event, tx_stuck); + + DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts); + DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts); + DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime); + DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn); + DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn); + DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization); + DEBUGFS_FWSTATS_ADD(ps, upsd_utilization); + + DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop); + DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data); + DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); + DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); + DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); + + DEBUGFS_ADD(tx_queue_len, wl->rootdir); + DEBUGFS_ADD(retry_count, wl->rootdir); + DEBUGFS_ADD(excessive_retries, wl->rootdir); + + DEBUGFS_ADD(gpio_power, wl->rootdir); + + entry = debugfs_create_x32("debug_level", 0600, wl->rootdir, + &wl12xx_debug_level); + if (!entry || IS_ERR(entry)) + goto err; + + return 0; + +err: + if (IS_ERR(entry)) + ret = PTR_ERR(entry); + else + ret = -ENOMEM; + + return ret; +} + +void wl1271_debugfs_reset(struct wl1271 *wl) +{ + if (!wl->rootdir) + return; + + memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats)); + wl->stats.retry_count = 0; + wl->stats.excessive_retries = 0; +} + +int wl1271_debugfs_init(struct wl1271 *wl) +{ + int ret; + + wl->rootdir = debugfs_create_dir(KBUILD_MODNAME, + wl->hw->wiphy->debugfsdir); + + if (IS_ERR(wl->rootdir)) { + ret = PTR_ERR(wl->rootdir); + wl->rootdir = NULL; + goto err; + } + + wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), + GFP_KERNEL); + + if (!wl->stats.fw_stats) { + ret = -ENOMEM; + goto err_fw; + } + + wl->stats.fw_stats_update = jiffies; + + ret = wl1271_debugfs_add_files(wl); + + if (ret < 0) + goto err_file; + + return 0; + +err_file: + kfree(wl->stats.fw_stats); + wl->stats.fw_stats = NULL; + +err_fw: + debugfs_remove_recursive(wl->rootdir); + wl->rootdir = NULL; + +err: + return ret; +} + +void wl1271_debugfs_exit(struct wl1271 *wl) +{ + kfree(wl->stats.fw_stats); + wl->stats.fw_stats = NULL; + + debugfs_remove_recursive(wl->rootdir); + wl->rootdir = NULL; + +} diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.h b/drivers/net/wireless/wl12xx/debugfs.h index 00a45b2669ad..254c5b292cf6 100644 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.h +++ b/drivers/net/wireless/wl12xx/debugfs.h @@ -21,10 +21,10 @@ * */ -#ifndef WL1271_DEBUGFS_H -#define WL1271_DEBUGFS_H +#ifndef __DEBUGFS_H__ +#define __DEBUGFS_H__ -#include "wl1271.h" +#include "wl12xx.h" int wl1271_debugfs_init(struct wl1271 *wl); void wl1271_debugfs_exit(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/event.c index 7b3f50382963..f9146f5242fb 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -21,12 +21,12 @@ * */ -#include "wl1271.h" -#include "wl1271_reg.h" -#include "wl1271_io.h" -#include "wl1271_event.h" -#include "wl1271_ps.h" -#include "wl1271_scan.h" +#include "wl12xx.h" +#include "reg.h" +#include "io.h" +#include "event.h" +#include "ps.h" +#include "scan.h" #include "wl12xx_80211.h" void wl1271_pspoll_work(struct work_struct *work) @@ -134,8 +134,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl, /* go to extremely low power mode */ wl1271_ps_elp_sleep(wl); - if (ret < 0) - break; break; case EVENT_EXIT_POWER_SAVE_FAIL: wl1271_debug(DEBUG_PSM, "PSM exit failed"); diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/event.h index e4751667cf5e..6cce0143adb5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/event.h @@ -22,8 +22,8 @@ * */ -#ifndef __WL1271_EVENT_H__ -#define __WL1271_EVENT_H__ +#ifndef __EVENT_H__ +#define __EVENT_H__ /* * Mbox events diff --git a/drivers/net/wireless/wl12xx/wl1271_ini.h b/drivers/net/wireless/wl12xx/ini.h index 2313047d4015..c330a2583dfd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ini.h +++ b/drivers/net/wireless/wl12xx/ini.h @@ -21,8 +21,8 @@ * */ -#ifndef __WL1271_INI_H__ -#define __WL1271_INI_H__ +#ifndef __INI_H__ +#define __INI_H__ #define WL1271_INI_MAX_SMART_REFLEX_PARAM 16 diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/init.c index 8044bba70ee7..785a5304bfc4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -25,11 +25,11 @@ #include <linux/module.h> #include <linux/slab.h> -#include "wl1271_init.h" +#include "init.h" #include "wl12xx_80211.h" -#include "wl1271_acx.h" -#include "wl1271_cmd.h" -#include "wl1271_reg.h" +#include "acx.h" +#include "cmd.h" +#include "reg.h" static int wl1271_init_hwenc_config(struct wl1271 *wl) { @@ -53,18 +53,16 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl) int wl1271_init_templates_config(struct wl1271 *wl) { int ret, i; - size_t size; /* send empty templates for fw memory reservation */ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, - sizeof(struct wl12xx_probe_req_template), + WL1271_CMD_TEMPL_MAX_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; - size = sizeof(struct wl12xx_probe_req_template); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, - NULL, size, 0, + NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; @@ -102,6 +100,13 @@ int wl1271_init_templates_config(struct wl1271 *wl) if (ret < 0) return ret; + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, NULL, + sizeof + (struct wl12xx_arp_rsp_template), + 0, WL1271_RATE_AUTOMATIC); + if (ret < 0) + return ret; + for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, WL1271_CMD_TEMPL_MAX_SIZE, i, @@ -290,7 +295,7 @@ int wl1271_hw_init(struct wl1271 *wl) goto out_free_memmap; /* Default fragmentation threshold */ - ret = wl1271_acx_frag_threshold(wl); + ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); if (ret < 0) goto out_free_memmap; diff --git a/drivers/net/wireless/wl12xx/wl1271_init.h b/drivers/net/wireless/wl12xx/init.h index bc26f8c53b91..7762421f8602 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.h +++ b/drivers/net/wireless/wl12xx/init.h @@ -21,10 +21,10 @@ * */ -#ifndef __WL1271_INIT_H__ -#define __WL1271_INIT_H__ +#ifndef __INIT_H__ +#define __INIT_H__ -#include "wl1271.h" +#include "wl12xx.h" int wl1271_hw_init_power_auth(struct wl1271 *wl); int wl1271_init_templates_config(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/io.c index c8759acef131..d557f73e7c19 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.c +++ b/drivers/net/wireless/wl12xx/io.c @@ -26,9 +26,9 @@ #include <linux/crc7.h> #include <linux/spi/spi.h> -#include "wl1271.h" +#include "wl12xx.h" #include "wl12xx_80211.h" -#include "wl1271_io.h" +#include "io.h" #define OCP_CMD_LOOP 32 @@ -113,6 +113,7 @@ int wl1271_set_partition(struct wl1271 *wl, return 0; } +EXPORT_SYMBOL_GPL(wl1271_set_partition); void wl1271_io_reset(struct wl1271 *wl) { diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/io.h index c1f92e65ded0..844b32b170bb 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/io.h @@ -22,10 +22,10 @@ * */ -#ifndef __WL1271_IO_H__ -#define __WL1271_IO_H__ +#ifndef __IO_H__ +#define __IO_H__ -#include "wl1271_reg.h" +#include "reg.h" #define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/main.c index 48a4b9961ae6..062247ef3ad2 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -31,20 +31,20 @@ #include <linux/platform_device.h> #include <linux/slab.h> -#include "wl1271.h" +#include "wl12xx.h" #include "wl12xx_80211.h" -#include "wl1271_reg.h" -#include "wl1271_io.h" -#include "wl1271_event.h" -#include "wl1271_tx.h" -#include "wl1271_rx.h" -#include "wl1271_ps.h" -#include "wl1271_init.h" -#include "wl1271_debugfs.h" -#include "wl1271_cmd.h" -#include "wl1271_boot.h" -#include "wl1271_testmode.h" -#include "wl1271_scan.h" +#include "reg.h" +#include "io.h" +#include "event.h" +#include "tx.h" +#include "rx.h" +#include "ps.h" +#include "init.h" +#include "debugfs.h" +#include "cmd.h" +#include "boot.h" +#include "testmode.h" +#include "scan.h" #define WL1271_BOOT_RETRIES 3 @@ -335,6 +335,28 @@ out: return NOTIFY_OK; } +static int wl1271_reg_notify(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_supported_band *band; + struct ieee80211_channel *ch; + int i; + + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + for (i = 0; i < band->n_channels; i++) { + ch = &band->channels[i]; + if (ch->flags & IEEE80211_CHAN_DISABLED) + continue; + + if (ch->flags & IEEE80211_CHAN_RADAR) + ch->flags |= IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_PASSIVE_SCAN; + + } + + return 0; +} + static void wl1271_conf_init(struct wl1271 *wl) { @@ -404,7 +426,7 @@ static int wl1271_plt_init(struct wl1271 *wl) goto out_free_memmap; /* Default fragmentation threshold */ - ret = wl1271_acx_frag_threshold(wl); + ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); if (ret < 0) goto out_free_memmap; @@ -481,9 +503,9 @@ static void wl1271_fw_status(struct wl1271 *wl, total += cnt; } - /* if more blocks are available now, schedule some tx work */ - if (total && !skb_queue_empty(&wl->tx_queue)) - ieee80211_queue_work(wl->hw, &wl->tx_work); + /* if more blocks are available now, tx work can be scheduled */ + if (total) + clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); /* update the host-chipset time offset */ getnstimeofday(&ts); @@ -529,6 +551,15 @@ static void wl1271_irq_work(struct work_struct *work) intr &= WL1271_INTR_MASK; + if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { + wl1271_error("watchdog interrupt received! " + "starting recovery."); + ieee80211_queue_work(wl->hw, &wl->recovery_work); + + /* restarting the chip. ignore any other interrupt. */ + goto out; + } + if (intr & WL1271_ACX_INTR_DATA) { wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); @@ -537,6 +568,16 @@ static void wl1271_irq_work(struct work_struct *work) (wl->tx_results_count & 0xff)) wl1271_tx_complete(wl); + /* Check if any tx blocks were freed */ + if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && + wl->tx_queue_count) { + /* + * In order to avoid starvation of the TX path, + * call the work function directly. + */ + wl1271_tx_work_locked(wl); + } + wl1271_rx(wl, wl->fw_status); } @@ -850,30 +891,54 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); struct ieee80211_sta *sta = txinfo->control.sta; unsigned long flags; + int q; - /* peek into the rates configured in the STA entry */ + /* + * peek into the rates configured in the STA entry. + * The rates set after connection stage, The first block only BG sets: + * the compare is for bit 0-16 of sta_rate_set. The second block add + * HT rates in case of HT supported. + */ spin_lock_irqsave(&wl->wl_lock, flags); - if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) { + if (sta && + (sta->supp_rates[conf->channel->band] != + (wl->sta_rate_set & HW_BG_RATES_MASK))) { wl->sta_rate_set = sta->supp_rates[conf->channel->band]; set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); } + +#ifdef CONFIG_WL12XX_HT + if (sta && + sta->ht_cap.ht_supported && + ((wl->sta_rate_set >> HW_HT_RATES_OFFSET) != + sta->ht_cap.mcs.rx_mask[0])) { + /* Clean MCS bits before setting them */ + wl->sta_rate_set &= HW_BG_RATES_MASK; + wl->sta_rate_set |= + (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET); + set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); + } +#endif + wl->tx_queue_count++; spin_unlock_irqrestore(&wl->wl_lock, flags); /* queue the packet */ - skb_queue_tail(&wl->tx_queue, skb); + q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); + skb_queue_tail(&wl->tx_queue[q], skb); /* * The chip specific setup must run before the first TX packet - * before that, the tx_work will not be initialized! */ - ieee80211_queue_work(wl->hw, &wl->tx_work); + if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) + ieee80211_queue_work(wl->hw, &wl->tx_work); /* * The workqueue is slow to process the tx_queue and we need stop * the queue here, otherwise the queue will get too long. */ - if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_HIGH_WATERMARK) { + if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) { wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); spin_lock_irqsave(&wl->wl_lock, flags); @@ -919,18 +984,19 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, struct wiphy *wiphy = hw->wiphy; int retries = WL1271_BOOT_RETRIES; int ret = 0; + bool booted = false; wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", vif->type, vif->addr); mutex_lock(&wl->mutex); if (wl->vif) { + wl1271_debug(DEBUG_MAC80211, + "multiple vifs are not supported yet"); ret = -EBUSY; goto out; } - wl->vif = vif; - switch (vif->type) { case NL80211_IFTYPE_STATION: wl->bss_type = BSS_TYPE_STA_BSS; @@ -968,15 +1034,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, if (ret < 0) goto irq_disable; - wl->state = WL1271_STATE_ON; - wl1271_info("firmware booted (%s)", wl->chip.fw_ver); - - /* update hw/fw version info in wiphy struct */ - wiphy->hw_version = wl->chip.id; - strncpy(wiphy->fw_version, wl->chip.fw_ver, - sizeof(wiphy->fw_version)); - - goto out; + booted = true; + break; irq_disable: wl1271_disable_interrupts(wl); @@ -994,8 +1053,31 @@ power_off: wl1271_power_off(wl); } - wl1271_error("firmware boot failed despite %d retries", - WL1271_BOOT_RETRIES); + if (!booted) { + wl1271_error("firmware boot failed despite %d retries", + WL1271_BOOT_RETRIES); + goto out; + } + + wl->vif = vif; + wl->state = WL1271_STATE_ON; + wl1271_info("firmware booted (%s)", wl->chip.fw_ver); + + /* update hw/fw version info in wiphy struct */ + wiphy->hw_version = wl->chip.id; + strncpy(wiphy->fw_version, wl->chip.fw_ver, + sizeof(wiphy->fw_version)); + + /* + * Now we know if 11a is supported (info from the NVS), so disable + * 11a channels if not supported + */ + if (!wl->enable_11a) + wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels = 0; + + wl1271_debug(DEBUG_MAC80211, "11a is %ssupported", + wl->enable_11a ? "" : "not "); + out: mutex_unlock(&wl->mutex); @@ -1025,6 +1107,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) wl->scan.state = WL1271_SCAN_STATE_IDLE; kfree(wl->scan.scanned_ch); wl->scan.scanned_ch = NULL; + wl->scan.req = NULL; ieee80211_scan_completed(wl->hw, true); } @@ -1088,10 +1171,16 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, struct wl1271 *wl = hw->priv; mutex_lock(&wl->mutex); - WARN_ON(wl->vif != vif); - __wl1271_op_remove_interface(wl); - mutex_unlock(&wl->mutex); + /* + * wl->vif can be null here if someone shuts down the interface + * just when hardware recovery has been started. + */ + if (wl->vif) { + WARN_ON(wl->vif != vif); + __wl1271_op_remove_interface(wl); + } + mutex_unlock(&wl->mutex); cancel_work_sync(&wl->recovery_work); } @@ -1312,8 +1401,10 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state == WL1271_STATE_OFF)) { + ret = -EAGAIN; goto out; + } ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) @@ -1536,6 +1627,11 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mutex_lock(&wl->mutex); + if (unlikely(wl->state == WL1271_STATE_OFF)) { + ret = -EAGAIN; + goto out_unlock; + } + ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out_unlock; @@ -1645,6 +1741,16 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); + if (wl->state == WL1271_STATE_OFF) { + /* + * We cannot return -EBUSY here because cfg80211 will expect + * a call to ieee80211_scan_completed if we do - in this case + * there won't be any call. + */ + ret = -EAGAIN; + goto out; + } + ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out; @@ -1659,6 +1765,34 @@ out: return ret; } +static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) +{ + struct wl1271 *wl = hw->priv; + int ret = 0; + + mutex_lock(&wl->mutex); + + if (unlikely(wl->state == WL1271_STATE_OFF)) { + ret = -EAGAIN; + goto out; + } + + ret = wl1271_ps_elp_wakeup(wl, false); + if (ret < 0) + goto out; + + ret = wl1271_acx_frag_threshold(wl, (u16)value); + if (ret < 0) + wl1271_warning("wl1271_op_set_frag_threshold failed: %d", ret); + + wl1271_ps_elp_sleep(wl); + +out: + mutex_unlock(&wl->mutex); + + return ret; +} + static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) { struct wl1271 *wl = hw->priv; @@ -1666,8 +1800,10 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state == WL1271_STATE_OFF)) { + ret = -EAGAIN; goto out; + } ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) @@ -1685,21 +1821,21 @@ out: return ret; } -static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *beacon) +static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, + int offset) { - u8 *ptr = beacon->data + - offsetof(struct ieee80211_mgmt, u.beacon.variable); + u8 *ptr = skb->data + offset; /* find the location of the ssid in the beacon */ - while (ptr < beacon->data + beacon->len) { + while (ptr < skb->data + skb->len) { if (ptr[0] == WLAN_EID_SSID) { wl->ssid_len = ptr[1]; memcpy(wl->ssid, ptr+2, wl->ssid_len); return; } - ptr += ptr[1]; + ptr += (ptr[1] + 2); } - wl1271_error("ad-hoc beacon template has no SSID!\n"); + wl1271_error("No SSID in IEs!\n"); } static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, @@ -1709,6 +1845,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, { enum wl1271_cmd_ps_mode mode; struct wl1271 *wl = hw->priv; + struct ieee80211_sta *sta = ieee80211_find_sta(vif, bss_conf->bssid); bool do_join = false; bool set_assoc = false; int ret; @@ -1717,6 +1854,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out; @@ -1738,8 +1878,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (beacon) { struct ieee80211_hdr *hdr; + int ieoffset = offsetof(struct ieee80211_mgmt, + u.beacon.variable); + + wl1271_ssid_set(wl, beacon, ieoffset); - wl1271_ssid_set(wl, beacon); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, beacon->data, beacon->len, 0, @@ -1819,6 +1962,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { u32 rates; + int ieoffset; wl->aid = bss_conf->aid; set_assoc = true; @@ -1847,13 +1991,13 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, goto out_sleep; /* - * The SSID is intentionally set to NULL here - the - * firmware will set the probe request with a - * broadcast SSID regardless of what we set in the - * template. + * Get a template for hardware connection maintenance */ - ret = wl1271_cmd_build_probe_req(wl, NULL, 0, - NULL, 0, wl->band); + dev_kfree_skb(wl->probereq); + wl->probereq = wl1271_cmd_build_ap_probe_req(wl, NULL); + ieoffset = offsetof(struct ieee80211_mgmt, + u.probe_req.variable); + wl1271_ssid_set(wl, wl->probereq, ieoffset); /* enable the connection monitoring feature */ ret = wl1271_acx_conn_monit_params(wl, true); @@ -1876,6 +2020,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); wl->aid = 0; + /* free probe-request template */ + dev_kfree_skb(wl->probereq); + wl->probereq = NULL; + /* re-enable dynamic ps - just in case */ ieee80211_enable_dyn_ps(wl->vif); @@ -1891,9 +2039,12 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, /* Disable the keep-alive feature */ ret = wl1271_acx_keep_alive_mode(wl, false); - if (ret < 0) goto out_sleep; + + /* restore the bssid filter and go to dummy bssid */ + wl1271_unjoin(wl); + wl1271_dummy_join(wl); } } @@ -1927,14 +2078,61 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } } + /* + * Takes care of: New association with HT enable, + * HT information change in beacon. + */ + if (sta && + (changed & BSS_CHANGED_HT) && + (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { + ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true); + if (ret < 0) { + wl1271_warning("Set ht cap true failed %d", ret); + goto out_sleep; + } + ret = wl1271_acx_set_ht_information(wl, + bss_conf->ht_operation_mode); + if (ret < 0) { + wl1271_warning("Set ht information failed %d", ret); + goto out_sleep; + } + } + /* + * Takes care of: New association without HT, + * Disassociation. + */ + else if (sta && (changed & BSS_CHANGED_ASSOC)) { + ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, false); + if (ret < 0) { + wl1271_warning("Set ht cap false failed %d", ret); + goto out_sleep; + } + } + if (changed & BSS_CHANGED_ARP_FILTER) { __be32 addr = bss_conf->arp_addr_list[0]; WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); - if (bss_conf->arp_addr_cnt == 1 && bss_conf->arp_filter_enabled) - ret = wl1271_acx_arp_ip_filter(wl, true, addr); - else - ret = wl1271_acx_arp_ip_filter(wl, false, addr); + if (bss_conf->arp_addr_cnt == 1 && + bss_conf->arp_filter_enabled) { + /* + * The template should have been configured only upon + * association. however, it seems that the correct ip + * isn't being set (when sending), so we have to + * reconfigure the template upon every ip change. + */ + ret = wl1271_cmd_build_arp_rsp(wl, addr); + if (ret < 0) { + wl1271_warning("build arp rsp failed: %d", ret); + goto out_sleep; + } + + ret = wl1271_acx_arp_ip_filter(wl, + (ACX_ARP_FILTER_ARP_FILTERING | + ACX_ARP_FILTER_AUTO_ARP), + addr); + } else + ret = wl1271_acx_arp_ip_filter(wl, 0, addr); if (ret < 0) goto out_sleep; @@ -1966,6 +2164,11 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); + if (unlikely(wl->state == WL1271_STATE_OFF)) { + ret = -EAGAIN; + goto out; + } + ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out; @@ -2009,6 +2212,9 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw) mutex_lock(&wl->mutex); + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out; @@ -2030,14 +2236,14 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, { struct wl1271 *wl = hw->priv; struct ieee80211_conf *conf = &hw->conf; - + if (idx != 0) return -ENOENT; - + survey->channel = conf->channel; survey->filled = SURVEY_INFO_NOISE_DBM; survey->noise = wl->noise; - + return 0; } @@ -2084,37 +2290,34 @@ static struct ieee80211_rate wl1271_rates[] = { .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, }; -/* - * Can't be const, mac80211 writes to this. The order of the channels here - * is designed to improve scanning. - */ +/* can't be const, mac80211 writes to this */ static struct ieee80211_channel wl1271_channels[] = { { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, - { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, - { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, - { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, - { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, - { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, - { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, - { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, - { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, - { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, + { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, + { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, + { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, + { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, + { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, + { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, + { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, + { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, + { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, }; /* mapping to indexes for wl1271_rates */ static const u8 wl1271_rate_to_idx_2ghz[] = { /* MCS rates are used only with 11n */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ + 7, /* CONF_HW_RXTX_RATE_MCS7 */ + 6, /* CONF_HW_RXTX_RATE_MCS6 */ + 5, /* CONF_HW_RXTX_RATE_MCS5 */ + 4, /* CONF_HW_RXTX_RATE_MCS4 */ + 3, /* CONF_HW_RXTX_RATE_MCS3 */ + 2, /* CONF_HW_RXTX_RATE_MCS2 */ + 1, /* CONF_HW_RXTX_RATE_MCS1 */ + 0, /* CONF_HW_RXTX_RATE_MCS0 */ 11, /* CONF_HW_RXTX_RATE_54 */ 10, /* CONF_HW_RXTX_RATE_48 */ @@ -2134,12 +2337,34 @@ static const u8 wl1271_rate_to_idx_2ghz[] = { 0 /* CONF_HW_RXTX_RATE_1 */ }; +/* 11n STA capabilities */ +#define HW_RX_HIGHEST_RATE 72 + +#ifdef CONFIG_WL12XX_HT +#define WL12XX_HT_CAP { \ + .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20, \ + .ht_supported = true, \ + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \ + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \ + .mcs = { \ + .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \ + .rx_highest = cpu_to_le16(HW_RX_HIGHEST_RATE), \ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ + }, \ +} +#else +#define WL12XX_HT_CAP { \ + .ht_supported = false, \ +} +#endif + /* can't be const, mac80211 writes to this */ static struct ieee80211_supported_band wl1271_band_2ghz = { .channels = wl1271_channels, .n_channels = ARRAY_SIZE(wl1271_channels), .bitrates = wl1271_rates, .n_bitrates = ARRAY_SIZE(wl1271_rates), + .ht_cap = WL12XX_HT_CAP, }; /* 5 GHz data rates for WL1273 */ @@ -2170,66 +2395,55 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = { .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, }; -/* - * 5 GHz band channels for WL1273 - can't be const, mac80211 writes to this. - * The order of the channels here is designed to improve scanning. - */ +/* 5 GHz band channels for WL1273 */ static struct ieee80211_channel wl1271_channels_5ghz[] = { - { .hw_value = 183, .center_freq = 4915}, - { .hw_value = 188, .center_freq = 4940}, + { .hw_value = 7, .center_freq = 5035}, { .hw_value = 8, .center_freq = 5040}, - { .hw_value = 34, .center_freq = 5170}, - { .hw_value = 44, .center_freq = 5220}, - { .hw_value = 60, .center_freq = 5300}, - { .hw_value = 112, .center_freq = 5560}, - { .hw_value = 132, .center_freq = 5660}, - { .hw_value = 157, .center_freq = 5785}, - { .hw_value = 184, .center_freq = 4920}, - { .hw_value = 189, .center_freq = 4945}, { .hw_value = 9, .center_freq = 5045}, - { .hw_value = 36, .center_freq = 5180}, - { .hw_value = 46, .center_freq = 5230}, - { .hw_value = 64, .center_freq = 5320}, - { .hw_value = 116, .center_freq = 5580}, - { .hw_value = 136, .center_freq = 5680}, - { .hw_value = 192, .center_freq = 4960}, { .hw_value = 11, .center_freq = 5055}, - { .hw_value = 38, .center_freq = 5190}, - { .hw_value = 48, .center_freq = 5240}, - { .hw_value = 100, .center_freq = 5500}, - { .hw_value = 120, .center_freq = 5600}, - { .hw_value = 140, .center_freq = 5700}, - { .hw_value = 185, .center_freq = 4925}, - { .hw_value = 196, .center_freq = 4980}, { .hw_value = 12, .center_freq = 5060}, - { .hw_value = 40, .center_freq = 5200}, - { .hw_value = 52, .center_freq = 5260}, - { .hw_value = 104, .center_freq = 5520}, - { .hw_value = 124, .center_freq = 5620}, - { .hw_value = 149, .center_freq = 5745}, - { .hw_value = 161, .center_freq = 5805}, - { .hw_value = 187, .center_freq = 4935}, - { .hw_value = 7, .center_freq = 5035}, { .hw_value = 16, .center_freq = 5080}, + { .hw_value = 34, .center_freq = 5170}, + { .hw_value = 36, .center_freq = 5180}, + { .hw_value = 38, .center_freq = 5190}, + { .hw_value = 40, .center_freq = 5200}, { .hw_value = 42, .center_freq = 5210}, + { .hw_value = 44, .center_freq = 5220}, + { .hw_value = 46, .center_freq = 5230}, + { .hw_value = 48, .center_freq = 5240}, + { .hw_value = 52, .center_freq = 5260}, { .hw_value = 56, .center_freq = 5280}, + { .hw_value = 60, .center_freq = 5300}, + { .hw_value = 64, .center_freq = 5320}, + { .hw_value = 100, .center_freq = 5500}, + { .hw_value = 104, .center_freq = 5520}, { .hw_value = 108, .center_freq = 5540}, + { .hw_value = 112, .center_freq = 5560}, + { .hw_value = 116, .center_freq = 5580}, + { .hw_value = 120, .center_freq = 5600}, + { .hw_value = 124, .center_freq = 5620}, { .hw_value = 128, .center_freq = 5640}, + { .hw_value = 132, .center_freq = 5660}, + { .hw_value = 136, .center_freq = 5680}, + { .hw_value = 140, .center_freq = 5700}, + { .hw_value = 149, .center_freq = 5745}, { .hw_value = 153, .center_freq = 5765}, + { .hw_value = 157, .center_freq = 5785}, + { .hw_value = 161, .center_freq = 5805}, { .hw_value = 165, .center_freq = 5825}, }; /* mapping to indexes for wl1271_rates_5ghz */ static const u8 wl1271_rate_to_idx_5ghz[] = { /* MCS rates are used only with 11n */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ + 7, /* CONF_HW_RXTX_RATE_MCS7 */ + 6, /* CONF_HW_RXTX_RATE_MCS6 */ + 5, /* CONF_HW_RXTX_RATE_MCS5 */ + 4, /* CONF_HW_RXTX_RATE_MCS4 */ + 3, /* CONF_HW_RXTX_RATE_MCS3 */ + 2, /* CONF_HW_RXTX_RATE_MCS2 */ + 1, /* CONF_HW_RXTX_RATE_MCS1 */ + 0, /* CONF_HW_RXTX_RATE_MCS0 */ 7, /* CONF_HW_RXTX_RATE_54 */ 6, /* CONF_HW_RXTX_RATE_48 */ @@ -2254,6 +2468,7 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { .n_channels = ARRAY_SIZE(wl1271_channels_5ghz), .bitrates = wl1271_rates_5ghz, .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), + .ht_cap = WL12XX_HT_CAP, }; static const u8 *wl1271_band_rate_to_idx[] = { @@ -2273,6 +2488,7 @@ static const struct ieee80211_ops wl1271_ops = { .set_key = wl1271_op_set_key, .hw_scan = wl1271_op_hw_scan, .bss_info_changed = wl1271_op_bss_info_changed, + .set_frag_threshold = wl1271_op_set_frag_threshold, .set_rts_threshold = wl1271_op_set_rts_threshold, .conf_tx = wl1271_op_conf_tx, .get_tsf = wl1271_op_get_tsf, @@ -2281,18 +2497,18 @@ static const struct ieee80211_ops wl1271_ops = { }; -u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate) +u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band) { u8 idx; - BUG_ON(wl->band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); + BUG_ON(band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) { wl1271_error("Illegal RX rate from HW: %d", rate); return 0; } - idx = wl1271_band_rate_to_idx[wl->band][rate]; + idx = wl1271_band_rate_to_idx[band][rate]; if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) { wl1271_error("Unsupported RX rate from HW: %d", rate); return 0; @@ -2401,6 +2617,8 @@ int wl1271_register_hw(struct wl1271 *wl) wl->mac80211_registered = true; + wl1271_debugfs_init(wl); + register_netdevice_notifier(&wl1271_dev_notifier); wl1271_notice("loaded"); @@ -2451,12 +2669,21 @@ int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); wl->hw->wiphy->max_scan_ssids = 1; + /* + * Maximum length of elements in scanning probe request templates + * should be the maximum length possible for a template, without + * the IEEE80211 header of the template + */ + wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - + sizeof(struct ieee80211_header); wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; wl->hw->queues = 4; wl->hw->max_rates = 1; + wl->hw->wiphy->reg_notifier = wl1271_reg_notify; + SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); return 0; @@ -2495,7 +2722,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->hw = hw; wl->plat_dev = plat_dev; - skb_queue_head_init(&wl->tx_queue); + for (i = 0; i < NUM_TX_QUEUES; i++) + skb_queue_head_init(&wl->tx_queue[i]); INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); @@ -2521,6 +2749,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->sg_enabled = true; wl->hw_pg_ver = -1; + memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); for (i = 0; i < ACX_TX_DESCRIPTORS; i++) wl->tx_frames[i] = NULL; @@ -2532,8 +2761,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) /* Apply default driver configuration. */ wl1271_conf_init(wl); - wl1271_debugfs_init(wl); - order = get_order(WL1271_AGGR_BUFFER_SIZE); wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); if (!wl->aggr_buf) { @@ -2610,6 +2837,11 @@ int wl1271_free_hw(struct wl1271 *wl) } EXPORT_SYMBOL_GPL(wl1271_free_hw); +u32 wl12xx_debug_level; +EXPORT_SYMBOL_GPL(wl12xx_debug_level); +module_param_named(debug_level, wl12xx_debug_level, uint, DEBUG_NONE); +MODULE_PARM_DESC(debug_level, "wl12xx debugging level"); + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/ps.c index e3c332e2f97c..60a3738eadb0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -21,9 +21,9 @@ * */ -#include "wl1271_reg.h" -#include "wl1271_ps.h" -#include "wl1271_io.h" +#include "reg.h" +#include "ps.h" +#include "io.h" #define WL1271_WAKEUP_TIMEOUT 500 diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/ps.h index 6ba7b032736f..8415060f08e5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.h +++ b/drivers/net/wireless/wl12xx/ps.h @@ -21,11 +21,11 @@ * */ -#ifndef __WL1271_PS_H__ -#define __WL1271_PS_H__ +#ifndef __PS_H__ +#define __PS_H__ -#include "wl1271.h" -#include "wl1271_acx.h" +#include "wl12xx.h" +#include "acx.h" int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, u32 rates, bool send); diff --git a/drivers/net/wireless/wl12xx/wl1271_reg.h b/drivers/net/wireless/wl12xx/reg.h index 990960771528..990960771528 100644 --- a/drivers/net/wireless/wl12xx/wl1271_reg.h +++ b/drivers/net/wireless/wl12xx/reg.h diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/rx.c index bea133b6e489..682304c30b81 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -23,11 +23,11 @@ #include <linux/gfp.h> -#include "wl1271.h" -#include "wl1271_acx.h" -#include "wl1271_reg.h" -#include "wl1271_rx.h" -#include "wl1271_io.h" +#include "wl12xx.h" +#include "acx.h" +#include "reg.h" +#include "rx.h" +#include "io.h" static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, u32 drv_rx_counter) @@ -48,10 +48,24 @@ static void wl1271_rx_status(struct wl1271 *wl, struct ieee80211_rx_status *status, u8 beacon) { + enum ieee80211_band desc_band; + memset(status, 0, sizeof(struct ieee80211_rx_status)); status->band = wl->band; - status->rate_idx = wl1271_rate_to_idx(wl, desc->rate); + + if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG) + desc_band = IEEE80211_BAND_2GHZ; + else + desc_band = IEEE80211_BAND_5GHZ; + + status->rate_idx = wl1271_rate_to_idx(desc->rate, desc_band); + +#ifdef CONFIG_WL12XX_HT + /* 11n support */ + if (desc->rate <= CONF_HW_RXTX_RATE_MCS0) + status->flag |= RX_FLAG_HT; +#endif status->signal = desc->rssi; @@ -170,10 +184,14 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) while (pkt_offset < buf_size) { pkt_length = wl1271_rx_get_buf_size(status, drv_rx_counter); - if (wl1271_rx_handle_data(wl, - wl->aggr_buf + pkt_offset, - pkt_length) < 0) - break; + /* + * the handle data call can only fail in memory-outage + * conditions, in that case the received frame will just + * be dropped. + */ + wl1271_rx_handle_data(wl, + wl->aggr_buf + pkt_offset, + pkt_length); wl->rx_counter++; drv_rx_counter++; drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.h b/drivers/net/wireless/wl12xx/rx.h index 13a232333b13..3abb26fe0364 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.h +++ b/drivers/net/wireless/wl12xx/rx.h @@ -22,8 +22,8 @@ * */ -#ifndef __WL1271_RX_H__ -#define __WL1271_RX_H__ +#ifndef __RX_H__ +#define __RX_H__ #include <linux/bitops.h> @@ -116,6 +116,6 @@ struct wl1271_rx_descriptor { } __packed; void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); -u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); +u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); #endif diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/scan.c index 909bb47995b6..6f897b9d90ca 100644 --- a/drivers/net/wireless/wl12xx/wl1271_scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -23,10 +23,10 @@ #include <linux/ieee80211.h> -#include "wl1271.h" -#include "wl1271_cmd.h" -#include "wl1271_scan.h" -#include "wl1271_acx.h" +#include "wl12xx.h" +#include "cmd.h" +#include "scan.h" +#include "acx.h" void wl1271_scan_complete_work(struct work_struct *work) { @@ -48,14 +48,19 @@ void wl1271_scan_complete_work(struct work_struct *work) wl->scan.state = WL1271_SCAN_STATE_IDLE; kfree(wl->scan.scanned_ch); wl->scan.scanned_ch = NULL; - mutex_unlock(&wl->mutex); - + wl->scan.req = NULL; ieee80211_scan_completed(wl->hw, false); + /* restore hardware connection monitoring template */ + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + wl1271_cmd_build_ap_probe_req(wl, wl->probereq); + if (wl->scan.failed) { wl1271_info("Scan completed due to error."); ieee80211_queue_work(wl->hw, &wl->recovery_work); } + mutex_unlock(&wl->mutex); + } diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.h b/drivers/net/wireless/wl12xx/scan.h index 6d57127b5e6b..421a750add5a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_scan.h +++ b/drivers/net/wireless/wl12xx/scan.h @@ -21,10 +21,10 @@ * */ -#ifndef __WL1271_SCAN_H__ -#define __WL1271_SCAN_H__ +#ifndef __SCAN_H__ +#define __SCAN_H__ -#include "wl1271.h" +#include "wl12xx.h" int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, struct cfg80211_scan_request *req); diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 784ef3432641..93cbb8d5aba9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -32,9 +32,9 @@ #include <linux/wl12xx.h> #include <linux/pm_runtime.h> -#include "wl1271.h" +#include "wl12xx.h" #include "wl12xx_80211.h" -#include "wl1271_io.h" +#include "io.h" #ifndef SDIO_VENDOR_ID_TI #define SDIO_VENDOR_ID_TI 0x0097 diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c new file mode 100644 index 000000000000..9fcbd3dd8490 --- /dev/null +++ b/drivers/net/wireless/wl12xx/sdio_test.c @@ -0,0 +1,520 @@ +/* + * SDIO testing driver for wl12xx + * + * Copyright (C) 2010 Nokia Corporation + * + * Contact: Roger Quadros <roger.quadros@nokia.com> + * + * wl12xx read/write routines taken from the main module + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/crc7.h> +#include <linux/vmalloc.h> +#include <linux/mmc/sdio_func.h> +#include <linux/mmc/sdio_ids.h> +#include <linux/mmc/card.h> +#include <linux/gpio.h> +#include <linux/wl12xx.h> +#include <linux/kthread.h> +#include <linux/firmware.h> +#include <linux/pm_runtime.h> + +#include "wl12xx.h" +#include "io.h" +#include "boot.h" + +#ifndef SDIO_VENDOR_ID_TI +#define SDIO_VENDOR_ID_TI 0x0097 +#endif + +#ifndef SDIO_DEVICE_ID_TI_WL1271 +#define SDIO_DEVICE_ID_TI_WL1271 0x4076 +#endif + +static bool rx, tx; + +module_param(rx, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(rx, "Perform rx test. Default (0). " + "This test continuously reads data from the SDIO device.\n"); + +module_param(tx, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(tx, "Perform tx test. Default (0). " + "This test continuously writes data to the SDIO device.\n"); + +struct wl1271_test { + struct wl1271 wl; + struct task_struct *test_task; +}; + +static const struct sdio_device_id wl1271_devices[] = { + { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) }, + {} +}; + +static inline struct sdio_func *wl_to_func(struct wl1271 *wl) +{ + return wl->if_priv; +} + +static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl) +{ + return &(wl_to_func(wl)->dev); +} + +static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed) +{ + int ret = 0; + struct sdio_func *func = wl_to_func(wl); + + if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { + ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); + wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", + addr, ((u8 *)buf)[0]); + } else { + if (fixed) + ret = sdio_readsb(func, buf, addr, len); + else + ret = sdio_memcpy_fromio(func, buf, addr, len); + + wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes", + addr, len); + wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); + } + + if (ret) + wl1271_error("sdio read failed (%d)", ret); +} + +static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed) +{ + int ret = 0; + struct sdio_func *func = wl_to_func(wl); + + if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { + sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); + wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", + addr, ((u8 *)buf)[0]); + } else { + wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %zu bytes", + addr, len); + wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); + + if (fixed) + ret = sdio_writesb(func, addr, buf, len); + else + ret = sdio_memcpy_toio(func, addr, buf, len); + } + if (ret) + wl1271_error("sdio write failed (%d)", ret); + +} + +static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable) +{ + struct sdio_func *func = wl_to_func(wl); + int ret; + + /* Let the SDIO stack handle wlan_enable control, so we + * keep host claimed while wlan is in use to keep wl1271 + * alive. + */ + if (enable) { + /* Power up the card */ + ret = pm_runtime_get_sync(&func->dev); + if (ret < 0) + goto out; + sdio_claim_host(func); + sdio_enable_func(func); + sdio_release_host(func); + } else { + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); + + /* Power down the card */ + ret = pm_runtime_put_sync(&func->dev); + } + +out: + return ret; +} + +static void wl1271_sdio_disable_interrupts(struct wl1271 *wl) +{ +} + +static void wl1271_sdio_enable_interrupts(struct wl1271 *wl) +{ +} + + +static struct wl1271_if_operations sdio_ops = { + .read = wl1271_sdio_raw_read, + .write = wl1271_sdio_raw_write, + .power = wl1271_sdio_set_power, + .dev = wl1271_sdio_wl_to_dev, + .enable_irq = wl1271_sdio_enable_interrupts, + .disable_irq = wl1271_sdio_disable_interrupts, +}; + +static void wl1271_fw_wakeup(struct wl1271 *wl) +{ + u32 elp_reg; + + elp_reg = ELPCTRL_WAKE_UP; + wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); +} + +static int wl1271_fetch_firmware(struct wl1271 *wl) +{ + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); + + if (ret < 0) { + wl1271_error("could not get firmware: %d", ret); + return ret; + } + + if (fw->size % 4) { + wl1271_error("firmware size is not multiple of 32 bits: %zu", + fw->size); + ret = -EILSEQ; + goto out; + } + + wl->fw_len = fw->size; + wl->fw = vmalloc(wl->fw_len); + + if (!wl->fw) { + wl1271_error("could not allocate memory for the firmware"); + ret = -ENOMEM; + goto out; + } + + memcpy(wl->fw, fw->data, wl->fw_len); + + ret = 0; + +out: + release_firmware(fw); + + return ret; +} + +static int wl1271_fetch_nvs(struct wl1271 *wl) +{ + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); + + if (ret < 0) { + wl1271_error("could not get nvs file: %d", ret); + return ret; + } + + wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); + + if (!wl->nvs) { + wl1271_error("could not allocate memory for the nvs file"); + ret = -ENOMEM; + goto out; + } + + wl->nvs_len = fw->size; + +out: + release_firmware(fw); + + return ret; +} + +static int wl1271_chip_wakeup(struct wl1271 *wl) +{ + struct wl1271_partition_set partition; + int ret; + + msleep(WL1271_PRE_POWER_ON_SLEEP); + ret = wl1271_power_on(wl); + if (ret) + return ret; + + msleep(WL1271_POWER_ON_SLEEP); + + /* We don't need a real memory partition here, because we only want + * to use the registers at this point. */ + memset(&partition, 0, sizeof(partition)); + partition.reg.start = REGISTERS_BASE; + partition.reg.size = REGISTERS_DOWN_SIZE; + wl1271_set_partition(wl, &partition); + + /* ELP module wake up */ + wl1271_fw_wakeup(wl); + + /* whal_FwCtrl_BootSm() */ + + /* 0. read chip id from CHIP_ID */ + wl->chip.id = wl1271_read32(wl, CHIP_ID_B); + + /* 1. check if chip id is valid */ + + switch (wl->chip.id) { + case CHIP_ID_1271_PG10: + wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", + wl->chip.id); + break; + case CHIP_ID_1271_PG20: + wl1271_notice("chip id 0x%x (1271 PG20)", + wl->chip.id); + break; + default: + wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); + return -ENODEV; + } + + return ret; +} + +static struct wl1271_partition_set part_down = { + .mem = { + .start = 0x00000000, + .size = 0x000177c0 + }, + .reg = { + .start = REGISTERS_BASE, + .size = 0x00008800 + }, + .mem2 = { + .start = 0x00000000, + .size = 0x00000000 + }, + .mem3 = { + .start = 0x00000000, + .size = 0x00000000 + }, +}; + +static int tester(void *data) +{ + struct wl1271 *wl = data; + struct sdio_func *func = wl_to_func(wl); + struct device *pdev = &func->dev; + int ret = 0; + bool rx_started = 0; + bool tx_started = 0; + uint8_t *tx_buf, *rx_buf; + int test_size = PAGE_SIZE; + u32 addr = 0; + struct wl1271_partition_set partition; + + /* We assume chip is powered up and firmware fetched */ + + memcpy(&partition, &part_down, sizeof(partition)); + partition.mem.start = addr; + wl1271_set_partition(wl, &partition); + + tx_buf = kmalloc(test_size, GFP_KERNEL); + rx_buf = kmalloc(test_size, GFP_KERNEL); + if (!tx_buf || !rx_buf) { + dev_err(pdev, + "Could not allocate memory. Test will not run.\n"); + ret = -ENOMEM; + goto free; + } + + memset(tx_buf, 0x5a, test_size); + + /* write something in data area so we can read it back */ + wl1271_write(wl, addr, tx_buf, test_size, false); + + while (!kthread_should_stop()) { + if (rx && !rx_started) { + dev_info(pdev, "starting rx test\n"); + rx_started = 1; + } else if (!rx && rx_started) { + dev_info(pdev, "stopping rx test\n"); + rx_started = 0; + } + + if (tx && !tx_started) { + dev_info(pdev, "starting tx test\n"); + tx_started = 1; + } else if (!tx && tx_started) { + dev_info(pdev, "stopping tx test\n"); + tx_started = 0; + } + + if (rx_started) + wl1271_read(wl, addr, rx_buf, test_size, false); + + if (tx_started) + wl1271_write(wl, addr, tx_buf, test_size, false); + + if (!rx_started && !tx_started) + msleep(100); + } + +free: + kfree(tx_buf); + kfree(rx_buf); + return ret; +} + +static int __devinit wl1271_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + const struct wl12xx_platform_data *wlan_data; + struct wl1271 *wl; + struct wl1271_test *wl_test; + int ret = 0; + + /* wl1271 has 2 sdio functions we handle just the wlan part */ + if (func->num != 0x02) + return -ENODEV; + + wl_test = kzalloc(sizeof(struct wl1271_test), GFP_KERNEL); + if (!wl_test) { + dev_err(&func->dev, "Could not allocate memory\n"); + return -ENOMEM; + } + + wl = &wl_test->wl; + + wl->if_priv = func; + wl->if_ops = &sdio_ops; + + /* Grab access to FN0 for ELP reg. */ + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + + wlan_data = wl12xx_get_platform_data(); + if (IS_ERR(wlan_data)) { + ret = PTR_ERR(wlan_data); + dev_err(&func->dev, "missing wlan platform data: %d\n", ret); + goto out_free; + } + + wl->irq = wlan_data->irq; + wl->ref_clock = wlan_data->board_ref_clock; + + sdio_set_drvdata(func, wl_test); + + + /* power up the device */ + ret = wl1271_chip_wakeup(wl); + if (ret) { + dev_err(&func->dev, "could not wake up chip\n"); + goto out_free; + } + + if (wl->fw == NULL) { + ret = wl1271_fetch_firmware(wl); + if (ret < 0) { + dev_err(&func->dev, "firmware fetch error\n"); + goto out_off; + } + } + + /* fetch NVS */ + if (wl->nvs == NULL) { + ret = wl1271_fetch_nvs(wl); + if (ret < 0) { + dev_err(&func->dev, "NVS fetch error\n"); + goto out_off; + } + } + + ret = wl1271_load_firmware(wl); + if (ret < 0) { + dev_err(&func->dev, "firmware load error: %d\n", ret); + goto out_free; + } + + dev_info(&func->dev, "initialized\n"); + + /* I/O testing will be done in the tester thread */ + + wl_test->test_task = kthread_run(tester, wl, "sdio_tester"); + if (IS_ERR(wl_test->test_task)) { + dev_err(&func->dev, "unable to create kernel thread\n"); + ret = PTR_ERR(wl_test->test_task); + goto out_free; + } + + return 0; + +out_off: + /* power off the chip */ + wl1271_power_off(wl); + +out_free: + kfree(wl_test); + return ret; +} + +static void __devexit wl1271_remove(struct sdio_func *func) +{ + struct wl1271_test *wl_test = sdio_get_drvdata(func); + + /* stop the I/O test thread */ + kthread_stop(wl_test->test_task); + + /* power off the chip */ + wl1271_power_off(&wl_test->wl); + + vfree(wl_test->wl.fw); + wl_test->wl.fw = NULL; + kfree(wl_test->wl.nvs); + wl_test->wl.nvs = NULL; + + kfree(wl_test); +} + +static struct sdio_driver wl1271_sdio_driver = { + .name = "wl12xx_sdio_test", + .id_table = wl1271_devices, + .probe = wl1271_probe, + .remove = __devexit_p(wl1271_remove), +}; + +static int __init wl1271_init(void) +{ + int ret; + + ret = sdio_register_driver(&wl1271_sdio_driver); + if (ret < 0) + pr_err("failed to register sdio driver: %d\n", ret); + + return ret; +} +module_init(wl1271_init); + +static void __exit wl1271_exit(void) +{ + sdio_unregister_driver(&wl1271_sdio_driver); +} +module_exit(wl1271_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Roger Quadros <roger.quadros@nokia.com>"); + diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/spi.c index ef801680773f..46714910f98c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -28,11 +28,11 @@ #include <linux/wl12xx.h> #include <linux/slab.h> -#include "wl1271.h" +#include "wl12xx.h" #include "wl12xx_80211.h" -#include "wl1271_io.h" +#include "io.h" -#include "wl1271_reg.h" +#include "reg.h" #define WSPI_CMD_READ 0x40000000 #define WSPI_CMD_WRITE 0x00000000 diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/testmode.c index a3aa84386c88..e64403b6896d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c @@ -20,13 +20,13 @@ * 02110-1301 USA * */ -#include "wl1271_testmode.h" +#include "testmode.h" #include <linux/slab.h> #include <net/genetlink.h> -#include "wl1271.h" -#include "wl1271_acx.h" +#include "wl12xx.h" +#include "acx.h" #define WL1271_TM_MAX_DATA_LENGTH 1024 @@ -37,6 +37,7 @@ enum wl1271_tm_commands { WL1271_TM_CMD_CONFIGURE, WL1271_TM_CMD_NVS_PUSH, WL1271_TM_CMD_SET_PLT_MODE, + WL1271_TM_CMD_RECOVER, __WL1271_TM_CMD_AFTER_LAST }; @@ -248,6 +249,15 @@ static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[]) return ret; } +static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[]) +{ + wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover"); + + ieee80211_queue_work(wl->hw, &wl->recovery_work); + + return 0; +} + int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) { struct wl1271 *wl = hw->priv; @@ -272,6 +282,8 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) return wl1271_tm_cmd_nvs_push(wl, tb); case WL1271_TM_CMD_SET_PLT_MODE: return wl1271_tm_cmd_set_plt_mode(wl, tb); + case WL1271_TM_CMD_RECOVER: + return wl1271_tm_cmd_recover(wl, tb); default: return -EOPNOTSUPP; } diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.h b/drivers/net/wireless/wl12xx/testmode.h index c196d28f9d9d..8071654259ea 100644 --- a/drivers/net/wireless/wl12xx/wl1271_testmode.h +++ b/drivers/net/wireless/wl12xx/testmode.h @@ -21,8 +21,8 @@ * */ -#ifndef __WL1271_TESTMODE_H__ -#define __WL1271_TESTMODE_H__ +#ifndef __TESTMODE_H__ +#define __TESTMODE_H__ #include <net/mac80211.h> diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/tx.c index e3dc13c4d01a..b44c75cd8c1e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -24,23 +24,32 @@ #include <linux/kernel.h> #include <linux/module.h> -#include "wl1271.h" -#include "wl1271_io.h" -#include "wl1271_reg.h" -#include "wl1271_ps.h" -#include "wl1271_tx.h" +#include "wl12xx.h" +#include "io.h" +#include "reg.h" +#include "ps.h" +#include "tx.h" -static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb) +static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb) { - int i; - for (i = 0; i < ACX_TX_DESCRIPTORS; i++) - if (wl->tx_frames[i] == NULL) { - wl->tx_frames[i] = skb; - wl->tx_frames_cnt++; - return i; - } + int id; + + id = find_first_zero_bit(wl->tx_frames_map, ACX_TX_DESCRIPTORS); + if (id >= ACX_TX_DESCRIPTORS) + return -EBUSY; - return -EBUSY; + __set_bit(id, wl->tx_frames_map); + wl->tx_frames[id] = skb; + wl->tx_frames_cnt++; + return id; +} + +static void wl1271_free_tx_id(struct wl1271 *wl, int id) +{ + if (__test_and_clear_bit(id, wl->tx_frames_map)) { + wl->tx_frames[id] = NULL; + wl->tx_frames_cnt--; + } } static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, @@ -52,10 +61,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, int id, ret = -EBUSY; if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) - return -EBUSY; + return -EAGAIN; /* allocate free identifier for the packet */ - id = wl1271_tx_id(wl, skb); + id = wl1271_alloc_tx_id(wl, skb); if (id < 0) return id; @@ -79,8 +88,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, "tx_allocate: size: %d, blocks: %d, id: %d", total_len, total_blocks, id); } else { - wl->tx_frames[id] = NULL; - wl->tx_frames_cnt--; + wl1271_free_tx_id(wl, id); } return ret; @@ -117,7 +125,6 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, /* queue (we use same identifiers for tid's and ac's */ ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); desc->tid = ac; - desc->aid = TX_HW_DEFAULT_AID; desc->reserved = 0; @@ -201,42 +208,105 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) rate_set >>= 1; } +#ifdef CONFIG_WL12XX_HT + /* MCS rates indication are on bits 16 - 23 */ + rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates; + + for (bit = 0; bit < 8; bit++) { + if (rate_set & 0x1) + enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit); + rate_set >>= 1; + } +#endif + return enabled_rates; } -void wl1271_tx_work(struct work_struct *work) +static void handle_tx_low_watermark(struct wl1271 *wl) +{ + unsigned long flags; + + if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && + wl->tx_queue_count <= WL1271_TX_QUEUE_LOW_WATERMARK) { + /* firmware buffer has space, restart queues */ + spin_lock_irqsave(&wl->wl_lock, flags); + ieee80211_wake_queues(wl->hw); + clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); + spin_unlock_irqrestore(&wl->wl_lock, flags); + } +} + +static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) +{ + struct sk_buff *skb = NULL; + unsigned long flags; + + skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]); + if (skb) + goto out; + skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]); + if (skb) + goto out; + skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]); + if (skb) + goto out; + skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]); + +out: + if (skb) { + spin_lock_irqsave(&wl->wl_lock, flags); + wl->tx_queue_count--; + spin_unlock_irqrestore(&wl->wl_lock, flags); + } + + return skb; +} + +static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) +{ + unsigned long flags; + int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); + + skb_queue_head(&wl->tx_queue[q], skb); + spin_lock_irqsave(&wl->wl_lock, flags); + wl->tx_queue_count++; + spin_unlock_irqrestore(&wl->wl_lock, flags); +} + +void wl1271_tx_work_locked(struct wl1271 *wl) { - struct wl1271 *wl = container_of(work, struct wl1271, tx_work); struct sk_buff *skb; bool woken_up = false; u32 sta_rates = 0; - u32 buf_offset; + u32 buf_offset = 0; + bool sent_packets = false; int ret; /* check if the rates supported by the AP have changed */ if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags))) { unsigned long flags; + spin_lock_irqsave(&wl->wl_lock, flags); sta_rates = wl->sta_rate_set; spin_unlock_irqrestore(&wl->wl_lock, flags); } - mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; /* if rates have changed, re-configure the rate policy */ if (unlikely(sta_rates)) { + ret = wl1271_ps_elp_wakeup(wl, false); + if (ret < 0) + goto out; + woken_up = true; + wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); wl1271_acx_rate_policies(wl); } - /* Prepare the transfer buffer, by aggregating all - * available packets */ - buf_offset = 0; - while ((skb = skb_dequeue(&wl->tx_queue))) { + while ((skb = wl1271_skb_dequeue(wl))) { if (!woken_up) { ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) @@ -245,13 +315,25 @@ void wl1271_tx_work(struct work_struct *work) } ret = wl1271_prepare_tx_frame(wl, skb, buf_offset); - if (ret == -EBUSY) { + if (ret == -EAGAIN) { + /* + * Aggregation buffer is full. + * Flush buffer and try again. + */ + wl1271_skb_queue_head(wl, skb); + wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, + buf_offset, true); + sent_packets = true; + buf_offset = 0; + continue; + } else if (ret == -EBUSY) { /* - * Either the firmware buffer is full, or the - * aggregation buffer is. + * Firmware buffer is full. * Queue back last skb, and stop aggregating. */ - skb_queue_head(&wl->tx_queue, skb); + wl1271_skb_queue_head(wl, skb); + /* No work left, avoid scheduling redundant tx work */ + set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); goto out_ack; } else if (ret < 0) { dev_kfree_skb(skb); @@ -265,14 +347,25 @@ out_ack: if (buf_offset) { wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, buf_offset, true); + sent_packets = true; + } + if (sent_packets) { /* interrupt the firmware with the new packets */ wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); + handle_tx_low_watermark(wl); } out: if (woken_up) wl1271_ps_elp_sleep(wl); +} +void wl1271_tx_work(struct work_struct *work) +{ + struct wl1271 *wl = container_of(work, struct wl1271, tx_work); + + mutex_lock(&wl->mutex); + wl1271_tx_work_locked(wl); mutex_unlock(&wl->mutex); } @@ -298,7 +391,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, if (result->status == TX_SUCCESS) { if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) info->flags |= IEEE80211_TX_STAT_ACK; - rate = wl1271_rate_to_idx(wl, result->rate_class_index); + rate = wl1271_rate_to_idx(result->rate_class_index, wl->band); retries = result->ack_failures; } else if (result->status == TX_RETRY_EXCEEDED) { wl->stats.excessive_retries++; @@ -335,8 +428,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, /* return the packet to the stack */ ieee80211_tx_status(wl->hw, skb); - wl->tx_frames[result->id] = NULL; - wl->tx_frames_cnt--; + wl1271_free_tx_id(wl, result->id); } /* Called upon reception of a TX complete interrupt */ @@ -375,19 +467,6 @@ void wl1271_tx_complete(struct wl1271 *wl) wl->tx_results_count++; } - - if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && - skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) { - unsigned long flags; - - /* firmware buffer has space, restart queues */ - wl1271_debug(DEBUG_TX, "tx_complete: waking queues"); - spin_lock_irqsave(&wl->wl_lock, flags); - ieee80211_wake_queues(wl->hw); - clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); - spin_unlock_irqrestore(&wl->wl_lock, flags); - ieee80211_queue_work(wl->hw, &wl->tx_work); - } } /* caller must hold wl->mutex */ @@ -397,19 +476,27 @@ void wl1271_tx_reset(struct wl1271 *wl) struct sk_buff *skb; /* TX failure */ - while ((skb = skb_dequeue(&wl->tx_queue))) { - wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); - ieee80211_tx_status(wl->hw, skb); + for (i = 0; i < NUM_TX_QUEUES; i++) { + while ((skb = skb_dequeue(&wl->tx_queue[i]))) { + wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); + ieee80211_tx_status(wl->hw, skb); + } } + wl->tx_queue_count = 0; + + /* + * Make sure the driver is at a consistent state, in case this + * function is called from a context other than interface removal. + */ + handle_tx_low_watermark(wl); for (i = 0; i < ACX_TX_DESCRIPTORS; i++) if (wl->tx_frames[i] != NULL) { skb = wl->tx_frames[i]; - wl->tx_frames[i] = NULL; + wl1271_free_tx_id(wl, i); wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); ieee80211_tx_status(wl->hw, skb); } - wl->tx_frames_cnt = 0; } #define WL1271_TX_FLUSH_TIMEOUT 500000 @@ -424,8 +511,7 @@ void wl1271_tx_flush(struct wl1271 *wl) mutex_lock(&wl->mutex); wl1271_debug(DEBUG_TX, "flushing tx buffer: %d", wl->tx_frames_cnt); - if ((wl->tx_frames_cnt == 0) && - skb_queue_empty(&wl->tx_queue)) { + if ((wl->tx_frames_cnt == 0) && (wl->tx_queue_count == 0)) { mutex_unlock(&wl->mutex); return; } diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/tx.h index d12a129ad11c..903e5dc69b7a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -22,8 +22,8 @@ * */ -#ifndef __WL1271_TX_H__ -#define __WL1271_TX_H__ +#ifndef __TX_H__ +#define __TX_H__ #define TX_HW_BLOCK_SPARE 2 #define TX_HW_BLOCK_SIZE 252 @@ -140,10 +140,11 @@ static inline int wl1271_tx_get_queue(int queue) } void wl1271_tx_work(struct work_struct *work); +void wl1271_tx_work_locked(struct wl1271 *wl); void wl1271_tx_complete(struct wl1271 *wl); void wl1271_tx_reset(struct wl1271 *wl); void wl1271_tx_flush(struct wl1271 *wl); -u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); +u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); #endif diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c deleted file mode 100644 index 66c2b90ddfd4..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Luciano Coelho <luciano.coelho@nokia.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "wl1271_debugfs.h" - -#include <linux/skbuff.h> -#include <linux/slab.h> - -#include "wl1271.h" -#include "wl1271_acx.h" -#include "wl1271_ps.h" -#include "wl1271_io.h" - -/* ms */ -#define WL1271_DEBUGFS_STATS_LIFETIME 1000 - -/* debugfs macros idea from mac80211 */ - -#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ -static ssize_t name## _read(struct file *file, char __user *userbuf, \ - size_t count, loff_t *ppos) \ -{ \ - struct wl1271 *wl = file->private_data; \ - char buf[buflen]; \ - int res; \ - \ - res = scnprintf(buf, buflen, fmt "\n", ##value); \ - return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ -} \ - \ -static const struct file_operations name## _ops = { \ - .read = name## _read, \ - .open = wl1271_open_file_generic, \ - .llseek = generic_file_llseek, \ -}; - -#define DEBUGFS_ADD(name, parent) \ - wl->debugfs.name = debugfs_create_file(#name, 0400, parent, \ - wl, &name## _ops); \ - if (IS_ERR(wl->debugfs.name)) { \ - ret = PTR_ERR(wl->debugfs.name); \ - wl->debugfs.name = NULL; \ - goto out; \ - } - -#define DEBUGFS_DEL(name) \ - do { \ - debugfs_remove(wl->debugfs.name); \ - wl->debugfs.name = NULL; \ - } while (0) - -#define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt) \ -static ssize_t sub## _ ##name## _read(struct file *file, \ - char __user *userbuf, \ - size_t count, loff_t *ppos) \ -{ \ - struct wl1271 *wl = file->private_data; \ - char buf[buflen]; \ - int res; \ - \ - wl1271_debugfs_update_stats(wl); \ - \ - res = scnprintf(buf, buflen, fmt "\n", \ - wl->stats.fw_stats->sub.name); \ - return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ -} \ - \ -static const struct file_operations sub## _ ##name## _ops = { \ - .read = sub## _ ##name## _read, \ - .open = wl1271_open_file_generic, \ - .llseek = generic_file_llseek, \ -}; - -#define DEBUGFS_FWSTATS_ADD(sub, name) \ - DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics) - -#define DEBUGFS_FWSTATS_DEL(sub, name) \ - DEBUGFS_DEL(sub## _ ##name) - -static void wl1271_debugfs_update_stats(struct wl1271 *wl) -{ - int ret; - - mutex_lock(&wl->mutex); - - ret = wl1271_ps_elp_wakeup(wl, false); - if (ret < 0) - goto out; - - if (wl->state == WL1271_STATE_ON && - time_after(jiffies, wl->stats.fw_stats_update + - msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) { - wl1271_acx_statistics(wl, wl->stats.fw_stats); - wl->stats.fw_stats_update = jiffies; - } - - wl1271_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); -} - -static int wl1271_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u"); -DEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u"); -DEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u"); -DEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u"); -/* skipping wep.reserved */ -DEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u"); -/* skipping cont_miss_bcns_spread for now */ -DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u"); -DEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data, - 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u"); - -DEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count); -DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u", - wl->stats.excessive_retries); - -static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - u32 queue_len; - char buf[20]; - int res; - - queue_len = skb_queue_len(&wl->tx_queue); - - res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); - return simple_read_from_buffer(userbuf, count, ppos, buf, res); -} - -static const struct file_operations tx_queue_len_ops = { - .read = tx_queue_len_read, - .open = wl1271_open_file_generic, - .llseek = default_llseek, -}; - -static ssize_t gpio_power_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - bool state = test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); - - int res; - char buf[10]; - - res = scnprintf(buf, sizeof(buf), "%d\n", state); - - return simple_read_from_buffer(user_buf, count, ppos, buf, res); -} - -static ssize_t gpio_power_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - char buf[10]; - size_t len; - unsigned long value; - int ret; - - mutex_lock(&wl->mutex); - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) { - ret = -EFAULT; - goto out; - } - buf[len] = '\0'; - - ret = strict_strtoul(buf, 0, &value); - if (ret < 0) { - wl1271_warning("illegal value in gpio_power"); - goto out; - } - - if (value) - wl1271_power_on(wl); - else - wl1271_power_off(wl); - -out: - mutex_unlock(&wl->mutex); - return count; -} - -static const struct file_operations gpio_power_ops = { - .read = gpio_power_read, - .write = gpio_power_write, - .open = wl1271_open_file_generic, - .llseek = default_llseek, -}; - -static void wl1271_debugfs_delete_files(struct wl1271 *wl) -{ - DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); - - DEBUGFS_FWSTATS_DEL(rx, out_of_mem); - DEBUGFS_FWSTATS_DEL(rx, hdr_overflow); - DEBUGFS_FWSTATS_DEL(rx, hw_stuck); - DEBUGFS_FWSTATS_DEL(rx, dropped); - DEBUGFS_FWSTATS_DEL(rx, fcs_err); - DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig); - DEBUGFS_FWSTATS_DEL(rx, path_reset); - DEBUGFS_FWSTATS_DEL(rx, reset_counter); - - DEBUGFS_FWSTATS_DEL(dma, rx_requested); - DEBUGFS_FWSTATS_DEL(dma, rx_errors); - DEBUGFS_FWSTATS_DEL(dma, tx_requested); - DEBUGFS_FWSTATS_DEL(dma, tx_errors); - - DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt); - DEBUGFS_FWSTATS_DEL(isr, fiqs); - DEBUGFS_FWSTATS_DEL(isr, rx_headers); - DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow); - DEBUGFS_FWSTATS_DEL(isr, rx_rdys); - DEBUGFS_FWSTATS_DEL(isr, irqs); - DEBUGFS_FWSTATS_DEL(isr, tx_procs); - DEBUGFS_FWSTATS_DEL(isr, decrypt_done); - DEBUGFS_FWSTATS_DEL(isr, dma0_done); - DEBUGFS_FWSTATS_DEL(isr, dma1_done); - DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete); - DEBUGFS_FWSTATS_DEL(isr, commands); - DEBUGFS_FWSTATS_DEL(isr, rx_procs); - DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes); - DEBUGFS_FWSTATS_DEL(isr, host_acknowledges); - DEBUGFS_FWSTATS_DEL(isr, pci_pm); - DEBUGFS_FWSTATS_DEL(isr, wakeups); - DEBUGFS_FWSTATS_DEL(isr, low_rssi); - - DEBUGFS_FWSTATS_DEL(wep, addr_key_count); - DEBUGFS_FWSTATS_DEL(wep, default_key_count); - /* skipping wep.reserved */ - DEBUGFS_FWSTATS_DEL(wep, key_not_found); - DEBUGFS_FWSTATS_DEL(wep, decrypt_fail); - DEBUGFS_FWSTATS_DEL(wep, packets); - DEBUGFS_FWSTATS_DEL(wep, interrupt); - - DEBUGFS_FWSTATS_DEL(pwr, ps_enter); - DEBUGFS_FWSTATS_DEL(pwr, elp_enter); - DEBUGFS_FWSTATS_DEL(pwr, missing_bcns); - DEBUGFS_FWSTATS_DEL(pwr, wake_on_host); - DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp); - DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps); - DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps); - DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons); - DEBUGFS_FWSTATS_DEL(pwr, power_save_off); - DEBUGFS_FWSTATS_DEL(pwr, enable_ps); - DEBUGFS_FWSTATS_DEL(pwr, disable_ps); - DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps); - /* skipping cont_miss_bcns_spread for now */ - DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons); - - DEBUGFS_FWSTATS_DEL(mic, rx_pkts); - DEBUGFS_FWSTATS_DEL(mic, calc_failure); - - DEBUGFS_FWSTATS_DEL(aes, encrypt_fail); - DEBUGFS_FWSTATS_DEL(aes, decrypt_fail); - DEBUGFS_FWSTATS_DEL(aes, encrypt_packets); - DEBUGFS_FWSTATS_DEL(aes, decrypt_packets); - DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt); - DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt); - - DEBUGFS_FWSTATS_DEL(event, heart_beat); - DEBUGFS_FWSTATS_DEL(event, calibration); - DEBUGFS_FWSTATS_DEL(event, rx_mismatch); - DEBUGFS_FWSTATS_DEL(event, rx_mem_empty); - DEBUGFS_FWSTATS_DEL(event, rx_pool); - DEBUGFS_FWSTATS_DEL(event, oom_late); - DEBUGFS_FWSTATS_DEL(event, phy_transmit_error); - DEBUGFS_FWSTATS_DEL(event, tx_stuck); - - DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts); - DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts); - DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime); - DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn); - DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn); - DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization); - DEBUGFS_FWSTATS_DEL(ps, upsd_utilization); - - DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop); - DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data); - DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); - DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data); - DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); - - DEBUGFS_DEL(tx_queue_len); - DEBUGFS_DEL(retry_count); - DEBUGFS_DEL(excessive_retries); - - DEBUGFS_DEL(gpio_power); -} - -static int wl1271_debugfs_add_files(struct wl1271 *wl) -{ - int ret = 0; - - DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); - - DEBUGFS_FWSTATS_ADD(rx, out_of_mem); - DEBUGFS_FWSTATS_ADD(rx, hdr_overflow); - DEBUGFS_FWSTATS_ADD(rx, hw_stuck); - DEBUGFS_FWSTATS_ADD(rx, dropped); - DEBUGFS_FWSTATS_ADD(rx, fcs_err); - DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig); - DEBUGFS_FWSTATS_ADD(rx, path_reset); - DEBUGFS_FWSTATS_ADD(rx, reset_counter); - - DEBUGFS_FWSTATS_ADD(dma, rx_requested); - DEBUGFS_FWSTATS_ADD(dma, rx_errors); - DEBUGFS_FWSTATS_ADD(dma, tx_requested); - DEBUGFS_FWSTATS_ADD(dma, tx_errors); - - DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt); - DEBUGFS_FWSTATS_ADD(isr, fiqs); - DEBUGFS_FWSTATS_ADD(isr, rx_headers); - DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow); - DEBUGFS_FWSTATS_ADD(isr, rx_rdys); - DEBUGFS_FWSTATS_ADD(isr, irqs); - DEBUGFS_FWSTATS_ADD(isr, tx_procs); - DEBUGFS_FWSTATS_ADD(isr, decrypt_done); - DEBUGFS_FWSTATS_ADD(isr, dma0_done); - DEBUGFS_FWSTATS_ADD(isr, dma1_done); - DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete); - DEBUGFS_FWSTATS_ADD(isr, commands); - DEBUGFS_FWSTATS_ADD(isr, rx_procs); - DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes); - DEBUGFS_FWSTATS_ADD(isr, host_acknowledges); - DEBUGFS_FWSTATS_ADD(isr, pci_pm); - DEBUGFS_FWSTATS_ADD(isr, wakeups); - DEBUGFS_FWSTATS_ADD(isr, low_rssi); - - DEBUGFS_FWSTATS_ADD(wep, addr_key_count); - DEBUGFS_FWSTATS_ADD(wep, default_key_count); - /* skipping wep.reserved */ - DEBUGFS_FWSTATS_ADD(wep, key_not_found); - DEBUGFS_FWSTATS_ADD(wep, decrypt_fail); - DEBUGFS_FWSTATS_ADD(wep, packets); - DEBUGFS_FWSTATS_ADD(wep, interrupt); - - DEBUGFS_FWSTATS_ADD(pwr, ps_enter); - DEBUGFS_FWSTATS_ADD(pwr, elp_enter); - DEBUGFS_FWSTATS_ADD(pwr, missing_bcns); - DEBUGFS_FWSTATS_ADD(pwr, wake_on_host); - DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp); - DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps); - DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps); - DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons); - DEBUGFS_FWSTATS_ADD(pwr, power_save_off); - DEBUGFS_FWSTATS_ADD(pwr, enable_ps); - DEBUGFS_FWSTATS_ADD(pwr, disable_ps); - DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps); - /* skipping cont_miss_bcns_spread for now */ - DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons); - - DEBUGFS_FWSTATS_ADD(mic, rx_pkts); - DEBUGFS_FWSTATS_ADD(mic, calc_failure); - - DEBUGFS_FWSTATS_ADD(aes, encrypt_fail); - DEBUGFS_FWSTATS_ADD(aes, decrypt_fail); - DEBUGFS_FWSTATS_ADD(aes, encrypt_packets); - DEBUGFS_FWSTATS_ADD(aes, decrypt_packets); - DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt); - DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt); - - DEBUGFS_FWSTATS_ADD(event, heart_beat); - DEBUGFS_FWSTATS_ADD(event, calibration); - DEBUGFS_FWSTATS_ADD(event, rx_mismatch); - DEBUGFS_FWSTATS_ADD(event, rx_mem_empty); - DEBUGFS_FWSTATS_ADD(event, rx_pool); - DEBUGFS_FWSTATS_ADD(event, oom_late); - DEBUGFS_FWSTATS_ADD(event, phy_transmit_error); - DEBUGFS_FWSTATS_ADD(event, tx_stuck); - - DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts); - DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts); - DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime); - DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn); - DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn); - DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization); - DEBUGFS_FWSTATS_ADD(ps, upsd_utilization); - - DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop); - DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data); - DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); - DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); - DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); - - DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); - DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); - DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); - - DEBUGFS_ADD(gpio_power, wl->debugfs.rootdir); - -out: - if (ret < 0) - wl1271_debugfs_delete_files(wl); - - return ret; -} - -void wl1271_debugfs_reset(struct wl1271 *wl) -{ - memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats)); - wl->stats.retry_count = 0; - wl->stats.excessive_retries = 0; -} - -int wl1271_debugfs_init(struct wl1271 *wl) -{ - int ret; - - wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); - - if (IS_ERR(wl->debugfs.rootdir)) { - ret = PTR_ERR(wl->debugfs.rootdir); - wl->debugfs.rootdir = NULL; - goto err; - } - - wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics", - wl->debugfs.rootdir); - - if (IS_ERR(wl->debugfs.fw_statistics)) { - ret = PTR_ERR(wl->debugfs.fw_statistics); - wl->debugfs.fw_statistics = NULL; - goto err_root; - } - - wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), - GFP_KERNEL); - - if (!wl->stats.fw_stats) { - ret = -ENOMEM; - goto err_fw; - } - - wl->stats.fw_stats_update = jiffies; - - ret = wl1271_debugfs_add_files(wl); - - if (ret < 0) - goto err_file; - - return 0; - -err_file: - kfree(wl->stats.fw_stats); - wl->stats.fw_stats = NULL; - -err_fw: - debugfs_remove(wl->debugfs.fw_statistics); - wl->debugfs.fw_statistics = NULL; - -err_root: - debugfs_remove(wl->debugfs.rootdir); - wl->debugfs.rootdir = NULL; - -err: - return ret; -} - -void wl1271_debugfs_exit(struct wl1271 *wl) -{ - wl1271_debugfs_delete_files(wl); - - kfree(wl->stats.fw_stats); - wl->stats.fw_stats = NULL; - - debugfs_remove(wl->debugfs.fw_statistics); - wl->debugfs.fw_statistics = NULL; - - debugfs_remove(wl->debugfs.rootdir); - wl->debugfs.rootdir = NULL; - -} diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl12xx.h index 8a4cd763e5a2..ce3d31f98c55 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -22,8 +22,8 @@ * */ -#ifndef __WL1271_H__ -#define __WL1271_H__ +#ifndef __WL12XX_H__ +#define __WL12XX_H__ #include <linux/mutex.h> #include <linux/completion.h> @@ -32,8 +32,8 @@ #include <linux/bitops.h> #include <net/mac80211.h> -#include "wl1271_conf.h" -#include "wl1271_ini.h" +#include "conf.h" +#include "ini.h" #define DRIVER_NAME "wl1271" #define DRIVER_PREFIX DRIVER_NAME ": " @@ -60,31 +60,32 @@ enum { DEBUG_ALL = ~0, }; -#define DEBUG_LEVEL (DEBUG_NONE) +extern u32 wl12xx_debug_level; #define DEBUG_DUMP_LIMIT 1024 #define wl1271_error(fmt, arg...) \ - printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg) + pr_err(DRIVER_PREFIX "ERROR " fmt "\n", ##arg) #define wl1271_warning(fmt, arg...) \ - printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg) + pr_warning(DRIVER_PREFIX "WARNING " fmt "\n", ##arg) #define wl1271_notice(fmt, arg...) \ - printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg) + pr_info(DRIVER_PREFIX fmt "\n", ##arg) #define wl1271_info(fmt, arg...) \ - printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg) + pr_info(DRIVER_PREFIX fmt "\n", ##arg) #define wl1271_debug(level, fmt, arg...) \ do { \ - if (level & DEBUG_LEVEL) \ - printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \ + if (level & wl12xx_debug_level) \ + pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \ } while (0) +/* TODO: use pr_debug_hex_dump when it will be available */ #define wl1271_dump(level, prefix, buf, len) \ do { \ - if (level & DEBUG_LEVEL) \ + if (level & wl12xx_debug_level) \ print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ DUMP_PREFIX_OFFSET, 16, 1, \ buf, \ @@ -94,7 +95,7 @@ enum { #define wl1271_dump_ascii(level, prefix, buf, len) \ do { \ - if (level & DEBUG_LEVEL) \ + if (level & wl12xx_debug_level) \ print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ DUMP_PREFIX_OFFSET, 16, 1, \ buf, \ @@ -174,108 +175,6 @@ struct wl1271_stats { unsigned int excessive_retries; }; -struct wl1271_debugfs { - struct dentry *rootdir; - struct dentry *fw_statistics; - - struct dentry *tx_internal_desc_overflow; - - struct dentry *rx_out_of_mem; - struct dentry *rx_hdr_overflow; - struct dentry *rx_hw_stuck; - struct dentry *rx_dropped; - struct dentry *rx_fcs_err; - struct dentry *rx_xfr_hint_trig; - struct dentry *rx_path_reset; - struct dentry *rx_reset_counter; - - struct dentry *dma_rx_requested; - struct dentry *dma_rx_errors; - struct dentry *dma_tx_requested; - struct dentry *dma_tx_errors; - - struct dentry *isr_cmd_cmplt; - struct dentry *isr_fiqs; - struct dentry *isr_rx_headers; - struct dentry *isr_rx_mem_overflow; - struct dentry *isr_rx_rdys; - struct dentry *isr_irqs; - struct dentry *isr_tx_procs; - struct dentry *isr_decrypt_done; - struct dentry *isr_dma0_done; - struct dentry *isr_dma1_done; - struct dentry *isr_tx_exch_complete; - struct dentry *isr_commands; - struct dentry *isr_rx_procs; - struct dentry *isr_hw_pm_mode_changes; - struct dentry *isr_host_acknowledges; - struct dentry *isr_pci_pm; - struct dentry *isr_wakeups; - struct dentry *isr_low_rssi; - - struct dentry *wep_addr_key_count; - struct dentry *wep_default_key_count; - /* skipping wep.reserved */ - struct dentry *wep_key_not_found; - struct dentry *wep_decrypt_fail; - struct dentry *wep_packets; - struct dentry *wep_interrupt; - - struct dentry *pwr_ps_enter; - struct dentry *pwr_elp_enter; - struct dentry *pwr_missing_bcns; - struct dentry *pwr_wake_on_host; - struct dentry *pwr_wake_on_timer_exp; - struct dentry *pwr_tx_with_ps; - struct dentry *pwr_tx_without_ps; - struct dentry *pwr_rcvd_beacons; - struct dentry *pwr_power_save_off; - struct dentry *pwr_enable_ps; - struct dentry *pwr_disable_ps; - struct dentry *pwr_fix_tsf_ps; - /* skipping cont_miss_bcns_spread for now */ - struct dentry *pwr_rcvd_awake_beacons; - - struct dentry *mic_rx_pkts; - struct dentry *mic_calc_failure; - - struct dentry *aes_encrypt_fail; - struct dentry *aes_decrypt_fail; - struct dentry *aes_encrypt_packets; - struct dentry *aes_decrypt_packets; - struct dentry *aes_encrypt_interrupt; - struct dentry *aes_decrypt_interrupt; - - struct dentry *event_heart_beat; - struct dentry *event_calibration; - struct dentry *event_rx_mismatch; - struct dentry *event_rx_mem_empty; - struct dentry *event_rx_pool; - struct dentry *event_oom_late; - struct dentry *event_phy_transmit_error; - struct dentry *event_tx_stuck; - - struct dentry *ps_pspoll_timeouts; - struct dentry *ps_upsd_timeouts; - struct dentry *ps_upsd_max_sptime; - struct dentry *ps_upsd_max_apturn; - struct dentry *ps_pspoll_max_apturn; - struct dentry *ps_pspoll_utilization; - struct dentry *ps_upsd_utilization; - - struct dentry *rxpipe_rx_prep_beacon_drop; - struct dentry *rxpipe_descr_host_int_trig_rx_data; - struct dentry *rxpipe_beacon_buffer_thres_host_int_trig_rx_data; - struct dentry *rxpipe_missed_beacon_host_int_trig_rx_data; - struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data; - - struct dentry *tx_queue_len; - - struct dentry *retry_count; - struct dentry *excessive_retries; - struct dentry *gpio_power; -}; - #define NUM_TX_QUEUES 4 #define NUM_RX_PKT_DESC 8 @@ -351,6 +250,7 @@ struct wl1271 { #define WL1271_FLAG_IDLE_REQUESTED (11) #define WL1271_FLAG_PSPOLL_FAILURE (12) #define WL1271_FLAG_STA_STATE_SENT (13) +#define WL1271_FLAG_FW_TX_BUSY (14) unsigned long flags; struct wl1271_partition_set part; @@ -392,11 +292,13 @@ struct wl1271 { int session_counter; /* Frames scheduled for transmission, not handled yet */ - struct sk_buff_head tx_queue; + struct sk_buff_head tx_queue[NUM_TX_QUEUES]; + int tx_queue_count; struct work_struct tx_work; /* Pending TX frames */ + unsigned long tx_frames_map[BITS_TO_LONGS(ACX_TX_DESCRIPTORS)]; struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; int tx_frames_cnt; @@ -429,10 +331,18 @@ struct wl1271 { struct wl1271_scan scan; struct delayed_work scan_complete_work; + /* probe-req template for the current AP */ + struct sk_buff *probereq; + /* Our association ID */ u16 aid; - /* currently configured rate set */ + /* + * currently configured rate set: + * bits 0-15 - 802.11abg rates + * bits 16-23 - 802.11n MCS index mask + * support only 1 stream, thus only 8 bits for the MCS rates (0-7). + */ u32 sta_rate_set; u32 basic_rate_set; u32 basic_rate; @@ -468,7 +378,7 @@ struct wl1271 { int last_rssi_event; struct wl1271_stats stats; - struct wl1271_debugfs debugfs; + struct dentry *rootdir; __le32 buffer_32; u32 buffer_cmd; @@ -509,4 +419,8 @@ int wl1271_plt_stop(struct wl1271 *wl); #define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */ #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ +/* Macros to handle wl1271.sta_rate_set */ +#define HW_BG_RATES_MASK 0xffff +#define HW_HT_RATES_OFFSET 16 + #endif diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h index 184628027213..be21032f4dc1 100644 --- a/drivers/net/wireless/wl12xx/wl12xx_80211.h +++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h @@ -2,6 +2,7 @@ #define __WL12XX_80211_H__ #include <linux/if_ether.h> /* ETH_ALEN */ +#include <linux/if_arp.h> /* RATES */ #define IEEE80211_CCK_RATE_1MB 0x02 @@ -133,11 +134,17 @@ struct wl12xx_qos_null_data_template { __le16 qos_ctl; } __packed; -struct wl12xx_probe_req_template { - struct ieee80211_header header; - struct wl12xx_ie_ssid ssid; - struct wl12xx_ie_rates rates; - struct wl12xx_ie_rates ext_rates; +struct wl12xx_arp_rsp_template { + struct ieee80211_hdr_3addr hdr; + + u8 llc_hdr[sizeof(rfc1042_header)]; + u16 llc_type; + + struct arphdr arp_hdr; + u8 sender_hw[ETH_ALEN]; + u32 sender_ip; + u8 target_hw[ETH_ALEN]; + u32 target_ip; } __packed; diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 390d77f762c4..415eec401e2e 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -30,6 +30,7 @@ static struct usb_device_id zd1201_table[] = { {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */ {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */ {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */ + {USB_DEVICE(0x1044, 0x8004)}, /* Gigabyte GN-WLBZ101 */ {USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */ {} }; @@ -1829,7 +1830,7 @@ err_zd: static void zd1201_disconnect(struct usb_interface *interface) { - struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface); + struct zd1201 *zd = usb_get_intfdata(interface); struct hlist_node *node, *node2; struct zd1201_frag *frag; diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index 87a95bcfee57..6a9b66051cf7 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -117,6 +117,7 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr /* Allocate a single memory block for values and addresses. */ count16 = 2*count; + /* zd_addr_t is __nocast, so the kmalloc needs an explicit cast */ a16 = (zd_addr_t *) kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)), GFP_KERNEL); if (!a16) { @@ -1448,7 +1449,7 @@ int zd_rfwritev_locked(struct zd_chip *chip, */ int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value) { - struct zd_ioreq16 ioreqs[] = { + const struct zd_ioreq16 ioreqs[] = { { CR244, (value >> 16) & 0xff }, { CR243, (value >> 8) & 0xff }, { CR242, value & 0xff }, @@ -1475,7 +1476,7 @@ int zd_rfwritev_cr_locked(struct zd_chip *chip, int zd_chip_set_multicast_hash(struct zd_chip *chip, struct zd_mc_hash *hash) { - struct zd_ioreq32 ioreqs[] = { + const struct zd_ioreq32 ioreqs[] = { { CR_GROUP_HASH_P1, hash->low }, { CR_GROUP_HASH_P2, hash->high }, }; diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 43307bd42a69..6107304cb94c 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -1207,7 +1207,6 @@ static void housekeeping_enable(struct zd_mac *mac) static void housekeeping_disable(struct zd_mac *mac) { dev_dbg_f(zd_mac_dev(mac), "\n"); - cancel_rearming_delayed_workqueue(zd_workqueue, - &mac->housekeeping.link_led_work); + cancel_delayed_work_sync(&mac->housekeeping.link_led_work); zd_chip_control_leds(&mac->chip, ZD_LED_OFF); } diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 818e1480ca93..06041cb1c422 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -55,6 +55,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x129b, 0x1666), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x1435, 0x0711), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x14ea, 0xab10), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, @@ -92,6 +93,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x2019, 0x5303), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x2019, 0xed01), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, |