brcm80211: move under broadcom vendor directory

Part of reorganising wireless drivers directory and Kconfig. Note that I had to
edit Makefiles from subdirectories to use the new location.

Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
Kalle Valo
2015-11-17 19:52:05 +02:00
parent 423e3ce336
commit 05491d2ccf
119 changed files with 12 additions and 12 deletions

View File

@@ -0,0 +1,48 @@
#
# Makefile fragment for Broadcom 802.11n Networking Device Driver
#
# Copyright (c) 2010 Broadcom Corporation
#
# 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.
ccflags-y := \
-D__CHECK_ENDIAN__ \
-Idrivers/net/wireless/broadcom/brcm80211/brcmsmac \
-Idrivers/net/wireless/broadcom/brcm80211/brcmsmac/phy \
-Idrivers/net/wireless/broadcom/brcm80211/include
brcmsmac-y := \
mac80211_if.o \
ucode_loader.o \
ampdu.o \
antsel.o \
channel.o \
main.o \
phy_shim.o \
pmu.o \
rate.o \
stf.o \
aiutils.o \
phy/phy_cmn.o \
phy/phy_lcn.o \
phy/phy_n.o \
phy/phytbl_lcn.o \
phy/phytbl_n.o \
phy/phy_qmath.o \
dma.o \
brcms_trace_events.o \
debug.o
brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o
obj-$(CONFIG_BRCMSMAC) += brcmsmac.o

View File

@@ -0,0 +1,710 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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.
*
* File contents: support functions for PCI/PCIe
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/delay.h>
#include <defs.h>
#include <chipcommon.h>
#include <brcmu_utils.h>
#include <brcm_hw_ids.h>
#include <soc.h>
#include "types.h"
#include "pub.h"
#include "pmu.h"
#include "aiutils.h"
/* slow_clk_ctl */
/* slow clock source mask */
#define SCC_SS_MASK 0x00000007
/* source of slow clock is LPO */
#define SCC_SS_LPO 0x00000000
/* source of slow clock is crystal */
#define SCC_SS_XTAL 0x00000001
/* source of slow clock is PCI */
#define SCC_SS_PCI 0x00000002
/* LPOFreqSel, 1: 160Khz, 0: 32KHz */
#define SCC_LF 0x00000200
/* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */
#define SCC_LP 0x00000400
/* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */
#define SCC_FS 0x00000800
/* IgnorePllOffReq, 1/0:
* power logic ignores/honors PLL clock disable requests from core
*/
#define SCC_IP 0x00001000
/* XtalControlEn, 1/0:
* power logic does/doesn't disable crystal when appropriate
*/
#define SCC_XC 0x00002000
/* XtalPU (RO), 1/0: crystal running/disabled */
#define SCC_XP 0x00004000
/* ClockDivider (SlowClk = 1/(4+divisor)) */
#define SCC_CD_MASK 0xffff0000
#define SCC_CD_SHIFT 16
/* system_clk_ctl */
/* ILPen: Enable Idle Low Power */
#define SYCC_IE 0x00000001
/* ALPen: Enable Active Low Power */
#define SYCC_AE 0x00000002
/* ForcePLLOn */
#define SYCC_FP 0x00000004
/* Force ALP (or HT if ALPen is not set */
#define SYCC_AR 0x00000008
/* Force HT */
#define SYCC_HR 0x00000010
/* ClkDiv (ILP = 1/(4 * (divisor + 1)) */
#define SYCC_CD_MASK 0xffff0000
#define SYCC_CD_SHIFT 16
#define CST4329_SPROM_OTP_SEL_MASK 0x00000003
/* OTP is powered up, use def. CIS, no SPROM */
#define CST4329_DEFCIS_SEL 0
/* OTP is powered up, SPROM is present */
#define CST4329_SPROM_SEL 1
/* OTP is powered up, no SPROM */
#define CST4329_OTP_SEL 2
/* OTP is powered down, SPROM is present */
#define CST4329_OTP_PWRDN 3
#define CST4329_SPI_SDIO_MODE_MASK 0x00000004
#define CST4329_SPI_SDIO_MODE_SHIFT 2
/* 43224 chip-specific ChipControl register bits */
#define CCTRL43224_GPIO_TOGGLE 0x8000
/* 12 mA drive strength */
#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0
/* 12 mA drive strength for later 43224s */
#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0
/* 43236 Chip specific ChipStatus register bits */
#define CST43236_SFLASH_MASK 0x00000040
#define CST43236_OTP_MASK 0x00000080
#define CST43236_HSIC_MASK 0x00000100 /* USB/HSIC */
#define CST43236_BP_CLK 0x00000200 /* 120/96Mbps */
#define CST43236_BOOT_MASK 0x00001800
#define CST43236_BOOT_SHIFT 11
#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */
#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */
#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */
#define CST43236_BOOT_FROM_INVALID 3
/* 4331 chip-specific ChipControl register bits */
/* 0 disable */
#define CCTRL4331_BT_COEXIST (1<<0)
/* 0 SECI is disabled (JTAG functional) */
#define CCTRL4331_SECI (1<<1)
/* 0 disable */
#define CCTRL4331_EXT_LNA (1<<2)
/* sprom/gpio13-15 mux */
#define CCTRL4331_SPROM_GPIO13_15 (1<<3)
/* 0 ext pa disable, 1 ext pa enabled */
#define CCTRL4331_EXTPA_EN (1<<4)
/* set drive out GPIO_CLK on sprom_cs pin */
#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5)
/* use sprom_cs pin as PCIE mdio interface */
#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6)
/* aband extpa will be at gpio2/5 and sprom_dout */
#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7)
/* override core control on pipe_AuxClkEnable */
#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8)
/* override core control on pipe_AuxPowerDown */
#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9)
/* pcie_auxclkenable */
#define CCTRL4331_PCIE_AUXCLKEN (1<<10)
/* pcie_pipe_pllpowerdown */
#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11)
/* enable bt_shd0 at gpio4 */
#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16)
/* enable bt_shd1 at gpio5 */
#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17)
/* 4331 Chip specific ChipStatus register bits */
/* crystal frequency 20/40Mhz */
#define CST4331_XTAL_FREQ 0x00000001
#define CST4331_SPROM_PRESENT 0x00000002
#define CST4331_OTP_PRESENT 0x00000004
#define CST4331_LDO_RF 0x00000008
#define CST4331_LDO_PAR 0x00000010
/* 4319 chip-specific ChipStatus register bits */
#define CST4319_SPI_CPULESSUSB 0x00000001
#define CST4319_SPI_CLK_POL 0x00000002
#define CST4319_SPI_CLK_PH 0x00000008
/* gpio [7:6], SDIO CIS selection */
#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0
#define CST4319_SPROM_OTP_SEL_SHIFT 6
/* use default CIS, OTP is powered up */
#define CST4319_DEFCIS_SEL 0x00000000
/* use SPROM, OTP is powered up */
#define CST4319_SPROM_SEL 0x00000040
/* use OTP, OTP is powered up */
#define CST4319_OTP_SEL 0x00000080
/* use SPROM, OTP is powered down */
#define CST4319_OTP_PWRDN 0x000000c0
/* gpio [8], sdio/usb mode */
#define CST4319_SDIO_USB_MODE 0x00000100
#define CST4319_REMAP_SEL_MASK 0x00000600
#define CST4319_ILPDIV_EN 0x00000800
#define CST4319_XTAL_PD_POL 0x00001000
#define CST4319_LPO_SEL 0x00002000
#define CST4319_RES_INIT_MODE 0x0000c000
/* PALDO is configured with external PNP */
#define CST4319_PALDO_EXTPNP 0x00010000
#define CST4319_CBUCK_MODE_MASK 0x00060000
#define CST4319_CBUCK_MODE_BURST 0x00020000
#define CST4319_CBUCK_MODE_LPBURST 0x00060000
#define CST4319_RCAL_VALID 0x01000000
#define CST4319_RCAL_VALUE_MASK 0x3e000000
#define CST4319_RCAL_VALUE_SHIFT 25
/* 4336 chip-specific ChipStatus register bits */
#define CST4336_SPI_MODE_MASK 0x00000001
#define CST4336_SPROM_PRESENT 0x00000002
#define CST4336_OTP_PRESENT 0x00000004
#define CST4336_ARMREMAP_0 0x00000008
#define CST4336_ILPDIV_EN_MASK 0x00000010
#define CST4336_ILPDIV_EN_SHIFT 4
#define CST4336_XTAL_PD_POL_MASK 0x00000020
#define CST4336_XTAL_PD_POL_SHIFT 5
#define CST4336_LPO_SEL_MASK 0x00000040
#define CST4336_LPO_SEL_SHIFT 6
#define CST4336_RES_INIT_MODE_MASK 0x00000180
#define CST4336_RES_INIT_MODE_SHIFT 7
#define CST4336_CBUCK_MODE_MASK 0x00000600
#define CST4336_CBUCK_MODE_SHIFT 9
/* 4313 chip-specific ChipStatus register bits */
#define CST4313_SPROM_PRESENT 1
#define CST4313_OTP_PRESENT 2
#define CST4313_SPROM_OTP_SEL_MASK 0x00000002
#define CST4313_SPROM_OTP_SEL_SHIFT 0
/* 4313 Chip specific ChipControl register bits */
/* 12 mA drive strengh for later 4313 */
#define CCTRL_4313_12MA_LED_DRIVE 0x00000007
/* Manufacturer Ids */
#define MFGID_ARM 0x43b
#define MFGID_BRCM 0x4bf
#define MFGID_MIPS 0x4a7
/* Enumeration ROM registers */
#define ER_EROMENTRY 0x000
#define ER_REMAPCONTROL 0xe00
#define ER_REMAPSELECT 0xe04
#define ER_MASTERSELECT 0xe10
#define ER_ITCR 0xf00
#define ER_ITIP 0xf04
/* Erom entries */
#define ER_TAG 0xe
#define ER_TAG1 0x6
#define ER_VALID 1
#define ER_CI 0
#define ER_MP 2
#define ER_ADD 4
#define ER_END 0xe
#define ER_BAD 0xffffffff
/* EROM CompIdentA */
#define CIA_MFG_MASK 0xfff00000
#define CIA_MFG_SHIFT 20
#define CIA_CID_MASK 0x000fff00
#define CIA_CID_SHIFT 8
#define CIA_CCL_MASK 0x000000f0
#define CIA_CCL_SHIFT 4
/* EROM CompIdentB */
#define CIB_REV_MASK 0xff000000
#define CIB_REV_SHIFT 24
#define CIB_NSW_MASK 0x00f80000
#define CIB_NSW_SHIFT 19
#define CIB_NMW_MASK 0x0007c000
#define CIB_NMW_SHIFT 14
#define CIB_NSP_MASK 0x00003e00
#define CIB_NSP_SHIFT 9
#define CIB_NMP_MASK 0x000001f0
#define CIB_NMP_SHIFT 4
/* EROM AddrDesc */
#define AD_ADDR_MASK 0xfffff000
#define AD_SP_MASK 0x00000f00
#define AD_SP_SHIFT 8
#define AD_ST_MASK 0x000000c0
#define AD_ST_SHIFT 6
#define AD_ST_SLAVE 0x00000000
#define AD_ST_BRIDGE 0x00000040
#define AD_ST_SWRAP 0x00000080
#define AD_ST_MWRAP 0x000000c0
#define AD_SZ_MASK 0x00000030
#define AD_SZ_SHIFT 4
#define AD_SZ_4K 0x00000000
#define AD_SZ_8K 0x00000010
#define AD_SZ_16K 0x00000020
#define AD_SZ_SZD 0x00000030
#define AD_AG32 0x00000008
#define AD_ADDR_ALIGN 0x00000fff
#define AD_SZ_BASE 0x00001000 /* 4KB */
/* EROM SizeDesc */
#define SD_SZ_MASK 0xfffff000
#define SD_SG32 0x00000008
#define SD_SZ_ALIGN 0x00000fff
/* PCI config space bit 4 for 4306c0 slow clock source */
#define PCI_CFG_GPIO_SCS 0x10
/* PCI config space GPIO 14 for Xtal power-up */
#define PCI_CFG_GPIO_XTAL 0x40
/* PCI config space GPIO 15 for PLL power-down */
#define PCI_CFG_GPIO_PLL 0x80
/* power control defines */
#define PLL_DELAY 150 /* us pll on delay */
#define FREF_DELAY 200 /* us fref change delay */
#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */
/* resetctrl */
#define AIRC_RESET 1
#define NOREV -1 /* Invalid rev */
/* GPIO Based LED powersave defines */
#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */
#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */
/* When Srom support present, fields in sromcontrol */
#define SRC_START 0x80000000
#define SRC_BUSY 0x80000000
#define SRC_OPCODE 0x60000000
#define SRC_OP_READ 0x00000000
#define SRC_OP_WRITE 0x20000000
#define SRC_OP_WRDIS 0x40000000
#define SRC_OP_WREN 0x60000000
#define SRC_OTPSEL 0x00000010
#define SRC_LOCK 0x00000008
#define SRC_SIZE_MASK 0x00000006
#define SRC_SIZE_1K 0x00000000
#define SRC_SIZE_4K 0x00000002
#define SRC_SIZE_16K 0x00000004
#define SRC_SIZE_SHIFT 1
#define SRC_PRESENT 0x00000001
/* External PA enable mask */
#define GPIO_CTRL_EPA_EN_MASK 0x40
#define DEFAULT_GPIOTIMERVAL \
((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
#define BADIDX (SI_MAXCORES + 1)
#define IS_SIM(chippkg) \
((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
#define GOODCOREADDR(x, b) \
(((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
IS_ALIGNED((x), SI_CORE_SIZE))
struct aidmp {
u32 oobselina30; /* 0x000 */
u32 oobselina74; /* 0x004 */
u32 PAD[6];
u32 oobselinb30; /* 0x020 */
u32 oobselinb74; /* 0x024 */
u32 PAD[6];
u32 oobselinc30; /* 0x040 */
u32 oobselinc74; /* 0x044 */
u32 PAD[6];
u32 oobselind30; /* 0x060 */
u32 oobselind74; /* 0x064 */
u32 PAD[38];
u32 oobselouta30; /* 0x100 */
u32 oobselouta74; /* 0x104 */
u32 PAD[6];
u32 oobseloutb30; /* 0x120 */
u32 oobseloutb74; /* 0x124 */
u32 PAD[6];
u32 oobseloutc30; /* 0x140 */
u32 oobseloutc74; /* 0x144 */
u32 PAD[6];
u32 oobseloutd30; /* 0x160 */
u32 oobseloutd74; /* 0x164 */
u32 PAD[38];
u32 oobsynca; /* 0x200 */
u32 oobseloutaen; /* 0x204 */
u32 PAD[6];
u32 oobsyncb; /* 0x220 */
u32 oobseloutben; /* 0x224 */
u32 PAD[6];
u32 oobsyncc; /* 0x240 */
u32 oobseloutcen; /* 0x244 */
u32 PAD[6];
u32 oobsyncd; /* 0x260 */
u32 oobseloutden; /* 0x264 */
u32 PAD[38];
u32 oobaextwidth; /* 0x300 */
u32 oobainwidth; /* 0x304 */
u32 oobaoutwidth; /* 0x308 */
u32 PAD[5];
u32 oobbextwidth; /* 0x320 */
u32 oobbinwidth; /* 0x324 */
u32 oobboutwidth; /* 0x328 */
u32 PAD[5];
u32 oobcextwidth; /* 0x340 */
u32 oobcinwidth; /* 0x344 */
u32 oobcoutwidth; /* 0x348 */
u32 PAD[5];
u32 oobdextwidth; /* 0x360 */
u32 oobdinwidth; /* 0x364 */
u32 oobdoutwidth; /* 0x368 */
u32 PAD[37];
u32 ioctrlset; /* 0x400 */
u32 ioctrlclear; /* 0x404 */
u32 ioctrl; /* 0x408 */
u32 PAD[61];
u32 iostatus; /* 0x500 */
u32 PAD[127];
u32 ioctrlwidth; /* 0x700 */
u32 iostatuswidth; /* 0x704 */
u32 PAD[62];
u32 resetctrl; /* 0x800 */
u32 resetstatus; /* 0x804 */
u32 resetreadid; /* 0x808 */
u32 resetwriteid; /* 0x80c */
u32 PAD[60];
u32 errlogctrl; /* 0x900 */
u32 errlogdone; /* 0x904 */
u32 errlogstatus; /* 0x908 */
u32 errlogaddrlo; /* 0x90c */
u32 errlogaddrhi; /* 0x910 */
u32 errlogid; /* 0x914 */
u32 errloguser; /* 0x918 */
u32 errlogflags; /* 0x91c */
u32 PAD[56];
u32 intstatus; /* 0xa00 */
u32 PAD[127];
u32 config; /* 0xe00 */
u32 PAD[63];
u32 itcr; /* 0xf00 */
u32 PAD[3];
u32 itipooba; /* 0xf10 */
u32 itipoobb; /* 0xf14 */
u32 itipoobc; /* 0xf18 */
u32 itipoobd; /* 0xf1c */
u32 PAD[4];
u32 itipoobaout; /* 0xf30 */
u32 itipoobbout; /* 0xf34 */
u32 itipoobcout; /* 0xf38 */
u32 itipoobdout; /* 0xf3c */
u32 PAD[4];
u32 itopooba; /* 0xf50 */
u32 itopoobb; /* 0xf54 */
u32 itopoobc; /* 0xf58 */
u32 itopoobd; /* 0xf5c */
u32 PAD[4];
u32 itopoobain; /* 0xf70 */
u32 itopoobbin; /* 0xf74 */
u32 itopoobcin; /* 0xf78 */
u32 itopoobdin; /* 0xf7c */
u32 PAD[4];
u32 itopreset; /* 0xf90 */
u32 PAD[15];
u32 peripherialid4; /* 0xfd0 */
u32 peripherialid5; /* 0xfd4 */
u32 peripherialid6; /* 0xfd8 */
u32 peripherialid7; /* 0xfdc */
u32 peripherialid0; /* 0xfe0 */
u32 peripherialid1; /* 0xfe4 */
u32 peripherialid2; /* 0xfe8 */
u32 peripherialid3; /* 0xfec */
u32 componentid0; /* 0xff0 */
u32 componentid1; /* 0xff4 */
u32 componentid2; /* 0xff8 */
u32 componentid3; /* 0xffc */
};
static bool
ai_buscore_setup(struct si_info *sii, struct bcma_device *cc)
{
/* no cores found, bail out */
if (cc->bus->nr_cores == 0)
return false;
/* get chipcommon rev */
sii->pub.ccrev = cc->id.rev;
/* get chipcommon chipstatus */
sii->chipst = bcma_read32(cc, CHIPCREGOFFS(chipstatus));
/* get chipcommon capabilites */
sii->pub.cccaps = bcma_read32(cc, CHIPCREGOFFS(capabilities));
/* get pmu rev and caps */
if (ai_get_cccaps(&sii->pub) & CC_CAP_PMU) {
sii->pub.pmucaps = bcma_read32(cc,
CHIPCREGOFFS(pmucapabilities));
sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
}
return true;
}
static struct si_info *ai_doattach(struct si_info *sii,
struct bcma_bus *pbus)
{
struct si_pub *sih = &sii->pub;
struct bcma_device *cc;
sii->icbus = pbus;
sii->pcibus = pbus->host_pci;
/* switch to Chipcommon core */
cc = pbus->drv_cc.core;
sih->chip = pbus->chipinfo.id;
sih->chiprev = pbus->chipinfo.rev;
sih->chippkg = pbus->chipinfo.pkg;
sih->boardvendor = pbus->boardinfo.vendor;
sih->boardtype = pbus->boardinfo.type;
if (!ai_buscore_setup(sii, cc))
goto exit;
/* === NVRAM, clock is ready === */
bcma_write32(cc, CHIPCREGOFFS(gpiopullup), 0);
bcma_write32(cc, CHIPCREGOFFS(gpiopulldown), 0);
/* PMU specific initializations */
if (ai_get_cccaps(sih) & CC_CAP_PMU) {
(void)si_pmu_measure_alpclk(sih);
}
return sii;
exit:
return NULL;
}
/*
* Allocate a si handle and do the attach.
*/
struct si_pub *
ai_attach(struct bcma_bus *pbus)
{
struct si_info *sii;
/* alloc struct si_info */
sii = kzalloc(sizeof(struct si_info), GFP_ATOMIC);
if (sii == NULL)
return NULL;
if (ai_doattach(sii, pbus) == NULL) {
kfree(sii);
return NULL;
}
return (struct si_pub *) sii;
}
/* may be called with core in reset */
void ai_detach(struct si_pub *sih)
{
struct si_info *sii;
sii = container_of(sih, struct si_info, pub);
if (sii == NULL)
return;
kfree(sii);
}
/*
* read/modify chipcommon core register.
*/
uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val)
{
struct bcma_device *cc;
u32 w;
struct si_info *sii;
sii = container_of(sih, struct si_info, pub);
cc = sii->icbus->drv_cc.core;
/* mask and set */
if (mask || val)
bcma_maskset32(cc, regoff, ~mask, val);
/* readback */
w = bcma_read32(cc, regoff);
return w;
}
/* return the slow clock source - LPO, XTAL, or PCI */
static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc)
{
return SCC_SS_XTAL;
}
/*
* return the ILP (slowclock) min or max frequency
* precondition: we've established the chip has dynamic clk control
*/
static uint ai_slowclk_freq(struct si_pub *sih, bool max_freq,
struct bcma_device *cc)
{
uint div;
/* Chipc rev 10 is InstaClock */
div = bcma_read32(cc, CHIPCREGOFFS(system_clk_ctl));
div = 4 * ((div >> SYCC_CD_SHIFT) + 1);
return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div);
}
static void
ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc)
{
uint slowmaxfreq, pll_delay, slowclk;
uint pll_on_delay, fref_sel_delay;
pll_delay = PLL_DELAY;
/*
* If the slow clock is not sourced by the xtal then
* add the xtal_on_delay since the xtal will also be
* powered down by dynamic clk control logic.
*/
slowclk = ai_slowclk_src(sih, cc);
if (slowclk != SCC_SS_XTAL)
pll_delay += XTAL_ON_DELAY;
/* Starting with 4318 it is ILP that is used for the delays */
slowmaxfreq =
ai_slowclk_freq(sih, false, cc);
pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
bcma_write32(cc, CHIPCREGOFFS(pll_on_delay), pll_on_delay);
bcma_write32(cc, CHIPCREGOFFS(fref_sel_delay), fref_sel_delay);
}
/* initialize power control delay registers */
void ai_clkctl_init(struct si_pub *sih)
{
struct si_info *sii = container_of(sih, struct si_info, pub);
struct bcma_device *cc;
if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL))
return;
cc = sii->icbus->drv_cc.core;
if (cc == NULL)
return;
/* set all Instaclk chip ILP to 1 MHz */
bcma_maskset32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_CD_MASK,
(ILP_DIV_1MHZ << SYCC_CD_SHIFT));
ai_clkctl_setdelay(sih, cc);
}
/*
* return the value suitable for writing to the
* dot11 core FAST_PWRUP_DELAY register
*/
u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
{
struct si_info *sii;
struct bcma_device *cc;
uint slowminfreq;
u16 fpdelay;
sii = container_of(sih, struct si_info, pub);
if (ai_get_cccaps(sih) & CC_CAP_PMU) {
fpdelay = si_pmu_fast_pwrup_delay(sih);
return fpdelay;
}
if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL))
return 0;
fpdelay = 0;
cc = sii->icbus->drv_cc.core;
if (cc) {
slowminfreq = ai_slowclk_freq(sih, false, cc);
fpdelay = (((bcma_read32(cc, CHIPCREGOFFS(pll_on_delay)) + 2)
* 1000000) + (slowminfreq - 1)) / slowminfreq;
}
return fpdelay;
}
/*
* clock control policy function throught chipcommon
*
* set dynamic clk control mode (forceslow, forcefast, dynamic)
* returns true if we are forcing fast clock
* this is a wrapper over the next internal function
* to allow flexible policy settings for outside caller
*/
bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode)
{
struct si_info *sii;
struct bcma_device *cc;
sii = container_of(sih, struct si_info, pub);
cc = sii->icbus->drv_cc.core;
bcma_core_set_clockmode(cc, mode);
return mode == BCMA_CLKMODE_FAST;
}
/* Enable BT-COEX & Ex-PA for 4313 */
void ai_epa_4313war(struct si_pub *sih)
{
struct si_info *sii = container_of(sih, struct si_info, pub);
struct bcma_device *cc;
cc = sii->icbus->drv_cc.core;
/* EPA Fix */
bcma_set32(cc, CHIPCREGOFFS(gpiocontrol), GPIO_CTRL_EPA_EN_MASK);
}
/* check if the device is removed */
bool ai_deviceremoved(struct si_pub *sih)
{
u32 w = 0;
struct si_info *sii;
sii = container_of(sih, struct si_info, pub);
if (sii->icbus->hosttype != BCMA_HOSTTYPE_PCI)
return false;
pci_read_config_dword(sii->pcibus, PCI_VENDOR_ID, &w);
if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM)
return true;
return false;
}

View File

@@ -0,0 +1,229 @@
/*
* Copyright (c) 2011 Broadcom Corporation
*
* 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 _BRCM_AIUTILS_H_
#define _BRCM_AIUTILS_H_
#include <linux/bcma/bcma.h>
#include "types.h"
/*
* SOC Interconnect Address Map.
* All regions may not exist on all chips.
*/
/* each core gets 4Kbytes for registers */
#define SI_CORE_SIZE 0x1000
/*
* Max cores (this is arbitrary, for software
* convenience and could be changed if we
* make any larger chips
*/
#define SI_MAXCORES 16
/* Client Mode sb2pcitranslation2 size in bytes */
#define SI_PCI_DMA_SZ 0x40000000
/* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */
#define SI_PCIE_DMA_H32 0x80000000
/* chipcommon being the first core: */
#define SI_CC_IDX 0
/* SOC Interconnect types (aka chip types) */
#define SOCI_AI 1
/* A register that is common to all cores to
* communicate w/PMU regarding clock control.
*/
#define SI_CLK_CTL_ST 0x1e0 /* clock control and status */
/* clk_ctl_st register */
#define CCS_FORCEALP 0x00000001 /* force ALP request */
#define CCS_FORCEHT 0x00000002 /* force HT request */
#define CCS_FORCEILP 0x00000004 /* force ILP request */
#define CCS_ALPAREQ 0x00000008 /* ALP Avail Request */
#define CCS_HTAREQ 0x00000010 /* HT Avail Request */
#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */
#define CCS_ERSRC_REQ_MASK 0x00000700 /* external resource requests */
#define CCS_ERSRC_REQ_SHIFT 8
#define CCS_ALPAVAIL 0x00010000 /* ALP is available */
#define CCS_HTAVAIL 0x00020000 /* HT is available */
#define CCS_BP_ON_APL 0x00040000 /* RO: running on ALP clock */
#define CCS_BP_ON_HT 0x00080000 /* RO: running on HT clock */
#define CCS_ERSRC_STS_MASK 0x07000000 /* external resource status */
#define CCS_ERSRC_STS_SHIFT 24
/* HT avail in chipc and pcmcia on 4328a0 */
#define CCS0_HTAVAIL 0x00010000
/* ALP avail in chipc and pcmcia on 4328a0 */
#define CCS0_ALPAVAIL 0x00020000
/* Not really related to SOC Interconnect, but a couple of software
* conventions for the use the flash space:
*/
/* Minumum amount of flash we support */
#define FLASH_MIN 0x00020000 /* Minimum flash size */
#define CC_SROM_OTP 0x800 /* SROM/OTP address space */
/* gpiotimerval */
#define GPIO_ONTIME_SHIFT 16
/* Fields in clkdiv */
#define CLKD_OTP 0x000f0000
#define CLKD_OTP_SHIFT 16
/* dynamic clock control defines */
#define LPOMINFREQ 25000 /* low power oscillator min */
#define LPOMAXFREQ 43000 /* low power oscillator max */
#define XTALMINFREQ 19800000 /* 20 MHz - 1% */
#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */
#define PCIMINFREQ 25000000 /* 25 MHz */
#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */
#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
/* clkctl xtal what flags */
#define XTAL 0x1 /* primary crystal oscillator (2050) */
#define PLL 0x2 /* main chip pll */
/* GPIO usage priorities */
#define GPIO_DRV_PRIORITY 0 /* Driver */
#define GPIO_APP_PRIORITY 1 /* Application */
#define GPIO_HI_PRIORITY 2 /* Highest priority. Ignore GPIO
* reservation
*/
/* GPIO pull up/down */
#define GPIO_PULLUP 0
#define GPIO_PULLDN 1
/* GPIO event regtype */
#define GPIO_REGEVT 0 /* GPIO register event */
#define GPIO_REGEVT_INTMSK 1 /* GPIO register event int mask */
#define GPIO_REGEVT_INTPOL 2 /* GPIO register event int polarity */
/* device path */
#define SI_DEVPATH_BUFSZ 16 /* min buffer size in bytes */
/* SI routine enumeration: to be used by update function with multiple hooks */
#define SI_DOATTACH 1
#define SI_PCIDOWN 2
#define SI_PCIUP 3
/*
* Data structure to export all chip specific common variables
* public (read-only) portion of aiutils handle returned by si_attach()
*/
struct si_pub {
int ccrev; /* chip common core rev */
u32 cccaps; /* chip common capabilities */
int pmurev; /* pmu core rev */
u32 pmucaps; /* pmu capabilities */
uint boardtype; /* board type */
uint boardvendor; /* board vendor */
uint chip; /* chip number */
uint chiprev; /* chip revision */
uint chippkg; /* chip package option */
};
struct pci_dev;
struct gpioh_item {
void *arg;
bool level;
void (*handler) (u32 stat, void *arg);
u32 event;
struct gpioh_item *next;
};
/* misc si info needed by some of the routines */
struct si_info {
struct si_pub pub; /* back plane public state (must be first) */
struct bcma_bus *icbus; /* handle to soc interconnect bus */
struct pci_dev *pcibus; /* handle to pci bus */
u32 chipst; /* chip status */
};
/*
* Many of the routines below take an 'sih' handle as their first arg.
* Allocate this by calling si_attach(). Free it by calling si_detach().
* At any one time, the sih is logically focused on one particular si core
* (the "current core").
* Use si_setcore() or si_setcoreidx() to change the association to another core
*/
/* AMBA Interconnect exported externs */
u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val);
/* === exported functions === */
struct si_pub *ai_attach(struct bcma_bus *pbus);
void ai_detach(struct si_pub *sih);
uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val);
void ai_clkctl_init(struct si_pub *sih);
u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih);
bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode);
bool ai_deviceremoved(struct si_pub *sih);
/* Enable Ex-PA for 4313 */
void ai_epa_4313war(struct si_pub *sih);
static inline u32 ai_get_cccaps(struct si_pub *sih)
{
return sih->cccaps;
}
static inline int ai_get_pmurev(struct si_pub *sih)
{
return sih->pmurev;
}
static inline u32 ai_get_pmucaps(struct si_pub *sih)
{
return sih->pmucaps;
}
static inline uint ai_get_boardtype(struct si_pub *sih)
{
return sih->boardtype;
}
static inline uint ai_get_boardvendor(struct si_pub *sih)
{
return sih->boardvendor;
}
static inline uint ai_get_chip_id(struct si_pub *sih)
{
return sih->chip;
}
static inline uint ai_get_chiprev(struct si_pub *sih)
{
return sih->chiprev;
}
static inline uint ai_get_chippkg(struct si_pub *sih)
{
return sih->chippkg;
}
#endif /* _BRCM_AIUTILS_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_AMPDU_H_
#define _BRCM_AMPDU_H_
/*
* Data structure representing an in-progress session for accumulating
* frames for AMPDU.
*
* wlc: pointer to common driver data
* skb_list: queue of skb's for AMPDU
* max_ampdu_len: maximum length for this AMPDU
* max_ampdu_frames: maximum number of frames for this AMPDU
* ampdu_len: total number of bytes accumulated for this AMPDU
* dma_len: DMA length of this AMPDU
*/
struct brcms_ampdu_session {
struct brcms_c_info *wlc;
struct sk_buff_head skb_list;
unsigned max_ampdu_len;
u16 max_ampdu_frames;
u16 ampdu_len;
u16 dma_len;
};
void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
struct brcms_c_info *wlc);
int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
struct sk_buff *p);
void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session);
struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc);
void brcms_c_ampdu_detach(struct ampdu_info *ampdu);
void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
struct sk_buff *p, struct tx_status *txs);
void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc);
void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu);
#endif /* _BRCM_AMPDU_H_ */

