diff options
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r-- | drivers/net/wireless/b43/Kconfig | 9 | ||||
-rw-r--r-- | drivers/net/wireless/b43/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/b43/b43.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 71 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_ac.c | 92 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_ac.h | 38 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_common.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_common.h | 2 |
8 files changed, 213 insertions, 12 deletions
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 64a5b672e30a..759fb8d41fc9 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -166,6 +166,15 @@ config B43_PHY_LCN Say N, this is BROKEN and crashes driver. +config B43_PHY_AC + bool "Support for AC-PHY (802.11ac) devices (BROKEN)" + depends on B43 && B43_BCMA && BROKEN + ---help--- + This PHY type can be found in the following chipsets: + PCI: BCM4352, BCM4360 + + Say N, this is BROKEN and crashes driver. + # This config option automatically enables b43 LEDS support, # if it's possible. config B43_LEDS diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 9f7965aae93d..c624d4d90e4f 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -13,6 +13,7 @@ b43-$(CONFIG_B43_PHY_HT) += phy_ht.o b43-$(CONFIG_B43_PHY_HT) += tables_phy_ht.o b43-$(CONFIG_B43_PHY_HT) += radio_2059.o b43-$(CONFIG_B43_PHY_LCN) += phy_lcn.o tables_phy_lcn.o +b43-$(CONFIG_B43_PHY_AC) += phy_ac.o b43-y += sysfs.o b43-y += xmit.o b43-y += dma.o diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index bb12586cd7cd..036552439816 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -500,6 +500,8 @@ enum { #define B43_BCMA_IOCTL_PHY_BW_10MHZ 0x00000000 /* 10 MHz bandwidth, 40 MHz PHY */ #define B43_BCMA_IOCTL_PHY_BW_20MHZ 0x00000040 /* 20 MHz bandwidth, 80 MHz PHY */ #define B43_BCMA_IOCTL_PHY_BW_40MHZ 0x00000080 /* 40 MHz bandwidth, 160 MHz PHY */ +#define B43_BCMA_IOCTL_PHY_BW_80MHZ 0x000000C0 /* 80 MHz bandwidth */ +#define B43_BCMA_IOCTL_DAC 0x00000300 /* Highspeed DAC mode control field */ #define B43_BCMA_IOCTL_GMODE 0x00002000 /* G Mode Enable */ /* BCMA 802.11 core specific IO status (BCMA_IOST) flags */ @@ -941,6 +943,7 @@ struct b43_wl { bool beacon1_uploaded; bool beacon_templates_virgin; /* Never wrote the templates? */ struct work_struct beacon_update_trigger; + spinlock_t beacon_lock; /* The current QOS parameters for the 4 queues. */ struct b43_qos_params qos_params[B43_QOS_QUEUE_NUM]; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 47731cb0d815..2c9088633ec6 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1262,6 +1262,23 @@ static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) flags |= B43_BCMA_IOCTL_GMODE; b43_device_enable(dev, flags); + if (dev->phy.type == B43_PHYTYPE_AC) { + u16 tmp; + + tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); + tmp &= ~B43_BCMA_IOCTL_DAC; + tmp |= 0x100; + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); + + tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); + tmp &= ~B43_BCMA_IOCTL_PHY_CLKEN; + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); + + tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); + tmp |= B43_BCMA_IOCTL_PHY_CLKEN; + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); + } + bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); b43_bcma_phy_reset(dev); bcma_core_pll_ctl(dev->dev->bdev, req, status, true); @@ -1601,12 +1618,26 @@ static void b43_write_beacon_template(struct b43_wldev *dev, unsigned int rate; u16 ctl; int antenna; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon); + struct ieee80211_tx_info *info; + unsigned long flags; + struct sk_buff *beacon_skb; - bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); - len = min_t(size_t, dev->wl->current_beacon->len, - 0x200 - sizeof(struct b43_plcp_hdr6)); + spin_lock_irqsave(&dev->wl->beacon_lock, flags); + info = IEEE80211_SKB_CB(dev->wl->current_beacon); rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value; + /* Clone the beacon, so it cannot go away, while we write it to hw. */ + beacon_skb = skb_clone(dev->wl->current_beacon, GFP_ATOMIC); + spin_unlock_irqrestore(&dev->wl->beacon_lock, flags); + + if (!beacon_skb) { + b43dbg(dev->wl, "Could not upload beacon. " + "Failed to clone beacon skb."); + return; + } + + bcn = (const struct ieee80211_mgmt *)(beacon_skb->data); + len = min_t(size_t, beacon_skb->len, + 0x200 - sizeof(struct b43_plcp_hdr6)); b43_write_template_common(dev, (const u8 *)bcn, len, ram_offset, shm_size_offset, rate); @@ -1674,6 +1705,8 @@ static void b43_write_beacon_template(struct b43_wldev *dev, B43_SHM_SH_DTIMPER, 0); } b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset); + + dev_kfree_skb_any(beacon_skb); } static void b43_upload_beacon0(struct b43_wldev *dev) @@ -1790,13 +1823,13 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) mutex_unlock(&wl->mutex); } -/* Asynchronously update the packet templates in template RAM. - * Locking: Requires wl->mutex to be locked. */ +/* Asynchronously update the packet templates in template RAM. */ static void b43_update_templates(struct b43_wl *wl) { - struct sk_buff *beacon; + struct sk_buff *beacon, *old_beacon; + unsigned long flags; - /* This is the top half of the ansynchronous beacon update. + /* This is the top half of the asynchronous beacon update. * The bottom half is the beacon IRQ. * Beacon update must be asynchronous to avoid sending an * invalid beacon. This can happen for example, if the firmware @@ -1810,12 +1843,17 @@ static void b43_update_templates(struct b43_wl *wl) if (unlikely(!beacon)) return; - if (wl->current_beacon) - dev_kfree_skb_any(wl->current_beacon); + spin_lock_irqsave(&wl->beacon_lock, flags); + old_beacon = wl->current_beacon; wl->current_beacon = beacon; wl->beacon0_uploaded = false; wl->beacon1_uploaded = false; + spin_unlock_irqrestore(&wl->beacon_lock, flags); + ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger); + + if (old_beacon) + dev_kfree_skb_any(old_beacon); } static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) @@ -4318,6 +4356,7 @@ redo: mutex_unlock(&wl->mutex); cancel_delayed_work_sync(&dev->periodic_work); cancel_work_sync(&wl->tx_work); + b43_leds_stop(dev); mutex_lock(&wl->mutex); dev = wl->current_dev; if (!dev || b43_status(dev) < B43_STAT_STARTED) { @@ -4505,6 +4544,12 @@ static int b43_phy_versioning(struct b43_wldev *dev) unsupported = 1; break; #endif +#ifdef CONFIG_B43_PHY_AC + case B43_PHYTYPE_AC: + if (phy_rev > 1) + unsupported = 1; + break; +#endif default: unsupported = 1; } @@ -4601,6 +4646,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) if (radio_id != 0x2064) unsupported = 1; break; + case B43_PHYTYPE_AC: + if (radio_id != 0x2069) + unsupported = 1; + break; default: B43_WARN_ON(1); } @@ -5094,7 +5143,6 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, { struct b43_wl *wl = hw_to_b43_wl(hw); - /* FIXME: add locking */ b43_update_templates(wl); return 0; @@ -5584,6 +5632,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) wl->hw = hw; mutex_init(&wl->mutex); spin_lock_init(&wl->hardirq_lock); + spin_lock_init(&wl->beacon_lock); INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); INIT_WORK(&wl->tx_work, b43_tx_work); diff --git a/drivers/net/wireless/b43/phy_ac.c b/drivers/net/wireless/b43/phy_ac.c new file mode 100644 index 000000000000..e75633d67938 --- /dev/null +++ b/drivers/net/wireless/b43/phy_ac.c @@ -0,0 +1,92 @@ +/* + * Broadcom B43 wireless driver + * IEEE 802.11ac AC-PHY support + * + * Copyright (c) 2015 Rafał Miłecki <zajec5@gmail.com> + * + * 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 (at your + * option) any later version. + */ + +#include "b43.h" +#include "phy_ac.h" + +/************************************************** + * Basic PHY ops + **************************************************/ + +static int b43_phy_ac_op_allocate(struct b43_wldev *dev) +{ + struct b43_phy_ac *phy_ac; + + phy_ac = kzalloc(sizeof(*phy_ac), GFP_KERNEL); + if (!phy_ac) + return -ENOMEM; + dev->phy.ac = phy_ac; + + return 0; +} + +static void b43_phy_ac_op_free(struct b43_wldev *dev) +{ + struct b43_phy *phy = &dev->phy; + struct b43_phy_ac *phy_ac = phy->ac; + + kfree(phy_ac); + phy->ac = NULL; +} + +static void b43_phy_ac_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, + u16 set) +{ + b43_write16f(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_phy_ac_op_radio_read(struct b43_wldev *dev, u16 reg) +{ + b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); + return b43_read16(dev, B43_MMIO_RADIO24_DATA); +} + +static void b43_phy_ac_op_radio_write(struct b43_wldev *dev, u16 reg, + u16 value) +{ + b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); + b43_write16(dev, B43_MMIO_RADIO24_DATA, value); +} + +static unsigned int b43_phy_ac_op_get_default_chan(struct b43_wldev *dev) +{ + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + return 11; + return 36; +} + +static enum b43_txpwr_result +b43_phy_ac_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi) +{ + return B43_TXPWR_RES_DONE; +} + +static void b43_phy_ac_op_adjust_txpower(struct b43_wldev *dev) +{ +} + +/************************************************** + * PHY ops struct + **************************************************/ + +const struct b43_phy_operations b43_phyops_ac = { + .allocate = b43_phy_ac_op_allocate, + .free = b43_phy_ac_op_free, + .phy_maskset = b43_phy_ac_op_maskset, + .radio_read = b43_phy_ac_op_radio_read, + .radio_write = b43_phy_ac_op_radio_write, + .get_default_chan = b43_phy_ac_op_get_default_chan, + .recalc_txpower = b43_phy_ac_op_recalc_txpower, + .adjust_txpower = b43_phy_ac_op_adjust_txpower, +}; diff --git a/drivers/net/wireless/b43/phy_ac.h b/drivers/net/wireless/b43/phy_ac.h new file mode 100644 index 000000000000..d1ca79e0eb24 --- /dev/null +++ b/drivers/net/wireless/b43/phy_ac.h @@ -0,0 +1,38 @@ +#ifndef B43_PHY_AC_H_ +#define B43_PHY_AC_H_ + +#include "phy_common.h" + +#define B43_PHY_AC_BBCFG 0x001 +#define B43_PHY_AC_BBCFG_RSTCCA 0x4000 /* Reset CCA */ +#define B43_PHY_AC_BANDCTL 0x003 /* Band control */ +#define B43_PHY_AC_BANDCTL_5GHZ 0x0001 +#define B43_PHY_AC_TABLE_ID 0x00d +#define B43_PHY_AC_TABLE_OFFSET 0x00e +#define B43_PHY_AC_TABLE_DATA1 0x00f +#define B43_PHY_AC_TABLE_DATA2 0x010 +#define B43_PHY_AC_TABLE_DATA3 0x011 +#define B43_PHY_AC_CLASSCTL 0x140 /* Classifier control */ +#define B43_PHY_AC_CLASSCTL_CCKEN 0x0001 /* CCK enable */ +#define B43_PHY_AC_CLASSCTL_OFDMEN 0x0002 /* OFDM enable */ +#define B43_PHY_AC_CLASSCTL_WAITEDEN 0x0004 /* Waited enable */ +#define B43_PHY_AC_BW1A 0x371 +#define B43_PHY_AC_BW2 0x372 +#define B43_PHY_AC_BW3 0x373 +#define B43_PHY_AC_BW4 0x374 +#define B43_PHY_AC_BW5 0x375 +#define B43_PHY_AC_BW6 0x376 +#define B43_PHY_AC_RFCTL_CMD 0x408 +#define B43_PHY_AC_C1_CLIP 0x6d4 +#define B43_PHY_AC_C1_CLIP_DIS 0x4000 +#define B43_PHY_AC_C2_CLIP 0x8d4 +#define B43_PHY_AC_C2_CLIP_DIS 0x4000 +#define B43_PHY_AC_C3_CLIP 0xad4 +#define B43_PHY_AC_C3_CLIP_DIS 0x4000 + +struct b43_phy_ac { +}; + +extern const struct b43_phy_operations b43_phyops_ac; + +#endif /* B43_PHY_AC_H_ */ diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index ee27b06074e1..ec2b9c577b90 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -33,6 +33,7 @@ #include "phy_lp.h" #include "phy_ht.h" #include "phy_lcn.h" +#include "phy_ac.h" #include "b43.h" #include "main.h" @@ -70,6 +71,11 @@ int b43_phy_allocate(struct b43_wldev *dev) phy->ops = &b43_phyops_lcn; #endif break; + case B43_PHYTYPE_AC: +#ifdef CONFIG_B43_PHY_AC + phy->ops = &b43_phyops_ac; +#endif + break; } if (B43_WARN_ON(!phy->ops)) return -ENODEV; @@ -572,7 +578,8 @@ void b43_phy_force_clock(struct b43_wldev *dev, bool force) u32 tmp; WARN_ON(dev->phy.type != B43_PHYTYPE_N && - dev->phy.type != B43_PHYTYPE_HT); + dev->phy.type != B43_PHYTYPE_HT && + dev->phy.type != B43_PHYTYPE_AC); switch (dev->dev->bus_type) { #ifdef CONFIG_B43_BCMA diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index 3912274f71e3..78d86526799e 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -222,6 +222,8 @@ struct b43_phy { struct b43_phy_ht *ht; /* LCN-PHY specific information */ struct b43_phy_lcn *lcn; + /* AC-PHY specific information */ + struct b43_phy_ac *ac; }; /* Band support flags. */ |