View File

@@ -0,0 +1,309 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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/slab.h>
#include <net/mac80211.h>
#include "types.h"
#include "main.h"
#include "phy_shim.h"
#include "antsel.h"
#include "debug.h"
#define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */
#define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */
#define ANT_SELCFG_TX_UNICAST 0 /* unicast tx antenna configuration */
#define ANT_SELCFG_RX_UNICAST 1 /* unicast rx antenna configuration */
#define ANT_SELCFG_TX_DEF 2 /* default tx antenna configuration */
#define ANT_SELCFG_RX_DEF 3 /* default rx antenna configuration */
/* useful macros */
#define BRCMS_ANTSEL_11N_0(ant) ((((ant) & ANT_SELCFG_MASK) >> 4) & 0xf)
#define BRCMS_ANTSEL_11N_1(ant) (((ant) & ANT_SELCFG_MASK) & 0xf)
#define BRCMS_ANTIDX_11N(ant) (((BRCMS_ANTSEL_11N_0(ant)) << 2) +\
(BRCMS_ANTSEL_11N_1(ant)))
#define BRCMS_ANT_ISAUTO_11N(ant) (((ant) & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO)
#define BRCMS_ANTSEL_11N(ant) ((ant) & ANT_SELCFG_MASK)
/* antenna switch */
/* defines for no boardlevel antenna diversity */
#define ANT_SELCFG_DEF_2x2 0x01 /* default antenna configuration */
/* 2x3 antdiv defines and tables for GPIO communication */
#define ANT_SELCFG_NUM_2x3 3
#define ANT_SELCFG_DEF_2x3 0x01 /* default antenna configuration */
/* 2x4 antdiv rev4 defines and tables for GPIO communication */
#define ANT_SELCFG_NUM_2x4 4
#define ANT_SELCFG_DEF_2x4 0x02 /* default antenna configuration */
static const u16 mimo_2x4_div_antselpat_tbl[] = {
0, 0, 0x9, 0xa, /* ant0: 0 ant1: 2,3 */
0, 0, 0x5, 0x6, /* ant0: 1 ant1: 2,3 */
0, 0, 0, 0, /* n.a. */
0, 0, 0, 0 /* n.a. */
};
static const u8 mimo_2x4_div_antselid_tbl[16] = {
0, 0, 0, 0, 0, 2, 3, 0,
0, 0, 1, 0, 0, 0, 0, 0 /* pat to antselid */
};
static const u16 mimo_2x3_div_antselpat_tbl[] = {
16, 0, 1, 16, /* ant0: 0 ant1: 1,2 */
16, 16, 16, 16, /* n.a. */
16, 2, 16, 16, /* ant0: 2 ant1: 1 */
16, 16, 16, 16 /* n.a. */
};
static const u8 mimo_2x3_div_antselid_tbl[16] = {
0, 1, 2, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 /* pat to antselid */
};
/* boardlevel antenna selection: init antenna selection structure */
static void
brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel,
bool auto_sel)
{
if (asi->antsel_type == ANTSEL_2x3) {
u8 antcfg_def = ANT_SELCFG_DEF_2x3 |
((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0);
antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def;
antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def;
antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def;
antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def;
antsel->num_antcfg = ANT_SELCFG_NUM_2x3;
} else if (asi->antsel_type == ANTSEL_2x4) {
antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4;
antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4;
antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4;
antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4;
antsel->num_antcfg = ANT_SELCFG_NUM_2x4;
} else { /* no antenna selection available */
antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2;
antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2;
antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2;
antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2;
antsel->num_antcfg = 0;
}
}
struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
{
struct antsel_info *asi;
struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC);
if (!asi)
return NULL;
asi->wlc = wlc;
asi->pub = wlc->pub;
asi->antsel_type = ANTSEL_NA;
asi->antsel_avail = false;
asi->antsel_antswitch = sprom->antswitch;
if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) {
switch (asi->antsel_antswitch) {
case ANTSWITCH_TYPE_1:
case ANTSWITCH_TYPE_2:
case ANTSWITCH_TYPE_3:
/* 4321/2 board with 2x3 switch logic */
asi->antsel_type = ANTSEL_2x3;
/* Antenna selection availability */
if ((sprom->ant_available_bg == 7) ||
(sprom->ant_available_a == 7)) {
asi->antsel_avail = true;
} else if (
sprom->ant_available_bg == 3 ||
sprom->ant_available_a == 3) {
asi->antsel_avail = false;
} else {
asi->antsel_avail = false;
brcms_err(wlc->hw->d11core,
"antsel_attach: 2o3 "
"board cfg invalid\n");
}
break;
default:
break;
}
} else if ((asi->pub->sromrev == 4) &&
(sprom->ant_available_bg == 7) &&
(sprom->ant_available_a == 0)) {
/* hack to match old 4321CB2 cards with 2of3 antenna switch */
asi->antsel_type = ANTSEL_2x3;
asi->antsel_avail = true;
} else if (asi->pub->boardflags2 & BFL2_2X4_DIV) {
asi->antsel_type = ANTSEL_2x4;
asi->antsel_avail = true;
}
/* Set the antenna selection type for the low driver */
brcms_b_antsel_type_set(wlc->hw, asi->antsel_type);
/* Init (auto/manual) antenna selection */
brcms_c_antsel_init_cfg(asi, &asi->antcfg_11n, true);
brcms_c_antsel_init_cfg(asi, &asi->antcfg_cur, true);
return asi;
}
void brcms_c_antsel_detach(struct antsel_info *asi)
{
kfree(asi);
}
/*
* boardlevel antenna selection:
* convert ant_cfg to mimo_antsel (ucode interface)
*/
static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg)
{
u8 idx = BRCMS_ANTIDX_11N(BRCMS_ANTSEL_11N(ant_cfg));
u16 mimo_antsel = 0;
if (asi->antsel_type == ANTSEL_2x4) {
/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf);
return mimo_antsel;
} else if (asi->antsel_type == ANTSEL_2x3) {
/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf);
return mimo_antsel;
}
return mimo_antsel;
}
/* boardlevel antenna selection: ucode interface control */
static int brcms_c_antsel_cfgupd(struct antsel_info *asi,
struct brcms_antselcfg *antsel)
{
struct brcms_c_info *wlc = asi->wlc;
u8 ant_cfg;
u16 mimo_antsel;
/* 1) Update TX antconfig for all frames that are not unicast data
* (aka default TX)
*/
ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF];
mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg);
brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_TXDFLT, mimo_antsel);
/*
* Update driver stats for currently selected
* default tx/rx antenna config
*/
asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg;
/* 2) Update RX antconfig for all frames that are not unicast data
* (aka default RX)
*/
ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF];
mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg);
brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_RXDFLT, mimo_antsel);
/*
* Update driver stats for currently selected
* default tx/rx antenna config
*/
asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg;
return 0;
}
void brcms_c_antsel_init(struct antsel_info *asi)
{
if ((asi->antsel_type == ANTSEL_2x3) ||
(asi->antsel_type == ANTSEL_2x4))
brcms_c_antsel_cfgupd(asi, &asi->antcfg_11n);
}
/* boardlevel antenna selection: convert id to ant_cfg */
static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id)
{
u8 antcfg = ANT_SELCFG_DEF_2x2;
if (asi->antsel_type == ANTSEL_2x4) {
/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2));
return antcfg;
} else if (asi->antsel_type == ANTSEL_2x3) {
/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1));
return antcfg;
}
return antcfg;
}
void
brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel,
u8 antselid, u8 fbantselid, u8 *antcfg,
u8 *fbantcfg)
{
u8 ant;
/* if use default, assign it and return */
if (usedef) {
*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_DEF];
*fbantcfg = *antcfg;
return;
}
if (!sel) {
*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
*fbantcfg = *antcfg;
} else {
ant = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
if ((ant & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO) {
*antcfg = brcms_c_antsel_id2antcfg(asi, antselid);
*fbantcfg = brcms_c_antsel_id2antcfg(asi, fbantselid);
} else {
*antcfg =
asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
*fbantcfg = *antcfg;
}
}
return;
}
/* boardlevel antenna selection: convert mimo_antsel (ucode interface) to id */
u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel)
{
u8 antselid = 0;
if (asi->antsel_type == ANTSEL_2x4) {
/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
antselid = mimo_2x4_div_antselid_tbl[(antsel & 0xf)];
return antselid;
} else if (asi->antsel_type == ANTSEL_2x3) {
/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
antselid = mimo_2x3_div_antselid_tbl[(antsel & 0xf)];
return antselid;
}
return antselid;
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_ANTSEL_H_
#define _BRCM_ANTSEL_H_
struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc);
void brcms_c_antsel_detach(struct antsel_info *asi);
void brcms_c_antsel_init(struct antsel_info *asi);
void brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel,
u8 id, u8 fbid, u8 *antcfg, u8 *fbantcfg);
u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel);
#endif /* _BRCM_ANTSEL_H_ */

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 2011 Broadcom Corporation
*
* 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.
*/
#if !defined(__TRACE_BRCMSMAC_H) || defined(TRACE_HEADER_MULTI_READ)
#define __TRACE_BRCMSMAC_H
#include <linux/tracepoint.h>
#undef TRACE_SYSTEM
#define TRACE_SYSTEM brcmsmac
/*
* We define a tracepoint, its arguments, its printk format and its
* 'fast binary record' layout.
*/
TRACE_EVENT(brcms_timer,
/* TPPROTO is the prototype of the function called by this tracepoint */
TP_PROTO(struct brcms_timer *t),
/*
* TPARGS(firstarg, p) are the parameters names, same as found in the
* prototype.
*/
TP_ARGS(t),
/*
* Fast binary tracing: define the trace record via TP_STRUCT__entry().
* You can think about it like a regular C structure local variable
* definition.
*/
TP_STRUCT__entry(
__field(uint, ms)
__field(uint, set)
__field(uint, periodic)
),
TP_fast_assign(
__entry->ms = t->ms;
__entry->set = t->set;
__entry->periodic = t->periodic;
),
TP_printk(
"ms=%u set=%u periodic=%u",
__entry->ms, __entry->set, __entry->periodic
)
);
TRACE_EVENT(brcms_dpc,
TP_PROTO(unsigned long data),
TP_ARGS(data),
TP_STRUCT__entry(
__field(unsigned long, data)
),
TP_fast_assign(
__entry->data = data;
),
TP_printk(
"data=%p",
(void *)__entry->data
)
);
TRACE_EVENT(brcms_macintstatus,
TP_PROTO(const struct device *dev, int in_isr, u32 macintstatus,
u32 mask),
TP_ARGS(dev, in_isr, macintstatus, mask),
TP_STRUCT__entry(
__string(dev, dev_name(dev))
__field(int, in_isr)
__field(u32, macintstatus)
__field(u32, mask)
),
TP_fast_assign(
__assign_str(dev, dev_name(dev));
__entry->in_isr = in_isr;
__entry->macintstatus = macintstatus;
__entry->mask = mask;
),
TP_printk("[%s] in_isr=%d macintstatus=%#x mask=%#x", __get_str(dev),
__entry->in_isr, __entry->macintstatus, __entry->mask)
);
#endif /* __TRACE_BRCMSMAC_H */
#ifdef CONFIG_BRCM_TRACING
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE brcms_trace_brcmsmac
#include <trace/define_trace.h>
#endif /* CONFIG_BRCM_TRACING */

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2011 Broadcom Corporation
*
* 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.
*/
#if !defined(__TRACE_BRCMSMAC_MSG_H) || defined(TRACE_HEADER_MULTI_READ)
#define __TRACE_BRCMSMAC_MSG_H
#include <linux/tracepoint.h>
#undef TRACE_SYSTEM
#define TRACE_SYSTEM brcmsmac_msg
#define MAX_MSG_LEN 100
DECLARE_EVENT_CLASS(brcms_msg_event,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf),
TP_STRUCT__entry(
__dynamic_array(char, msg, MAX_MSG_LEN)
),
TP_fast_assign(
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
MAX_MSG_LEN, vaf->fmt,
*vaf->va) >= MAX_MSG_LEN);
),
TP_printk("%s", __get_str(msg))
);
DEFINE_EVENT(brcms_msg_event, brcms_info,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf)
);
DEFINE_EVENT(brcms_msg_event, brcms_warn,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf)
);
DEFINE_EVENT(brcms_msg_event, brcms_err,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf)
);
DEFINE_EVENT(brcms_msg_event, brcms_crit,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf)
);
TRACE_EVENT(brcms_dbg,
TP_PROTO(u32 level, const char *func, struct va_format *vaf),
TP_ARGS(level, func, vaf),
TP_STRUCT__entry(
__field(u32, level)
__string(func, func)
__dynamic_array(char, msg, MAX_MSG_LEN)
),
TP_fast_assign(
__entry->level = level;
__assign_str(func, func);
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
MAX_MSG_LEN, vaf->fmt,
*vaf->va) >= MAX_MSG_LEN);
),
TP_printk("%s: %s", __get_str(func), __get_str(msg))
);
#endif /* __TRACE_BRCMSMAC_MSG_H */
#ifdef CONFIG_BRCM_TRACING
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE brcms_trace_brcmsmac_msg
#include <trace/define_trace.h>
#endif /* CONFIG_BRCM_TRACING */

View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2011 Broadcom Corporation
*
* 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.
*/
#if !defined(__TRACE_BRCMSMAC_TX_H) || defined(TRACE_HEADER_MULTI_READ)
#define __TRACE_BRCMSMAC_TX_H
#include <linux/tracepoint.h>
#undef TRACE_SYSTEM
#define TRACE_SYSTEM brcmsmac_tx
TRACE_EVENT(brcms_txdesc,
TP_PROTO(const struct device *dev,
void *txh, size_t txh_len),
TP_ARGS(dev, txh, txh_len),
TP_STRUCT__entry(
__string(dev, dev_name(dev))
__dynamic_array(u8, txh, txh_len)
),
TP_fast_assign(
__assign_str(dev, dev_name(dev));
memcpy(__get_dynamic_array(txh), txh, txh_len);
),
TP_printk("[%s] txdesc", __get_str(dev))
);
TRACE_EVENT(brcms_txstatus,
TP_PROTO(const struct device *dev, u16 framelen, u16 frameid,
u16 status, u16 lasttxtime, u16 sequence, u16 phyerr,
u16 ackphyrxsh),
TP_ARGS(dev, framelen, frameid, status, lasttxtime, sequence, phyerr,
ackphyrxsh),
TP_STRUCT__entry(
__string(dev, dev_name(dev))
__field(u16, framelen)
__field(u16, frameid)
__field(u16, status)
__field(u16, lasttxtime)
__field(u16, sequence)
__field(u16, phyerr)
__field(u16, ackphyrxsh)
),
TP_fast_assign(
__assign_str(dev, dev_name(dev));
__entry->framelen = framelen;
__entry->frameid = frameid;
__entry->status = status;
__entry->lasttxtime = lasttxtime;
__entry->sequence = sequence;
__entry->phyerr = phyerr;
__entry->ackphyrxsh = ackphyrxsh;
),
TP_printk("[%s] FrameId %#04x TxStatus %#04x LastTxTime %#04x "
"Seq %#04x PHYTxStatus %#04x RxAck %#04x",
__get_str(dev), __entry->frameid, __entry->status,
__entry->lasttxtime, __entry->sequence, __entry->phyerr,
__entry->ackphyrxsh)
);
TRACE_EVENT(brcms_ampdu_session,
TP_PROTO(const struct device *dev, unsigned max_ampdu_len,
u16 max_ampdu_frames, u16 ampdu_len, u16 ampdu_frames,
u16 dma_len),
TP_ARGS(dev, max_ampdu_len, max_ampdu_frames, ampdu_len, ampdu_frames,
dma_len),
TP_STRUCT__entry(
__string(dev, dev_name(dev))
__field(unsigned, max_ampdu_len)
__field(u16, max_ampdu_frames)
__field(u16, ampdu_len)
__field(u16, ampdu_frames)
__field(u16, dma_len)
),
TP_fast_assign(
__assign_str(dev, dev_name(dev));
__entry->max_ampdu_len = max_ampdu_len;
__entry->max_ampdu_frames = max_ampdu_frames;
__entry->ampdu_len = ampdu_len;
__entry->ampdu_frames = ampdu_frames;
__entry->dma_len = dma_len;
),
TP_printk("[%s] ampdu session max_len=%u max_frames=%u len=%u frames=%u dma_len=%u",
__get_str(dev), __entry->max_ampdu_len,
__entry->max_ampdu_frames, __entry->ampdu_len,
__entry->ampdu_frames, __entry->dma_len)
);
#endif /* __TRACE_BRCMSMAC_TX_H */
#ifdef CONFIG_BRCM_TRACING
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE brcms_trace_brcmsmac_tx
#include <trace/define_trace.h>
#endif /* CONFIG_BRCM_TRACING */

View File

@@ -0,0 +1,23 @@
/*
* Copyright (c) 2011 Broadcom Corporation
*
* 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/module.h> /* bug in tracepoint.h, it should include this */
#ifndef __CHECKER__
#include "mac80211_if.h"
#define CREATE_TRACE_POINTS
#include "brcms_trace_events.h"
#endif

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2011 Broadcom Corporation
*
* 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 __BRCMS_TRACE_EVENTS_H
#define __BRCMS_TRACE_EVENTS_H
#include <linux/types.h>
#include <linux/device.h>
#include <linux/tracepoint.h>
#include "mac80211_if.h"
#ifndef CONFIG_BRCM_TRACING
#undef TRACE_EVENT
#define TRACE_EVENT(name, proto, ...) \
static inline void trace_ ## name(proto) {}
#undef DECLARE_EVENT_CLASS
#define DECLARE_EVENT_CLASS(...)
#undef DEFINE_EVENT
#define DEFINE_EVENT(evt_class, name, proto, ...) \
static inline void trace_ ## name(proto) {}
#endif
#include "brcms_trace_brcmsmac.h"
#include "brcms_trace_brcmsmac_tx.h"
#include "brcms_trace_brcmsmac_msg.h"
#endif /* __TRACE_BRCMSMAC_H */

View File

@@ -0,0 +1,774 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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/types.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <net/regulatory.h>
#include <defs.h>
#include "pub.h"
#include "phy/phy_hal.h"
#include "main.h"
#include "stf.h"
#include "channel.h"
#include "mac80211_if.h"
#include "debug.h"
/* QDB() macro takes a dB value and converts to a quarter dB value */
#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
#define LOCALE_MIMO_IDX_bn 0
#define LOCALE_MIMO_IDX_11n 0
/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14
/* maxpwr mapping to 5GHz band channels:
* maxpwr[0] - channels [34-48]
* maxpwr[1] - channels [52-60]
* maxpwr[2] - channels [62-64]
* maxpwr[3] - channels [100-140]
* maxpwr[4] - channels [149-165]
*/
#define BAND_5G_PWR_LVLS 5 /* 5 power levels for 5G */
#define LC(id) LOCALE_MIMO_IDX_ ## id
#define LOCALES(mimo2, mimo5) \
{LC(mimo2), LC(mimo5)}
/* macro to get 5 GHz channel group index for tx power */
#define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \
(((c) < 62) ? 1 : \
(((c) < 100) ? 2 : \
(((c) < 149) ? 3 : 4))))
#define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \
NL80211_RRF_NO_IR)
#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \
NL80211_RRF_NO_IR)
#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \
NL80211_RRF_DFS | \
NL80211_RRF_NO_IR)
#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \
NL80211_RRF_DFS | \
NL80211_RRF_NO_IR)
#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \
NL80211_RRF_NO_IR)
static const struct ieee80211_regdomain brcms_regdom_x2 = {
.n_reg_rules = 6,
.alpha2 = "X2",
.reg_rules = {
BRCM_2GHZ_2412_2462,
BRCM_2GHZ_2467_2472,
BRCM_5GHZ_5180_5240,
BRCM_5GHZ_5260_5320,
BRCM_5GHZ_5500_5700,
BRCM_5GHZ_5745_5825,
}
};
/* locale per-channel tx power limits for MIMO frames
* maxpwr arrays are index by channel for 2.4 GHz limits, and
* by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
*/
struct locale_mimo_info {
/* tx 20 MHz power limits, qdBm units */
s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE];
/* tx 40 MHz power limits, qdBm units */
s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE];
};
/* Country names and abbreviations with locale defined from ISO 3166 */
struct country_info {
const u8 locale_mimo_2G; /* 2.4G mimo info */
const u8 locale_mimo_5G; /* 5G mimo info */
};
struct brcms_regd {
struct country_info country;
const struct ieee80211_regdomain *regdomain;
};
struct brcms_cm_info {
struct brcms_pub *pub;
struct brcms_c_info *wlc;
const struct brcms_regd *world_regd;
};
/*
* MIMO Locale Definitions - 2.4 GHz
*/
static const struct locale_mimo_info locale_bn = {
{QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
QDB(13), QDB(13), QDB(13)},
{0, 0, QDB(13), QDB(13), QDB(13),
QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
QDB(13), 0, 0},
};
static const struct locale_mimo_info *g_mimo_2g_table[] = {
&locale_bn
};
/*
* MIMO Locale Definitions - 5 GHz
*/
static const struct locale_mimo_info locale_11n = {
{ /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)},
{QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)},
};
static const struct locale_mimo_info *g_mimo_5g_table[] = {
&locale_11n
};
static const struct brcms_regd cntry_locales[] = {
/* Worldwide RoW 2, must always be at index 0 */
{
.country = LOCALES(bn, 11n),
.regdomain = &brcms_regdom_x2,
},
};
static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx)
{
if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table))
return NULL;
return g_mimo_2g_table[locale_idx];
}
static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx)
{
if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table))
return NULL;
return g_mimo_5g_table[locale_idx];
}
/*
* Indicates whether the country provided is valid to pass
* to cfg80211 or not.
*
* returns true if valid; false if not.
*/
static bool brcms_c_country_valid(const char *ccode)
{
/*
* only allow ascii alpha uppercase for the first 2
* chars.
*/
if (!((0x80 & ccode[0]) == 0 && ccode[0] >= 0x41 && ccode[0] <= 0x5A &&
(0x80 & ccode[1]) == 0 && ccode[1] >= 0x41 && ccode[1] <= 0x5A))
return false;
/*
* do not match ISO 3166-1 user assigned country codes
* that may be in the driver table
*/
if (!strcmp("AA", ccode) || /* AA */
!strcmp("ZZ", ccode) || /* ZZ */
ccode[0] == 'X' || /* XA - XZ */
(ccode[0] == 'Q' && /* QM - QZ */
(ccode[1] >= 'M' && ccode[1] <= 'Z')))
return false;
if (!strcmp("NA", ccode))
return false;
return true;
}
static const struct brcms_regd *brcms_world_regd(const char *regdom, int len)
{
const struct brcms_regd *regd = NULL;
int i;
for (i = 0; i < ARRAY_SIZE(cntry_locales); i++) {
if (!strncmp(regdom, cntry_locales[i].regdomain->alpha2, len)) {
regd = &cntry_locales[i];
break;
}
}
return regd;
}
static const struct brcms_regd *brcms_default_world_regd(void)
{
return &cntry_locales[0];
}
/* JP, J1 - J10 are Japan ccodes */
static bool brcms_c_japan_ccode(const char *ccode)
{
return (ccode[0] == 'J' &&
(ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
}
static void
brcms_c_channel_min_txpower_limits_with_local_constraint(
struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
u8 local_constraint_qdbm)
{
int j;
/* CCK Rates */
for (j = 0; j < WL_TX_POWER_CCK_NUM; j++)
txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm);
/* 20 MHz Legacy OFDM SISO */
for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++)
txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm);
/* 20 MHz Legacy OFDM CDD */
for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
txpwr->ofdm_cdd[j] =
min(txpwr->ofdm_cdd[j], local_constraint_qdbm);
/* 40 MHz Legacy OFDM SISO */
for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
txpwr->ofdm_40_siso[j] =
min(txpwr->ofdm_40_siso[j], local_constraint_qdbm);
/* 40 MHz Legacy OFDM CDD */
for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
txpwr->ofdm_40_cdd[j] =
min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm);
/* 20MHz MCS 0-7 SISO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_20_siso[j] =
min(txpwr->mcs_20_siso[j], local_constraint_qdbm);
/* 20MHz MCS 0-7 CDD */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_20_cdd[j] =
min(txpwr->mcs_20_cdd[j], local_constraint_qdbm);
/* 20MHz MCS 0-7 STBC */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_20_stbc[j] =
min(txpwr->mcs_20_stbc[j], local_constraint_qdbm);
/* 20MHz MCS 8-15 MIMO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
txpwr->mcs_20_mimo[j] =
min(txpwr->mcs_20_mimo[j], local_constraint_qdbm);
/* 40MHz MCS 0-7 SISO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_40_siso[j] =
min(txpwr->mcs_40_siso[j], local_constraint_qdbm);
/* 40MHz MCS 0-7 CDD */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_40_cdd[j] =
min(txpwr->mcs_40_cdd[j], local_constraint_qdbm);
/* 40MHz MCS 0-7 STBC */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_40_stbc[j] =
min(txpwr->mcs_40_stbc[j], local_constraint_qdbm);
/* 40MHz MCS 8-15 MIMO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
txpwr->mcs_40_mimo[j] =
min(txpwr->mcs_40_mimo[j], local_constraint_qdbm);
/* 40MHz MCS 32 */
txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm);
}
/*
* set the driver's current country and regulatory information
* using a country code as the source. Look up built in country
* information found with the country code.
*/
static void
brcms_c_set_country(struct brcms_cm_info *wlc_cm,
const struct brcms_regd *regd)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
if ((wlc->pub->_n_enab & SUPPORT_11N) !=
wlc->protection->nmode_user)
brcms_c_set_nmode(wlc);
brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
return;
}
struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
{
struct brcms_cm_info *wlc_cm;
struct brcms_pub *pub = wlc->pub;
struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
const char *ccode = sprom->alpha2;
int ccode_len = sizeof(sprom->alpha2);
wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
if (wlc_cm == NULL)
return NULL;
wlc_cm->pub = pub;
wlc_cm->wlc = wlc;
wlc->cmi = wlc_cm;
/* store the country code for passing up as a regulatory hint */
wlc_cm->world_regd = brcms_world_regd(ccode, ccode_len);
if (brcms_c_country_valid(ccode))
strncpy(wlc->pub->srom_ccode, ccode, ccode_len);
/*
* If no custom world domain is found in the SROM, use the
* default "X2" domain.
*/
if (!wlc_cm->world_regd) {
wlc_cm->world_regd = brcms_default_world_regd();
ccode = wlc_cm->world_regd->regdomain->alpha2;
ccode_len = BRCM_CNTRY_BUF_SZ - 1;
}
/* save default country for exiting 11d regulatory mode */
strncpy(wlc->country_default, ccode, ccode_len);
/* initialize autocountry_default to driver default */
strncpy(wlc->autocountry_default, ccode, ccode_len);
brcms_c_set_country(wlc_cm, wlc_cm->world_regd);
return wlc_cm;
}
void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
{
kfree(wlc_cm);
}
void
brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
u8 local_constraint_qdbm)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
struct txpwr_limits txpwr;
brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
brcms_c_channel_min_txpower_limits_with_local_constraint(
wlc_cm, &txpwr, local_constraint_qdbm
);
/* set or restore gmode as required by regulatory */
if (ch->flags & IEEE80211_CHAN_NO_OFDM)
brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
else
brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
brcms_b_set_chanspec(wlc->hw, chanspec,
!!(ch->flags & IEEE80211_CHAN_NO_IR),
&txpwr);
}
void
brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
struct txpwr_limits *txpwr)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
uint i;
uint chan;
int maxpwr;
int delta;
const struct country_info *country;
struct brcms_band *band;
int conducted_max = BRCMS_TXPWR_MAX;
const struct locale_mimo_info *li_mimo;
int maxpwr20, maxpwr40;
int maxpwr_idx;
uint j;
memset(txpwr, 0, sizeof(struct txpwr_limits));
if (WARN_ON(!ch))
return;
country = &wlc_cm->world_regd->country;
chan = CHSPEC_CHANNEL(chanspec);
band = wlc->bandstate[chspec_bandunit(chanspec)];
li_mimo = (band->bandtype == BRCM_BAND_5G) ?
brcms_c_get_mimo_5g(country->locale_mimo_5G) :
brcms_c_get_mimo_2g(country->locale_mimo_2G);
delta = band->antgain;
if (band->bandtype == BRCM_BAND_2G)
conducted_max = QDB(22);
maxpwr = QDB(ch->max_power) - delta;
maxpwr = max(maxpwr, 0);
maxpwr = min(maxpwr, conducted_max);
/* CCK txpwr limits for 2.4G band */
if (band->bandtype == BRCM_BAND_2G) {
for (i = 0; i < BRCMS_NUM_RATES_CCK; i++)
txpwr->cck[i] = (u8) maxpwr;
}
for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
txpwr->ofdm[i] = (u8) maxpwr;
/*
* OFDM 40 MHz SISO has the same power as the corresponding
* MCS0-7 rate unless overriden by the locale specific code.
* We set this value to 0 as a flag (presumably 0 dBm isn't
* a possibility) and then copy the MCS0-7 value to the 40 MHz
* value if it wasn't explicitly set.
*/
txpwr->ofdm_40_siso[i] = 0;
txpwr->ofdm_cdd[i] = (u8) maxpwr;
txpwr->ofdm_40_cdd[i] = 0;
}
delta = 0;
if (band->antgain > QDB(6))
delta = band->antgain - QDB(6); /* Excess over 6 dB */
if (band->bandtype == BRCM_BAND_2G)
maxpwr_idx = (chan - 1);
else
maxpwr_idx = CHANNEL_POWER_IDX_5G(chan);
maxpwr20 = li_mimo->maxpwr20[maxpwr_idx];
maxpwr40 = li_mimo->maxpwr40[maxpwr_idx];
maxpwr20 = maxpwr20 - delta;
maxpwr20 = max(maxpwr20, 0);
maxpwr40 = maxpwr40 - delta;
maxpwr40 = max(maxpwr40, 0);
/* Fill in the MCS 0-7 (SISO) rates */
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
/*
* 20 MHz has the same power as the corresponding OFDM rate
* unless overriden by the locale specific code.
*/
txpwr->mcs_20_siso[i] = txpwr->ofdm[i];
txpwr->mcs_40_siso[i] = 0;
}
/* Fill in the MCS 0-7 CDD rates */
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
txpwr->mcs_20_cdd[i] = (u8) maxpwr20;
txpwr->mcs_40_cdd[i] = (u8) maxpwr40;
}
/*
* These locales have SISO expressed in the
* table and override CDD later
*/
if (li_mimo == &locale_bn) {
if (li_mimo == &locale_bn) {
maxpwr20 = QDB(16);
maxpwr40 = 0;
if (chan >= 3 && chan <= 11)
maxpwr40 = QDB(16);
}
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
txpwr->mcs_20_siso[i] = (u8) maxpwr20;
txpwr->mcs_40_siso[i] = (u8) maxpwr40;
}
}
/* Fill in the MCS 0-7 STBC rates */
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
txpwr->mcs_20_stbc[i] = 0;
txpwr->mcs_40_stbc[i] = 0;
}
/* Fill in the MCS 8-15 SDM rates */
for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) {
txpwr->mcs_20_mimo[i] = (u8) maxpwr20;
txpwr->mcs_40_mimo[i] = (u8) maxpwr40;
}
/* Fill in MCS32 */
txpwr->mcs32 = (u8) maxpwr40;
for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
if (txpwr->ofdm_40_cdd[i] == 0)
txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
if (i == 0) {
i = i + 1;
if (txpwr->ofdm_40_cdd[i] == 0)
txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
}
}
/*
* Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO
* value if it wasn't provided explicitly.
*/
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
if (txpwr->mcs_40_siso[i] == 0)
txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i];
}
for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
if (txpwr->ofdm_40_siso[i] == 0)
txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
if (i == 0) {
i = i + 1;
if (txpwr->ofdm_40_siso[i] == 0)
txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
}
}
/*
* Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding
* STBC values if they weren't provided explicitly.
*/
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
if (txpwr->mcs_20_stbc[i] == 0)
txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i];
if (txpwr->mcs_40_stbc[i] == 0)
txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i];
}
return;
}
/*
* Verify the chanspec is using a legal set of parameters, i.e. that the
* chanspec specified a band, bw, ctl_sb and channel and that the
* combination could be legal given any set of circumstances.
* RETURNS: true is the chanspec is malformed, false if it looks good.
*/
static bool brcms_c_chspec_malformed(u16 chanspec)
{
/* must be 2G or 5G band */
if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
return true;
/* must be 20 or 40 bandwidth */
if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
return true;
/* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */
if (CHSPEC_IS20(chanspec)) {
if (!CHSPEC_SB_NONE(chanspec))
return true;
} else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) {
return true;
}
return false;
}
/*
* Validate the chanspec for this locale, for 40MHZ we need to also
* check that the sidebands are valid 20MZH channels in this locale
* and they are also a legal HT combination
*/
static bool
brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
u8 channel = CHSPEC_CHANNEL(chspec);
/* check the chanspec */
if (brcms_c_chspec_malformed(chspec)) {
brcms_err(wlc->hw->d11core, "wl%d: malformed chanspec 0x%x\n",
wlc->pub->unit, chspec);
return false;
}
if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
chspec_bandunit(chspec))
return false;
return true;
}
bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec)
{
return brcms_c_valid_chanspec_ext(wlc_cm, chspec);
}
static bool brcms_is_radar_freq(u16 center_freq)
{
return center_freq >= 5260 && center_freq <= 5700;
}
static void brcms_reg_apply_radar_flags(struct wiphy *wiphy)
{
struct ieee80211_supported_band *sband;
struct ieee80211_channel *ch;
int i;
sband = wiphy->bands[IEEE80211_BAND_5GHZ];
if (!sband)
return;
for (i = 0; i < sband->n_channels; i++) {
ch = &sband->channels[i];
if (!brcms_is_radar_freq(ch->center_freq))
continue;
/*
* All channels in this range should be passive and have
* DFS enabled.
*/
if (!(ch->flags & IEEE80211_CHAN_DISABLED))
ch->flags |= IEEE80211_CHAN_RADAR |
IEEE80211_CHAN_NO_IR |
IEEE80211_CHAN_NO_IR;
}
}
static void
brcms_reg_apply_beaconing_flags(struct wiphy *wiphy,
enum nl80211_reg_initiator initiator)
{
struct ieee80211_supported_band *sband;
struct ieee80211_channel *ch;
const struct ieee80211_reg_rule *rule;
int band, i;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
sband = wiphy->bands[band];
if (!sband)
continue;
for (i = 0; i < sband->n_channels; i++) {
ch = &sband->channels[i];
if (ch->flags &
(IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR))
continue;
if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
rule = freq_reg_info(wiphy,
MHZ_TO_KHZ(ch->center_freq));
if (IS_ERR(rule))
continue;
if (!(rule->flags & NL80211_RRF_NO_IR))
ch->flags &= ~IEEE80211_CHAN_NO_IR;
} else if (ch->beacon_found) {
ch->flags &= ~IEEE80211_CHAN_NO_IR;
}
}
}
}
static void brcms_reg_notifier(struct wiphy *wiphy,
struct regulatory_request *request)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct brcms_info *wl = hw->priv;
struct brcms_c_info *wlc = wl->wlc;
struct ieee80211_supported_band *sband;
struct ieee80211_channel *ch;
int band, i;
bool ch_found = false;
brcms_reg_apply_radar_flags(wiphy);
if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
brcms_reg_apply_beaconing_flags(wiphy, request->initiator);
/* Disable radio if all channels disallowed by regulatory */
for (band = 0; !ch_found && band < IEEE80211_NUM_BANDS; band++) {
sband = wiphy->bands[band];
if (!sband)
continue;
for (i = 0; !ch_found && i < sband->n_channels; i++) {
ch = &sband->channels[i];
if (!(ch->flags & IEEE80211_CHAN_DISABLED))
ch_found = true;
}
}
if (ch_found) {
mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
} else {
mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
brcms_err(wlc->hw->d11core,
"wl%d: %s: no valid channel for \"%s\"\n",
wlc->pub->unit, __func__, request->alpha2);
}
if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
brcms_c_japan_ccode(request->alpha2));
}
void brcms_c_regd_init(struct brcms_c_info *wlc)
{
struct wiphy *wiphy = wlc->wiphy;
const struct brcms_regd *regd = wlc->cmi->world_regd;
struct ieee80211_supported_band *sband;
struct ieee80211_channel *ch;
struct brcms_chanvec sup_chan;
struct brcms_band *band;
int band_idx, i;
/* Disable any channels not supported by the phy */
for (band_idx = 0; band_idx < wlc->pub->_nbands; band_idx++) {
band = wlc->bandstate[band_idx];
wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
&sup_chan);
if (band_idx == BAND_2G_INDEX)
sband = wiphy->bands[IEEE80211_BAND_2GHZ];
else
sband = wiphy->bands[IEEE80211_BAND_5GHZ];
for (i = 0; i < sband->n_channels; i++) {
ch = &sband->channels[i];
if (!isset(sup_chan.vec, ch->hw_value))
ch->flags |= IEEE80211_CHAN_DISABLED;
}
}
wlc->wiphy->reg_notifier = brcms_reg_notifier;
wlc->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
REGULATORY_STRICT_REG;
wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain);
brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER);
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_CHANNEL_H_
#define _BRCM_CHANNEL_H_
/* conversion for phy txpwr calculations that use .25 dB units */
#define BRCMS_TXPWR_DB_FACTOR 4
/* bits for locale_info flags */
#define BRCMS_PEAK_CONDUCTED 0x00 /* Peak for locals */
#define BRCMS_EIRP 0x01 /* Flag for EIRP */
#define BRCMS_DFS_TPC 0x02 /* Flag for DFS TPC */
#define BRCMS_NO_OFDM 0x04 /* Flag for No OFDM */
#define BRCMS_NO_40MHZ 0x08 /* Flag for No MIMO 40MHz */
#define BRCMS_NO_MIMO 0x10 /* Flag for No MIMO, 20 or 40 MHz */
#define BRCMS_RADAR_TYPE_EU 0x20 /* Flag for EU */
#define BRCMS_DFS_FCC BRCMS_DFS_TPC /* Flag for DFS FCC */
#define BRCMS_DFS_EU (BRCMS_DFS_TPC | BRCMS_RADAR_TYPE_EU) /* Flag for DFS EU */
struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc);
void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm);
bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec);
void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
struct txpwr_limits *txpwr);
void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
u8 local_constraint_qdbm);
void brcms_c_regd_init(struct brcms_c_info *wlc);
#endif /* _WLC_CHANNEL_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,270 @@
/*
* Copyright (c) 2012 Broadcom Corporation
* Copyright (c) 2012 Canonical Ltd.
*
* 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/debugfs.h>
#include <linux/if_ether.h>
#include <linux/if.h>
#include <linux/net.h>
#include <linux/netdevice.h>
#include <linux/ieee80211.h>
#include <linux/module.h>
#include <net/mac80211.h>
#include <defs.h>
#include <brcmu_wifi.h>
#include <brcmu_utils.h>
#include "types.h"
#include "main.h"
#include "debug.h"
#include "brcms_trace_events.h"
#include "phy/phy_int.h"
static struct dentry *root_folder;
void brcms_debugfs_init(void)
{
root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL);
if (IS_ERR(root_folder))
root_folder = NULL;
}
void brcms_debugfs_exit(void)
{
if (!root_folder)
return;
debugfs_remove_recursive(root_folder);
root_folder = NULL;
}
int brcms_debugfs_attach(struct brcms_pub *drvr)
{
if (!root_folder)
return -ENODEV;
drvr->dbgfs_dir = debugfs_create_dir(
dev_name(&drvr->wlc->hw->d11core->dev), root_folder);
return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
}
void brcms_debugfs_detach(struct brcms_pub *drvr)
{
if (!IS_ERR_OR_NULL(drvr->dbgfs_dir))
debugfs_remove_recursive(drvr->dbgfs_dir);
}
struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr)
{
return drvr->dbgfs_dir;
}
static
int brcms_debugfs_hardware_read(struct seq_file *s, void *data)
{
struct brcms_pub *drvr = s->private;
struct brcms_hardware *hw = drvr->wlc->hw;
struct bcma_device *core = hw->d11core;
struct bcma_bus *bus = core->bus;
char boardrev[BRCMU_BOARDREV_LEN];
seq_printf(s, "chipnum 0x%x\n"
"chiprev 0x%x\n"
"chippackage 0x%x\n"
"corerev 0x%x\n"
"boardid 0x%x\n"
"boardvendor 0x%x\n"
"boardrev %s\n"
"boardflags 0x%x\n"
"boardflags2 0x%x\n"
"ucoderev 0x%x\n"
"radiorev 0x%x\n"
"phytype 0x%x\n"
"phyrev 0x%x\n"
"anarev 0x%x\n"
"nvramrev %d\n",
bus->chipinfo.id, bus->chipinfo.rev, bus->chipinfo.pkg,
core->id.rev, bus->boardinfo.type, bus->boardinfo.vendor,
brcmu_boardrev_str(hw->boardrev, boardrev),
drvr->wlc->hw->boardflags, drvr->wlc->hw->boardflags2,
drvr->wlc->ucode_rev, hw->band->radiorev,
hw->band->phytype, hw->band->phyrev, hw->band->pi->ana_rev,
hw->sromrev);
return 0;
}
static int brcms_debugfs_macstat_read(struct seq_file *s, void *data)
{
struct brcms_pub *drvr = s->private;
struct brcms_info *wl = drvr->ieee_hw->priv;
struct macstat stats;
int i;
spin_lock_bh(&wl->lock);
stats = *(drvr->wlc->core->macstat_snapshot);
spin_unlock_bh(&wl->lock);
seq_printf(s, "txallfrm: %d\n", stats.txallfrm);
seq_printf(s, "txrtsfrm: %d\n", stats.txrtsfrm);
seq_printf(s, "txctsfrm: %d\n", stats.txctsfrm);
seq_printf(s, "txackfrm: %d\n", stats.txackfrm);
seq_printf(s, "txdnlfrm: %d\n", stats.txdnlfrm);
seq_printf(s, "txbcnfrm: %d\n", stats.txbcnfrm);
seq_printf(s, "txfunfl[8]:");
for (i = 0; i < ARRAY_SIZE(stats.txfunfl); i++)
seq_printf(s, " %d", stats.txfunfl[i]);
seq_printf(s, "\ntxtplunfl: %d\n", stats.txtplunfl);
seq_printf(s, "txphyerr: %d\n", stats.txphyerr);
seq_printf(s, "pktengrxducast: %d\n", stats.pktengrxducast);
seq_printf(s, "pktengrxdmcast: %d\n", stats.pktengrxdmcast);
seq_printf(s, "rxfrmtoolong: %d\n", stats.rxfrmtoolong);
seq_printf(s, "rxfrmtooshrt: %d\n", stats.rxfrmtooshrt);
seq_printf(s, "rxinvmachdr: %d\n", stats.rxinvmachdr);
seq_printf(s, "rxbadfcs: %d\n", stats.rxbadfcs);
seq_printf(s, "rxbadplcp: %d\n", stats.rxbadplcp);
seq_printf(s, "rxcrsglitch: %d\n", stats.rxcrsglitch);
seq_printf(s, "rxstrt: %d\n", stats.rxstrt);
seq_printf(s, "rxdfrmucastmbss: %d\n", stats.rxdfrmucastmbss);
seq_printf(s, "rxmfrmucastmbss: %d\n", stats.rxmfrmucastmbss);
seq_printf(s, "rxcfrmucast: %d\n", stats.rxcfrmucast);
seq_printf(s, "rxrtsucast: %d\n", stats.rxrtsucast);
seq_printf(s, "rxctsucast: %d\n", stats.rxctsucast);
seq_printf(s, "rxackucast: %d\n", stats.rxackucast);
seq_printf(s, "rxdfrmocast: %d\n", stats.rxdfrmocast);
seq_printf(s, "rxmfrmocast: %d\n", stats.rxmfrmocast);
seq_printf(s, "rxcfrmocast: %d\n", stats.rxcfrmocast);
seq_printf(s, "rxrtsocast: %d\n", stats.rxrtsocast);
seq_printf(s, "rxctsocast: %d\n", stats.rxctsocast);
seq_printf(s, "rxdfrmmcast: %d\n", stats.rxdfrmmcast);
seq_printf(s, "rxmfrmmcast: %d\n", stats.rxmfrmmcast);
seq_printf(s, "rxcfrmmcast: %d\n", stats.rxcfrmmcast);
seq_printf(s, "rxbeaconmbss: %d\n", stats.rxbeaconmbss);
seq_printf(s, "rxdfrmucastobss: %d\n", stats.rxdfrmucastobss);
seq_printf(s, "rxbeaconobss: %d\n", stats.rxbeaconobss);
seq_printf(s, "rxrsptmout: %d\n", stats.rxrsptmout);
seq_printf(s, "bcntxcancl: %d\n", stats.bcntxcancl);
seq_printf(s, "rxf0ovfl: %d\n", stats.rxf0ovfl);
seq_printf(s, "rxf1ovfl: %d\n", stats.rxf1ovfl);
seq_printf(s, "rxf2ovfl: %d\n", stats.rxf2ovfl);
seq_printf(s, "txsfovfl: %d\n", stats.txsfovfl);
seq_printf(s, "pmqovfl: %d\n", stats.pmqovfl);
seq_printf(s, "rxcgprqfrm: %d\n", stats.rxcgprqfrm);
seq_printf(s, "rxcgprsqovfl: %d\n", stats.rxcgprsqovfl);
seq_printf(s, "txcgprsfail: %d\n", stats.txcgprsfail);
seq_printf(s, "txcgprssuc: %d\n", stats.txcgprssuc);
seq_printf(s, "prs_timeout: %d\n", stats.prs_timeout);
seq_printf(s, "rxnack: %d\n", stats.rxnack);
seq_printf(s, "frmscons: %d\n", stats.frmscons);
seq_printf(s, "txnack: %d\n", stats.txnack);
seq_printf(s, "txglitch_nack: %d\n", stats.txglitch_nack);
seq_printf(s, "txburst: %d\n", stats.txburst);
seq_printf(s, "bphy_rxcrsglitch: %d\n", stats.bphy_rxcrsglitch);
seq_printf(s, "phywatchdog: %d\n", stats.phywatchdog);
seq_printf(s, "bphy_badplcp: %d\n", stats.bphy_badplcp);
return 0;
}
struct brcms_debugfs_entry {
int (*read)(struct seq_file *seq, void *data);
struct brcms_pub *drvr;
};
static int brcms_debugfs_entry_open(struct inode *inode, struct file *f)
{
struct brcms_debugfs_entry *entry = inode->i_private;
return single_open(f, entry->read, entry->drvr);
}
static const struct file_operations brcms_debugfs_def_ops = {
.owner = THIS_MODULE,
.open = brcms_debugfs_entry_open,
.release = single_release,
.read = seq_read,
.llseek = seq_lseek
};
static int
brcms_debugfs_add_entry(struct brcms_pub *drvr, const char *fn,
int (*read_fn)(struct seq_file *seq, void *data))
{
struct device *dev = &drvr->wlc->hw->d11core->dev;
struct dentry *dentry = drvr->dbgfs_dir;
struct brcms_debugfs_entry *entry;
if (IS_ERR_OR_NULL(dentry))
return -ENOENT;
entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
entry->read = read_fn;
entry->drvr = drvr;
dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
&brcms_debugfs_def_ops);
return PTR_ERR_OR_ZERO(dentry);
}
void brcms_debugfs_create_files(struct brcms_pub *drvr)
{
if (IS_ERR_OR_NULL(drvr->dbgfs_dir))
return;
brcms_debugfs_add_entry(drvr, "hardware", brcms_debugfs_hardware_read);
brcms_debugfs_add_entry(drvr, "macstat", brcms_debugfs_macstat_read);
}
#define __brcms_fn(fn) \
void __brcms_ ##fn(struct device *dev, const char *fmt, ...) \
{ \
struct va_format vaf = { \
.fmt = fmt, \
}; \
va_list args; \
\
va_start(args, fmt); \
vaf.va = &args; \
dev_ ##fn(dev, "%pV", &vaf); \
trace_brcms_ ##fn(&vaf); \
va_end(args); \
}
__brcms_fn(info)
__brcms_fn(warn)
__brcms_fn(err)
__brcms_fn(crit)
#if defined(CONFIG_BRCMDBG) || defined(CONFIG_BRCM_TRACING)
void __brcms_dbg(struct device *dev, u32 level, const char *func,
const char *fmt, ...)
{
struct va_format vaf = {
.fmt = fmt,
};
va_list args;
va_start(args, fmt);
vaf.va = &args;
#ifdef CONFIG_BRCMDBG
if ((brcm_msg_level & level) && net_ratelimit())
dev_err(dev, "%s %pV", func, &vaf);
#endif
trace_brcms_dbg(level, func, &vaf);
va_end(args);
}
#endif

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2012 Broadcom Corporation
* Copyright (c) 2012 Canonical Ltd.
*
* 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 _BRCMS_DEBUG_H_
#define _BRCMS_DEBUG_H_
#include <linux/device.h>
#include <linux/bcma/bcma.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include "main.h"
#include "mac80211_if.h"
__printf(2, 3)
void __brcms_info(struct device *dev, const char *fmt, ...);
__printf(2, 3)
void __brcms_warn(struct device *dev, const char *fmt, ...);
__printf(2, 3)
void __brcms_err(struct device *dev, const char *fmt, ...);
__printf(2, 3)
void __brcms_crit(struct device *dev, const char *fmt, ...);
#if defined(CONFIG_BRCMDBG) || defined(CONFIG_BRCM_TRACING)
__printf(4, 5)
void __brcms_dbg(struct device *dev, u32 level, const char *func,
const char *fmt, ...);
#else
static inline __printf(4, 5)
void __brcms_dbg(struct device *dev, u32 level, const char *func,
const char *fmt, ...)
{
}
#endif
/*
* Debug macros cannot be used when wlc is uninitialized. Generally
* this means any code that could run before brcms_c_attach() has
* returned successfully probably shouldn't use the following macros.
*/
#define brcms_dbg(core, l, f, a...) __brcms_dbg(&(core)->dev, l, __func__, f, ##a)
#define brcms_info(core, f, a...) __brcms_info(&(core)->dev, f, ##a)
#define brcms_warn(core, f, a...) __brcms_warn(&(core)->dev, f, ##a)
#define brcms_err(core, f, a...) __brcms_err(&(core)->dev, f, ##a)
#define brcms_crit(core, f, a...) __brcms_crit(&(core)->dev, f, ##a)
#define brcms_dbg_info(core, f, a...) brcms_dbg(core, BRCM_DL_INFO, f, ##a)
#define brcms_dbg_mac80211(core, f, a...) brcms_dbg(core, BRCM_DL_MAC80211, f, ##a)
#define brcms_dbg_rx(core, f, a...) brcms_dbg(core, BRCM_DL_RX, f, ##a)
#define brcms_dbg_tx(core, f, a...) brcms_dbg(core, BRCM_DL_TX, f, ##a)
#define brcms_dbg_int(core, f, a...) brcms_dbg(core, BRCM_DL_INT, f, ##a)
#define brcms_dbg_dma(core, f, a...) brcms_dbg(core, BRCM_DL_DMA, f, ##a)
#define brcms_dbg_ht(core, f, a...) brcms_dbg(core, BRCM_DL_HT, f, ##a)
struct brcms_pub;
void brcms_debugfs_init(void);
void brcms_debugfs_exit(void);
int brcms_debugfs_attach(struct brcms_pub *drvr);
void brcms_debugfs_detach(struct brcms_pub *drvr);
struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr);
void brcms_debugfs_create_files(struct brcms_pub *drvr);
#endif /* _BRCMS_DEBUG_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_DMA_H_
#define _BRCM_DMA_H_
#include <linux/delay.h>
#include <linux/skbuff.h>
#include "types.h" /* forward structure declarations */
/* map/unmap direction */
#define DMA_TX 1 /* TX direction for DMA */
#define DMA_RX 2 /* RX direction for DMA */
/* DMA structure:
* support two DMA engines: 32 bits address or 64 bit addressing
* basic DMA register set is per channel(transmit or receive)
* a pair of channels is defined for convenience
*/
/* 32 bits addressing */
struct dma32diag { /* diag access */
u32 fifoaddr; /* diag address */
u32 fifodatalow; /* low 32bits of data */
u32 fifodatahigh; /* high 32bits of data */
u32 pad; /* reserved */
};
/* 64 bits addressing */
/* dma registers per channel(xmt or rcv) */
struct dma64regs {
u32 control; /* enable, et al */
u32 ptr; /* last descriptor posted to chip */
u32 addrlow; /* desc ring base address low 32-bits (8K aligned) */
u32 addrhigh; /* desc ring base address bits 63:32 (8K aligned) */
u32 status0; /* current descriptor, xmt state */
u32 status1; /* active descriptor, xmt error */
};
/* range param for dma_getnexttxp() and dma_txreclaim */
enum txd_range {
DMA_RANGE_ALL = 1,
DMA_RANGE_TRANSMITTED,
DMA_RANGE_TRANSFERED
};
/*
* Exported data structure (read-only)
*/
/* export structure */
struct dma_pub {
uint txavail; /* # free tx descriptors */
uint dmactrlflags; /* dma control flags */
/* rx error counters */
uint rxgiants; /* rx giant frames */
uint rxnobuf; /* rx out of dma descriptors */
/* tx error counters */
uint txnobuf; /* tx out of dma descriptors */
};
extern struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc,
uint txregbase, uint rxregbase,
uint ntxd, uint nrxd,
uint rxbufsize, int rxextheadroom,
uint nrxpost, uint rxoffset);
void dma_rxinit(struct dma_pub *pub);
int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list);
bool dma_rxfill(struct dma_pub *pub);
bool dma_rxreset(struct dma_pub *pub);
bool dma_txreset(struct dma_pub *pub);
void dma_txinit(struct dma_pub *pub);
int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,
struct sk_buff *p0);
void dma_txflush(struct dma_pub *pub);
int dma_txpending(struct dma_pub *pub);
void dma_kick_tx(struct dma_pub *pub);
void dma_txsuspend(struct dma_pub *pub);
bool dma_txsuspended(struct dma_pub *pub);
void dma_txresume(struct dma_pub *pub);
void dma_txreclaim(struct dma_pub *pub, enum txd_range range);
void dma_rxreclaim(struct dma_pub *pub);
void dma_detach(struct dma_pub *pub);
unsigned long dma_getvar(struct dma_pub *pub, const char *name);
struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range);
void dma_counterreset(struct dma_pub *pub);
void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)
(void *pkt, void *arg_a), void *arg_a);
/*
* DMA(Bug) on bcm47xx chips seems to declare that the packet is ready, but
* the packet length is not updated yet (by DMA) on the expected time.
* Workaround is to hold processor till DMA updates the length, and stay off
* the bus to allow DMA update the length in buffer
*/
static inline void dma_spin_for_len(uint len, struct sk_buff *head)
{
#if defined(CONFIG_BCM47XX)
if (!len) {
while (!(len = *(u16 *) KSEG1ADDR(head->data)))
udelay(1);
*(u16 *) (head->data) = cpu_to_le16((u16) len);
}
#endif /* defined(CONFIG_BCM47XX) */
}
#endif /* _BRCM_DMA_H_ */

View File

@@ -0,0 +1,126 @@
#include <net/mac80211.h>
#include <linux/bcma/bcma_driver_chipcommon.h>
#include <linux/gpio.h>
#include "mac80211_if.h"
#include "pub.h"
#include "main.h"
#include "led.h"
/* number of leds */
#define BRCMS_LED_NO 4
/* behavior mask */
#define BRCMS_LED_BEH_MASK 0x7f
/* activelow (polarity) bit */
#define BRCMS_LED_AL_MASK 0x80
/* radio enabled */
#define BRCMS_LED_RADIO 3
static void brcms_radio_led_ctrl(struct brcms_info *wl, bool state)
{
if (wl->radio_led.gpio == -1)
return;
if (wl->radio_led.active_low)
state = !state;
if (state)
gpio_set_value(wl->radio_led.gpio, 1);
else
gpio_set_value(wl->radio_led.gpio, 0);
}
/* Callback from the LED subsystem. */
static void brcms_led_brightness_set(struct led_classdev *led_dev,
enum led_brightness brightness)
{
struct brcms_info *wl = container_of(led_dev,
struct brcms_info, led_dev);
brcms_radio_led_ctrl(wl, brightness);
}
void brcms_led_unregister(struct brcms_info *wl)
{
if (wl->led_dev.dev)
led_classdev_unregister(&wl->led_dev);
if (wl->radio_led.gpio != -1)
gpio_free(wl->radio_led.gpio);
}
int brcms_led_register(struct brcms_info *wl)
{
int i, err;
struct brcms_led *radio_led = &wl->radio_led;
/* get CC core */
struct bcma_drv_cc *cc_drv = &wl->wlc->hw->d11core->bus->drv_cc;
struct gpio_chip *bcma_gpio = &cc_drv->gpio;
struct ssb_sprom *sprom = &wl->wlc->hw->d11core->bus->sprom;
u8 *leds[] = { &sprom->gpio0,
&sprom->gpio1,
&sprom->gpio2,
&sprom->gpio3 };
unsigned gpio = -1;
bool active_low = false;
/* none by default */
radio_led->gpio = -1;
radio_led->active_low = false;
if (!bcma_gpio || !gpio_is_valid(bcma_gpio->base))
return -ENODEV;
/* find radio enabled LED */
for (i = 0; i < BRCMS_LED_NO; i++) {
u8 led = *leds[i];
if ((led & BRCMS_LED_BEH_MASK) == BRCMS_LED_RADIO) {
gpio = bcma_gpio->base + i;
if (led & BRCMS_LED_AL_MASK)
active_low = true;
break;
}
}
if (gpio == -1 || !gpio_is_valid(gpio))
return -ENODEV;
/* request and configure LED gpio */
err = gpio_request_one(gpio,
active_low ? GPIOF_OUT_INIT_HIGH
: GPIOF_OUT_INIT_LOW,
"radio on");
if (err) {
wiphy_err(wl->wiphy, "requesting led gpio %d failed (err: %d)\n",
gpio, err);
return err;
}
err = gpio_direction_output(gpio, 1);
if (err) {
wiphy_err(wl->wiphy, "cannot set led gpio %d to output (err: %d)\n",
gpio, err);
return err;
}
snprintf(wl->radio_led.name, sizeof(wl->radio_led.name),
"brcmsmac-%s:radio", wiphy_name(wl->wiphy));
wl->led_dev.name = wl->radio_led.name;
wl->led_dev.default_trigger =
ieee80211_get_radio_led_name(wl->pub->ieee_hw);
wl->led_dev.brightness_set = brcms_led_brightness_set;
err = led_classdev_register(wiphy_dev(wl->wiphy), &wl->led_dev);
if (err) {
wiphy_err(wl->wiphy, "cannot register led device: %s (err: %d)\n",
wl->radio_led.name, err);
return err;
}
wiphy_info(wl->wiphy, "registered radio enabled led device: %s gpio: %d\n",
wl->radio_led.name,
gpio);
radio_led->gpio = gpio;
radio_led->active_low = active_low;
return 0;
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2012 Broadcom Corporation
*
* 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 _BRCM_LED_H_
#define _BRCM_LED_H_
struct brcms_led {
char name[32];
unsigned gpio;
bool active_low;
};
#ifdef CONFIG_BCMA_DRIVER_GPIO
void brcms_led_unregister(struct brcms_info *wl);
int brcms_led_register(struct brcms_info *wl);
#else
static inline void brcms_led_unregister(struct brcms_info *wl) {};
static inline int brcms_led_register(struct brcms_info *wl)
{
return -ENOTSUPP;
};
#endif
#endif /* _BRCM_LED_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_MAC80211_IF_H_
#define _BRCM_MAC80211_IF_H_
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/leds.h>
#include "ucode_loader.h"
#include "led.h"
/*
* Starting index for 5G rates in the
* legacy rate table.
*/
#define BRCMS_LEGACY_5G_RATE_OFFSET 4
/* softmac ioctl definitions */
#define BRCMS_SET_SHORTSLOT_OVERRIDE 146
struct brcms_timer {
struct delayed_work dly_wrk;
struct brcms_info *wl;
void (*fn) (void *); /* function called upon expiration */
void *arg; /* fixed argument provided to called function */
uint ms;
bool periodic;
bool set; /* indicates if timer is active */
struct brcms_timer *next; /* for freeing on unload */
#ifdef DEBUG
char *name; /* Description of the timer */
#endif
};
struct brcms_if {
uint subunit; /* WDS/BSS unit */
struct pci_dev *pci_dev;
};
#define MAX_FW_IMAGES 4
struct brcms_firmware {
u32 fw_cnt;
const struct firmware *fw_bin[MAX_FW_IMAGES];
const struct firmware *fw_hdr[MAX_FW_IMAGES];
u32 hdr_num_entries[MAX_FW_IMAGES];
};
struct brcms_info {
struct brcms_pub *pub; /* pointer to public wlc state */
struct brcms_c_info *wlc; /* pointer to private common data */
u32 magic;
int irq;
spinlock_t lock; /* per-device perimeter lock */
spinlock_t isr_lock; /* per-device ISR synchronization lock */
/* tx flush */
wait_queue_head_t tx_flush_wq;
/* timer related fields */
atomic_t callbacks; /* # outstanding callback functions */
struct brcms_timer *timers; /* timer cleanup queue */
struct tasklet_struct tasklet; /* dpc tasklet */
bool resched; /* dpc needs to be and is rescheduled */
struct brcms_firmware fw;
struct wiphy *wiphy;
struct brcms_ucode ucode;
bool mute_tx;
struct brcms_led radio_led;
struct led_classdev led_dev;
};
/* misc callbacks */
void brcms_init(struct brcms_info *wl);
uint brcms_reset(struct brcms_info *wl);
void brcms_intrson(struct brcms_info *wl);
u32 brcms_intrsoff(struct brcms_info *wl);
void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask);
int brcms_up(struct brcms_info *wl);
void brcms_down(struct brcms_info *wl);
void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
bool state, int prio);
bool brcms_rfkill_set_hw_state(struct brcms_info *wl);
/* timer functions */
struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
void (*fn) (void *arg), void *arg,
const char *name);
void brcms_free_timer(struct brcms_timer *timer);
void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic);
bool brcms_del_timer(struct brcms_timer *timer);
void brcms_dpc(unsigned long data);
void brcms_timer(struct brcms_timer *t);
void brcms_fatal_error(struct brcms_info *wl);
#endif /* _BRCM_MAC80211_IF_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,669 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_MAIN_H_
#define _BRCM_MAIN_H_
#include <linux/etherdevice.h>
#include <brcmu_utils.h>
#include "types.h"
#include "d11.h"
#include "scb.h"
#define INVCHANNEL 255 /* invalid channel */
/* max # brcms_c_module_register() calls */
#define BRCMS_MAXMODULES 22
#define SEQNUM_SHIFT 4
#define SEQNUM_MAX 0x1000
#define NTXRATE 64 /* # tx MPDUs rate is reported for */
/* Maximum wait time for a MAC suspend */
/* uS: 83mS is max packet time (64KB ampdu @ 6Mbps) */
#define BRCMS_MAX_MAC_SUSPEND 83000
/* responses for probe requests older that this are tossed, zero to disable */
#define BRCMS_PRB_RESP_TIMEOUT 0 /* Disable probe response timeout */
/* transmit buffer max headroom for protocol headers */
#define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN)
/* Macros for doing definition and get/set of bitfields
* Usage example, e.g. a three-bit field (bits 4-6):
* #define <NAME>_M BITFIELD_MASK(3)
* #define <NAME>_S 4
* ...
* regval = R_REG(osh, &regs->regfoo);
* field = GFIELD(regval, <NAME>);
* regval = SFIELD(regval, <NAME>, 1);
* W_REG(osh, &regs->regfoo, regval);
*/
#define BITFIELD_MASK(width) \
(((unsigned)1 << (width)) - 1)
#define GFIELD(val, field) \
(((val) >> field ## _S) & field ## _M)
#define SFIELD(val, field, bits) \
(((val) & (~(field ## _M << field ## _S))) | \
((unsigned)(bits) << field ## _S))
#define SW_TIMER_MAC_STAT_UPD 30 /* periodic MAC stats update */
/* max # supported core revisions (0 .. MAXCOREREV - 1) */
#define MAXCOREREV 28
/* Double check that unsupported cores are not enabled */
#if CONF_MSK(D11CONF, 0x4f) || CONF_GE(D11CONF, MAXCOREREV)
#error "Configuration for D11CONF includes unsupported versions."
#endif /* Bad versions */
/* values for shortslot_override */
#define BRCMS_SHORTSLOT_AUTO -1 /* Driver will manage Shortslot setting */
#define BRCMS_SHORTSLOT_OFF 0 /* Turn off short slot */
#define BRCMS_SHORTSLOT_ON 1 /* Turn on short slot */
/* value for short/long and mixmode/greenfield preamble */
#define BRCMS_LONG_PREAMBLE (0)
#define BRCMS_SHORT_PREAMBLE (1 << 0)
#define BRCMS_GF_PREAMBLE (1 << 1)
#define BRCMS_MM_PREAMBLE (1 << 2)
#define BRCMS_IS_MIMO_PREAMBLE(_pre) (((_pre) == BRCMS_GF_PREAMBLE) || \
((_pre) == BRCMS_MM_PREAMBLE))
/* TxFrameID */
/* seq and frag bits: SEQNUM_SHIFT, FRAGNUM_MASK (802.11.h) */
/* rate epoch bits: TXFID_RATE_SHIFT, TXFID_RATE_MASK ((wlc_rate.c) */
#define TXFID_QUEUE_MASK 0x0007 /* Bits 0-2 */
#define TXFID_SEQ_MASK 0x7FE0 /* Bits 5-15 */
#define TXFID_SEQ_SHIFT 5 /* Number of bit shifts */
#define TXFID_RATE_PROBE_MASK 0x8000 /* Bit 15 for rate probe */
#define TXFID_RATE_MASK 0x0018 /* Mask for bits 3 and 4 */
#define TXFID_RATE_SHIFT 3 /* Shift 3 bits for rate mask */
/* promote boardrev */
#define BOARDREV_PROMOTABLE 0xFF /* from */
#define BOARDREV_PROMOTED 1 /* to */
#define DATA_BLOCK_TX_SUPR (1 << 4)
/* Ucode MCTL_WAKE override bits */
#define BRCMS_WAKE_OVERRIDE_CLKCTL 0x01
#define BRCMS_WAKE_OVERRIDE_PHYREG 0x02
#define BRCMS_WAKE_OVERRIDE_MACSUSPEND 0x04
#define BRCMS_WAKE_OVERRIDE_TXFIFO 0x08
#define BRCMS_WAKE_OVERRIDE_FORCEFAST 0x10
/* stuff pulled in from wlc.c */
/* Interrupt bit error summary. Don't include I_RU: we refill DMA at other
* times; and if we run out, constant I_RU interrupts may cause lockup. We
* will still get error counts from rx0ovfl.
*/
#define I_ERRORS (I_PC | I_PD | I_DE | I_RO | I_XU)
/* default software intmasks */
#define DEF_RXINTMASK (I_RI) /* enable rx int on rxfifo only */
#define DEF_MACINTMASK (MI_TXSTOP | MI_TBTT | MI_ATIMWINEND | MI_PMQ | \
MI_PHYTXERR | MI_DMAINT | MI_TFS | MI_BG_NOISE | \
MI_CCA | MI_TO | MI_GP0 | MI_RFDISABLE | MI_PWRUP)
#define MAXTXPKTS 6 /* max # pkts pending */
/* frameburst */
#define MAXTXFRAMEBURST 8 /* vanilla xpress mode: max frames/burst */
#define MAXFRAMEBURST_TXOP 10000 /* Frameburst TXOP in usec */
#define NFIFO 6 /* # tx/rx fifopairs */
/* PLL requests */
/* pll is shared on old chips */
#define BRCMS_PLLREQ_SHARED 0x1
/* hold pll for radio monitor register checking */
#define BRCMS_PLLREQ_RADIO_MON 0x2
/* hold/release pll for some short operation */
#define BRCMS_PLLREQ_FLIP 0x4
#define CHANNEL_BANDUNIT(wlc, ch) \
(((ch) <= CH_MAX_2G_CHANNEL) ? BAND_2G_INDEX : BAND_5G_INDEX)
#define OTHERBANDUNIT(wlc) \
((uint)((wlc)->band->bandunit ? BAND_2G_INDEX : BAND_5G_INDEX))
/*
* 802.11 protection information
*
* _g: use g spec protection, driver internal.
* g_override: override for use of g spec protection.
* gmode_user: user config gmode, operating band->gmode is different.
* overlap: Overlap BSS/IBSS protection for both 11g and 11n.
* nmode_user: user config nmode, operating pub->nmode is different.
* n_cfg: use OFDM protection on MIMO frames.
* n_cfg_override: override for use of N protection.
* nongf: non-GF present protection.
* nongf_override: override for use of GF protection.
* n_pam_override: override for preamble: MM or GF.
* n_obss: indicated OBSS Non-HT STA present.
*/
struct brcms_protection {
bool _g;
s8 g_override;
u8 gmode_user;
s8 overlap;
s8 nmode_user;
s8 n_cfg;
s8 n_cfg_override;
bool nongf;
s8 nongf_override;
s8 n_pam_override;
bool n_obss;
};
/*
* anything affecting the single/dual streams/antenna operation
*
* hw_txchain: HW txchain bitmap cfg.
* txchain: txchain bitmap being used.
* txstreams: number of txchains being used.
* hw_rxchain: HW rxchain bitmap cfg.
* rxchain: rxchain bitmap being used.
* rxstreams: number of rxchains being used.
* ant_rx_ovr: rx antenna override.
* txant: userTx antenna setting.
* phytxant: phyTx antenna setting in txheader.
* ss_opmode: singlestream Operational mode, 0:siso; 1:cdd.
* ss_algosel_auto: if true, use wlc->stf->ss_algo_channel;
* else use wlc->band->stf->ss_mode_band.
* ss_algo_channel: ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC.
* rxchain_restore_delay: delay time to restore default rxchain.
* ldpc: AUTO/ON/OFF ldpc cap supported.
* txcore[MAX_STREAMS_SUPPORTED + 1]: bitmap of selected core for each Nsts.
* spatial_policy:
*/
struct brcms_stf {
u8 hw_txchain;
u8 txchain;
u8 txstreams;
u8 hw_rxchain;
u8 rxchain;
u8 rxstreams;
u8 ant_rx_ovr;
s8 txant;
u16 phytxant;
u8 ss_opmode;
bool ss_algosel_auto;
u16 ss_algo_channel;
u8 rxchain_restore_delay;
s8 ldpc;
u8 txcore[MAX_STREAMS_SUPPORTED + 1];
s8 spatial_policy;
};
#define BRCMS_STF_SS_STBC_TX(wlc, scb) \
(((wlc)->stf->txstreams > 1) && (((wlc)->band->band_stf_stbc_tx == ON) \
|| (((scb)->flags & SCB_STBCCAP) && \
(wlc)->band->band_stf_stbc_tx == AUTO && \
isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC))))
#define BRCMS_STBC_CAP_PHY(wlc) (BRCMS_ISNPHY(wlc->band) && \
NREV_GE(wlc->band->phyrev, 3))
#define BRCMS_SGI_CAP_PHY(wlc) ((BRCMS_ISNPHY(wlc->band) && \
NREV_GE(wlc->band->phyrev, 3)) || \
BRCMS_ISLCNPHY(wlc->band))
#define BRCMS_CHAN_PHYTYPE(x) (((x) & RXS_CHAN_PHYTYPE_MASK) \
>> RXS_CHAN_PHYTYPE_SHIFT)
#define BRCMS_CHAN_CHANNEL(x) (((x) & RXS_CHAN_ID_MASK) \
>> RXS_CHAN_ID_SHIFT)
/*
* core state (mac)
*/
struct brcms_core {
uint coreidx; /* # sb enumerated core */
/* fifo */
uint *txavail[NFIFO]; /* # tx descriptors available */
struct macstat *macstat_snapshot; /* mac hw prev read values */
};
/*
* band state (phy+ana+radio)
*/
struct brcms_band {
int bandtype; /* BRCM_BAND_2G, BRCM_BAND_5G */
uint bandunit; /* bandstate[] index */
u16 phytype; /* phytype */
u16 phyrev;
u16 radioid;
u16 radiorev;
struct brcms_phy_pub *pi; /* pointer to phy specific information */
bool abgphy_encore;
u8 gmode; /* currently active gmode */
struct scb *hwrs_scb; /* permanent scb for hw rateset */
/* band-specific copy of default_bss.rateset */
struct brcms_c_rateset defrateset;
u8 band_stf_ss_mode; /* Configured STF type, 0:siso; 1:cdd */
s8 band_stf_stbc_tx; /* STBC TX 0:off; 1:force on; -1:auto */
/* rates supported by chip (phy-specific) */
struct brcms_c_rateset hw_rateset;
u8 basic_rate[BRCM_MAXRATE + 1]; /* basic rates indexed by rate */
bool mimo_cap_40; /* 40 MHz cap enabled on this band */
s8 antgain; /* antenna gain from srom */
u16 CWmin; /* minimum size of contention window, in unit of aSlotTime */
u16 CWmax; /* maximum size of contention window, in unit of aSlotTime */
struct ieee80211_supported_band band;
};
/* module control blocks */
struct modulecb {
/* module name : NULL indicates empty array member */
char name[32];
/* handle passed when handler 'doiovar' is called */
struct brcms_info *hdl;
int (*down_fn)(void *handle); /* down handler. Note: the int returned
* by the down function is a count of the
* number of timers that could not be
* freed.
*/
};
struct brcms_hw_band {
int bandtype; /* BRCM_BAND_2G, BRCM_BAND_5G */
uint bandunit; /* bandstate[] index */
u16 mhfs[MHFMAX]; /* MHF array shadow */
u8 bandhw_stf_ss_mode; /* HW configured STF type, 0:siso; 1:cdd */
u16 CWmin;
u16 CWmax;
u32 core_flags;
u16 phytype; /* phytype */
u16 phyrev;
u16 radioid;
u16 radiorev;
struct brcms_phy_pub *pi; /* pointer to phy specific information */
bool abgphy_encore;
};
struct brcms_hardware {
bool _piomode; /* true if pio mode */
struct brcms_c_info *wlc;
/* fifo */
struct dma_pub *di[NFIFO]; /* dma handles, per fifo */
uint unit; /* device instance number */
/* version info */
u16 vendorid; /* PCI vendor id */
u16 deviceid; /* PCI device id */
uint corerev; /* core revision */
u8 sromrev; /* version # of the srom */
u16 boardrev; /* version # of particular board */
u32 boardflags; /* Board specific flags from srom */
u32 boardflags2; /* More board flags if sromrev >= 4 */
u32 machwcap; /* MAC capabilities */
u32 machwcap_backup; /* backup of machwcap */
struct si_pub *sih; /* SI handle (cookie for siutils calls) */
struct bcma_device *d11core; /* pointer to 802.11 core */
struct phy_shim_info *physhim; /* phy shim layer handler */
struct shared_phy *phy_sh; /* pointer to shared phy state */
struct brcms_hw_band *band;/* pointer to active per-band state */
/* band state per phy/radio */
struct brcms_hw_band *bandstate[MAXBANDS];
u16 bmac_phytxant; /* cache of high phytxant state */
bool shortslot; /* currently using 11g ShortSlot timing */
u16 SRL; /* 802.11 dot11ShortRetryLimit */
u16 LRL; /* 802.11 dot11LongRetryLimit */
u16 SFBL; /* Short Frame Rate Fallback Limit */
u16 LFBL; /* Long Frame Rate Fallback Limit */
bool up; /* d11 hardware up and running */
uint now; /* # elapsed seconds */
uint _nbands; /* # bands supported */
u16 chanspec; /* bmac chanspec shadow */
uint *txavail[NFIFO]; /* # tx descriptors available */
const u16 *xmtfifo_sz; /* fifo size in 256B for each xmt fifo */
u32 pllreq; /* pll requests to keep PLL on */
u8 suspended_fifos; /* Which TX fifo to remain awake for */
u32 maccontrol; /* Cached value of maccontrol */
uint mac_suspend_depth; /* current depth of mac_suspend levels */
u32 wake_override; /* bit flags to force MAC to WAKE mode */
u32 mute_override; /* Prevent ucode from sending beacons */
u8 etheraddr[ETH_ALEN]; /* currently configured ethernet address */
bool noreset; /* true= do not reset hw, used by WLC_OUT */
bool forcefastclk; /* true if h/w is forcing to use fast clk */
bool clk; /* core is out of reset and has clock */
bool sbclk; /* sb has clock */
bool phyclk; /* phy is out of reset and has clock */
bool ucode_loaded; /* true after ucode downloaded */
u8 hw_stf_ss_opmode; /* STF single stream operation mode */
u8 antsel_type; /* Type of boardlevel mimo antenna switch-logic
* 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
*/
u32 antsel_avail; /*
* put struct antsel_info here if more info is
* needed
*/
};
/*
* Principal common driver data structure.
*
* pub: pointer to driver public state.
* wl: pointer to specific private state.
* hw: HW related state.
* clkreq_override: setting for clkreq for PCIE : Auto, 0, 1.
* fastpwrup_dly: time in us needed to bring up d11 fast clock.
* macintstatus: bit channel between isr and dpc.
* macintmask: sw runtime master macintmask value.
* defmacintmask: default "on" macintmask value.
* clk: core is out of reset and has clock.
* core: pointer to active io core.
* band: pointer to active per-band state.
* corestate: per-core state (one per hw core).
* bandstate: per-band state (one per phy/radio).
* qvalid: DirFrmQValid and BcMcFrmQValid.
* ampdu: ampdu module handler.
* asi: antsel module handler.
* cmi: channel manager module handler.
* vendorid: PCI vendor id.
* deviceid: PCI device id.
* ucode_rev: microcode revision.
* machwcap: MAC capabilities, BMAC shadow.
* perm_etheraddr: original sprom local ethernet address.
* bandlocked: disable auto multi-band switching.
* bandinit_pending: track band init in auto band.
* radio_monitor: radio timer is running.
* going_down: down path intermediate variable.
* wdtimer: timer for watchdog routine.
* radio_timer: timer for hw radio button monitor routine.
* monitor: monitor (MPDU sniffing) mode.
* bcnmisc_monitor: bcns promisc mode override for monitor.
* _rifs: enable per-packet rifs.
* bcn_li_bcn: beacon listen interval in # beacons.
* bcn_li_dtim: beacon listen interval in # dtims.
* WDarmed: watchdog timer is armed.
* WDlast: last time wlc_watchdog() was called.
* edcf_txop[IEEE80211_NUM_ACS]: current txop for each ac.
* wme_retries: per-AC retry limits.
* bsscfg: set of BSS configurations, idx 0 is default and always valid.
* cfg: the primary bsscfg (can be AP or STA).
* modulecb:
* mimoft: SIGN or 11N.
* cck_40txbw: 11N, cck tx b/w override when in 40MHZ mode.
* ofdm_40txbw: 11N, ofdm tx b/w override when in 40MHZ mode.
* mimo_40txbw: 11N, mimo tx b/w override when in 40MHZ mode.
* default_bss: configured BSS parameters.
* mc_fid_counter: BC/MC FIFO frame ID counter.
* country_default: saved country for leaving 802.11d auto-country mode.
* autocountry_default: initial country for 802.11d auto-country mode.
* prb_resp_timeout: do not send prb resp if request older
* than this, 0 = disable.
* home_chanspec: shared home chanspec.
* chanspec: target operational channel.
* usr_fragthresh: user configured fragmentation threshold.
* fragthresh[NFIFO]: per-fifo fragmentation thresholds.
* RTSThresh: 802.11 dot11RTSThreshold.
* SRL: 802.11 dot11ShortRetryLimit.
* LRL: 802.11 dot11LongRetryLimit.
* SFBL: Short Frame Rate Fallback Limit.
* LFBL: Long Frame Rate Fallback Limit.
* shortslot: currently using 11g ShortSlot timing.
* shortslot_override: 11g ShortSlot override.
* include_legacy_erp: include Legacy ERP info elt ID 47 as well as g ID 42.
* PLCPHdr_override: 802.11b Preamble Type override.
* stf:
* bcn_rspec: save bcn ratespec purpose.
* tempsense_lasttime;
* tx_duty_cycle_ofdm: maximum allowed duty cycle for OFDM.
* tx_duty_cycle_cck: maximum allowed duty cycle for CCK.
* wiphy:
* pri_scb: primary Station Control Block
*/
struct brcms_c_info {
struct brcms_pub *pub;
struct brcms_info *wl;
struct brcms_hardware *hw;
/* clock */
u16 fastpwrup_dly;
/* interrupt */
u32 macintstatus;
u32 macintmask;
u32 defmacintmask;
bool clk;
/* multiband */
struct brcms_core *core;
struct brcms_band *band;
struct brcms_core *corestate;
struct brcms_band *bandstate[MAXBANDS];
/* packet queue */
uint qvalid;
struct ampdu_info *ampdu;
struct antsel_info *asi;
struct brcms_cm_info *cmi;
u16 vendorid;
u16 deviceid;
uint ucode_rev;
u8 perm_etheraddr[ETH_ALEN];
bool bandlocked;
bool bandinit_pending;
bool radio_monitor;
bool going_down;
bool beacon_template_virgin;
struct brcms_timer *wdtimer;
struct brcms_timer *radio_timer;
/* promiscuous */
uint filter_flags;
/* driver feature */
bool _rifs;
/* AP-STA synchronization, power save */
u8 bcn_li_bcn;
u8 bcn_li_dtim;
bool WDarmed;
u32 WDlast;
/* WME */
u16 edcf_txop[IEEE80211_NUM_ACS];
u16 wme_retries[IEEE80211_NUM_ACS];
struct brcms_bss_cfg *bsscfg;
struct modulecb *modulecb;
u8 mimoft;
s8 cck_40txbw;
s8 ofdm_40txbw;
s8 mimo_40txbw;
struct brcms_bss_info *default_bss;
u16 mc_fid_counter;
char country_default[BRCM_CNTRY_BUF_SZ];
char autocountry_default[BRCM_CNTRY_BUF_SZ];
u16 prb_resp_timeout;
u16 home_chanspec;
/* PHY parameters */
u16 chanspec;
u16 usr_fragthresh;
u16 fragthresh[NFIFO];
u16 RTSThresh;
u16 SRL;
u16 LRL;
u16 SFBL;
u16 LFBL;
/* network config */
bool shortslot;
s8 shortslot_override;
bool include_legacy_erp;
struct brcms_protection *protection;
s8 PLCPHdr_override;
struct brcms_stf *stf;
u32 bcn_rspec;
uint tempsense_lasttime;
u16 tx_duty_cycle_ofdm;
u16 tx_duty_cycle_cck;
struct wiphy *wiphy;
struct scb pri_scb;
struct sk_buff *beacon;
u16 beacon_tim_offset;
u16 beacon_dtim_period;
struct sk_buff *probe_resp;
};
/* antsel module specific state */
struct antsel_info {
struct brcms_c_info *wlc; /* pointer to main wlc structure */
struct brcms_pub *pub; /* pointer to public fn */
u8 antsel_type; /* Type of boardlevel mimo antenna switch-logic
* 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
*/
u8 antsel_antswitch; /* board level antenna switch type */
bool antsel_avail; /* Ant selection availability (SROM based) */
struct brcms_antselcfg antcfg_11n; /* antenna configuration */
struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */
};
enum brcms_bss_type {
BRCMS_TYPE_STATION,
BRCMS_TYPE_AP,
BRCMS_TYPE_ADHOC,
};
/*
* BSS configuration state
*
* wlc: wlc to which this bsscfg belongs to.
* type: interface type
* SSID_len: the length of SSID
* SSID: SSID string
*
*
* BSSID: BSSID (associated)
* cur_etheraddr: h/w address
* flags: BSSCFG flags; see below
*
* current_bss: BSS parms in ASSOCIATED state
*
*
* ID: 'unique' ID of this bsscfg, assigned at bsscfg allocation
*/
struct brcms_bss_cfg {
struct brcms_c_info *wlc;
enum brcms_bss_type type;
u8 SSID_len;
u8 SSID[IEEE80211_MAX_SSID_LEN];
u8 BSSID[ETH_ALEN];
struct brcms_bss_info *current_bss;
};
int brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p);
int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
uint *blocks);
int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config);
void brcms_c_mac_promisc(struct brcms_c_info *wlc, uint filter_flags);
u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, uint mac_len);
u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec,
bool use_rspec, u16 mimo_ctlchbw);
u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
u32 rts_rate, u32 frame_rate,
u8 rts_preamble_type, u8 frame_preamble_type,
uint frame_len, bool ba);
void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
struct ieee80211_sta *sta, void (*dma_callback_fn));
void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend);
int brcms_c_set_nmode(struct brcms_c_info *wlc);
void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, u32 bcn_rate);
void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type);
void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec,
bool mute, struct txpwr_limits *txpwr);
void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v);
u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset);
void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val,
int bands);
void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags);
void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val);
void brcms_b_phy_reset(struct brcms_hardware *wlc_hw);
void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw);
void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw);
void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
u32 override_bit);
void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
u32 override_bit);
void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset,
int len, void *buf);
u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate);
void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset,
const void *buf, int len, u32 sel);
void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset,
void *buf, int len, u32 sel);
void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode);
u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw);
void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk);
void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk);
void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on);
void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant);
void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode);
void brcms_c_init_scb(struct scb *scb);
#endif /* _BRCM_MAIN_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,284 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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.
*/
/*
* phy_hal.h: functionality exported from the phy to higher layers
*/
#ifndef _BRCM_PHY_HAL_H_
#define _BRCM_PHY_HAL_H_
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
#include <phy_shim.h>
#define IDCODE_VER_MASK 0x0000000f
#define IDCODE_VER_SHIFT 0
#define IDCODE_MFG_MASK 0x00000fff
#define IDCODE_MFG_SHIFT 0
#define IDCODE_ID_MASK 0x0ffff000
#define IDCODE_ID_SHIFT 12
#define IDCODE_REV_MASK 0xf0000000
#define IDCODE_REV_SHIFT 28
#define NORADIO_ID 0xe4f5
#define NORADIO_IDCODE 0x4e4f5246
#define BCM2055_ID 0x2055
#define BCM2055_IDCODE 0x02055000
#define BCM2055A0_IDCODE 0x1205517f
#define BCM2056_ID 0x2056
#define BCM2056_IDCODE 0x02056000
#define BCM2056A0_IDCODE 0x1205617f
#define BCM2057_ID 0x2057
#define BCM2057_IDCODE 0x02057000
#define BCM2057A0_IDCODE 0x1205717f
#define BCM2064_ID 0x2064
#define BCM2064_IDCODE 0x02064000
#define BCM2064A0_IDCODE 0x0206417f
#define PHY_TPC_HW_OFF false
#define PHY_TPC_HW_ON true
#define PHY_PERICAL_DRIVERUP 1
#define PHY_PERICAL_WATCHDOG 2
#define PHY_PERICAL_PHYINIT 3
#define PHY_PERICAL_JOIN_BSS 4
#define PHY_PERICAL_START_IBSS 5
#define PHY_PERICAL_UP_BSS 6
#define PHY_PERICAL_CHAN 7
#define PHY_FULLCAL 8
#define PHY_PERICAL_DISABLE 0
#define PHY_PERICAL_SPHASE 1
#define PHY_PERICAL_MPHASE 2
#define PHY_PERICAL_MANUAL 3
#define PHY_HOLD_FOR_ASSOC 1
#define PHY_HOLD_FOR_SCAN 2
#define PHY_HOLD_FOR_RM 4
#define PHY_HOLD_FOR_PLT 8
#define PHY_HOLD_FOR_MUTE 16
#define PHY_HOLD_FOR_NOT_ASSOC 0x20
#define PHY_MUTE_FOR_PREISM 1
#define PHY_MUTE_ALL 0xffffffff
#define PHY_NOISE_FIXED_VAL (-95)
#define PHY_NOISE_FIXED_VAL_NPHY (-92)
#define PHY_NOISE_FIXED_VAL_LCNPHY (-92)
#define PHY_MODE_CAL 0x0002
#define PHY_MODE_NOISEM 0x0004
#define BRCMS_TXPWR_DB_FACTOR 4
/* a large TX Power as an init value to factor out of min() calculations,
* keep low enough to fit in an s8, units are .25 dBm
*/
#define BRCMS_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */
#define BRCMS_NUM_RATES_CCK 4
#define BRCMS_NUM_RATES_OFDM 8
#define BRCMS_NUM_RATES_MCS_1_STREAM 8
#define BRCMS_NUM_RATES_MCS_2_STREAM 8
#define BRCMS_NUM_RATES_MCS_3_STREAM 8
#define BRCMS_NUM_RATES_MCS_4_STREAM 8
#define BRCMS_RSSI_INVALID 0 /* invalid RSSI value */
struct d11regs;
struct phy_shim_info;
struct txpwr_limits {
u8 cck[BRCMS_NUM_RATES_CCK];
u8 ofdm[BRCMS_NUM_RATES_OFDM];
u8 ofdm_cdd[BRCMS_NUM_RATES_OFDM];
u8 ofdm_40_siso[BRCMS_NUM_RATES_OFDM];
u8 ofdm_40_cdd[BRCMS_NUM_RATES_OFDM];
u8 mcs_20_siso[BRCMS_NUM_RATES_MCS_1_STREAM];
u8 mcs_20_cdd[BRCMS_NUM_RATES_MCS_1_STREAM];
u8 mcs_20_stbc[BRCMS_NUM_RATES_MCS_1_STREAM];
u8 mcs_20_mimo[BRCMS_NUM_RATES_MCS_2_STREAM];
u8 mcs_40_siso[BRCMS_NUM_RATES_MCS_1_STREAM];
u8 mcs_40_cdd[BRCMS_NUM_RATES_MCS_1_STREAM];
u8 mcs_40_stbc[BRCMS_NUM_RATES_MCS_1_STREAM];
u8 mcs_40_mimo[BRCMS_NUM_RATES_MCS_2_STREAM];
u8 mcs32;
};
struct tx_power {
u32 flags;
u16 chanspec; /* txpwr report for this channel */
u16 local_chanspec; /* channel on which we are associated */
u8 local_max; /* local max according to the AP */
u8 local_constraint; /* local constraint according to the AP */
s8 antgain[2]; /* Ant gain for each band - from SROM */
u8 rf_cores; /* count of RF Cores being reported */
u8 est_Pout[4]; /* Latest tx power out estimate per RF chain */
u8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain
* without adjustment */
u8 est_Pout_cck; /* Latest CCK tx power out estimate */
u8 tx_power_max[4]; /* Maximum target power among all rates */
/* Index of the rate with the max target power */
u8 tx_power_max_rate_ind[4];
/* User limit */
u8 user_limit[WL_TX_POWER_RATES];
/* Regulatory power limit */
u8 reg_limit[WL_TX_POWER_RATES];
/* Max power board can support (SROM) */
u8 board_limit[WL_TX_POWER_RATES];
/* Latest target power */
u8 target[WL_TX_POWER_RATES];
};
struct tx_inst_power {
u8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */
u8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */
};
struct brcms_chanvec {
u8 vec[MAXCHANNEL / NBBY];
};
struct shared_phy_params {
struct si_pub *sih;
struct phy_shim_info *physhim;
uint unit;
uint corerev;
u16 vid;
u16 did;
uint chip;
uint chiprev;
uint chippkg;
uint sromrev;
uint boardtype;
uint boardrev;
u32 boardflags;
u32 boardflags2;
};
struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp);
struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh,
struct bcma_device *d11core, int bandtype,
struct wiphy *wiphy);
void wlc_phy_detach(struct brcms_phy_pub *ppi);
bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype,
u16 *phyrev, u16 *radioid, u16 *radiover);
bool wlc_phy_get_encore(struct brcms_phy_pub *pih);
u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih);
void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate);
void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate);
void wlc_phy_init(struct brcms_phy_pub *ppi, u16 chanspec);
void wlc_phy_watchdog(struct brcms_phy_pub *ppi);
int wlc_phy_down(struct brcms_phy_pub *ppi);
u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih);
void wlc_phy_cal_init(struct brcms_phy_pub *ppi);
void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init);
void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec);
u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi);
void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch);
u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi);
void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw);
int wlc_phy_rssi_compute(struct brcms_phy_pub *pih, struct d11rxhdr *rxh);
void wlc_phy_por_inform(struct brcms_phy_pub *ppi);
void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi);
bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi);
void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag);
void wlc_phy_switch_radio(struct brcms_phy_pub *ppi, bool on);
void wlc_phy_anacore(struct brcms_phy_pub *ppi, bool on);
void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi);
void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi,
bool wide_filter);
void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
struct brcms_chanvec *channels);
u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band);
void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan, u8 *_min_,
u8 *_max_, int rate);
void wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan,
u8 *_max_, u8 *_min_);
void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, uint band,
s32 *, s32 *, u32 *);
void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *,
u16 chanspec);
int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override);
int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override);
void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi,
struct txpwr_limits *);
bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi);
void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl);
u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi);
u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi);
bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *pih);
void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain);
void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain);
void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain);
u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih);
s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec);
void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val);
void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason);
void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *ppi);
void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock);
void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi);
void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val);
void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi);
void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, u32 id, bool val);
void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, u32 flags);
void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type);
void wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi,
struct tx_power *power, uint channel);
void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal);
bool wlc_phy_test_ison(struct brcms_phy_pub *ppi);
void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, u8 txpwr_percent);
void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war);
void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt);
void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap);
void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end);
void wlc_phy_freqtrack_start(struct brcms_phy_pub *ppi);
void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi);
const u8 *wlc_phy_get_ofdm_rate_lookup(void);
s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi,
u8 mcs_offset);
s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset);
#endif /* _BRCM_PHY_HAL_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,121 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_PHY_LCN_H_
#define _BRCM_PHY_LCN_H_
#include <types.h>
struct brcms_phy_lcnphy {
int lcnphy_txrf_sp_9_override;
u8 lcnphy_full_cal_channel;
u8 lcnphy_cal_counter;
u16 lcnphy_cal_temper;
bool lcnphy_recal;
u8 lcnphy_rc_cap;
u32 lcnphy_mcs20_po;
u8 lcnphy_tr_isolation_mid;
u8 lcnphy_tr_isolation_low;
u8 lcnphy_tr_isolation_hi;
u8 lcnphy_bx_arch;
u8 lcnphy_rx_power_offset;
u8 lcnphy_rssi_vf;
u8 lcnphy_rssi_vc;
u8 lcnphy_rssi_gs;
u8 lcnphy_tssi_val;
u8 lcnphy_rssi_vf_lowtemp;
u8 lcnphy_rssi_vc_lowtemp;
u8 lcnphy_rssi_gs_lowtemp;
u8 lcnphy_rssi_vf_hightemp;
u8 lcnphy_rssi_vc_hightemp;
u8 lcnphy_rssi_gs_hightemp;
s16 lcnphy_pa0b0;
s16 lcnphy_pa0b1;
s16 lcnphy_pa0b2;
u16 lcnphy_rawtempsense;
u8 lcnphy_measPower;
u8 lcnphy_tempsense_slope;
u8 lcnphy_freqoffset_corr;
u8 lcnphy_tempsense_option;
u8 lcnphy_tempcorrx;
bool lcnphy_iqcal_swp_dis;
bool lcnphy_hw_iqcal_en;
uint lcnphy_bandedge_corr;
bool lcnphy_spurmod;
u16 lcnphy_tssi_tx_cnt;
u16 lcnphy_tssi_idx;
u16 lcnphy_tssi_npt;
u16 lcnphy_target_tx_freq;
s8 lcnphy_tx_power_idx_override;
u16 lcnphy_noise_samples;
u32 lcnphy_papdRxGnIdx;
u32 lcnphy_papd_rxGnCtrl_init;
u32 lcnphy_gain_idx_14_lowword;
u32 lcnphy_gain_idx_14_hiword;
u32 lcnphy_gain_idx_27_lowword;
u32 lcnphy_gain_idx_27_hiword;
s16 lcnphy_ofdmgainidxtableoffset;
s16 lcnphy_dsssgainidxtableoffset;
u32 lcnphy_tr_R_gain_val;
u32 lcnphy_tr_T_gain_val;
s8 lcnphy_input_pwr_offset_db;
u16 lcnphy_Med_Low_Gain_db;
u16 lcnphy_Very_Low_Gain_db;
s8 lcnphy_lastsensed_temperature;
s8 lcnphy_pkteng_rssi_slope;
u8 lcnphy_saved_tx_user_target[TXP_NUM_RATES];
u8 lcnphy_volt_winner;
u8 lcnphy_volt_low;
u8 lcnphy_54_48_36_24mbps_backoff;
u8 lcnphy_11n_backoff;
u8 lcnphy_lowerofdm;
u8 lcnphy_cck;
u8 lcnphy_psat_2pt3_detected;
s32 lcnphy_lowest_Re_div_Im;
s8 lcnphy_final_papd_cal_idx;
u16 lcnphy_extstxctrl4;
u16 lcnphy_extstxctrl0;
u16 lcnphy_extstxctrl1;
s16 lcnphy_cck_dig_filt_type;
s16 lcnphy_ofdm_dig_filt_type;
struct lcnphy_cal_results lcnphy_cal_results;
u8 lcnphy_psat_pwr;
u8 lcnphy_psat_indx;
s32 lcnphy_min_phase;
u8 lcnphy_final_idx;
u8 lcnphy_start_idx;
u8 lcnphy_current_index;
u16 lcnphy_logen_buf_1;
u16 lcnphy_local_ovr_2;
u16 lcnphy_local_oval_6;
u16 lcnphy_local_oval_5;
u16 lcnphy_logen_mixer_1;
u8 lcnphy_aci_stat;
uint lcnphy_aci_start_time;
s8 lcnphy_tx_power_offset[TXP_NUM_RATES];
};
#endif /* _BRCM_PHY_LCN_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,308 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 "phy_qmath.h"
/*
* Description: This function make 16 bit unsigned multiplication.
* To fit the output into 16 bits the 32 bit multiplication result is right
* shifted by 16 bits.
*/
u16 qm_mulu16(u16 op1, u16 op2)
{
return (u16) (((u32) op1 * (u32) op2) >> 16);
}
/*
* Description: This function make 16 bit multiplication and return the result
* in 16 bits. To fit the multiplication result into 16 bits the multiplication
* result is right shifted by 15 bits. Right shifting 15 bits instead of 16 bits
* is done to remove the extra sign bit formed due to the multiplication.
* When both the 16bit inputs are 0x8000 then the output is saturated to
* 0x7fffffff.
*/
s16 qm_muls16(s16 op1, s16 op2)
{
s32 result;
if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000)
result = 0x7fffffff;
else
result = ((s32) (op1) * (s32) (op2));
return (s16) (result >> 15);
}
/*
* Description: This function add two 32 bit numbers and return the 32bit
* result. If the result overflow 32 bits, the output will be saturated to
* 32bits.
*/
s32 qm_add32(s32 op1, s32 op2)
{
s32 result;
result = op1 + op2;
if (op1 < 0 && op2 < 0 && result > 0)
result = 0x80000000;
else if (op1 > 0 && op2 > 0 && result < 0)
result = 0x7fffffff;
return result;
}
/*
* Description: This function add two 16 bit numbers and return the 16bit
* result. If the result overflow 16 bits, the output will be saturated to
* 16bits.
*/
s16 qm_add16(s16 op1, s16 op2)
{
s16 result;
s32 temp = (s32) op1 + (s32) op2;
if (temp > (s32) 0x7fff)
result = (s16) 0x7fff;
else if (temp < (s32) 0xffff8000)
result = (s16) 0xffff8000;
else
result = (s16) temp;
return result;
}
/*
* Description: This function make 16 bit subtraction and return the 16bit
* result. If the result overflow 16 bits, the output will be saturated to
* 16bits.
*/
s16 qm_sub16(s16 op1, s16 op2)
{
s16 result;
s32 temp = (s32) op1 - (s32) op2;
if (temp > (s32) 0x7fff)
result = (s16) 0x7fff;
else if (temp < (s32) 0xffff8000)
result = (s16) 0xffff8000;
else
result = (s16) temp;
return result;
}
/*
* Description: This function make a 32 bit saturated left shift when the
* specified shift is +ve. This function will make a 32 bit right shift when
* the specified shift is -ve. This function return the result after shifting
* operation.
*/
s32 qm_shl32(s32 op, int shift)
{
int i;
s32 result;
result = op;
if (shift > 31)
shift = 31;
else if (shift < -31)
shift = -31;
if (shift >= 0) {
for (i = 0; i < shift; i++)
result = qm_add32(result, result);
} else {
result = result >> (-shift);
}
return result;
}
/*
* Description: This function make a 16 bit saturated left shift when the
* specified shift is +ve. This function will make a 16 bit right shift when
* the specified shift is -ve. This function return the result after shifting
* operation.
*/
s16 qm_shl16(s16 op, int shift)
{
int i;
s16 result;
result = op;
if (shift > 15)
shift = 15;
else if (shift < -15)
shift = -15;
if (shift > 0) {
for (i = 0; i < shift; i++)
result = qm_add16(result, result);
} else {
result = result >> (-shift);
}
return result;
}
/*
* Description: This function make a 16 bit right shift when shift is +ve.
* This function make a 16 bit saturated left shift when shift is -ve. This
* function return the result of the shift operation.
*/
s16 qm_shr16(s16 op, int shift)
{
return qm_shl16(op, -shift);
}
/*
* Description: This function return the number of redundant sign bits in a
* 32 bit number. Example: qm_norm32(0x00000080) = 23
*/
s16 qm_norm32(s32 op)
{
u16 u16extraSignBits;
if (op == 0) {
return 31;
} else {
u16extraSignBits = 0;
while ((op >> 31) == (op >> 30)) {
u16extraSignBits++;
op = op << 1;
}
}
return u16extraSignBits;
}
/* This table is log2(1+(i/32)) where i=[0:1:31], in q.15 format */
static const s16 log_table[] = {
0,
1455,
2866,
4236,
5568,
6863,
8124,
9352,
10549,
11716,
12855,
13968,
15055,
16117,
17156,
18173,
19168,
20143,
21098,
22034,
22952,
23852,
24736,
25604,
26455,
27292,
28114,
28922,
29717,
30498,
31267,
32024
};
#define LOG_TABLE_SIZE 32 /* log_table size */
#define LOG2_LOG_TABLE_SIZE 5 /* log2(log_table size) */
#define Q_LOG_TABLE 15 /* qformat of log_table */
#define LOG10_2 19728 /* log10(2) in q.16 */
/*
* Description:
* This routine takes the input number N and its q format qN and compute
* the log10(N). This routine first normalizes the input no N. Then N is in
* mag*(2^x) format. mag is any number in the range 2^30-(2^31 - 1).
* Then log2(mag * 2^x) = log2(mag) + x is computed. From that
* log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed.
* This routine looks the log2 value in the table considering
* LOG2_LOG_TABLE_SIZE+1 MSBs. As the MSB is always 1, only next
* LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup. Next 16 MSBs are used
* for interpolation.
* Inputs:
* N - number to which log10 has to be found.
* qN - q format of N
* log10N - address where log10(N) will be written.
* qLog10N - address where log10N qformat will be written.
* Note/Problem:
* For accurate results input should be in normalized or near normalized form.
*/
void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N)
{
s16 s16norm, s16tableIndex, s16errorApproximation;
u16 u16offset;
s32 s32log;
/* normalize the N. */
s16norm = qm_norm32(N);
N = N << s16norm;
/* The qformat of N after normalization.
* -30 is added to treat the no as between 1.0 to 2.0
* i.e. after adding the -30 to the qformat the decimal point will be
* just rigtht of the MSB. (i.e. after sign bit and 1st MSB). i.e.
* at the right side of 30th bit.
*/
qN = qN + s16norm - 30;
/* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the
* MSB */
s16tableIndex = (s16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE)));
/* remove the MSB. the MSB is always 1 after normalization. */
s16tableIndex =
s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1);
/* remove the (1+LOG2_OF_LOG_TABLE_SIZE) MSBs in the N. */
N = N & ((1 << (32 - (2 + LOG2_LOG_TABLE_SIZE))) - 1);
/* take the offset as the 16 MSBS after table index.
*/
u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16)));
/* look the log value in the table. */
s32log = log_table[s16tableIndex]; /* q.15 format */
/* interpolate using the offset. q.15 format. */
s16errorApproximation = (s16) qm_mulu16(u16offset,
(u16) (log_table[s16tableIndex + 1] -
log_table[s16tableIndex]));
/* q.15 format */
s32log = qm_add16((s16) s32log, s16errorApproximation);
/* adjust for the qformat of the N as
* log2(mag * 2^x) = log2(mag) + x
*/
s32log = qm_add32(s32log, ((s32) -qN) << 15); /* q.15 format */
/* normalize the result. */
s16norm = qm_norm32(s32log);
/* bring all the important bits into lower 16 bits */
/* q.15+s16norm-16 format */
s32log = qm_shl32(s32log, s16norm - 16);
/* compute the log10(N) by multiplying log2(N) with log10(2).
* as log10(mag * 2^x) = log2(mag * 2^x) * log10(2)
* log10N in q.15+s16norm-16+1 (LOG10_2 is in q.16)
*/
*log10N = qm_muls16((s16) s32log, (s16) LOG10_2);
/* write the q format of the result. */
*qLog10N = 15 + s16norm - 16 + 1;
return;
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_QMATH_H_
#define _BRCM_QMATH_H_
#include <types.h>
u16 qm_mulu16(u16 op1, u16 op2);
s16 qm_muls16(s16 op1, s16 op2);
s32 qm_add32(s32 op1, s32 op2);
s16 qm_add16(s16 op1, s16 op2);
s16 qm_sub16(s16 op1, s16 op2);
s32 qm_shl32(s32 op, int shift);
s16 qm_shl16(s16 op, int shift);
s16 qm_shr16(s16 op, int shift);
s16 qm_norm32(s32 op);
void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N);
#endif /* #ifndef _BRCM_QMATH_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,167 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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.
*/
#define NPHY_TBL_ID_GAIN1 0
#define NPHY_TBL_ID_GAIN2 1
#define NPHY_TBL_ID_GAINBITS1 2
#define NPHY_TBL_ID_GAINBITS2 3
#define NPHY_TBL_ID_GAINLIMIT 4
#define NPHY_TBL_ID_WRSSIGainLimit 5
#define NPHY_TBL_ID_RFSEQ 7
#define NPHY_TBL_ID_AFECTRL 8
#define NPHY_TBL_ID_ANTSWCTRLLUT 9
#define NPHY_TBL_ID_IQLOCAL 15
#define NPHY_TBL_ID_NOISEVAR 16
#define NPHY_TBL_ID_SAMPLEPLAY 17
#define NPHY_TBL_ID_CORE1TXPWRCTL 26
#define NPHY_TBL_ID_CORE2TXPWRCTL 27
#define NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL 30
#define NPHY_TBL_ID_EPSILONTBL0 31
#define NPHY_TBL_ID_SCALARTBL0 32
#define NPHY_TBL_ID_EPSILONTBL1 33
#define NPHY_TBL_ID_SCALARTBL1 34
#define NPHY_TO_BPHY_OFF 0xc00
#define NPHY_BandControl_currentBand 0x0001
#define RFCC_CHIP0_PU 0x0400
#define RFCC_POR_FORCE 0x0040
#define RFCC_OE_POR_FORCE 0x0080
#define NPHY_RfctrlIntc_override_OFF 0
#define NPHY_RfctrlIntc_override_TRSW 1
#define NPHY_RfctrlIntc_override_PA 2
#define NPHY_RfctrlIntc_override_EXT_LNA_PU 3
#define NPHY_RfctrlIntc_override_EXT_LNA_GAIN 4
#define RIFS_ENABLE 0x80
#define BPHY_BAND_SEL_UP20 0x10
#define NPHY_MLenable 0x02
#define NPHY_RfseqMode_CoreActv_override 0x0001
#define NPHY_RfseqMode_Trigger_override 0x0002
#define NPHY_RfseqCoreActv_TxRxChain0 (0x11)
#define NPHY_RfseqCoreActv_TxRxChain1 (0x22)
#define NPHY_RfseqTrigger_rx2tx 0x0001
#define NPHY_RfseqTrigger_tx2rx 0x0002
#define NPHY_RfseqTrigger_updategainh 0x0004
#define NPHY_RfseqTrigger_updategainl 0x0008
#define NPHY_RfseqTrigger_updategainu 0x0010
#define NPHY_RfseqTrigger_reset2rx 0x0020
#define NPHY_RfseqStatus_rx2tx 0x0001
#define NPHY_RfseqStatus_tx2rx 0x0002
#define NPHY_RfseqStatus_updategainh 0x0004
#define NPHY_RfseqStatus_updategainl 0x0008
#define NPHY_RfseqStatus_updategainu 0x0010
#define NPHY_RfseqStatus_reset2rx 0x0020
#define NPHY_ClassifierCtrl_cck_en 0x1
#define NPHY_ClassifierCtrl_ofdm_en 0x2
#define NPHY_ClassifierCtrl_waited_en 0x4
#define NPHY_IQFlip_ADC1 0x0001
#define NPHY_IQFlip_ADC2 0x0010
#define NPHY_sampleCmd_STOP 0x0002
#define RX_GF_OR_MM 0x0004
#define RX_GF_MM_AUTO 0x0100
#define NPHY_iqloCalCmdGctl_IQLO_CAL_EN 0x8000
#define NPHY_IqestCmd_iqstart 0x1
#define NPHY_IqestCmd_iqMode 0x2
#define NPHY_TxPwrCtrlCmd_pwrIndex_init 0x40
#define NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 0x19
#define PRIM_SEL_UP20 0x8000
#define NPHY_RFSEQ_RX2TX 0x0
#define NPHY_RFSEQ_TX2RX 0x1
#define NPHY_RFSEQ_RESET2RX 0x2
#define NPHY_RFSEQ_UPDATEGAINH 0x3
#define NPHY_RFSEQ_UPDATEGAINL 0x4
#define NPHY_RFSEQ_UPDATEGAINU 0x5
#define NPHY_RFSEQ_CMD_NOP 0x0
#define NPHY_RFSEQ_CMD_RXG_FBW 0x1
#define NPHY_RFSEQ_CMD_TR_SWITCH 0x2
#define NPHY_RFSEQ_CMD_EXT_PA 0x3
#define NPHY_RFSEQ_CMD_RXPD_TXPD 0x4
#define NPHY_RFSEQ_CMD_TX_GAIN 0x5
#define NPHY_RFSEQ_CMD_RX_GAIN 0x6
#define NPHY_RFSEQ_CMD_SET_HPF_BW 0x7
#define NPHY_RFSEQ_CMD_CLR_HIQ_DIS 0x8
#define NPHY_RFSEQ_CMD_END 0xf
#define NPHY_REV3_RFSEQ_CMD_NOP 0x0
#define NPHY_REV3_RFSEQ_CMD_RXG_FBW 0x1
#define NPHY_REV3_RFSEQ_CMD_TR_SWITCH 0x2
#define NPHY_REV3_RFSEQ_CMD_INT_PA_PU 0x3
#define NPHY_REV3_RFSEQ_CMD_EXT_PA 0x4
#define NPHY_REV3_RFSEQ_CMD_RXPD_TXPD 0x5
#define NPHY_REV3_RFSEQ_CMD_TX_GAIN 0x6
#define NPHY_REV3_RFSEQ_CMD_RX_GAIN 0x7
#define NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS 0x8
#define NPHY_REV3_RFSEQ_CMD_SET_HPF_H_HPC 0x9
#define NPHY_REV3_RFSEQ_CMD_SET_LPF_H_HPC 0xa
#define NPHY_REV3_RFSEQ_CMD_SET_HPF_M_HPC 0xb
#define NPHY_REV3_RFSEQ_CMD_SET_LPF_M_HPC 0xc
#define NPHY_REV3_RFSEQ_CMD_SET_HPF_L_HPC 0xd
#define NPHY_REV3_RFSEQ_CMD_SET_LPF_L_HPC 0xe
#define NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS 0xf
#define NPHY_REV3_RFSEQ_CMD_END 0x1f
#define NPHY_RSSI_SEL_W1 0x0
#define NPHY_RSSI_SEL_W2 0x1
#define NPHY_RSSI_SEL_NB 0x2
#define NPHY_RSSI_SEL_IQ 0x3
#define NPHY_RSSI_SEL_TSSI_2G 0x4
#define NPHY_RSSI_SEL_TSSI_5G 0x5
#define NPHY_RSSI_SEL_TBD 0x6
#define NPHY_RAIL_I 0x0
#define NPHY_RAIL_Q 0x1
#define NPHY_FORCESIG_DECODEGATEDCLKS 0x8
#define NPHY_REV7_RfctrlOverride_cmd_rxrf_pu 0x0
#define NPHY_REV7_RfctrlOverride_cmd_rx_pu 0x1
#define NPHY_REV7_RfctrlOverride_cmd_tx_pu 0x2
#define NPHY_REV7_RfctrlOverride_cmd_rxgain 0x3
#define NPHY_REV7_RfctrlOverride_cmd_txgain 0x4
#define NPHY_REV7_RXGAINCODE_RFMXGAIN_MASK 0x000ff
#define NPHY_REV7_RXGAINCODE_LPFGAIN_MASK 0x0ff00
#define NPHY_REV7_RXGAINCODE_DVGAGAIN_MASK 0xf0000
#define NPHY_REV7_TXGAINCODE_TGAIN_MASK 0x7fff
#define NPHY_REV7_TXGAINCODE_LPFGAIN_MASK 0x8000
#define NPHY_REV7_TXGAINCODE_BIQ0GAIN_SHIFT 14
#define NPHY_REV7_RFCTRLOVERRIDE_ID0 0x0
#define NPHY_REV7_RFCTRLOVERRIDE_ID1 0x1
#define NPHY_REV7_RFCTRLOVERRIDE_ID2 0x2
#define NPHY_IqestIqAccLo(core) ((core == 0) ? 0x12c : 0x134)
#define NPHY_IqestIqAccHi(core) ((core == 0) ? 0x12d : 0x135)
#define NPHY_IqestipwrAccLo(core) ((core == 0) ? 0x12e : 0x136)
#define NPHY_IqestipwrAccHi(core) ((core == 0) ? 0x12f : 0x137)
#define NPHY_IqestqpwrAccLo(core) ((core == 0) ? 0x130 : 0x138)
#define NPHY_IqestqpwrAccHi(core) ((core == 0) ? 0x131 : 0x139)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 <types.h>
#include "phy_int.h"
extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[];
extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev0;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_ipa;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa_combo;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
extern const struct phytbl_info dot11lcnphytbl_info_rev0[];
extern const u32 dot11lcnphytbl_info_sz_rev0;
extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_2G_rev2[];
extern const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_5G_rev2[];
extern const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[];
extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[];
struct lcnphy_tx_gain_tbl_entry {
unsigned char gm;
unsigned char pga;
unsigned char pad;
unsigned char dac;
unsigned char bb_mult;
};
extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[];
extern const struct
lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[];
extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[];

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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.
*/
#define ANT_SWCTRL_TBL_REV3_IDX (0)
#include <types.h>
#include "phy_int.h"
extern const struct phytbl_info mimophytbl_info_rev0[],
mimophytbl_info_rev0_volatile[];
extern const u32 mimophytbl_info_sz_rev0,
mimophytbl_info_sz_rev0_volatile;
extern const struct phytbl_info mimophytbl_info_rev3[],
mimophytbl_info_rev3_volatile[],
mimophytbl_info_rev3_volatile1[],
mimophytbl_info_rev3_volatile2[],
mimophytbl_info_rev3_volatile3[];
extern const u32 mimophytbl_info_sz_rev3,
mimophytbl_info_sz_rev3_volatile,
mimophytbl_info_sz_rev3_volatile1,
mimophytbl_info_sz_rev3_volatile2,
mimophytbl_info_sz_rev3_volatile3;
extern const u32 noise_var_tbl_rev3[];
extern const struct phytbl_info mimophytbl_info_rev7[];
extern const u32 mimophytbl_info_sz_rev7;
extern const u32 noise_var_tbl_rev7[];
extern const struct phytbl_info mimophytbl_info_rev16[];
extern const u32 mimophytbl_info_sz_rev16;

View File

@@ -0,0 +1,216 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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.
*/
/*
* This is "two-way" interface, acting as the SHIM layer between driver
* and PHY layer. The driver can optionally call this translation layer
* to do some preprocessing, then reach PHY. On the PHY->driver direction,
* all calls go through this layer since PHY doesn't have access to the
* driver's brcms_hardware pointer.
*/
#include <linux/slab.h>
#include <net/mac80211.h>
#include "main.h"
#include "mac80211_if.h"
#include "phy_shim.h"
/* PHY SHIM module specific state */
struct phy_shim_info {
struct brcms_hardware *wlc_hw; /* pointer to main wlc_hw structure */
struct brcms_c_info *wlc; /* pointer to main wlc structure */
struct brcms_info *wl; /* pointer to os-specific private state */
};
struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw,
struct brcms_info *wl,
struct brcms_c_info *wlc) {
struct phy_shim_info *physhim = NULL;
physhim = kzalloc(sizeof(struct phy_shim_info), GFP_ATOMIC);
if (!physhim)
return NULL;
physhim->wlc_hw = wlc_hw;
physhim->wlc = wlc;
physhim->wl = wl;
return physhim;
}
void wlc_phy_shim_detach(struct phy_shim_info *physhim)
{
kfree(physhim);
}
struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
void (*fn)(struct brcms_phy *pi),
void *arg, const char *name)
{
return (struct wlapi_timer *)
brcms_init_timer(physhim->wl, (void (*)(void *))fn,
arg, name);
}
void wlapi_free_timer(struct wlapi_timer *t)
{
brcms_free_timer((struct brcms_timer *)t);
}
void
wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic)
{
brcms_add_timer((struct brcms_timer *)t, ms, periodic);
}
bool wlapi_del_timer(struct wlapi_timer *t)
{
return brcms_del_timer((struct brcms_timer *)t);
}
void wlapi_intrson(struct phy_shim_info *physhim)
{
brcms_intrson(physhim->wl);
}
u32 wlapi_intrsoff(struct phy_shim_info *physhim)
{
return brcms_intrsoff(physhim->wl);
}
void wlapi_intrsrestore(struct phy_shim_info *physhim, u32 macintmask)
{
brcms_intrsrestore(physhim->wl, macintmask);
}
void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, u16 v)
{
brcms_b_write_shm(physhim->wlc_hw, offset, v);
}
u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset)
{
return brcms_b_read_shm(physhim->wlc_hw, offset);
}
void
wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, u16 mask,
u16 val, int bands)
{
brcms_b_mhf(physhim->wlc_hw, idx, mask, val, bands);
}
void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags)
{
brcms_b_corereset(physhim->wlc_hw, flags);
}
void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim)
{
brcms_c_suspend_mac_and_wait(physhim->wlc);
}
void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode)
{
brcms_b_switch_macfreq(physhim->wlc_hw, spurmode);
}
void wlapi_enable_mac(struct phy_shim_info *physhim)
{
brcms_c_enable_mac(physhim->wlc);
}
void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, u32 val)
{
brcms_b_mctrl(physhim->wlc_hw, mask, val);
}
void wlapi_bmac_phy_reset(struct phy_shim_info *physhim)
{
brcms_b_phy_reset(physhim->wlc_hw);
}
void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw)
{
brcms_b_bw_set(physhim->wlc_hw, bw);
}
u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim)
{
return brcms_b_get_txant(physhim->wlc_hw);
}
void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk)
{
brcms_b_phyclk_fgc(physhim->wlc_hw, clk);
}
void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk)
{
brcms_b_macphyclk_set(physhim->wlc_hw, clk);
}
void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on)
{
brcms_b_core_phypll_ctl(physhim->wlc_hw, on);
}
void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim)
{
brcms_b_core_phypll_reset(physhim->wlc_hw);
}
void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *physhim)
{
brcms_c_ucode_wake_override_set(physhim->wlc_hw,
BRCMS_WAKE_OVERRIDE_PHYREG);
}
void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *physhim)
{
brcms_c_ucode_wake_override_clear(physhim->wlc_hw,
BRCMS_WAKE_OVERRIDE_PHYREG);
}
void
wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int offset,
int len, void *buf)
{
brcms_b_write_template_ram(physhim->wlc_hw, offset, len, buf);
}
u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, u8 rate)
{
return brcms_b_rate_shm_offset(physhim->wlc_hw, rate);
}
void wlapi_ucode_sample_init(struct phy_shim_info *physhim)
{
}
void
wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint offset, void *buf,
int len, u32 sel)
{
brcms_b_copyfrom_objmem(physhim->wlc_hw, offset, buf, len, sel);
}
void
wlapi_copyto_objmem(struct phy_shim_info *physhim, uint offset, const void *buf,
int l, u32 sel)
{
brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel);
}

View File

@@ -0,0 +1,172 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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.
*/
/*
* phy_shim.h: stuff defined in phy_shim.c and included only by the phy
*/
#ifndef _BRCM_PHY_SHIM_H_
#define _BRCM_PHY_SHIM_H_
#include "types.h"
#define RADAR_TYPE_NONE 0 /* Radar type None */
#define RADAR_TYPE_ETSI_1 1 /* ETSI 1 Radar type */
#define RADAR_TYPE_ETSI_2 2 /* ETSI 2 Radar type */
#define RADAR_TYPE_ETSI_3 3 /* ETSI 3 Radar type */
#define RADAR_TYPE_ITU_E 4 /* ITU E Radar type */
#define RADAR_TYPE_ITU_K 5 /* ITU K Radar type */
#define RADAR_TYPE_UNCLASSIFIED 6 /* Unclassified Radar type */
#define RADAR_TYPE_BIN5 7 /* long pulse radar type */
#define RADAR_TYPE_STG2 8 /* staggered-2 radar */
#define RADAR_TYPE_STG3 9 /* staggered-3 radar */
#define RADAR_TYPE_FRA 10 /* French radar */
/* French radar pulse widths */
#define FRA_T1_20MHZ 52770
#define FRA_T2_20MHZ 61538
#define FRA_T3_20MHZ 66002
#define FRA_T1_40MHZ 105541
#define FRA_T2_40MHZ 123077
#define FRA_T3_40MHZ 132004
#define FRA_ERR_20MHZ 60
#define FRA_ERR_40MHZ 120
#define ANTSEL_NA 0 /* No boardlevel selection available */
#define ANTSEL_2x4 1 /* 2x4 boardlevel selection available */
#define ANTSEL_2x3 2 /* 2x3 CB2 boardlevel selection available */
/* Rx Antenna diversity control values */
#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */
#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */
#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */
#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */
#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */
#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 /* default antdiv setting */
#define WL_ANT_RX_MAX 2 /* max 2 receive antennas */
#define WL_ANT_HT_RX_MAX 3 /* max 3 receive antennas/cores */
#define WL_ANT_IDX_1 0 /* antenna index 1 */
#define WL_ANT_IDX_2 1 /* antenna index 2 */
/* values for n_preamble_type */
#define BRCMS_N_PREAMBLE_MIXEDMODE 0
#define BRCMS_N_PREAMBLE_GF 1
#define BRCMS_N_PREAMBLE_GF_BRCM 2
#define WL_TX_POWER_RATES_LEGACY 45
#define WL_TX_POWER_MCS20_FIRST 12
#define WL_TX_POWER_MCS20_NUM 16
#define WL_TX_POWER_MCS40_FIRST 28
#define WL_TX_POWER_MCS40_NUM 17
#define WL_TX_POWER_RATES 101
#define WL_TX_POWER_CCK_FIRST 0
#define WL_TX_POWER_CCK_NUM 4
/* Index for first 20MHz OFDM SISO rate */
#define WL_TX_POWER_OFDM_FIRST 4
/* Index for first 20MHz OFDM CDD rate */
#define WL_TX_POWER_OFDM20_CDD_FIRST 12
/* Index for first 40MHz OFDM SISO rate */
#define WL_TX_POWER_OFDM40_SISO_FIRST 52
/* Index for first 40MHz OFDM CDD rate */
#define WL_TX_POWER_OFDM40_CDD_FIRST 60
#define WL_TX_POWER_OFDM_NUM 8
/* Index for first 20MHz MCS SISO rate */
#define WL_TX_POWER_MCS20_SISO_FIRST 20
/* Index for first 20MHz MCS CDD rate */
#define WL_TX_POWER_MCS20_CDD_FIRST 28
/* Index for first 20MHz MCS STBC rate */
#define WL_TX_POWER_MCS20_STBC_FIRST 36
/* Index for first 20MHz MCS SDM rate */
#define WL_TX_POWER_MCS20_SDM_FIRST 44
/* Index for first 40MHz MCS SISO rate */
#define WL_TX_POWER_MCS40_SISO_FIRST 68
/* Index for first 40MHz MCS CDD rate */
#define WL_TX_POWER_MCS40_CDD_FIRST 76
/* Index for first 40MHz MCS STBC rate */
#define WL_TX_POWER_MCS40_STBC_FIRST 84
/* Index for first 40MHz MCS SDM rate */
#define WL_TX_POWER_MCS40_SDM_FIRST 92
#define WL_TX_POWER_MCS_1_STREAM_NUM 8
#define WL_TX_POWER_MCS_2_STREAM_NUM 8
/* Index for 40MHz rate MCS 32 */
#define WL_TX_POWER_MCS_32 100
#define WL_TX_POWER_MCS_32_NUM 1
/* sslpnphy specifics */
/* Index for first 20MHz MCS SISO rate */
#define WL_TX_POWER_MCS20_SISO_FIRST_SSN 12
/* struct tx_power::flags bits */
#define WL_TX_POWER_F_ENABLED 1
#define WL_TX_POWER_F_HW 2
#define WL_TX_POWER_F_MIMO 4
#define WL_TX_POWER_F_SISO 8
/* values to force tx/rx chain */
#define BRCMS_N_TXRX_CHAIN0 0
#define BRCMS_N_TXRX_CHAIN1 1
struct brcms_phy;
struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw,
struct brcms_info *wl,
struct brcms_c_info *wlc);
void wlc_phy_shim_detach(struct phy_shim_info *physhim);
/* PHY to WL utility functions */
struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
void (*fn)(struct brcms_phy *pi),
void *arg, const char *name);
void wlapi_free_timer(struct wlapi_timer *t);
void wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic);
bool wlapi_del_timer(struct wlapi_timer *t);
void wlapi_intrson(struct phy_shim_info *physhim);
u32 wlapi_intrsoff(struct phy_shim_info *physhim);
void wlapi_intrsrestore(struct phy_shim_info *physhim, u32 macintmask);
void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, u16 v);
u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset);
void wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, u16 mask, u16 val,
int bands);
void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags);
void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim);
void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode);
void wlapi_enable_mac(struct phy_shim_info *physhim);
void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, u32 val);
void wlapi_bmac_phy_reset(struct phy_shim_info *physhim);
void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw);
void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk);
void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk);
void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on);
void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim);
void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *physhim);
void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *physhim);
void wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int o,
int len, void *buf);
u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, u8 rate);
void wlapi_ucode_sample_init(struct phy_shim_info *physhim);
void wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint, void *buf,
int, u32 sel);
void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint, const void *buf,
int, u32);
void wlapi_high_update_phy_mode(struct phy_shim_info *physhim, u32 phy_mode);
u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim);
#endif /* _BRCM_PHY_SHIM_H_ */

View File

@@ -0,0 +1,165 @@
/*
* Copyright (c) 2011 Broadcom Corporation
*
* 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/delay.h>
#include <linux/io.h>
#include <brcm_hw_ids.h>
#include <chipcommon.h>
#include <brcmu_utils.h>
#include "pub.h"
#include "aiutils.h"
#include "pmu.h"
#include "soc.h"
/*
* external LPO crystal frequency
*/
#define EXT_ILP_HZ 32768
/*
* Duration for ILP clock frequency measurment in milliseconds
*
* remark: 1000 must be an integer multiple of this duration
*/
#define ILP_CALC_DUR 10
/* Fields in pmucontrol */
#define PCTL_ILP_DIV_MASK 0xffff0000
#define PCTL_ILP_DIV_SHIFT 16
#define PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */
#define PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */
#define PCTL_HT_REQ_EN 0x00000100
#define PCTL_ALP_REQ_EN 0x00000080
#define PCTL_XTALFREQ_MASK 0x0000007c
#define PCTL_XTALFREQ_SHIFT 2
#define PCTL_ILP_DIV_EN 0x00000002
#define PCTL_LPO_SEL 0x00000001
/* ILP clock */
#define ILP_CLOCK 32000
/* ALP clock on pre-PMU chips */
#define ALP_CLOCK 20000000
/* pmustatus */
#define PST_EXTLPOAVAIL 0x0100
#define PST_WDRESET 0x0080
#define PST_INTPEND 0x0040
#define PST_SBCLKST 0x0030
#define PST_SBCLKST_ILP 0x0010
#define PST_SBCLKST_ALP 0x0020
#define PST_SBCLKST_HT 0x0030
#define PST_ALPAVAIL 0x0008
#define PST_HTAVAIL 0x0004
#define PST_RESINIT 0x0003
/* PMU resource bit position */
#define PMURES_BIT(bit) (1 << (bit))
/* PMU corerev and chip specific PLL controls.
* PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary
* number to differentiate different PLLs controlled by the same PMU rev.
*/
/* pmu XtalFreqRatio */
#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF
#define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000
#define PMU_XTALFREQ_REG_MEASURE_SHIFT 31
/* 4313 resources */
#define RES4313_BB_PU_RSRC 0
#define RES4313_ILP_REQ_RSRC 1
#define RES4313_XTAL_PU_RSRC 2
#define RES4313_ALP_AVAIL_RSRC 3
#define RES4313_RADIO_PU_RSRC 4
#define RES4313_BG_PU_RSRC 5
#define RES4313_VREG1P4_PU_RSRC 6
#define RES4313_AFE_PWRSW_RSRC 7
#define RES4313_RX_PWRSW_RSRC 8
#define RES4313_TX_PWRSW_RSRC 9
#define RES4313_BB_PWRSW_RSRC 10
#define RES4313_SYNTH_PWRSW_RSRC 11
#define RES4313_MISC_PWRSW_RSRC 12
#define RES4313_BB_PLL_PWRSW_RSRC 13
#define RES4313_HT_AVAIL_RSRC 14
#define RES4313_MACPHY_CLK_AVAIL_RSRC 15
u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
{
uint delay = PMU_MAX_TRANSITION_DLY;
switch (ai_get_chip_id(sih)) {
case BCMA_CHIP_ID_BCM43224:
case BCMA_CHIP_ID_BCM43225:
case BCMA_CHIP_ID_BCM4313:
delay = 3700;
break;
default:
break;
}
return (u16) delay;
}
u32 si_pmu_measure_alpclk(struct si_pub *sih)
{
struct si_info *sii = container_of(sih, struct si_info, pub);
struct bcma_device *core;
u32 alp_khz;
if (ai_get_pmurev(sih) < 10)
return 0;
/* Remember original core before switch to chipc */
core = sii->icbus->drv_cc.core;
if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) {
u32 ilp_ctr, alp_hz;
/*
* Enable the reg to measure the freq,
* in case it was disabled before
*/
bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq),
1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
/* Delay for well over 4 ILP clocks */
udelay(1000);
/* Read the latched number of ALP ticks per 4 ILP ticks */
ilp_ctr = bcma_read32(core, CHIPCREGOFFS(pmu_xtalfreq)) &
PMU_XTALFREQ_REG_ILPCTR_MASK;
/*
* Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT
* bit to save power
*/
bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq), 0);
/* Calculate ALP frequency */
alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
/*
* Round to nearest 100KHz, and at
* the same time convert to KHz
*/
alp_khz = (alp_hz + 50000) / 100000 * 100;
} else
alp_khz = 0;
return alp_khz;
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_PMU_H_
#define _BRCM_PMU_H_
#include "types.h"
u16 si_pmu_fast_pwrup_delay(struct si_pub *sih);
u32 si_pmu_measure_alpclk(struct si_pub *sih);
#endif /* _BRCM_PMU_H_ */

View File

@@ -0,0 +1,341 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_PUB_H_
#define _BRCM_PUB_H_
#include <linux/bcma/bcma.h>
#include <brcmu_wifi.h>
#include "types.h"
#include "defs.h"
#define BRCMS_NUMRATES 16 /* max # of rates in a rateset */
/* phy types */
#define PHY_TYPE_A 0 /* Phy type A */
#define PHY_TYPE_G 2 /* Phy type G */
#define PHY_TYPE_N 4 /* Phy type N */
#define PHY_TYPE_LP 5 /* Phy type Low Power A/B/G */
#define PHY_TYPE_SSN 6 /* Phy type Single Stream N */
#define PHY_TYPE_LCN 8 /* Phy type Single Stream N */
#define PHY_TYPE_LCNXN 9 /* Phy type 2-stream N */
#define PHY_TYPE_HT 7 /* Phy type 3-Stream N */
/* bw */
#define BRCMS_10_MHZ 10 /* 10Mhz nphy channel bandwidth */
#define BRCMS_20_MHZ 20 /* 20Mhz nphy channel bandwidth */
#define BRCMS_40_MHZ 40 /* 40Mhz nphy channel bandwidth */
#define BRCMS_RSSI_MINVAL -200 /* Low value, e.g. for forcing roam */
#define BRCMS_RSSI_NO_SIGNAL -91 /* NDIS RSSI link quality cutoffs */
#define BRCMS_RSSI_VERY_LOW -80 /* Very low quality cutoffs */
#define BRCMS_RSSI_LOW -70 /* Low quality cutoffs */
#define BRCMS_RSSI_GOOD -68 /* Good quality cutoffs */
#define BRCMS_RSSI_VERY_GOOD -58 /* Very good quality cutoffs */
#define BRCMS_RSSI_EXCELLENT -57 /* Excellent quality cutoffs */
/* a large TX Power as an init value to factor out of min() calculations,
* keep low enough to fit in an s8, units are .25 dBm
*/
#define BRCMS_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */
/* rate related definitions */
#define BRCMS_RATE_FLAG 0x80 /* Flag to indicate it is a basic rate */
#define BRCMS_RATE_MASK 0x7f /* Rate value mask w/o basic rate flag */
/* legacy rx Antenna diversity for SISO rates */
#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */
#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */
#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */
#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */
#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */
/* default antdiv setting */
#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0
/* legacy rx Antenna diversity for SISO rates */
/* Tx on antenna 0, "legacy term Main" */
#define ANT_TX_FORCE_0 0
/* Tx on antenna 1, "legacy term Aux" */
#define ANT_TX_FORCE_1 1
/* Tx on phy's last good Rx antenna */
#define ANT_TX_LAST_RX 3
/* driver's default tx antenna setting */
#define ANT_TX_DEF 3
/* Tx Chain values */
/* def bitmap of txchain */
#define TXCHAIN_DEF 0x1
/* default bitmap of tx chains for nphy */
#define TXCHAIN_DEF_NPHY 0x3
/* default bitmap of tx chains for nphy */
#define TXCHAIN_DEF_HTPHY 0x7
/* def bitmap of rxchain */
#define RXCHAIN_DEF 0x1
/* default bitmap of rx chains for nphy */
#define RXCHAIN_DEF_NPHY 0x3
/* default bitmap of rx chains for nphy */
#define RXCHAIN_DEF_HTPHY 0x7
/* no antenna switch */
#define ANTSWITCH_NONE 0
/* antenna switch on 4321CB2, 2of3 */
#define ANTSWITCH_TYPE_1 1
/* antenna switch on 4321MPCI, 2of3 */
#define ANTSWITCH_TYPE_2 2
/* antenna switch on 4322, 2of3 */
#define ANTSWITCH_TYPE_3 3
#define RXBUFSZ PKTBUFSZ
#define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */
struct brcm_rateset {
/* # rates in this set */
u32 count;
/* rates in 500kbps units w/hi bit set if basic */
u8 rates[WL_NUMRATES];
};
struct brcms_c_rateset {
uint count; /* number of rates in rates[] */
/* rates in 500kbps units w/hi bit set if basic */
u8 rates[BRCMS_NUMRATES];
u8 htphy_membership; /* HT PHY Membership */
u8 mcs[MCSSET_LEN]; /* supported mcs index bit map */
};
/* All the HT-specific default advertised capabilities (including AMPDU)
* should be grouped here at one place
*/
#define AMPDU_DEF_MPDU_DENSITY 6 /* default mpdu density (110 ==> 4us) */
/* wlc internal bss_info */
struct brcms_bss_info {
u8 BSSID[ETH_ALEN]; /* network BSSID */
u16 flags; /* flags for internal attributes */
u8 SSID_len; /* the length of SSID */
u8 SSID[32]; /* SSID string */
s16 RSSI; /* receive signal strength (in dBm) */
s16 SNR; /* receive signal SNR in dB */
u16 beacon_period; /* units are Kusec */
u16 chanspec; /* Channel num, bw, ctrl_sb and band */
struct brcms_c_rateset rateset; /* supported rates */
};
#define MAC80211_PROMISC_BCNS (1 << 0)
#define MAC80211_SCAN (1 << 1)
/*
* Public portion of common driver state structure.
* The wlc handle points at this.
*/
struct brcms_pub {
struct brcms_c_info *wlc;
struct ieee80211_hw *ieee_hw;
struct scb_ampdu *global_ampdu;
uint mac80211_state;
uint unit; /* device instance number */
uint corerev; /* core revision */
struct si_pub *sih; /* SI handle (cookie for siutils calls) */
bool up; /* interface up and running */
bool hw_off; /* HW is off */
bool hw_up; /* one time hw up/down */
bool _piomode; /* true if pio mode */
uint _nbands; /* # bands supported */
uint now; /* # elapsed seconds */
bool delayed_down; /* down delayed */
bool associated; /* true:part of [I]BSS, false: not */
/* (union of stas_associated, aps_associated) */
bool _ampdu; /* ampdu enabled or not */
u8 _n_enab; /* bitmap of 11N + HT support */
u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */
u32 radio_disabled; /* bit vector for radio disabled reasons */
u16 boardrev; /* version # of particular board */
u8 sromrev; /* version # of the srom */
char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */
u32 boardflags; /* Board specific flags from srom */
u32 boardflags2; /* More board flags if sromrev >= 4 */
bool phy_11ncapable; /* the PHY/HW is capable of 802.11N */
struct wl_cnt *_cnt; /* low-level counters in driver */
struct dentry *dbgfs_dir;
};
enum wlc_par_id {
IOV_MPC = 1,
IOV_RTSTHRESH,
IOV_QTXPOWER,
IOV_BCN_LI_BCN /* Beacon listen interval in # of beacons */
};
/***********************************************
* Feature-related macros to optimize out code *
* *********************************************
*/
#define ENAB_1x1 0x01
#define ENAB_2x2 0x02
#define ENAB_3x3 0x04
#define ENAB_4x4 0x08
#define SUPPORT_11N (ENAB_1x1|ENAB_2x2)
#define SUPPORT_HT (ENAB_1x1|ENAB_2x2|ENAB_3x3)
/* WL11N Support */
#define AMPDU_AGG_HOST 1
/* network protection config */
#define BRCMS_PROT_G_SPEC 1 /* SPEC g protection */
#define BRCMS_PROT_G_OVR 2 /* SPEC g prot override */
#define BRCMS_PROT_G_USER 3 /* gmode specified by user */
#define BRCMS_PROT_OVERLAP 4 /* overlap */
#define BRCMS_PROT_N_USER 10 /* nmode specified by user */
#define BRCMS_PROT_N_CFG 11 /* n protection */
#define BRCMS_PROT_N_CFG_OVR 12 /* n protection override */
#define BRCMS_PROT_N_NONGF 13 /* non-GF protection */
#define BRCMS_PROT_N_NONGF_OVR 14 /* non-GF protection override */
#define BRCMS_PROT_N_PAM_OVR 15 /* n preamble override */
#define BRCMS_PROT_N_OBSS 16 /* non-HT OBSS present */
/*
* 54g modes (basic bits may still be overridden)
*
* GMODE_LEGACY_B
* Rateset: 1b, 2b, 5.5, 11
* Preamble: Long
* Shortslot: Off
* GMODE_AUTO
* Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
* Extended Rateset: 6, 9, 12, 48
* Preamble: Long
* Shortslot: Auto
* GMODE_ONLY
* Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54
* Extended Rateset: 6b, 9, 12b, 48
* Preamble: Short required
* Shortslot: Auto
* GMODE_B_DEFERRED
* Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
* Extended Rateset: 6, 9, 12, 48
* Preamble: Long
* Shortslot: On
* GMODE_PERFORMANCE
* Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54
* Preamble: Short required
* Shortslot: On and required
* GMODE_LRS
* Rateset: 1b, 2b, 5.5b, 11b
* Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54
* Preamble: Long
* Shortslot: Auto
*/
#define GMODE_LEGACY_B 0
#define GMODE_AUTO 1
#define GMODE_ONLY 2
#define GMODE_B_DEFERRED 3
#define GMODE_PERFORMANCE 4
#define GMODE_LRS 5
#define GMODE_MAX 6
/* MCS values greater than this enable multiple streams */
#define HIGHEST_SINGLE_STREAM_MCS 7
#define MAXBANDS 2 /* Maximum #of bands */
/* max number of antenna configurations */
#define ANT_SELCFG_MAX 4
struct brcms_antselcfg {
u8 ant_config[ANT_SELCFG_MAX]; /* antenna configuration */
u8 num_antcfg; /* number of available antenna configurations */
};
/* common functions for every port */
struct brcms_c_info *brcms_c_attach(struct brcms_info *wl,
struct bcma_device *core, uint unit,
bool piomode, uint *perr);
uint brcms_c_detach(struct brcms_c_info *wlc);
int brcms_c_up(struct brcms_c_info *wlc);
uint brcms_c_down(struct brcms_c_info *wlc);
bool brcms_c_chipmatch(struct bcma_device *core);
void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx);
void brcms_c_reset(struct brcms_c_info *wlc);
void brcms_c_intrson(struct brcms_c_info *wlc);
u32 brcms_c_intrsoff(struct brcms_c_info *wlc);
void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask);
bool brcms_c_intrsupd(struct brcms_c_info *wlc);
bool brcms_c_isr(struct brcms_c_info *wlc);
bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded);
bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
struct ieee80211_hw *hw);
bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid);
void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val);
int brcms_c_get_header_len(void);
void brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset,
const u8 *addr);
void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
const struct ieee80211_tx_queue_params *arg,
bool suspend);
struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc);
void brcms_c_ampdu_flush(struct brcms_c_info *wlc, struct ieee80211_sta *sta,
u16 tid);
void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
u8 ba_wsize, uint max_rx_ampdu_bytes);
int brcms_c_module_register(struct brcms_pub *pub, const char *name,
struct brcms_info *hdl,
int (*down_fn)(void *handle));
int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
struct brcms_info *hdl);
void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc);
void brcms_c_enable_mac(struct brcms_c_info *wlc);
void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state);
void brcms_c_scan_start(struct brcms_c_info *wlc);
void brcms_c_scan_stop(struct brcms_c_info *wlc);
int brcms_c_get_curband(struct brcms_c_info *wlc);
int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel);
int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl);
void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
struct brcm_rateset *currs);
int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs);
int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period);
u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx);
void brcms_c_set_shortslot_override(struct brcms_c_info *wlc,
s8 sslot_override);
void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval);
u64 brcms_c_tsf_get(struct brcms_c_info *wlc);
void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf);
int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
int brcms_c_get_tx_power(struct brcms_c_info *wlc);
bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
void brcms_c_mute(struct brcms_c_info *wlc, bool on);
bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc);
void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr);
void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, const u8 *bssid,
u8 *ssid, size_t ssid_len);
void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr);
void brcms_c_update_beacon(struct brcms_c_info *wlc);
void brcms_c_set_new_beacon(struct brcms_c_info *wlc, struct sk_buff *beacon,
u16 tim_offset, u16 dtim_period);
void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc,
struct sk_buff *probe_resp);
void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable);
void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, size_t ssid_len);
#endif /* _BRCM_PUB_H_ */

View File

@@ -0,0 +1,514 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 <brcmu_wifi.h>
#include <brcmu_utils.h>
#include "d11.h"
#include "pub.h"
#include "rate.h"
/*
* Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate
* value
*/
const u8 rate_info[BRCM_MAXRATE + 1] = {
/* 0 1 2 3 4 5 6 7 8 9 */
/* 0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 10 */ 0x00, 0x37, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00,
/* 20 */ 0x00, 0x00, 0x6e, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00,
/* 50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 70 */ 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
/* 100 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c
};
/* rates are in units of Kbps */
const struct brcms_mcs_info mcs_table[MCS_TABLE_SIZE] = {
/* MCS 0: SS 1, MOD: BPSK, CR 1/2 */
{6500, 13500, CEIL(6500 * 10, 9), CEIL(13500 * 10, 9), 0x00,
BRCM_RATE_6M},
/* MCS 1: SS 1, MOD: QPSK, CR 1/2 */
{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x08,
BRCM_RATE_12M},
/* MCS 2: SS 1, MOD: QPSK, CR 3/4 */
{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x0A,
BRCM_RATE_18M},
/* MCS 3: SS 1, MOD: 16QAM, CR 1/2 */
{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x10,
BRCM_RATE_24M},
/* MCS 4: SS 1, MOD: 16QAM, CR 3/4 */
{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x12,
BRCM_RATE_36M},
/* MCS 5: SS 1, MOD: 64QAM, CR 2/3 */
{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x19,
BRCM_RATE_48M},
/* MCS 6: SS 1, MOD: 64QAM, CR 3/4 */
{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x1A,
BRCM_RATE_54M},
/* MCS 7: SS 1, MOD: 64QAM, CR 5/6 */
{65000, 135000, CEIL(65000 * 10, 9), CEIL(135000 * 10, 9), 0x1C,
BRCM_RATE_54M},
/* MCS 8: SS 2, MOD: BPSK, CR 1/2 */
{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x40,
BRCM_RATE_6M},
/* MCS 9: SS 2, MOD: QPSK, CR 1/2 */
{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x48,
BRCM_RATE_12M},
/* MCS 10: SS 2, MOD: QPSK, CR 3/4 */
{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x4A,
BRCM_RATE_18M},
/* MCS 11: SS 2, MOD: 16QAM, CR 1/2 */
{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x50,
BRCM_RATE_24M},
/* MCS 12: SS 2, MOD: 16QAM, CR 3/4 */
{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x52,
BRCM_RATE_36M},
/* MCS 13: SS 2, MOD: 64QAM, CR 2/3 */
{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0x59,
BRCM_RATE_48M},
/* MCS 14: SS 2, MOD: 64QAM, CR 3/4 */
{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x5A,
BRCM_RATE_54M},
/* MCS 15: SS 2, MOD: 64QAM, CR 5/6 */
{130000, 270000, CEIL(130000 * 10, 9), CEIL(270000 * 10, 9), 0x5C,
BRCM_RATE_54M},
/* MCS 16: SS 3, MOD: BPSK, CR 1/2 */
{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x80,
BRCM_RATE_6M},
/* MCS 17: SS 3, MOD: QPSK, CR 1/2 */
{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x88,
BRCM_RATE_12M},
/* MCS 18: SS 3, MOD: QPSK, CR 3/4 */
{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x8A,
BRCM_RATE_18M},
/* MCS 19: SS 3, MOD: 16QAM, CR 1/2 */
{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x90,
BRCM_RATE_24M},
/* MCS 20: SS 3, MOD: 16QAM, CR 3/4 */
{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x92,
BRCM_RATE_36M},
/* MCS 21: SS 3, MOD: 64QAM, CR 2/3 */
{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0x99,
BRCM_RATE_48M},
/* MCS 22: SS 3, MOD: 64QAM, CR 3/4 */
{175500, 364500, CEIL(175500 * 10, 9), CEIL(364500 * 10, 9), 0x9A,
BRCM_RATE_54M},
/* MCS 23: SS 3, MOD: 64QAM, CR 5/6 */
{195000, 405000, CEIL(195000 * 10, 9), CEIL(405000 * 10, 9), 0x9B,
BRCM_RATE_54M},
/* MCS 24: SS 4, MOD: BPSK, CR 1/2 */
{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0xC0,
BRCM_RATE_6M},
/* MCS 25: SS 4, MOD: QPSK, CR 1/2 */
{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0xC8,
BRCM_RATE_12M},
/* MCS 26: SS 4, MOD: QPSK, CR 3/4 */
{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0xCA,
BRCM_RATE_18M},
/* MCS 27: SS 4, MOD: 16QAM, CR 1/2 */
{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0xD0,
BRCM_RATE_24M},
/* MCS 28: SS 4, MOD: 16QAM, CR 3/4 */
{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0xD2,
BRCM_RATE_36M},
/* MCS 29: SS 4, MOD: 64QAM, CR 2/3 */
{208000, 432000, CEIL(208000 * 10, 9), CEIL(432000 * 10, 9), 0xD9,
BRCM_RATE_48M},
/* MCS 30: SS 4, MOD: 64QAM, CR 3/4 */
{234000, 486000, CEIL(234000 * 10, 9), CEIL(486000 * 10, 9), 0xDA,
BRCM_RATE_54M},
/* MCS 31: SS 4, MOD: 64QAM, CR 5/6 */
{260000, 540000, CEIL(260000 * 10, 9), CEIL(540000 * 10, 9), 0xDB,
BRCM_RATE_54M},
/* MCS 32: SS 1, MOD: BPSK, CR 1/2 */
{0, 6000, 0, CEIL(6000 * 10, 9), 0x00, BRCM_RATE_6M},
};
/*
* phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams
* Number of spatial streams: always 1 other fields: refer to table 78 of
* section 17.3.2.2 of the original .11a standard
*/
struct legacy_phycfg {
u32 rate_ofdm; /* ofdm mac rate */
/* phy ctl byte 3, code rate, modulation type, # of streams */
u8 tx_phy_ctl3;
};
/* Number of legacy_rate_cfg entries in the table */
#define LEGACY_PHYCFG_TABLE_SIZE 12
/*
* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate
* Eventually MIMOPHY would also be converted to this format
* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps
*/
static const struct
legacy_phycfg legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = {
{BRCM_RATE_1M, 0x00}, /* CCK 1Mbps, data rate 0 */
{BRCM_RATE_2M, 0x08}, /* CCK 2Mbps, data rate 1 */
{BRCM_RATE_5M5, 0x10}, /* CCK 5.5Mbps, data rate 2 */
{BRCM_RATE_11M, 0x18}, /* CCK 11Mbps, data rate 3 */
/* OFDM 6Mbps, code rate 1/2, BPSK, 1 spatial stream */
{BRCM_RATE_6M, 0x00},
/* OFDM 9Mbps, code rate 3/4, BPSK, 1 spatial stream */
{BRCM_RATE_9M, 0x02},
/* OFDM 12Mbps, code rate 1/2, QPSK, 1 spatial stream */
{BRCM_RATE_12M, 0x08},
/* OFDM 18Mbps, code rate 3/4, QPSK, 1 spatial stream */
{BRCM_RATE_18M, 0x0A},
/* OFDM 24Mbps, code rate 1/2, 16-QAM, 1 spatial stream */
{BRCM_RATE_24M, 0x10},
/* OFDM 36Mbps, code rate 3/4, 16-QAM, 1 spatial stream */
{BRCM_RATE_36M, 0x12},
/* OFDM 48Mbps, code rate 2/3, 64-QAM, 1 spatial stream */
{BRCM_RATE_48M, 0x19},
/* OFDM 54Mbps, code rate 3/4, 64-QAM, 1 spatial stream */
{BRCM_RATE_54M, 0x1A},
};
/* Hardware rates (also encodes default basic rates) */
const struct brcms_c_rateset cck_ofdm_mimo_rates = {
12,
/* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, */
{ 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
/* 54 Mbps */
0x6c},
0x00,
{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}
};
const struct brcms_c_rateset ofdm_mimo_rates = {
8,
/* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */
{ 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
0x00,
{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}
};
/* Default ratesets that include MCS32 for 40BW channels */
static const struct brcms_c_rateset cck_ofdm_40bw_mimo_rates = {
12,
/* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48 */
{ 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
/* 54 Mbps */
0x6c},
0x00,
{ 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}
};
static const struct brcms_c_rateset ofdm_40bw_mimo_rates = {
8,
/* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */
{ 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
0x00,
{ 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}
};
const struct brcms_c_rateset cck_ofdm_rates = {
12,
/* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48,*/
{ 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
/*54 Mbps */
0x6c},
0x00,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}
};
const struct brcms_c_rateset gphy_legacy_rates = {
4,
/* 1b, 2b, 5.5b, 11b Mbps */
{ 0x82, 0x84, 0x8b, 0x96},
0x00,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}
};
const struct brcms_c_rateset ofdm_rates = {
8,
/* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */
{ 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
0x00,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}
};
const struct brcms_c_rateset cck_rates = {
4,
/* 1b, 2b, 5.5, 11 Mbps */
{ 0x82, 0x84, 0x0b, 0x16},
0x00,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}
};
/* check if rateset is valid.
* if check_brate is true, rateset without a basic rate is considered NOT valid.
*/
static bool brcms_c_rateset_valid(struct brcms_c_rateset *rs, bool check_brate)
{
uint idx;
if (!rs->count)
return false;
if (!check_brate)
return true;
/* error if no basic rates */
for (idx = 0; idx < rs->count; idx++) {
if (rs->rates[idx] & BRCMS_RATE_FLAG)
return true;
}
return false;
}
void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams)
{
int i;
for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++)
rs->mcs[i] = 0;
}
/*
* filter based on hardware rateset, and sort filtered rateset with basic
* bit(s) preserved, and check if resulting rateset is valid.
*/
bool
brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs,
const struct brcms_c_rateset *hw_rs,
bool check_brate, u8 txstreams)
{
u8 rateset[BRCM_MAXRATE + 1];
u8 r;
uint count;
uint i;
memset(rateset, 0, sizeof(rateset));
count = rs->count;
for (i = 0; i < count; i++) {
/* mask off "basic rate" bit, BRCMS_RATE_FLAG */
r = (int)rs->rates[i] & BRCMS_RATE_MASK;
if ((r > BRCM_MAXRATE) || (rate_info[r] == 0))
continue;
rateset[r] = rs->rates[i]; /* preserve basic bit! */
}
/* fill out the rates in order, looking at only supported rates */
count = 0;
for (i = 0; i < hw_rs->count; i++) {
r = hw_rs->rates[i] & BRCMS_RATE_MASK;
if (rateset[r])
rs->rates[count++] = rateset[r];
}
rs->count = count;
/* only set the mcs rate bit if the equivalent hw mcs bit is set */
for (i = 0; i < MCSSET_LEN; i++)
rs->mcs[i] = (rs->mcs[i] & hw_rs->mcs[i]);
if (brcms_c_rateset_valid(rs, check_brate))
return true;
else
return false;
}
/* calculate the rate of a rx'd frame and return it as a ratespec */
u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp)
{
int phy_type;
u32 rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT;
phy_type =
((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT);
if ((phy_type == PHY_TYPE_N) || (phy_type == PHY_TYPE_SSN) ||
(phy_type == PHY_TYPE_LCN) || (phy_type == PHY_TYPE_HT)) {
switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) {
case PRXS0_CCK:
rspec =
cck_phy2mac_rate(
((struct cck_phy_hdr *) plcp)->signal);
break;
case PRXS0_OFDM:
rspec =
ofdm_phy2mac_rate(
((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
break;
case PRXS0_PREN:
rspec = (plcp[0] & MIMO_PLCP_MCS_MASK) | RSPEC_MIMORATE;
if (plcp[0] & MIMO_PLCP_40MHZ) {
/* indicate rspec is for 40 MHz mode */
rspec &= ~RSPEC_BW_MASK;
rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
}
break;
case PRXS0_STDN:
/* fallthru */
default:
/* not supported, error condition */
break;
}
if (plcp3_issgi(plcp[3]))
rspec |= RSPEC_SHORT_GI;
} else
if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM))
rspec = ofdm_phy2mac_rate(
((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
else
rspec = cck_phy2mac_rate(
((struct cck_phy_hdr *) plcp)->signal);
return rspec;
}
/* copy rateset src to dst as-is (no masking or sorting) */
void brcms_c_rateset_copy(const struct brcms_c_rateset *src,
struct brcms_c_rateset *dst)
{
memcpy(dst, src, sizeof(struct brcms_c_rateset));
}
/*
* Copy and selectively filter one rateset to another.
* 'basic_only' means only copy basic rates.
* 'rates' indicates cck (11b) and ofdm rates combinations.
* - 0: cck and ofdm
* - 1: cck only
* - 2: ofdm only
* 'xmask' is the copy mask (typically 0x7f or 0xff).
*/
void
brcms_c_rateset_filter(struct brcms_c_rateset *src, struct brcms_c_rateset *dst,
bool basic_only, u8 rates, uint xmask, bool mcsallow)
{
uint i;
uint r;
uint count;
count = 0;
for (i = 0; i < src->count; i++) {
r = src->rates[i];
if (basic_only && !(r & BRCMS_RATE_FLAG))
continue;
if (rates == BRCMS_RATES_CCK &&
is_ofdm_rate((r & BRCMS_RATE_MASK)))
continue;
if (rates == BRCMS_RATES_OFDM &&
is_cck_rate((r & BRCMS_RATE_MASK)))
continue;
dst->rates[count++] = r & xmask;
}
dst->count = count;
dst->htphy_membership = src->htphy_membership;
if (mcsallow && rates != BRCMS_RATES_CCK)
memcpy(&dst->mcs[0], &src->mcs[0], MCSSET_LEN);
else
brcms_c_rateset_mcs_clear(dst);
}
/* select rateset for a given phy_type and bandtype and filter it, sort it
* and fill rs_tgt with result
*/
void
brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt,
const struct brcms_c_rateset *rs_hw,
uint phy_type, int bandtype, bool cck_only,
uint rate_mask, bool mcsallow, u8 bw, u8 txstreams)
{
const struct brcms_c_rateset *rs_dflt;
struct brcms_c_rateset rs_sel;
if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) ||
(PHYTYPE_IS(phy_type, PHY_TYPE_N)) ||
(PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) ||
(PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) {
if (bandtype == BRCM_BAND_5G)
rs_dflt = (bw == BRCMS_20_MHZ ?
&ofdm_mimo_rates : &ofdm_40bw_mimo_rates);
else
rs_dflt = (bw == BRCMS_20_MHZ ?
&cck_ofdm_mimo_rates :
&cck_ofdm_40bw_mimo_rates);
} else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) {
rs_dflt = (bandtype == BRCM_BAND_5G) ?
&ofdm_rates : &cck_ofdm_rates;
} else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) {
rs_dflt = &ofdm_rates;
} else if (PHYTYPE_IS(phy_type, PHY_TYPE_G)) {
rs_dflt = &cck_ofdm_rates;
} else {
/* should not happen, error condition */
rs_dflt = &cck_rates; /* force cck */
}
/* if hw rateset is not supplied, assign selected rateset to it */
if (!rs_hw)
rs_hw = rs_dflt;
brcms_c_rateset_copy(rs_dflt, &rs_sel);
brcms_c_rateset_mcs_upd(&rs_sel, txstreams);
brcms_c_rateset_filter(&rs_sel, rs_tgt, false,
cck_only ? BRCMS_RATES_CCK : BRCMS_RATES_CCK_OFDM,
rate_mask, mcsallow);
brcms_c_rate_hwrs_filter_sort_validate(rs_tgt, rs_hw, false,
mcsallow ? txstreams : 1);
}
s16 brcms_c_rate_legacy_phyctl(uint rate)
{
uint i;
for (i = 0; i < LEGACY_PHYCFG_TABLE_SIZE; i++)
if (rate == legacy_phycfg_table[i].rate_ofdm)
return legacy_phycfg_table[i].tx_phy_ctl3;
return -1;
}
void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset)
{
uint i;
for (i = 0; i < MCSSET_LEN; i++)
rateset->mcs[i] = 0;
}
void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams)
{
memcpy(&rateset->mcs[0], &cck_ofdm_mimo_rates.mcs[0], MCSSET_LEN);
brcms_c_rateset_mcs_upd(rateset, txstreams);
}
/* Based on bandwidth passed, allow/disallow MCS 32 in the rateset */
void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw)
{
if (bw == BRCMS_40_MHZ)
setbit(rateset->mcs, 32);
else
clrbit(rateset->mcs, 32);
}

View File

@@ -0,0 +1,245 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_RATE_H_
#define _BRCM_RATE_H_
#include "types.h"
#include "d11.h"
#include "phy_hal.h"
extern const u8 rate_info[];
extern const struct brcms_c_rateset cck_ofdm_mimo_rates;
extern const struct brcms_c_rateset ofdm_mimo_rates;
extern const struct brcms_c_rateset cck_ofdm_rates;
extern const struct brcms_c_rateset ofdm_rates;
extern const struct brcms_c_rateset cck_rates;
extern const struct brcms_c_rateset gphy_legacy_rates;
extern const struct brcms_c_rateset rate_limit_1_2;
struct brcms_mcs_info {
/* phy rate in kbps [20Mhz] */
u32 phy_rate_20;
/* phy rate in kbps [40Mhz] */
u32 phy_rate_40;
/* phy rate in kbps [20Mhz] with SGI */
u32 phy_rate_20_sgi;
/* phy rate in kbps [40Mhz] with SGI */
u32 phy_rate_40_sgi;
/* phy ctl byte 3, code rate, modulation type, # of streams */
u8 tx_phy_ctl3;
/* matching legacy ofdm rate in 500bkps */
u8 leg_ofdm;
};
#define BRCMS_MAXMCS 32 /* max valid mcs index */
#define MCS_TABLE_SIZE 33 /* Number of mcs entries in the table */
extern const struct brcms_mcs_info mcs_table[];
#define MCS_TXS_MASK 0xc0 /* num tx streams - 1 bit mask */
#define MCS_TXS_SHIFT 6 /* num tx streams - 1 bit shift */
/* returns num tx streams - 1 */
static inline u8 mcs_2_txstreams(u8 mcs)
{
return (mcs_table[mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT;
}
static inline uint mcs_2_rate(u8 mcs, bool is40, bool sgi)
{
if (sgi) {
if (is40)
return mcs_table[mcs].phy_rate_40_sgi;
return mcs_table[mcs].phy_rate_20_sgi;
}
if (is40)
return mcs_table[mcs].phy_rate_40;
return mcs_table[mcs].phy_rate_20;
}
/* Macro to use the rate_info table */
#define BRCMS_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */
/*
* rate spec : holds rate and mode specific information required to generate a
* tx frame. Legacy CCK and OFDM information is held in the same manner as was
* done in the past (in the lower byte) the upper 3 bytes primarily hold MIMO
* specific information
*/
/* rate spec bit fields */
/* Either 500Kbps units or MIMO MCS idx */
#define RSPEC_RATE_MASK 0x0000007F
/* mimo MCS is stored in RSPEC_RATE_MASK */
#define RSPEC_MIMORATE 0x08000000
/* mimo bw mask */
#define RSPEC_BW_MASK 0x00000700
/* mimo bw shift */
#define RSPEC_BW_SHIFT 8
/* mimo Space/Time/Frequency mode mask */
#define RSPEC_STF_MASK 0x00003800
/* mimo Space/Time/Frequency mode shift */
#define RSPEC_STF_SHIFT 11
/* mimo coding type mask */
#define RSPEC_CT_MASK 0x0000C000
/* mimo coding type shift */
#define RSPEC_CT_SHIFT 14
/* mimo num STC streams per PLCP defn. */
#define RSPEC_STC_MASK 0x00300000
/* mimo num STC streams per PLCP defn. */
#define RSPEC_STC_SHIFT 20
/* mimo bit indicates adv coding in use */
#define RSPEC_LDPC_CODING 0x00400000
/* mimo bit indicates short GI in use */
#define RSPEC_SHORT_GI 0x00800000
/* bit indicates override both rate & mode */
#define RSPEC_OVERRIDE 0x80000000
/* bit indicates override rate only */
#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000
static inline bool rspec_active(u32 rspec)
{
return rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE);
}
static inline u8 rspec_phytxbyte2(u32 rspec)
{
return (rspec & 0xff00) >> 8;
}
static inline u32 rspec_get_bw(u32 rspec)
{
return (rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT;
}
static inline bool rspec_issgi(u32 rspec)
{
return (rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI;
}
static inline bool rspec_is40mhz(u32 rspec)
{
u32 bw = rspec_get_bw(rspec);
return bw == PHY_TXC1_BW_40MHZ || bw == PHY_TXC1_BW_40MHZ_DUP;
}
static inline uint rspec2rate(u32 rspec)
{
if (rspec & RSPEC_MIMORATE)
return mcs_2_rate(rspec & RSPEC_RATE_MASK, rspec_is40mhz(rspec),
rspec_issgi(rspec));
return rspec & RSPEC_RATE_MASK;
}
static inline u8 rspec_mimoplcp3(u32 rspec)
{
return (rspec & 0xf00000) >> 16;
}
static inline bool plcp3_issgi(u8 plcp)
{
return (plcp & (RSPEC_SHORT_GI >> 16)) != 0;
}
static inline uint rspec_stc(u32 rspec)
{
return (rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT;
}
static inline uint rspec_stf(u32 rspec)
{
return (rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT;
}
static inline bool is_mcs_rate(u32 ratespec)
{
return (ratespec & RSPEC_MIMORATE) != 0;
}
static inline bool is_ofdm_rate(u32 ratespec)
{
return !is_mcs_rate(ratespec) &&
(rate_info[ratespec & RSPEC_RATE_MASK] & BRCMS_RATE_FLAG);
}
static inline bool is_cck_rate(u32 ratespec)
{
u32 rate = (ratespec & BRCMS_RATE_MASK);
return !is_mcs_rate(ratespec) && (
rate == BRCM_RATE_1M || rate == BRCM_RATE_2M ||
rate == BRCM_RATE_5M5 || rate == BRCM_RATE_11M);
}
static inline bool is_single_stream(u8 mcs)
{
return mcs <= HIGHEST_SINGLE_STREAM_MCS || mcs == 32;
}
static inline u8 cck_rspec(u8 cck)
{
return cck & RSPEC_RATE_MASK;
}
/* Convert encoded rate value in plcp header to numerical rates in 500 KHz
* increments */
static inline u8 ofdm_phy2mac_rate(u8 rlpt)
{
return wlc_phy_get_ofdm_rate_lookup()[rlpt & 0x7];
}
static inline u8 cck_phy2mac_rate(u8 signal)
{
return signal/5;
}
/* Rates specified in brcms_c_rateset_filter() */
#define BRCMS_RATES_CCK_OFDM 0
#define BRCMS_RATES_CCK 1
#define BRCMS_RATES_OFDM 2
/* sanitize, and sort a rateset with the basic bit(s) preserved, validate
* rateset */
bool brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs,
const struct brcms_c_rateset *hw_rs,
bool check_brate, u8 txstreams);
/* copy rateset src to dst as-is (no masking or sorting) */
void brcms_c_rateset_copy(const struct brcms_c_rateset *src,
struct brcms_c_rateset *dst);
/* would be nice to have these documented ... */
u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp);
void brcms_c_rateset_filter(struct brcms_c_rateset *src,
struct brcms_c_rateset *dst, bool basic_only,
u8 rates, uint xmask, bool mcsallow);
void brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt,
const struct brcms_c_rateset *rs_hw, uint phy_type,
int bandtype, bool cck_only, uint rate_mask,
bool mcsallow, u8 bw, u8 txstreams);
s16 brcms_c_rate_legacy_phyctl(uint rate);
void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams);
void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset);
void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams);
void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw);
#endif /* _BRCM_RATE_H_ */

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_SCB_H_
#define _BRCM_SCB_H_
#include <linux/if_ether.h>
#include <brcmu_utils.h>
#include <defs.h>
#include "types.h"
#define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */
#define AMPDU_MAX_SCB_TID NUMPRIO
/* scb flags */
#define SCB_WMECAP 0x0040
#define SCB_HTCAP 0x10000 /* HT (MIMO) capable device */
#define SCB_IS40 0x80000 /* 40MHz capable */
#define SCB_STBCCAP 0x40000000 /* STBC Capable */
#define SCB_MAGIC 0xbeefcafe
/* structure to store per-tid state for the ampdu initiator */
struct scb_ampdu_tid_ini {
u8 tid; /* initiator tid for easy lookup */
/* tx retry count; indexed by seq modulo */
u8 txretry[AMPDU_TX_BA_MAX_WSIZE];
struct scb *scb; /* backptr for easy lookup */
u8 ba_wsize; /* negotiated ba window size (in pdu) */
};
struct scb_ampdu {
struct scb *scb; /* back pointer for easy reference */
u8 mpdu_density; /* mpdu density */
u8 max_pdu; /* max pdus allowed in ampdu */
u8 release; /* # of mpdus released at a time */
u16 min_len; /* min mpdu len to support the density */
u32 max_rx_ampdu_bytes; /* max ampdu rcv length; 8k, 16k, 32k, 64k */
/*
* This could easily be a ini[] pointer and we keep this info in wl
* itself instead of having mac80211 hold it for us. Also could be made
* dynamic per tid instead of static.
*/
/* initiator info - per tid (NUMPRIO): */
struct scb_ampdu_tid_ini ini[AMPDU_MAX_SCB_TID];
};
/* station control block - one per remote MAC address */
struct scb {
u32 magic;
u32 flags; /* various bit flags as defined below */
u32 flags2; /* various bit flags2 as defined below */
u8 state; /* current state bitfield of auth/assoc process */
u8 ea[ETH_ALEN]; /* station address */
uint fragresid[NUMPRIO];/* #bytes unused in frag buffer per prio */
u16 seqctl[NUMPRIO]; /* seqctl of last received frame (for dups) */
/* seqctl of last received frame (for dups) for non-QoS data and
* management */
u16 seqctl_nonqos;
u16 seqnum[NUMPRIO];/* WME: driver maintained sw seqnum per priority */
struct scb_ampdu scb_ampdu; /* AMPDU state including per tid info */
};
#endif /* _BRCM_SCB_H_ */

View File

@@ -0,0 +1,440 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 <net/mac80211.h>
#include "types.h"
#include "d11.h"
#include "rate.h"
#include "phy/phy_hal.h"
#include "channel.h"
#include "main.h"
#include "stf.h"
#include "debug.h"
#define MIN_SPATIAL_EXPANSION 0
#define MAX_SPATIAL_EXPANSION 1
#define BRCMS_STF_SS_STBC_RX(wlc) (BRCMS_ISNPHY(wlc->band) && \
NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6))
#define NSTS_1 1
#define NSTS_2 2
#define NSTS_3 3
#define NSTS_4 4
static const u8 txcore_default[5] = {
(0), /* bitmap of the core enabled */
(0x01), /* For Nsts = 1, enable core 1 */
(0x03), /* For Nsts = 2, enable core 1 & 2 */
(0x07), /* For Nsts = 3, enable core 1, 2 & 3 */
(0x0f) /* For Nsts = 4, enable all cores */
};
static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val)
{
/* MIMOPHYs rev3-6 cannot receive STBC with only one rx core active */
if (BRCMS_STF_SS_STBC_RX(wlc)) {
if ((wlc->stf->rxstreams == 1) && (val != HT_CAP_RX_STBC_NO))
return;
}
if (wlc->pub->up) {
brcms_c_update_beacon(wlc);
brcms_c_update_probe_resp(wlc, true);
}
}
/*
* every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to
* turn on/off txchain.
*/
void brcms_c_tempsense_upd(struct brcms_c_info *wlc)
{
struct brcms_phy_pub *pi = wlc->band->pi;
uint active_chains, txchain;
/* Check if the chip is too hot. Disable one Tx chain, if it is */
/* high 4 bits are for Rx chain, low 4 bits are for Tx chain */
active_chains = wlc_phy_stf_chain_active_get(pi);
txchain = active_chains & 0xf;
if (wlc->stf->txchain == wlc->stf->hw_txchain) {
if (txchain && (txchain < wlc->stf->hw_txchain))
/* turn off 1 tx chain */
brcms_c_stf_txchain_set(wlc, txchain, true);
} else if (wlc->stf->txchain < wlc->stf->hw_txchain) {
if (txchain == wlc->stf->hw_txchain)
/* turn back on txchain */
brcms_c_stf_txchain_set(wlc, txchain, true);
}
}
void
brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel,
u16 chanspec)
{
struct tx_power power;
u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id;
/* Clear previous settings */
*ss_algo_channel = 0;
if (!wlc->pub->up) {
*ss_algo_channel = (u16) -1;
return;
}
wlc_phy_txpower_get_current(wlc->band->pi, &power,
CHSPEC_CHANNEL(chanspec));
siso_mcs_id = (CHSPEC_IS40(chanspec)) ?
WL_TX_POWER_MCS40_SISO_FIRST : WL_TX_POWER_MCS20_SISO_FIRST;
cdd_mcs_id = (CHSPEC_IS40(chanspec)) ?
WL_TX_POWER_MCS40_CDD_FIRST : WL_TX_POWER_MCS20_CDD_FIRST;
stbc_mcs_id = (CHSPEC_IS40(chanspec)) ?
WL_TX_POWER_MCS40_STBC_FIRST : WL_TX_POWER_MCS20_STBC_FIRST;
/* criteria to choose stf mode */
/*
* the "+3dbm (12 0.25db units)" is to account for the fact that with
* CDD, tx occurs on both chains
*/
if (power.target[siso_mcs_id] > (power.target[cdd_mcs_id] + 12))
setbit(ss_algo_channel, PHY_TXC1_MODE_SISO);
else
setbit(ss_algo_channel, PHY_TXC1_MODE_CDD);
/*
* STBC is ORed into to algo channel as STBC requires per-packet SCB
* capability check so cannot be default mode of operation. One of
* SISO, CDD have to be set
*/
if (power.target[siso_mcs_id] <= (power.target[stbc_mcs_id] + 12))
setbit(ss_algo_channel, PHY_TXC1_MODE_STBC);
}
static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val)
{
if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON))
return false;
if ((int_val == ON) && (wlc->stf->txstreams == 1))
return false;
wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = (s8) int_val;
wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = (s8) int_val;
return true;
}
bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val)
{
if ((int_val != HT_CAP_RX_STBC_NO)
&& (int_val != HT_CAP_RX_STBC_ONE_STREAM))
return false;
if (BRCMS_STF_SS_STBC_RX(wlc)) {
if ((int_val != HT_CAP_RX_STBC_NO)
&& (wlc->stf->rxstreams == 1))
return false;
}
brcms_c_stf_stbc_rx_ht_update(wlc, int_val);
return true;
}
static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts,
u8 core_mask)
{
brcms_dbg_ht(wlc->hw->d11core, "wl%d: Nsts %d core_mask %x\n",
wlc->pub->unit, Nsts, core_mask);
if (hweight8(core_mask) > wlc->stf->txstreams)
core_mask = 0;
if ((hweight8(core_mask) == wlc->stf->txstreams) &&
((core_mask & ~wlc->stf->txchain)
|| !(core_mask & wlc->stf->txchain)))
core_mask = wlc->stf->txchain;
wlc->stf->txcore[Nsts] = core_mask;
/* Nsts = 1..4, txcore index = 1..4 */
if (Nsts == 1) {
/* Needs to update beacon and ucode generated response
* frames when 1 stream core map changed
*/
wlc->stf->phytxant = core_mask << PHY_TXC_ANT_SHIFT;
brcms_b_txant_set(wlc->hw, wlc->stf->phytxant);
if (wlc->clk) {
brcms_c_suspend_mac_and_wait(wlc);
brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
brcms_c_enable_mac(wlc);
}
}
return 0;
}
static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val)
{
int i;
u8 core_mask = 0;
brcms_dbg_ht(wlc->hw->d11core, "wl%d: val %x\n", wlc->pub->unit,
val);
wlc->stf->spatial_policy = (s8) val;
for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) {
core_mask = (val == MAX_SPATIAL_EXPANSION) ?
wlc->stf->txchain : txcore_default[i];
brcms_c_stf_txcore_set(wlc, (u8) i, core_mask);
}
return 0;
}
/*
* Centralized txant update function. call it whenever wlc->stf->txant and/or
* wlc->stf->txchain change.
*
* Antennas are controlled by ucode indirectly, which drives PHY or GPIO to
* achieve various tx/rx antenna selection schemes
*
* legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7
* means auto(last rx).
* for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7
* means last rx and do tx-antenna selection for SISO transmissions
* for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7
* means last rx and do tx-antenna selection for SISO transmissions
* for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7
* means both cores active
*/
static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
{
s8 txant;
txant = (s8) wlc->stf->txant;
if (BRCMS_PHY_11N_CAP(wlc->band)) {
if (txant == ANT_TX_FORCE_0) {
wlc->stf->phytxant = PHY_TXC_ANT_0;
} else if (txant == ANT_TX_FORCE_1) {
wlc->stf->phytxant = PHY_TXC_ANT_1;
if (BRCMS_ISNPHY(wlc->band) &&
NREV_GE(wlc->band->phyrev, 3)
&& NREV_LT(wlc->band->phyrev, 7))
wlc->stf->phytxant = PHY_TXC_ANT_2;
} else {
if (BRCMS_ISLCNPHY(wlc->band) ||
BRCMS_ISSSLPNPHY(wlc->band))
wlc->stf->phytxant = PHY_TXC_LCNPHY_ANT_LAST;
else {
/* catch out of sync wlc->stf->txcore */
WARN_ON(wlc->stf->txchain <= 0);
wlc->stf->phytxant =
wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
}
}
} else {
if (txant == ANT_TX_FORCE_0)
wlc->stf->phytxant = PHY_TXC_OLD_ANT_0;
else if (txant == ANT_TX_FORCE_1)
wlc->stf->phytxant = PHY_TXC_OLD_ANT_1;
else
wlc->stf->phytxant = PHY_TXC_OLD_ANT_LAST;
}
brcms_b_txant_set(wlc->hw, wlc->stf->phytxant);
}
int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force)
{
u8 txchain = (u8) int_val;
u8 txstreams;
uint i;
if (wlc->stf->txchain == txchain)
return 0;
if ((txchain & ~wlc->stf->hw_txchain)
|| !(txchain & wlc->stf->hw_txchain))
return -EINVAL;
/*
* if nrate override is configured to be non-SISO STF mode, reject
* reducing txchain to 1
*/
txstreams = (u8) hweight8(txchain);
if (txstreams > MAX_STREAMS_SUPPORTED)
return -EINVAL;
wlc->stf->txchain = txchain;
wlc->stf->txstreams = txstreams;
brcms_c_stf_stbc_tx_set(wlc, wlc->band->band_stf_stbc_tx);
brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
wlc->stf->txant =
(wlc->stf->txstreams == 1) ? ANT_TX_FORCE_0 : ANT_TX_DEF;
_brcms_c_stf_phy_txant_upd(wlc);
wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain,
wlc->stf->rxchain);
for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++)
brcms_c_stf_txcore_set(wlc, (u8) i, txcore_default[i]);
return 0;
}
/*
* update wlc->stf->ss_opmode which represents the operational stf_ss mode
* we're using
*/
int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band)
{
int ret_code = 0;
u8 prev_stf_ss;
u8 upd_stf_ss;
prev_stf_ss = wlc->stf->ss_opmode;
/*
* NOTE: opmode can only be SISO or CDD as STBC is decided on a
* per-packet basis
*/
if (BRCMS_STBC_CAP_PHY(wlc) &&
wlc->stf->ss_algosel_auto
&& (wlc->stf->ss_algo_channel != (u16) -1)) {
upd_stf_ss = (wlc->stf->txstreams == 1 ||
isset(&wlc->stf->ss_algo_channel,
PHY_TXC1_MODE_SISO)) ?
PHY_TXC1_MODE_SISO : PHY_TXC1_MODE_CDD;
} else {
if (wlc->band != band)
return ret_code;
upd_stf_ss = (wlc->stf->txstreams == 1) ?
PHY_TXC1_MODE_SISO : band->band_stf_ss_mode;
}
if (prev_stf_ss != upd_stf_ss) {
wlc->stf->ss_opmode = upd_stf_ss;
brcms_b_band_stf_ss_set(wlc->hw, upd_stf_ss);
}
return ret_code;
}
int brcms_c_stf_attach(struct brcms_c_info *wlc)
{
wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_SISO;
wlc->bandstate[BAND_5G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_CDD;
if (BRCMS_ISNPHY(wlc->band) &&
(wlc_phy_txpower_hw_ctrl_get(wlc->band->pi) != PHY_TPC_HW_ON))
wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode =
PHY_TXC1_MODE_CDD;
brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
brcms_c_stf_stbc_rx_ht_update(wlc, HT_CAP_RX_STBC_NO);
wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
if (BRCMS_STBC_CAP_PHY(wlc)) {
wlc->stf->ss_algosel_auto = true;
/* Init the default value */
wlc->stf->ss_algo_channel = (u16) -1;
}
return 0;
}
void brcms_c_stf_detach(struct brcms_c_info *wlc)
{
}
void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
{
_brcms_c_stf_phy_txant_upd(wlc);
}
void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc)
{
struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
/* get available rx/tx chains */
wlc->stf->hw_txchain = sprom->txchain;
wlc->stf->hw_rxchain = sprom->rxchain;
/* these parameter are intended to be used for all PHY types */
if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) {
if (BRCMS_ISNPHY(wlc->band))
wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY;
else
wlc->stf->hw_txchain = TXCHAIN_DEF;
}
wlc->stf->txchain = wlc->stf->hw_txchain;
wlc->stf->txstreams = (u8) hweight8(wlc->stf->hw_txchain);
if (wlc->stf->hw_rxchain == 0 || wlc->stf->hw_rxchain == 0xf) {
if (BRCMS_ISNPHY(wlc->band))
wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY;
else
wlc->stf->hw_rxchain = RXCHAIN_DEF;
}
wlc->stf->rxchain = wlc->stf->hw_rxchain;
wlc->stf->rxstreams = (u8) hweight8(wlc->stf->hw_rxchain);
/* initialize the txcore table */
memcpy(wlc->stf->txcore, txcore_default, sizeof(wlc->stf->txcore));
/* default spatial_policy */
wlc->stf->spatial_policy = MIN_SPATIAL_EXPANSION;
brcms_c_stf_spatial_policy_set(wlc, MIN_SPATIAL_EXPANSION);
}
static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
u32 rspec)
{
u16 phytxant = wlc->stf->phytxant;
if (rspec_stf(rspec) != PHY_TXC1_MODE_SISO)
phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
else if (wlc->stf->txant == ANT_TX_DEF)
phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
phytxant &= PHY_TXC_ANT_MASK;
return phytxant;
}
u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, u32 rspec)
{
return _brcms_c_stf_phytxchain_sel(wlc, rspec);
}
u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, u32 rspec)
{
u16 phytxant = wlc->stf->phytxant;
u16 mask = PHY_TXC_ANT_MASK;
/* for non-siso rates or default setting, use the available chains */
if (BRCMS_ISNPHY(wlc->band)) {
phytxant = _brcms_c_stf_phytxchain_sel(wlc, rspec);
mask = PHY_TXC_HTANT_MASK;
}
phytxant |= phytxant & mask;
return phytxant;
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_STF_H_
#define _BRCM_STF_H_
#include "types.h"
int brcms_c_stf_attach(struct brcms_c_info *wlc);
void brcms_c_stf_detach(struct brcms_c_info *wlc);
void brcms_c_tempsense_upd(struct brcms_c_info *wlc);
void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc,
u16 *ss_algo_channel, u16 chanspec);
int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band);
void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force);
bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val);
void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc);
u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, u32 rspec);
u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, u32 rspec);
#endif /* _BRCM_STF_H_ */

View File

@@ -0,0 +1,303 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_TYPES_H_
#define _BRCM_TYPES_H_
#include <linux/types.h>
#include <linux/io.h>
#define WL_CHAN_FREQ_RANGE_2G 0
#define WL_CHAN_FREQ_RANGE_5GL 1
#define WL_CHAN_FREQ_RANGE_5GM 2
#define WL_CHAN_FREQ_RANGE_5GH 3
/* boardflags */
/* Board has gpio 9 controlling the PA */
#define BFL_PACTRL 0x00000002
/* Not ok to power down the chip pll and oscillator */
#define BFL_NOPLLDOWN 0x00000020
/* Board supports the Front End Module */
#define BFL_FEM 0x00000800
/* Board has an external LNA in 2.4GHz band */
#define BFL_EXTLNA 0x00001000
/* Board has no PA */
#define BFL_NOPA 0x00010000
/* Power topology uses BUCKBOOST */
#define BFL_BUCKBOOST 0x00200000
/* Board has FEM and switch to share antenna w/ BT */
#define BFL_FEM_BT 0x00400000
/* Power topology doesn't use CBUCK */
#define BFL_NOCBUCK 0x00800000
/* Power topology uses PALDO */
#define BFL_PALDO 0x02000000
/* Board has an external LNA in 5GHz band */
#define BFL_EXTLNA_5GHz 0x10000000
/* boardflags2 */
/* Board has an external rxbb regulator */
#define BFL2_RXBB_INT_REG_DIS 0x00000001
/* Flag to implement alternative A-band PLL settings */
#define BFL2_APLL_WAR 0x00000002
/* Board permits enabling TX Power Control */
#define BFL2_TXPWRCTRL_EN 0x00000004
/* Board supports the 2X4 diversity switch */
#define BFL2_2X4_DIV 0x00000008
/* Board supports 5G band power gain */
#define BFL2_5G_PWRGAIN 0x00000010
/* Board overrides ASPM and Clkreq settings */
#define BFL2_PCIEWAR_OVR 0x00000020
#define BFL2_LEGACY 0x00000080
/* 4321mcm93 board uses Skyworks FEM */
#define BFL2_SKWRKFEM_BRD 0x00000100
/* Board has a WAR for clock-harmonic spurs */
#define BFL2_SPUR_WAR 0x00000200
/* Flag to narrow G-band PLL loop b/w */
#define BFL2_GPLL_WAR 0x00000400
/* Tx CCK pkts on Ant 0 only */
#define BFL2_SINGLEANT_CCK 0x00001000
/* WAR to reduce and avoid clock-harmonic spurs in 2G */
#define BFL2_2G_SPUR_WAR 0x00002000
/* Flag to widen G-band PLL loop b/w */
#define BFL2_GPLL_WAR2 0x00010000
#define BFL2_IPALVLSHIFT_3P3 0x00020000
/* Use internal envelope detector for TX IQCAL */
#define BFL2_INTERNDET_TXIQCAL 0x00040000
/* Keep the buffered Xtal output from radio "ON". Most drivers will turn it
* off without this flag to save power. */
#define BFL2_XTALBUFOUTEN 0x00080000
/*
* board specific GPIO assignment, gpio 0-3 are also customer-configurable
* led
*/
/* bit 9 controls the PA on new 4306 boards */
#define BOARD_GPIO_PACTRL 0x200
#define BOARD_GPIO_12 0x1000
#define BOARD_GPIO_13 0x2000
/* **** Core type/rev defaults **** */
#define D11CONF 0x0fffffb0 /* Supported D11 revs: 4, 5, 7-27
* also need to update wlc.h MAXCOREREV
*/
#define NCONF 0x000001ff /* Supported nphy revs:
* 0 4321a0
* 1 4321a1
* 2 4321b0/b1/c0/c1
* 3 4322a0
* 4 4322a1
* 5 4716a0
* 6 43222a0, 43224a0
* 7 43226a0
* 8 5357a0, 43236a0
*/
#define LCNCONF 0x00000007 /* Supported lcnphy revs:
* 0 4313a0, 4336a0, 4330a0
* 1
* 2 4330a0
*/
#define SSLPNCONF 0x0000000f /* Supported sslpnphy revs:
* 0 4329a0/k0
* 1 4329b0/4329C0
* 2 4319a0
* 3 5356a0
*/
/********************************************************************
* Phy/Core Configuration. Defines macros to to check core phy/rev *
* compile-time configuration. Defines default core support. *
* ******************************************************************
*/
/* Basic macros to check a configuration bitmask */
#define CONF_HAS(config, val) ((config) & (1 << (val)))
#define CONF_MSK(config, mask) ((config) & (mask))
#define MSK_RANGE(low, hi) ((1 << ((hi)+1)) - (1 << (low)))
#define CONF_RANGE(config, low, hi) (CONF_MSK(config, MSK_RANGE(low, high)))
#define CONF_IS(config, val) ((config) == (1 << (val)))
#define CONF_GE(config, val) ((config) & (0-(1 << (val))))
#define CONF_GT(config, val) ((config) & (0-2*(1 << (val))))
#define CONF_LT(config, val) ((config) & ((1 << (val))-1))
#define CONF_LE(config, val) ((config) & (2*(1 << (val))-1))
/* Wrappers for some of the above, specific to config constants */
#define NCONF_HAS(val) CONF_HAS(NCONF, val)
#define NCONF_MSK(mask) CONF_MSK(NCONF, mask)
#define NCONF_IS(val) CONF_IS(NCONF, val)
#define NCONF_GE(val) CONF_GE(NCONF, val)
#define NCONF_GT(val) CONF_GT(NCONF, val)
#define NCONF_LT(val) CONF_LT(NCONF, val)
#define NCONF_LE(val) CONF_LE(NCONF, val)
#define LCNCONF_HAS(val) CONF_HAS(LCNCONF, val)
#define LCNCONF_MSK(mask) CONF_MSK(LCNCONF, mask)
#define LCNCONF_IS(val) CONF_IS(LCNCONF, val)
#define LCNCONF_GE(val) CONF_GE(LCNCONF, val)
#define LCNCONF_GT(val) CONF_GT(LCNCONF, val)
#define LCNCONF_LT(val) CONF_LT(LCNCONF, val)
#define LCNCONF_LE(val) CONF_LE(LCNCONF, val)
#define D11CONF_HAS(val) CONF_HAS(D11CONF, val)
#define D11CONF_MSK(mask) CONF_MSK(D11CONF, mask)
#define D11CONF_IS(val) CONF_IS(D11CONF, val)
#define D11CONF_GE(val) CONF_GE(D11CONF, val)
#define D11CONF_GT(val) CONF_GT(D11CONF, val)
#define D11CONF_LT(val) CONF_LT(D11CONF, val)
#define D11CONF_LE(val) CONF_LE(D11CONF, val)
#define PHYCONF_HAS(val) CONF_HAS(PHYTYPE, val)
#define PHYCONF_IS(val) CONF_IS(PHYTYPE, val)
#define NREV_IS(var, val) \
(NCONF_HAS(val) && (NCONF_IS(val) || ((var) == (val))))
#define NREV_GE(var, val) \
(NCONF_GE(val) && (!NCONF_LT(val) || ((var) >= (val))))
#define NREV_GT(var, val) \
(NCONF_GT(val) && (!NCONF_LE(val) || ((var) > (val))))
#define NREV_LT(var, val) \
(NCONF_LT(val) && (!NCONF_GE(val) || ((var) < (val))))
#define NREV_LE(var, val) \
(NCONF_LE(val) && (!NCONF_GT(val) || ((var) <= (val))))
#define LCNREV_IS(var, val) \
(LCNCONF_HAS(val) && (LCNCONF_IS(val) || ((var) == (val))))
#define LCNREV_GE(var, val) \
(LCNCONF_GE(val) && (!LCNCONF_LT(val) || ((var) >= (val))))
#define LCNREV_GT(var, val) \
(LCNCONF_GT(val) && (!LCNCONF_LE(val) || ((var) > (val))))
#define LCNREV_LT(var, val) \
(LCNCONF_LT(val) && (!LCNCONF_GE(val) || ((var) < (val))))
#define LCNREV_LE(var, val) \
(LCNCONF_LE(val) && (!LCNCONF_GT(val) || ((var) <= (val))))
#define D11REV_IS(var, val) \
(D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val))))
#define D11REV_GE(var, val) \
(D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val))))
#define D11REV_GT(var, val) \
(D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val))))
#define D11REV_LT(var, val) \
(D11CONF_LT(val) && (!D11CONF_GE(val) || ((var) < (val))))
#define D11REV_LE(var, val) \
(D11CONF_LE(val) && (!D11CONF_GT(val) || ((var) <= (val))))
#define PHYTYPE_IS(var, val)\
(PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val))))
/* Set up PHYTYPE automatically: (depends on PHY_TYPE_X, from d11.h) */
#define _PHYCONF_N (1 << PHY_TYPE_N)
#define _PHYCONF_LCN (1 << PHY_TYPE_LCN)
#define _PHYCONF_SSLPN (1 << PHY_TYPE_SSN)
#define PHYTYPE (_PHYCONF_N | _PHYCONF_LCN | _PHYCONF_SSLPN)
/* Utility macro to identify 802.11n (HT) capable PHYs */
#define PHYTYPE_11N_CAP(phytype) \
(PHYTYPE_IS(phytype, PHY_TYPE_N) || \
PHYTYPE_IS(phytype, PHY_TYPE_LCN) || \
PHYTYPE_IS(phytype, PHY_TYPE_SSN))
/* Last but not least: shorter wlc-specific var checks */
#define BRCMS_ISNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_N)
#define BRCMS_ISLCNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_LCN)
#define BRCMS_ISSSLPNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_SSN)
#define BRCMS_PHY_11N_CAP(band) PHYTYPE_11N_CAP((band)->phytype)
/**********************************************************************
* ------------- End of Core phy/rev configuration. ----------------- *
* ********************************************************************
*/
#define BCMMSG(dev, fmt, args...) \
do { \
if (brcm_msg_level & BRCM_DL_INFO) \
wiphy_err(dev, "%s: " fmt, __func__, ##args); \
} while (0)
#ifdef CONFIG_BCM47XX
/*
* bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder
* transactions. As a fix, a read after write is performed on certain places
* in the code. Older chips and the newer 5357 family don't require this fix.
*/
#define bcma_wflush16(c, o, v) \
({ bcma_write16(c, o, v); (void)bcma_read16(c, o); })
#else
#define bcma_wflush16(c, o, v) bcma_write16(c, o, v)
#endif /* CONFIG_BCM47XX */
/* multi-bool data type: set of bools, mbool is true if any is set */
/* set one bool */
#define mboolset(mb, bit) ((mb) |= (bit))
/* clear one bool */
#define mboolclr(mb, bit) ((mb) &= ~(bit))
/* true if one bool is set */
#define mboolisset(mb, bit) (((mb) & (bit)) != 0)
#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val)))
#define CEIL(x, y) (((x) + ((y)-1)) / (y))
/* forward declarations */
struct wiphy;
struct ieee80211_sta;
struct ieee80211_tx_queue_params;
struct brcms_info;
struct brcms_c_info;
struct brcms_hardware;
struct brcms_band;
struct dma_pub;
struct si_pub;
struct tx_status;
struct d11rxhdr;
struct txpwr_limits;
/* iovar structure */
struct brcmu_iovar {
const char *name; /* name for lookup and display */
u16 varid; /* id for switch */
u16 flags; /* driver-specific flag bits */
u16 type; /* base type of argument */
u16 minlen; /* min length for buffer vars */
};
/* brcm_msg_level is a bit vector with defs in defs.h */
extern u32 brcm_msg_level;
#endif /* _BRCM_TYPES_H_ */

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 <defs.h>
#include "types.h"
#include <ucode_loader.h>
enum {
D11UCODE_NAMETAG_START = 0,
D11LCN0BSINITVALS24,
D11LCN0INITVALS24,
D11LCN1BSINITVALS24,
D11LCN1INITVALS24,
D11LCN2BSINITVALS24,
D11LCN2INITVALS24,
D11N0ABSINITVALS16,
D11N0BSINITVALS16,
D11N0INITVALS16,
D11UCODE_OVERSIGHT16_MIMO,
D11UCODE_OVERSIGHT16_MIMOSZ,
D11UCODE_OVERSIGHT24_LCN,
D11UCODE_OVERSIGHT24_LCNSZ,
D11UCODE_OVERSIGHT_BOMMAJOR,
D11UCODE_OVERSIGHT_BOMMINOR
};
int brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode)
{
int rc;
rc = brcms_check_firmwares(wl);
rc = rc < 0 ? rc :
brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn0bsinitvals24,
D11LCN0BSINITVALS24);
rc = rc < 0 ?
rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn0initvals24,
D11LCN0INITVALS24);
rc = rc < 0 ?
rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn1bsinitvals24,
D11LCN1BSINITVALS24);
rc = rc < 0 ?
rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn1initvals24,
D11LCN1INITVALS24);
rc = rc < 0 ? rc :
brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn2bsinitvals24,
D11LCN2BSINITVALS24);
rc = rc < 0 ?
rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn2initvals24,
D11LCN2INITVALS24);
rc = rc < 0 ?
rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0absinitvals16,
D11N0ABSINITVALS16);
rc = rc < 0 ?
rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0bsinitvals16,
D11N0BSINITVALS16);
rc = rc < 0 ?
rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0initvals16,
D11N0INITVALS16);
rc = rc < 0 ?
rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_16_mimo,
D11UCODE_OVERSIGHT16_MIMO);
rc = rc < 0 ?
rc : brcms_ucode_init_uint(wl, &ucode->bcm43xx_16_mimosz,
D11UCODE_OVERSIGHT16_MIMOSZ);
rc = rc < 0 ?
rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_24_lcn,
D11UCODE_OVERSIGHT24_LCN);
rc = rc < 0 ?
rc : brcms_ucode_init_uint(wl, &ucode->bcm43xx_24_lcnsz,
D11UCODE_OVERSIGHT24_LCNSZ);
rc = rc < 0 ?
rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_bommajor,
D11UCODE_OVERSIGHT_BOMMAJOR);
rc = rc < 0 ?
rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_bomminor,
D11UCODE_OVERSIGHT_BOMMINOR);
return rc;
}
void brcms_ucode_data_free(struct brcms_ucode *ucode)
{
brcms_ucode_free_buf((void *)ucode->d11lcn0bsinitvals24);
brcms_ucode_free_buf((void *)ucode->d11lcn0initvals24);
brcms_ucode_free_buf((void *)ucode->d11lcn1bsinitvals24);
brcms_ucode_free_buf((void *)ucode->d11lcn1initvals24);
brcms_ucode_free_buf((void *)ucode->d11lcn2bsinitvals24);
brcms_ucode_free_buf((void *)ucode->d11lcn2initvals24);
brcms_ucode_free_buf((void *)ucode->d11n0absinitvals16);
brcms_ucode_free_buf((void *)ucode->d11n0bsinitvals16);
brcms_ucode_free_buf((void *)ucode->d11n0initvals16);
brcms_ucode_free_buf((void *)ucode->bcm43xx_16_mimo);
brcms_ucode_free_buf((void *)ucode->bcm43xx_24_lcn);
brcms_ucode_free_buf((void *)ucode->bcm43xx_bommajor);
brcms_ucode_free_buf((void *)ucode->bcm43xx_bomminor);
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* 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 _BRCM_UCODE_H_
#define _BRCM_UCODE_H_
#include "types.h" /* forward structure declarations */
#define MIN_FW_SIZE 40000 /* minimum firmware file size in bytes */
#define MAX_FW_SIZE 150000
#define UCODE_LOADER_API_VER 0
struct d11init;
struct brcms_ucode {
struct d11init *d11lcn0bsinitvals24;
struct d11init *d11lcn0initvals24;
struct d11init *d11lcn1bsinitvals24;
struct d11init *d11lcn1initvals24;
struct d11init *d11lcn2bsinitvals24;
struct d11init *d11lcn2initvals24;
struct d11init *d11n0absinitvals16;
struct d11init *d11n0bsinitvals16;
struct d11init *d11n0initvals16;
__le32 *bcm43xx_16_mimo;
size_t bcm43xx_16_mimosz;
__le32 *bcm43xx_24_lcn;
size_t bcm43xx_24_lcnsz;
u32 *bcm43xx_bommajor;
u32 *bcm43xx_bomminor;
};
int brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode);
void brcms_ucode_data_free(struct brcms_ucode *ucode);
int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, unsigned int idx);
int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes,
unsigned int idx);
void brcms_ucode_free_buf(void *);
int brcms_check_firmwares(struct brcms_info *wl);
#endif /* _BRCM_UCODE_H_ */